# Starfighter

> A sleek stylized sci-fi starfighter with a faceted hexagonal fuselage, bubble cockpit, swept anhedral wings with wingtip cannons, twin engine nacelles with glowing exhausts, canted tail fins and retractable landing gear. Choose hull, accent and engine glow colors — a ready hero ship for space shooters and sci-fi games.

![Starfighter preview](https://codels.download/m/starfighter.png)

Multi-view sheet (3/4, front, side, top): https://codels.download/m/starfighter.sheet.png

## Facts

- Category: Vehicles › Spacecraft
- Size (W × H × D): 9.38 × 2.94 × 12.42 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,196 · Meshes: 38 · Materials: 5
- License: CC0-1.0 (Codels built-in)
- Tags: spaceship, low-poly, stylized, military, sci-fi, space, orbit, shooter, space-shooter, hero-asset, vehicle, metal, emissive, game-ready, mobile-friendly, parametric, color-blue, size-huge, poly-low
- Page: https://codels.download/models/starfighter

## Files

| Format | URL |
|---|---|
| three.js ES module (`createStarfighter()`) | https://codels.download/m/starfighter.js |
| React Three Fiber component (`<Starfighter />`) | https://codels.download/m/starfighter.jsx |
| Instancing module (`createStarfighterInstances(count, place)`, one draw call per material) | https://codels.download/m/starfighter.instanced.js |
| Standalone HTML demo | https://codels.download/m/starfighter.html |
| glTF binary | https://codels.download/m/starfighter.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/starfighter.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/starfighter.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/starfighter.obj · https://codels.download/m/starfighter.mtl |
| STL | https://codels.download/m/starfighter.stl |
| CodelSpec JSON | https://codels.download/m/starfighter.json |

## Parameters

Append them as query parameters to any URL above to get a customized variant (e.g. `?hullColor=...`).

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `hullColor` | color | #rrggbb | #d5dbe2 | #d5dbe2 |
| `accentColor` | color | #rrggbb | #e8742f | #e8742f |
| `glowColor` | color | #rrggbb | #46c9ff | #46c9ff |
| `gear` | boolean | true \| false | true | true |

## Parts

- ship (group)
  - fuselage (lathe · hull)
  - noseTip (lathe · accent)
  - cockpit (sphere · glass)
  - canopyFrame (box · dark)
  - intakeL (box · dark)
  - intakeR (box · dark)
  - wingL (group)
    - cannonL (cylinder · dark)
    - barrelL (cylinder · accent)
    - tipLightL (sphere · glow)
  - wingR (group)
    - cannonR (cylinder · dark)
    - barrelR (cylinder · accent)
    - tipLightR (sphere · glow)
  - engineL (group)
    - nacelle (cylinder · hull)
    - intakeRing (cylinder · accent)
    - intake (cylinder · dark)
    - nozzle (cylinder · dark)
    - exhaustGlow (cylinder · glow)
    - exhaustPlume (cone · glow)
    - tailFin (group)
  - engineR (group)
    - nacelle (cylinder · hull)
    - intakeRing (cylinder · accent)
    - intake (cylinder · dark)
    - nozzle (cylinder · dark)
    - exhaustGlow (cylinder · glow)
    - exhaustPlume (cone · glow)
    - tailFin (group)
  - noseGearStrut (cylinder · dark)
  - noseGearPad (cylinder · dark)
  - mainGearLStrut (cylinder · dark)
  - mainGearLPad (cylinder · dark)
  - mainGearRStrut (cylinder · dark)
  - mainGearRPad (cylinder · dark)

## How to use

Save the code below as `starfighter.js`, then:

```js
import { createStarfighter } from './starfighter.js';
const model = createStarfighter();
scene.add(model);
```

## Code

```js
/**
 * Starfighter — Codels 3D model library (https://codels.download/models/starfighter)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,196 · Size (W × H × D): 9.38 × 2.94 × 12.42 m
 *
 * Usage:
 *   import { createStarfighter } from './starfighter.js';
 *   
 *   const model = createStarfighter();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
  return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}

// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
  const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
  for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
  const options = bevel
    ? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
    : { depth, bevelEnabled: false };
  return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}

export function createStarfighter() {
  const root = new THREE.Group();
  root.name = 'Starfighter';

  // Materials
  const hullMat = new THREE.MeshStandardMaterial({ name: 'hull', color: 0xd5dbe2, roughness: 0.4, metalness: 0.35, flatShading: true });
  const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xe8742f, roughness: 0.45, metalness: 0.2, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x1f2c3a, roughness: 0.15, metalness: 0.35 });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x3a3f48, roughness: 0.55, metalness: 0.5, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x46c9ff, roughness: 0.4, emissive: 0x46c9ff, emissiveIntensity: 1.6, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.04, 0.22, 1.3);
  const boxGeo2 = new THREE.BoxGeometry(2.2, 0.02, 0.2);
  const cylinderGeo = new THREE.CylinderGeometry(0.09, 0.09, 2.6, 6);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.045, 0.045, 0.7, 6);
  const sphereGeo = new THREE.SphereGeometry(0.07, 6, 4);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.52, 0.6, 3.6, 10);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.65, 0.65, 0.28, 10);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.46, 0.46, 0.02, 10);
  const cylinderGeo6 = new THREE.CylinderGeometry(0.62, 0.62, 0.25, 10);
  const cylinderGeo7 = new THREE.CylinderGeometry(0.44, 0.44, 0.04, 10);
  const coneGeo = new THREE.ConeGeometry(0.4, 1.1, 10);
  const extrudeGeo = extrude([[-3, 0], [-4.9, 0], [-5.25, 1.35], [-4.55, 1.35]], 0.08, [], [0.03, 0.03, 1]);
  const extrudeGeo2 = extrude([[-4.9, 1.1], [-5.19, 1.1], [-5.25, 1.35], [-4.55, 1.35], [-4.62, 1.1]], 0.1);
  const cylinderGeo8 = new THREE.CylinderGeometry(0.24, 0.3, 0.12, 8);
  const cylinderGeo9 = new THREE.CylinderGeometry(0.07, 0.07, 0.6, 6);

  // Parts
  const ship = new THREE.Group();
  ship.name = 'ship';
  root.add(ship);
  const fuselage = new THREE.Mesh(lathe([[0, -4.9], [0.82, -4.9], [1.05, -3.5], [1.1, -1], [0.95, 1.5], [0.6, 3.6], [0.24, 5.4], [0, 6.1]], 6), hullMat);
  fuselage.name = 'fuselage';
  fuselage.position.set(0, 1.3, 0);
  fuselage.rotation.set(deg(90), 0, 0);
  fuselage.scale.set(1, 1, 0.6);
  ship.add(fuselage);
  const noseTip = new THREE.Mesh(lathe([[0.27, 5.25], [0.13, 5.75], [0, 6.12]], 6), accentMat);
  noseTip.name = 'noseTip';
  noseTip.position.set(0, 1.3, 0);
  noseTip.rotation.set(deg(90), 0, 0);
  noseTip.scale.set(1.04, 1, 0.624);
  ship.add(noseTip);
  const cockpit = new THREE.Mesh(new THREE.SphereGeometry(0.55, 12, 5, 0, Math.PI * 2, 0, Math.PI / 2), glassMat);
  cockpit.name = 'cockpit';
  cockpit.position.set(0, 1.6, 1.75);
  cockpit.scale.set(0.82, 0.95, 2.5);
  ship.add(cockpit);
  const canopyFrame = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.08, 1.2), darkMat);
  canopyFrame.name = 'canopyFrame';
  canopyFrame.position.set(0, 2.1, 1.3);
  ship.add(canopyFrame);
  const intakeL = new THREE.Mesh(boxGeo, darkMat);
  intakeL.name = 'intakeL';
  intakeL.position.set(0.85, 1.3, 0.2);
  ship.add(intakeL);
  const intakeR = new THREE.Mesh(boxGeo, darkMat);
  intakeR.name = 'intakeR';
  intakeR.position.set(-0.85, 1.3, 0.2);
  ship.add(intakeR);
  const wingL = new THREE.Group();
  wingL.name = 'wingL';
  wingL.position.set(0, 1.18, 0);
  wingL.rotation.set(0, 0, deg(-5));
  ship.add(wingL);
  const extrude9 = new THREE.Mesh(extrude([[0.3, 1.1], [4.5, -2.15], [4.65, -3.35], [0.3, -3.8]], 0.1, [], [0.04, 0.05, 1]), hullMat);
  extrude9.rotation.set(deg(90), 0, 0);
  wingL.add(extrude9);
  const box10 = new THREE.Mesh(boxGeo2, accentMat);
  box10.position.set(2.4, 0.095, -2.2);
  box10.rotation.set(0, deg(37), 0);
  wingL.add(box10);
  const cannonL = new THREE.Mesh(cylinderGeo, darkMat);
  cannonL.name = 'cannonL';
  cannonL.position.set(4.62, 0, -1.9);
  cannonL.rotation.set(deg(90), 0, 0);
  wingL.add(cannonL);
  const barrelL = new THREE.Mesh(cylinderGeo2, accentMat);
  barrelL.name = 'barrelL';
  barrelL.position.set(4.62, 0, -0.3);
  barrelL.rotation.set(deg(90), 0, 0);
  wingL.add(barrelL);
  const tipLightL = new THREE.Mesh(sphereGeo, glowMat);
  tipLightL.name = 'tipLightL';
  tipLightL.position.set(4.62, 0, -3.25);
  wingL.add(tipLightL);
  const wingR = new THREE.Group();
  wingR.name = 'wingR';
  wingR.position.set(0, 1.18, 0);
  wingR.rotation.set(0, 0, deg(5));
  ship.add(wingR);
  const extrude15 = new THREE.Mesh(extrude([[-0.3, 1.1], [-4.5, -2.15], [-4.65, -3.35], [-0.3, -3.8]], 0.1, [], [0.04, 0.05, 1]), hullMat);
  extrude15.rotation.set(deg(90), 0, 0);
  wingR.add(extrude15);
  const box16 = new THREE.Mesh(boxGeo2, accentMat);
  box16.position.set(-2.4, 0.095, -2.2);
  box16.rotation.set(0, deg(-37), 0);
  wingR.add(box16);
  const cannonR = new THREE.Mesh(cylinderGeo, darkMat);
  cannonR.name = 'cannonR';
  cannonR.position.set(-4.62, 0, -1.9);
  cannonR.rotation.set(deg(90), 0, 0);
  wingR.add(cannonR);
  const barrelR = new THREE.Mesh(cylinderGeo2, accentMat);
  barrelR.name = 'barrelR';
  barrelR.position.set(-4.62, 0, -0.3);
  barrelR.rotation.set(deg(90), 0, 0);
  wingR.add(barrelR);
  const tipLightR = new THREE.Mesh(sphereGeo, glowMat);
  tipLightR.name = 'tipLightR';
  tipLightR.position.set(-4.62, 0, -3.25);
  wingR.add(tipLightR);
  const engineL = new THREE.Group();
  engineL.name = 'engineL';
  engineL.position.set(1.22, 1.25, 0);
  ship.add(engineL);
  const nacelle = new THREE.Mesh(cylinderGeo3, hullMat);
  nacelle.name = 'nacelle';
  nacelle.position.set(0, 0, -3.3);
  nacelle.rotation.set(deg(-90), 0, 0);
  engineL.add(nacelle);
  const intakeRing = new THREE.Mesh(cylinderGeo4, accentMat);
  intakeRing.name = 'intakeRing';
  intakeRing.position.set(0, 0, -1.62);
  intakeRing.rotation.set(deg(90), 0, 0);
  engineL.add(intakeRing);
  const intake = new THREE.Mesh(cylinderGeo5, darkMat);
  intake.name = 'intake';
  intake.position.set(0, 0, -1.475);
  intake.rotation.set(deg(90), 0, 0);
  engineL.add(intake);
  const nozzle = new THREE.Mesh(cylinderGeo6, darkMat);
  nozzle.name = 'nozzle';
  nozzle.position.set(0, 0, -5.05);
  nozzle.rotation.set(deg(90), 0, 0);
  engineL.add(nozzle);
  const exhaustGlow = new THREE.Mesh(cylinderGeo7, glowMat);
  exhaustGlow.name = 'exhaustGlow';
  exhaustGlow.position.set(0, 0, -5.19);
  exhaustGlow.rotation.set(deg(90), 0, 0);
  engineL.add(exhaustGlow);
  const exhaustPlume = new THREE.Mesh(coneGeo, glowMat);
  exhaustPlume.name = 'exhaustPlume';
  exhaustPlume.position.set(0, 0, -5.75);
  exhaustPlume.rotation.set(deg(-90), 0, 0);
  engineL.add(exhaustPlume);
  const tailFin = new THREE.Group();
  tailFin.name = 'tailFin';
  tailFin.position.set(0, 0.4, 0);
  tailFin.rotation.set(0, 0, deg(-22));
  engineL.add(tailFin);
  const extrude28 = new THREE.Mesh(extrudeGeo, hullMat);
  extrude28.rotation.set(0, deg(-90), 0);
  tailFin.add(extrude28);
  const extrude29 = new THREE.Mesh(extrudeGeo2, accentMat);
  extrude29.rotation.set(0, deg(-90), 0);
  tailFin.add(extrude29);
  const engineR = new THREE.Group();
  engineR.name = 'engineR';
  engineR.position.set(-1.22, 1.25, 0);
  ship.add(engineR);
  const nacelle2 = new THREE.Mesh(cylinderGeo3, hullMat);
  nacelle2.name = 'nacelle';
  nacelle2.position.set(0, 0, -3.3);
  nacelle2.rotation.set(deg(-90), 0, 0);
  engineR.add(nacelle2);
  const intakeRing2 = new THREE.Mesh(cylinderGeo4, accentMat);
  intakeRing2.name = 'intakeRing';
  intakeRing2.position.set(0, 0, -1.62);
  intakeRing2.rotation.set(deg(90), 0, 0);
  engineR.add(intakeRing2);
  const intake2 = new THREE.Mesh(cylinderGeo5, darkMat);
  intake2.name = 'intake';
  intake2.position.set(0, 0, -1.475);
  intake2.rotation.set(deg(90), 0, 0);
  engineR.add(intake2);
  const nozzle2 = new THREE.Mesh(cylinderGeo6, darkMat);
  nozzle2.name = 'nozzle';
  nozzle2.position.set(0, 0, -5.05);
  nozzle2.rotation.set(deg(90), 0, 0);
  engineR.add(nozzle2);
  const exhaustGlow2 = new THREE.Mesh(cylinderGeo7, glowMat);
  exhaustGlow2.name = 'exhaustGlow';
  exhaustGlow2.position.set(0, 0, -5.19);
  exhaustGlow2.rotation.set(deg(90), 0, 0);
  engineR.add(exhaustGlow2);
  const exhaustPlume2 = new THREE.Mesh(coneGeo, glowMat);
  exhaustPlume2.name = 'exhaustPlume';
  exhaustPlume2.position.set(0, 0, -5.75);
  exhaustPlume2.rotation.set(deg(-90), 0, 0);
  engineR.add(exhaustPlume2);
  const tailFin2 = new THREE.Group();
  tailFin2.name = 'tailFin';
  tailFin2.position.set(0, 0.4, 0);
  tailFin2.rotation.set(0, 0, deg(22));
  engineR.add(tailFin2);
  const extrude38 = new THREE.Mesh(extrudeGeo, hullMat);
  extrude38.rotation.set(0, deg(-90), 0);
  tailFin2.add(extrude38);
  const extrude39 = new THREE.Mesh(extrudeGeo2, accentMat);
  extrude39.rotation.set(0, deg(-90), 0);
  tailFin2.add(extrude39);
  const noseGearStrut = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 0.8, 6), darkMat);
  noseGearStrut.name = 'noseGearStrut';
  noseGearStrut.position.set(0, 0.5, 3);
  ship.add(noseGearStrut);
  const noseGearPad = new THREE.Mesh(cylinderGeo8, darkMat);
  noseGearPad.name = 'noseGearPad';
  noseGearPad.position.set(0, 0.06, 3);
  ship.add(noseGearPad);
  const mainGearLStrut = new THREE.Mesh(cylinderGeo9, darkMat);
  mainGearLStrut.name = 'mainGearLStrut';
  mainGearLStrut.position.set(1.22, 0.4, -3);
  ship.add(mainGearLStrut);
  const mainGearLPad = new THREE.Mesh(cylinderGeo8, darkMat);
  mainGearLPad.name = 'mainGearLPad';
  mainGearLPad.position.set(1.22, 0.06, -3);
  ship.add(mainGearLPad);
  const mainGearRStrut = new THREE.Mesh(cylinderGeo9, darkMat);
  mainGearRStrut.name = 'mainGearRStrut';
  mainGearRStrut.position.set(-1.22, 0.4, -3);
  ship.add(mainGearRStrut);
  const mainGearRPad = new THREE.Mesh(cylinderGeo8, darkMat);
  mainGearRPad.name = 'mainGearRPad';
  mainGearRPad.position.set(-1.22, 0.06, -3);
  ship.add(mainGearRPad);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createStarfighter;
```

---
Codels — 3D models as code for three.js. Search more: https://codels.download/api/v1/models?q=<query> · Guide: https://codels.download/llms.txt
