# Space Shuttle

> A stylized reusable space shuttle orbiter with a white body and black heat-shield belly, double-delta wings, tall tail fin, cockpit windows, OMS pods and three main engine bells. Show it landed on its pivoting nose and main gear groups, or standing upright for launch on an orange external tank with two solid rocket boosters. Choose the mode, tank color and engine glow — great for space, launch-pad and sci-fi scenes.

![Space Shuttle preview](https://codels.download/m/space-shuttle.png)

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

## Facts

- Category: Vehicles › Spacecraft
- Size (W × H × D): 23.80 × 15.94 × 34.48 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 1,588 · Meshes: 49 · Materials: 5
- License: CC0-1.0 (Codels built-in)
- Tags: rocket, space-shuttle, spaceship, low-poly, stylized, modern, sci-fi, space, orbit, hero-asset, landmark, vehicle, metal, tall, emissive, game-ready, parametric, color-gray, color-white, size-huge, poly-medium
- Page: https://codels.download/models/space-shuttle

## Files

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

## Parameters

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

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `mode` | select | landed \| launch | landed | landed |
| `tankColor` | color | #rrggbb | #c9692f | #c9692f |
| `engineGlow` | boolean | true \| false | false | false |

## Parts

- orbiter (group)
  - fuselageTop (lathe · white)
  - fuselageBelly (lathe · tiles)
  - noseSection (group)
    - noseShape (group)
      - noseTop (lathe · white)
      - noseBelly (lathe · tiles)
      - noseCap (lathe · tiles)
      - cockpit (extrude · white)
      - windshield (box · glass)
      - sideWindow (box · glass)
      - sideWindow (box · glass)
  - payloadSeam (box · dark)
  - doorHinge (box · dark)
  - doorHinge (box · dark)
  - wingL (group)
    - wingTop (extrude · white)
    - wingBelly (extrude · tiles)
    - elevonLine (box · dark)
  - wingR (group)
    - wingTop (extrude · white)
    - wingBelly (extrude · tiles)
    - elevonLine (box · dark)
  - tailFin (extrude · white)
  - rudderLine (box · dark)
  - omsPodL (capsule · white)
  - omsNozzle (cylinder · metal)
  - omsPodR (capsule · white)
  - omsNozzle (cylinder · metal)
  - bodyFlap (box · tiles)
  - mainEngineTop (group)
    - bell (cylinder · metal)
    - nozzleExit (cylinder · dark)
  - mainEngineL (group)
    - bell (cylinder · metal)
    - nozzleExit (cylinder · dark)
  - mainEngineR (group)
    - bell (cylinder · metal)
    - nozzleExit (cylinder · dark)
  - noseGear (group)

## How to use

Save the code below as `space-shuttle.js`, then:

```js
import { createSpaceShuttle } from './space-shuttle.js';
const model = createSpaceShuttle();
scene.add(model);
```

## Code

```js
/**
 * Space Shuttle — Codels 3D model library (https://codels.download/models/space-shuttle)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,588 · Size (W × H × D): 23.80 × 15.94 × 34.48 m
 *
 * Usage:
 *   import { createSpaceShuttle } from './space-shuttle.js';
 *   
 *   const model = createSpaceShuttle();
 *   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 createSpaceShuttle() {
  const root = new THREE.Group();
  root.name = 'SpaceShuttle';

  // Materials
  const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xebe9e3, roughness: 0.55, metalness: 0.05, flatShading: true });
  const tilesMat = new THREE.MeshStandardMaterial({ name: 'tiles', color: 0x26272b, roughness: 0.8, flatShading: true });
  const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x9aa0a8, roughness: 0.35, metalness: 0.7, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x1d1f23, roughness: 0.6, metalness: 0.3, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x25313e, roughness: 0.2, metalness: 0.35 });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.05, 0.42, 0.9);
  const boxGeo2 = new THREE.BoxGeometry(0.05, 0.04, 17.5);
  const boxGeo3 = new THREE.BoxGeometry(5.6, 0.08, 0.06);
  const capsuleGeo = new THREE.CapsuleGeometry(1, 4.6, 3, 8);
  const cylinderGeo = new THREE.CylinderGeometry(0.42, 0.25, 0.7, 8);
  const cylinderGeo2 = new THREE.CylinderGeometry(1.12, 0.5, 2.8, 12);
  const cylinderGeo3 = new THREE.CylinderGeometry(1.04, 1.04, 0.04, 12);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.45, 0.45, 0.36, 12);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.225, 0.225, 0.38, 8);
  const cylinderGeo6 = new THREE.CylinderGeometry(0.16, 0.2, 2.1, 8);
  const boxGeo4 = new THREE.BoxGeometry(0.08, 1.47, 1.4);
  const cylinderGeo7 = new THREE.CylinderGeometry(0.6, 0.6, 0.36, 12);
  const cylinderGeo8 = new THREE.CylinderGeometry(0.3, 0.3, 0.38, 8);

  // Parts
  const orbiter = new THREE.Group();
  orbiter.name = 'orbiter';
  orbiter.position.set(0, 5, 0);
  root.add(orbiter);
  const fuselageTop = new THREE.Mesh(lathe([[0, -14], [2.45, -14], [2.8, -13.3], [2.8, 9]], 5, 1.1781, Math.PI * 1.25), whiteMat);
  fuselageTop.name = 'fuselageTop';
  fuselageTop.rotation.set(deg(90), 0, 0);
  orbiter.add(fuselageTop);
  const fuselageBelly = new THREE.Mesh(lathe([[0, -14], [2.45, -14], [2.8, -13.3], [2.8, 9]], 3, -1.1781, Math.PI * 0.75), tilesMat);
  fuselageBelly.name = 'fuselageBelly';
  fuselageBelly.rotation.set(deg(90), 0, 0);
  orbiter.add(fuselageBelly);
  const noseSection = new THREE.Group();
  noseSection.name = 'noseSection';
  noseSection.position.set(0, 2.5869, 9);
  noseSection.rotation.set(deg(6), 0, 0);
  orbiter.add(noseSection);
  const noseShape = new THREE.Group();
  noseShape.name = 'noseShape';
  noseShape.position.set(0, -2.5869, -9);
  noseSection.add(noseShape);
  const noseTop = new THREE.Mesh(lathe([[2.8, 9], [2.8, 11], [2.6, 12.8], [2.15, 14.4], [1.55, 15.9], [0.95, 17]], 5, 1.1781, Math.PI * 1.25), whiteMat);
  noseTop.name = 'noseTop';
  noseTop.rotation.set(deg(90), 0, 0);
  noseShape.add(noseTop);
  const noseBelly = new THREE.Mesh(lathe([[2.8, 9], [2.8, 11], [2.6, 12.8], [2.15, 14.4], [1.55, 15.9], [0.95, 17]], 3, -1.1781, Math.PI * 0.75), tilesMat);
  noseBelly.name = 'noseBelly';
  noseBelly.rotation.set(deg(90), 0, 0);
  noseShape.add(noseBelly);
  const noseCap = new THREE.Mesh(lathe([[0.95, 17], [0.45, 17.7], [0, 18]], 8, 0.3927, Math.PI * 2), tilesMat);
  noseCap.name = 'noseCap';
  noseCap.rotation.set(deg(90), 0, 0);
  noseShape.add(noseCap);
  const cockpit = new THREE.Mesh(extrude([[11.2, 2.4369], [14.5, 1.85], [13.25, 2.82], [11.2, 2.95]], 2.6), whiteMat);
  cockpit.name = 'cockpit';
  cockpit.rotation.set(0, deg(-90), 0);
  noseShape.add(cockpit);
  const windshield = new THREE.Mesh(new THREE.BoxGeometry(2.3, 0.05, 1.45), glassMat);
  windshield.name = 'windshield';
  windshield.position.set(0, 2.36, 13.89);
  windshield.rotation.set(deg(38), 0, 0);
  noseShape.add(windshield);
  const sideWindow = new THREE.Mesh(boxGeo, glassMat);
  sideWindow.name = 'sideWindow';
  sideWindow.position.set(1.31, 2.6, 12.6);
  noseShape.add(sideWindow);
  const sideWindow2 = new THREE.Mesh(boxGeo, glassMat);
  sideWindow2.name = 'sideWindow';
  sideWindow2.position.set(-1.31, 2.6, 12.6);
  noseShape.add(sideWindow2);
  const payloadSeam = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.04, 17.5), darkMat);
  payloadSeam.name = 'payloadSeam';
  payloadSeam.position.set(0, 2.5969, -3.6);
  orbiter.add(payloadSeam);
  const doorHinge = new THREE.Mesh(boxGeo2, darkMat);
  doorHinge.name = 'doorHinge';
  doorHinge.position.set(1.05, 2.5919, -3.6);
  orbiter.add(doorHinge);
  const doorHinge2 = new THREE.Mesh(boxGeo2, darkMat);
  doorHinge2.name = 'doorHinge';
  doorHinge2.position.set(-1.05, 2.5919, -3.6);
  orbiter.add(doorHinge2);
  const wingL = new THREE.Group();
  wingL.name = 'wingL';
  wingL.position.set(0, -2, 0);
  orbiter.add(wingL);
  const wingTop = new THREE.Mesh(extrude([[2, 6], [2.6, 6], [5, -1.5], [11.9, -10.6], [11.9, -12.4], [2, -13.6]], 0.28), whiteMat);
  wingTop.name = 'wingTop';
  wingTop.position.set(0, 0.14, 0);
  wingTop.rotation.set(deg(90), 0, 0);
  wingL.add(wingTop);
  const wingBelly = new THREE.Mesh(extrude([[2, 6], [2.6, 6], [5, -1.5], [11.9, -10.6], [11.9, -12.4], [2, -13.6]], 0.3), tilesMat);
  wingBelly.name = 'wingBelly';
  wingBelly.position.set(0, -0.15, 0);
  wingBelly.rotation.set(deg(90), 0, 0);
  wingL.add(wingBelly);
  const elevonLine = new THREE.Mesh(boxGeo3, darkMat);
  elevonLine.name = 'elevonLine';
  elevonLine.position.set(7, 0.29, -12);
  elevonLine.rotation.set(0, deg(7), 0);
  wingL.add(elevonLine);
  const wingR = new THREE.Group();
  wingR.name = 'wingR';
  wingR.position.set(0, -2, 0);
  orbiter.add(wingR);
  const wingTop2 = new THREE.Mesh(extrude([[-2, 6], [-2.6, 6], [-5, -1.5], [-11.9, -10.6], [-11.9, -12.4], [-2, -13.6]], 0.28), whiteMat);
  wingTop2.name = 'wingTop';
  wingTop2.position.set(0, 0.14, 0);
  wingTop2.rotation.set(deg(90), 0, 0);
  wingR.add(wingTop2);
  const wingBelly2 = new THREE.Mesh(extrude([[-2, 6], [-2.6, 6], [-5, -1.5], [-11.9, -10.6], [-11.9, -12.4], [-2, -13.6]], 0.3), tilesMat);
  wingBelly2.name = 'wingBelly';
  wingBelly2.position.set(0, -0.15, 0);
  wingBelly2.rotation.set(deg(90), 0, 0);
  wingR.add(wingBelly2);
  const elevonLine2 = new THREE.Mesh(boxGeo3, darkMat);
  elevonLine2.name = 'elevonLine';
  elevonLine2.position.set(-7, 0.29, -12);
  elevonLine2.rotation.set(0, deg(-7), 0);
  wingR.add(elevonLine2);
  const tailFin = new THREE.Mesh(extrude([[-5.6, 2.3869], [-11.4, 10.8869], [-13.3, 10.8869], [-14.1, 2.3869]], 0.45, [], [0.05, 0.05, 1]), whiteMat);
  tailFin.name = 'tailFin';
  tailFin.rotation.set(0, deg(-90), 0);
  orbiter.add(tailFin);
  const rudderLine = new THREE.Mesh(new THREE.BoxGeometry(0.6, 6.8, 0.08), darkMat);
  rudderLine.name = 'rudderLine';
  rudderLine.position.set(0, 7.1869, -12.25);
  rudderLine.rotation.set(deg(-7), 0, 0);
  orbiter.add(rudderLine);
  const omsPodL = new THREE.Mesh(capsuleGeo, whiteMat);
  omsPodL.name = 'omsPodL';
  omsPodL.position.set(1.75, 2.15, -10.4);
  omsPodL.rotation.set(deg(90), 0, 0);
  omsPodL.scale.set(1, 1, 0.85);
  orbiter.add(omsPodL);
  const omsNozzle = new THREE.Mesh(cylinderGeo, metalMat);
  omsNozzle.name = 'omsNozzle';
  omsNozzle.position.set(1.75, 2.15, -13.65);
  omsNozzle.rotation.set(deg(-90), 0, 0);
  orbiter.add(omsNozzle);
  const omsPodR = new THREE.Mesh(capsuleGeo, whiteMat);
  omsPodR.name = 'omsPodR';
  omsPodR.position.set(-1.75, 2.15, -10.4);
  omsPodR.rotation.set(deg(90), 0, 0);
  omsPodR.scale.set(1, 1, 0.85);
  orbiter.add(omsPodR);
  const omsNozzle2 = new THREE.Mesh(cylinderGeo, metalMat);
  omsNozzle2.name = 'omsNozzle';
  omsNozzle2.position.set(-1.75, 2.15, -13.65);
  omsNozzle2.rotation.set(deg(-90), 0, 0);
  orbiter.add(omsNozzle2);
  const bodyFlap = new THREE.Mesh(new THREE.BoxGeometry(4.6, 0.32, 2), tilesMat);
  bodyFlap.name = 'bodyFlap';
  bodyFlap.position.set(0, -2.35, -14.8);
  orbiter.add(bodyFlap);
  const mainEngineTop = new THREE.Group();
  mainEngineTop.name = 'mainEngineTop';
  mainEngineTop.position.set(0, 1.25, -14);
  orbiter.add(mainEngineTop);
  const bell = new THREE.Mesh(cylinderGeo2, metalMat);
  bell.name = 'bell';
  bell.position.set(0, 0, -1.4);
  bell.rotation.set(deg(-90), 0, 0);
  mainEngineTop.add(bell);
  const nozzleExit = new THREE.Mesh(cylinderGeo3, darkMat);
  nozzleExit.name = 'nozzleExit';
  nozzleExit.position.set(0, 0, -2.78);
  nozzleExit.rotation.set(deg(90), 0, 0);
  mainEngineTop.add(nozzleExit);
  const mainEngineL = new THREE.Group();
  mainEngineL.name = 'mainEngineL';
  mainEngineL.position.set(1.3, -0.95, -14);
  orbiter.add(mainEngineL);
  const bell2 = new THREE.Mesh(cylinderGeo2, metalMat);
  bell2.name = 'bell';
  bell2.position.set(0, 0, -1.4);
  bell2.rotation.set(deg(-90), 0, 0);
  mainEngineL.add(bell2);
  const nozzleExit2 = new THREE.Mesh(cylinderGeo3, darkMat);
  nozzleExit2.name = 'nozzleExit';
  nozzleExit2.position.set(0, 0, -2.78);
  nozzleExit2.rotation.set(deg(90), 0, 0);
  mainEngineL.add(nozzleExit2);
  const mainEngineR = new THREE.Group();
  mainEngineR.name = 'mainEngineR';
  mainEngineR.position.set(-1.3, -0.95, -14);
  orbiter.add(mainEngineR);
  const bell3 = new THREE.Mesh(cylinderGeo2, metalMat);
  bell3.name = 'bell';
  bell3.position.set(0, 0, -1.4);
  bell3.rotation.set(deg(-90), 0, 0);
  mainEngineR.add(bell3);
  const nozzleExit3 = new THREE.Mesh(cylinderGeo3, darkMat);
  nozzleExit3.name = 'nozzleExit';
  nozzleExit3.position.set(0, 0, -2.78);
  nozzleExit3.rotation.set(deg(90), 0, 0);
  mainEngineR.add(nozzleExit3);
  const noseGear = new THREE.Group();
  noseGear.name = 'noseGear';
  noseGear.position.set(0, -2.5869, 12.6);
  orbiter.add(noseGear);
  const strut = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.2, 1.9631, 8), metalMat);
  strut.name = 'strut';
  strut.position.set(0, -0.9816, 0);
  noseGear.add(strut);
  const gearDoor = new THREE.Mesh(new THREE.BoxGeometry(0.08, 1.3742, 1.4), tilesMat);
  gearDoor.name = 'gearDoor';
  gearDoor.position.set(0.35, -0.8834, 0.1);
  noseGear.add(gearDoor);
  const wheels = new THREE.Group();
  wheels.name = 'wheels';
  wheels.position.set(0, -1.9631, 0);
  noseGear.add(wheels);
  const tire = new THREE.Mesh(cylinderGeo4, darkMat);
  tire.name = 'tire';
  tire.position.set(-0.32, 0, 0);
  tire.rotation.set(0, 0, deg(90));
  wheels.add(tire);
  const hub = new THREE.Mesh(cylinderGeo5, metalMat);
  hub.name = 'hub';
  hub.position.set(-0.32, 0, 0);
  hub.rotation.set(0, 0, deg(90));
  wheels.add(hub);
  const tire2 = new THREE.Mesh(cylinderGeo4, darkMat);
  tire2.name = 'tire';
  tire2.position.set(0.32, 0, 0);
  tire2.rotation.set(0, 0, deg(90));
  wheels.add(tire2);
  const hub2 = new THREE.Mesh(cylinderGeo5, metalMat);
  hub2.name = 'hub';
  hub2.position.set(0.32, 0, 0);
  hub2.rotation.set(0, 0, deg(90));
  wheels.add(hub2);
  const mainGearL = new THREE.Group();
  mainGearL.name = 'mainGearL';
  mainGearL.position.set(3.3, -2.3, -4.6);
  orbiter.add(mainGearL);
  const strut2 = new THREE.Mesh(cylinderGeo6, metalMat);
  strut2.name = 'strut';
  strut2.position.set(0, -1.05, 0);
  mainGearL.add(strut2);
  const gearDoor2 = new THREE.Mesh(boxGeo4, tilesMat);
  gearDoor2.name = 'gearDoor';
  gearDoor2.position.set(0.45, -0.945, 0.1);
  mainGearL.add(gearDoor2);
  const wheels2 = new THREE.Group();
  wheels2.name = 'wheels';
  wheels2.position.set(0, -2.1, 0);
  mainGearL.add(wheels2);
  const tire3 = new THREE.Mesh(cylinderGeo7, darkMat);
  tire3.name = 'tire';
  tire3.position.set(-0.32, 0, 0);
  tire3.rotation.set(0, 0, deg(90));
  wheels2.add(tire3);
  const hub3 = new THREE.Mesh(cylinderGeo8, metalMat);
  hub3.name = 'hub';
  hub3.position.set(-0.32, 0, 0);
  hub3.rotation.set(0, 0, deg(90));
  wheels2.add(hub3);
  const tire4 = new THREE.Mesh(cylinderGeo7, darkMat);
  tire4.name = 'tire';
  tire4.position.set(0.32, 0, 0);
  tire4.rotation.set(0, 0, deg(90));
  wheels2.add(tire4);
  const hub4 = new THREE.Mesh(cylinderGeo8, metalMat);
  hub4.name = 'hub';
  hub4.position.set(0.32, 0, 0);
  hub4.rotation.set(0, 0, deg(90));
  wheels2.add(hub4);
  const mainGearR = new THREE.Group();
  mainGearR.name = 'mainGearR';
  mainGearR.position.set(-3.3, -2.3, -4.6);
  orbiter.add(mainGearR);
  const strut3 = new THREE.Mesh(cylinderGeo6, metalMat);
  strut3.name = 'strut';
  strut3.position.set(0, -1.05, 0);
  mainGearR.add(strut3);
  const gearDoor3 = new THREE.Mesh(boxGeo4, tilesMat);
  gearDoor3.name = 'gearDoor';
  gearDoor3.position.set(-0.45, -0.945, 0.1);
  mainGearR.add(gearDoor3);
  const wheels3 = new THREE.Group();
  wheels3.name = 'wheels';
  wheels3.position.set(0, -2.1, 0);
  mainGearR.add(wheels3);
  const tire5 = new THREE.Mesh(cylinderGeo7, darkMat);
  tire5.name = 'tire';
  tire5.position.set(-0.32, 0, 0);
  tire5.rotation.set(0, 0, deg(90));
  wheels3.add(tire5);
  const hub5 = new THREE.Mesh(cylinderGeo8, metalMat);
  hub5.name = 'hub';
  hub5.position.set(-0.32, 0, 0);
  hub5.rotation.set(0, 0, deg(90));
  wheels3.add(hub5);
  const tire6 = new THREE.Mesh(cylinderGeo7, darkMat);
  tire6.name = 'tire';
  tire6.position.set(0.32, 0, 0);
  tire6.rotation.set(0, 0, deg(90));
  wheels3.add(tire6);
  const hub6 = new THREE.Mesh(cylinderGeo8, metalMat);
  hub6.name = 'hub';
  hub6.position.set(0.32, 0, 0);
  hub6.rotation.set(0, 0, deg(90));
  wheels3.add(hub6);

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

export default createSpaceShuttle;
```

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