Codels
4.2K tris3.24 × 4.05 × 8.59 m

Use it in code

Remix in the editor
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
 * Steam Locomotive — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 4,224 · Size (W × H × D): 3.24 × 4.05 × 8.59 m
 *
 * Usage:
 *   import { createSteamLocomotive } from './steam-locomotive.js';
 *   
 *   const model = createSteamLocomotive();
 *   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 createSteamLocomotive() {
  const root = new THREE.Group();
  root.name = 'SteamLocomotive';

  // Materials
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0x2f5b3d, roughness: 0.5, metalness: 0.2, flatShading: true });
  const accentMat = new THREE.MeshStandardMaterial({ name: 'accent', color: 0xb8322a, roughness: 0.55, metalness: 0.15, flatShading: true });
  const blackMat = new THREE.MeshStandardMaterial({ name: 'black', color: 0x26272b, roughness: 0.7, metalness: 0.3, flatShading: true });
  const brassMat = new THREE.MeshStandardMaterial({ name: 'brass', color: 0xd4a640, roughness: 0.3, metalness: 0.8, flatShading: true });
  const steelMat = new THREE.MeshStandardMaterial({ name: 'steel', color: 0xa8adb3, roughness: 0.35, metalness: 0.75, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x2a3644, roughness: 0.2, metalness: 0.3, flatShading: true });
  const lampMat = new THREE.MeshStandardMaterial({ name: 'lamp', color: 0xfff4d6, roughness: 0.3, emissive: 0xffd27a, emissiveIntensity: 1.1, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.55, 0.06, 5.25);
  const boxGeo2 = new THREE.BoxGeometry(0.04, 0.12, 5.25);
  const cylinderGeo = new THREE.CylinderGeometry(0.772, 0.772, 0.06, 16, 1, true);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.018, 0.018, 4.25, 4);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.28, 0.28, 0.82, 10);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.3, 0.3, 0.05, 10, 1, true);
  const boxGeo3 = new THREE.BoxGeometry(0.2, 0.75, 0.6);
  const boxGeo4 = new THREE.BoxGeometry(0.05, 0.04, 0.75);
  const boxGeo5 = new THREE.BoxGeometry(0.05, 3.44, 0.12);
  const boxGeo6 = new THREE.BoxGeometry(0.12, 0.16, 0.2);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.035, 0.035, 0.25, 6);
  const boxGeo7 = new THREE.BoxGeometry(0.3, 0.04, 0.22);
  const boxGeo8 = new THREE.BoxGeometry(0.04, 1, 0.04);
  const boxGeo9 = new THREE.BoxGeometry(0.07, 0.9882, 0.05);
  const boxGeo10 = new THREE.BoxGeometry(0.07, 1.023, 0.05);
  const boxGeo11 = new THREE.BoxGeometry(0.07, 1.0804, 0.05);
  const boxGeo12 = new THREE.BoxGeometry(0.07, 1.1572, 0.05);
  const boxGeo13 = new THREE.BoxGeometry(0.08, 1.295, 0.08);
  const boxGeo14 = new THREE.BoxGeometry(0.06, 1.252, 0.06);
  const extrudeGeo = extrude([[-0.95, 1.66], [-0.95, 3.72], [-2.95, 3.72], [-2.95, 1.66]], 0.07, [[[-1.2, 2.75], [-1.2, 3.45], [-2.45, 3.45], [-2.45, 2.75]], [[-2.83, 1.91], [-2.83, 3.45], [-2.53, 3.45], [-2.53, 1.91]]]);
  const boxGeo15 = new THREE.BoxGeometry(0.02, 0.7, 1.25);
  const boxGeo16 = new THREE.BoxGeometry(0.03, 0.08, 1.8);
  const boxGeo17 = new THREE.BoxGeometry(0.5, 0.45, 0.02);
  const cylinderGeo6 = new THREE.CylinderGeometry(0.05, 0.05, 0.06, 8);
  const latheGeo = lathe([[0.68, -0.07], [0.75, -0.07], [0.75, 0.04], [0.78, 0.07], [0.68, 0.07], [0.68, -0.07]], 14, 0.2244, Math.PI * 2);
  const cylinderGeo7 = new THREE.CylinderGeometry(0.14, 0.16, 0.18, 6);
  const boxGeo18 = new THREE.BoxGeometry(0.05, 0.6, 0.07);
  const cylinderGeo8 = new THREE.CylinderGeometry(0.055, 0.055, 0.16, 6);
  const extrudeGeo2 = extrude([[-0.4307, 0.5132], [-0.6072, 0.2832], [-0.67, 0], [-0.6072, -0.2832], [-0.4307, -0.5132], [-0.1286, -0.1532], [-0.1813, -0.0845], [-0.2, 0], [-0.1813, 0.0845], [-0.1286, 0.1532]], 0.05);
  const latheGeo2 = lathe([[0.38, -0.06], [0.45, -0.06], [0.45, 0.03], [0.48, 0.06], [0.38, 0.06], [0.38, -0.06]], 12, 0, Math.PI * 2);
  const cylinderGeo9 = new THREE.CylinderGeometry(0.39, 0.39, 0.06, 12);
  const extrudeGeo3 = extrude([[-0.5132, -0.4307], [-0.2832, -0.6072], [0, -0.67], [0.2832, -0.6072], [0.5132, -0.4307], [0.1532, -0.1286], [0.0845, -0.1813], [0, -0.2], [-0.0845, -0.1813], [-0.1532, -0.1286]], 0.05);

  // Parts
  const body = new THREE.Group();
  body.name = 'body';
  root.add(body);
  const frame = new THREE.Mesh(new THREE.BoxGeometry(1, 0.62, 7.6), blackMat);
  frame.name = 'frame';
  frame.position.set(0, 1.22, 0.75);
  body.add(frame);
  const runningBoardL = new THREE.Mesh(boxGeo, blackMat);
  runningBoardL.name = 'runningBoardL';
  runningBoardL.position.set(1.05, 1.62, 1.68);
  body.add(runningBoardL);
  const box4 = new THREE.Mesh(boxGeo2, accentMat);
  box4.position.set(1.33, 1.59, 1.68);
  body.add(box4);
  const runningBoardR = new THREE.Mesh(boxGeo, blackMat);
  runningBoardR.name = 'runningBoardR';
  runningBoardR.position.set(-1.05, 1.62, 1.68);
  body.add(runningBoardR);
  const box6 = new THREE.Mesh(boxGeo2, accentMat);
  box6.position.set(-1.33, 1.59, 1.68);
  body.add(box6);
  const boiler = new THREE.Mesh(new THREE.CylinderGeometry(0.76, 0.76, 4.3, 16, 1, true), paintMat);
  boiler.name = 'boiler';
  boiler.position.set(0, 2.15, 1.25);
  boiler.rotation.set(deg(90), 0, 0);
  body.add(boiler);
  const cylinder8 = new THREE.Mesh(cylinderGeo, brassMat);
  cylinder8.position.set(0, 2.15, -0.5);
  cylinder8.rotation.set(deg(90), 0, 0);
  body.add(cylinder8);
  const cylinder9 = new THREE.Mesh(cylinderGeo, brassMat);
  cylinder9.position.set(0, 2.15, 1);
  cylinder9.rotation.set(deg(90), 0, 0);
  body.add(cylinder9);
  const cylinder10 = new THREE.Mesh(cylinderGeo, brassMat);
  cylinder10.position.set(0, 2.15, 2.4);
  cylinder10.rotation.set(deg(90), 0, 0);
  body.add(cylinder10);
  const smokebox = new THREE.Mesh(new THREE.CylinderGeometry(0.82, 0.82, 0.9, 16), blackMat);
  smokebox.name = 'smokebox';
  smokebox.position.set(0, 2.15, 3.85);
  smokebox.rotation.set(deg(90), 0, 0);
  body.add(smokebox);
  const smokeboxDoor = new THREE.Mesh(new THREE.CylinderGeometry(0.66, 0.7, 0.06, 16), blackMat);
  smokeboxDoor.name = 'smokeboxDoor';
  smokeboxDoor.position.set(0, 2.15, 4.32);
  smokeboxDoor.rotation.set(deg(90), 0, 0);
  body.add(smokeboxDoor);
  const cylinder13 = new THREE.Mesh(new THREE.CylinderGeometry(0.08, 0.08, 0.08, 8), brassMat);
  cylinder13.position.set(0, 2.15, 4.38);
  cylinder13.rotation.set(deg(90), 0, 0);
  body.add(cylinder13);
  const cylinder14 = new THREE.Mesh(cylinderGeo2, brassMat);
  cylinder14.position.set(0.86, 2.55, 1.275);
  cylinder14.rotation.set(deg(90), 0, 0);
  body.add(cylinder14);
  const cylinder15 = new THREE.Mesh(cylinderGeo2, brassMat);
  cylinder15.position.set(-0.86, 2.55, 1.275);
  cylinder15.rotation.set(deg(90), 0, 0);
  body.add(cylinder15);
  const smokestack = new THREE.Mesh(lathe([[0, 0], [0.27, 0], [0.22, 0.55], [0.25, 0.8], [0.36, 1.02], [0.38, 1.12], [0.3, 1.12], [0.26, 1.02], [0, 1.02]], 10), blackMat);
  smokestack.name = 'smokestack';
  smokestack.position.set(0, 2.93, 3.95);
  body.add(smokestack);
  const steamDome = new THREE.Mesh(lathe([[0.36, 0], [0.35, 0.22], [0.31, 0.36], [0.2, 0.46], [0, 0.5]], 10), brassMat);
  steamDome.name = 'steamDome';
  steamDome.position.set(0, 2.87, 1.25);
  body.add(steamDome);
  const sandDome = new THREE.Mesh(lathe([[0.3, 0], [0.29, 0.16], [0.24, 0.27], [0.14, 0.33], [0, 0.35]], 8), paintMat);
  sandDome.name = 'sandDome';
  sandDome.position.set(0, 2.87, 2.6);
  body.add(sandDome);
  const box19 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.3, 0.3), blackMat);
  box19.position.set(0, 3.04, 1.95);
  body.add(box19);
  const bell = new THREE.Mesh(lathe([[0.17, 0], [0.15, 0.06], [0.11, 0.18], [0.08, 0.26], [0, 0.28]], 8), brassMat);
  bell.name = 'bell';
  bell.position.set(0, 3.01, 1.95);
  body.add(bell);
  const whistle = new THREE.Mesh(new THREE.CylinderGeometry(0.035, 0.05, 0.3, 6), brassMat);
  whistle.name = 'whistle';
  whistle.position.set(0, 3.03, -0.6);
  body.add(whistle);
  const headlampBox = new THREE.Mesh(new THREE.BoxGeometry(0.48, 0.5, 0.5), blackMat);
  headlampBox.name = 'headlampBox';
  headlampBox.position.set(0, 3.18, 4.02);
  body.add(headlampBox);
  const box23 = new THREE.Mesh(new THREE.BoxGeometry(0.52, 0.06, 0.54), brassMat);
  box23.position.set(0, 3.46, 4.02);
  body.add(box23);
  const cylinder24 = new THREE.Mesh(new THREE.CylinderGeometry(0.18, 0.18, 0.05, 12), brassMat);
  cylinder24.position.set(0, 3.18, 4.28);
  cylinder24.rotation.set(deg(90), 0, 0);
  body.add(cylinder24);
  const headlamp = new THREE.Mesh(new THREE.CircleGeometry(0.16, 12), lampMat);
  headlamp.name = 'headlamp';
  headlamp.position.set(0, 3.18, 4.306);
  body.add(headlamp);
  const cylinderL = new THREE.Mesh(cylinderGeo3, blackMat);
  cylinderL.name = 'cylinderL';
  cylinderL.position.set(1, 1, 2.95);
  cylinderL.rotation.set(deg(90), 0, 0);
  body.add(cylinderL);
  const cylinder27 = new THREE.Mesh(cylinderGeo4, brassMat);
  cylinder27.position.set(1, 1, 3.3);
  cylinder27.rotation.set(deg(90), 0, 0);
  body.add(cylinder27);
  const box28 = new THREE.Mesh(boxGeo3, blackMat);
  box28.position.set(0.65, 1.4, 2.95);
  body.add(box28);
  const box29 = new THREE.Mesh(boxGeo4, steelMat);
  box29.position.set(1, 1.1, 2.18);
  body.add(box29);
  const box30 = new THREE.Mesh(boxGeo4, steelMat);
  box30.position.set(1, 0.9, 2.18);
  body.add(box30);
  const couplingRodL = new THREE.Mesh(boxGeo5, steelMat);
  couplingRodL.name = 'couplingRodL';
  couplingRodL.position.set(0.92, 0.78, 0.47);
  couplingRodL.rotation.set(deg(-90), 0, 0);
  body.add(couplingRodL);
  const crossheadL = new THREE.Mesh(boxGeo6, steelMat);
  crossheadL.name = 'crossheadL';
  crossheadL.position.set(1, 1, 2.2);
  body.add(crossheadL);
  const mainRodL = new THREE.Mesh(new THREE.BoxGeometry(0.05, 1.904, 0.13), steelMat);
  mainRodL.name = 'mainRodL';
  mainRodL.position.set(0.995, 0.89, 1.335);
  mainRodL.rotation.set(deg(-97.247), deg(-0.0418), deg(0.3285));
  body.add(mainRodL);
  const cylinder34 = new THREE.Mesh(cylinderGeo5, steelMat);
  cylinder34.position.set(1, 1, 2.375);
  cylinder34.rotation.set(deg(-90), 0, 0);
  body.add(cylinder34);
  const box35 = new THREE.Mesh(boxGeo7, blackMat);
  box35.position.set(1.25, 0.6, -1.25);
  body.add(box35);
  const box36 = new THREE.Mesh(boxGeo8, blackMat);
  box36.position.set(1.37, 1.1, -1.12);
  body.add(box36);
  const cylinderR = new THREE.Mesh(cylinderGeo3, blackMat);
  cylinderR.name = 'cylinderR';
  cylinderR.position.set(-1, 1, 2.95);
  cylinderR.rotation.set(deg(90), 0, 0);
  body.add(cylinderR);
  const cylinder38 = new THREE.Mesh(cylinderGeo4, brassMat);
  cylinder38.position.set(-1, 1, 3.3);
  cylinder38.rotation.set(deg(90), 0, 0);
  body.add(cylinder38);
  const box39 = new THREE.Mesh(boxGeo3, blackMat);
  box39.position.set(-0.65, 1.4, 2.95);
  body.add(box39);
  const box40 = new THREE.Mesh(boxGeo4, steelMat);
  box40.position.set(-1, 1.1, 2.18);
  body.add(box40);
  const box41 = new THREE.Mesh(boxGeo4, steelMat);
  box41.position.set(-1, 0.9, 2.18);
  body.add(box41);
  const couplingRodR = new THREE.Mesh(boxGeo5, steelMat);
  couplingRodR.name = 'couplingRodR';
  couplingRodR.position.set(-0.92, 1.1, 0.15);
  couplingRodR.rotation.set(deg(-90), 0, 0);
  body.add(couplingRodR);
  const crossheadR = new THREE.Mesh(boxGeo6, steelMat);
  crossheadR.name = 'crossheadR';
  crossheadR.position.set(-1, 1, 2.2);
  body.add(crossheadR);
  const mainRodR = new THREE.Mesh(new THREE.BoxGeometry(0.05, 2.2125, 0.13), steelMat);
  mainRodR.name = 'mainRodR';
  mainRodR.position.set(-0.995, 1.05, 1.175);
  mainRodR.rotation.set(deg(-87.2074), deg(-0.0136), deg(-0.2792));
  body.add(mainRodR);
  const cylinder45 = new THREE.Mesh(cylinderGeo5, steelMat);
  cylinder45.position.set(-1, 1, 2.375);
  cylinder45.rotation.set(deg(-90), 0, 0);
  body.add(cylinder45);
  const box46 = new THREE.Mesh(boxGeo7, blackMat);
  box46.position.set(-1.25, 0.6, -1.25);
  body.add(box46);
  const box47 = new THREE.Mesh(boxGeo8, blackMat);
  box47.position.set(-1.37, 1.1, -1.12);
  body.add(box47);
  const airPump = new THREE.Mesh(new THREE.CylinderGeometry(0.14, 0.14, 0.6, 8), blackMat);
  airPump.name = 'airPump';
  airPump.position.set(-1.05, 1.95, 0.9);
  body.add(airPump);
  const cylinder49 = new THREE.Mesh(new THREE.CylinderGeometry(0.16, 0.16, 0.06, 8), brassMat);
  cylinder49.position.set(-1.05, 2.28, 0.9);
  body.add(cylinder49);
  const pilotBeam = new THREE.Mesh(new THREE.BoxGeometry(2.7, 0.34, 0.24), accentMat);
  pilotBeam.name = 'pilotBeam';
  pilotBeam.position.set(0, 1.22, 4.45);
  body.add(pilotBeam);
  const coupler = new THREE.Mesh(new THREE.BoxGeometry(0.18, 0.18, 0.3), blackMat);
  coupler.name = 'coupler';
  coupler.position.set(0, 1.18, 4.65);
  body.add(coupler);
  const box52 = new THREE.Mesh(boxGeo9, accentMat);
  box52.position.set(-1.125, 0.58, 4.64);
  box52.rotation.set(deg(-17.6255), deg(38.4571), deg(-168.8228));
  body.add(box52);
  const box53 = new THREE.Mesh(boxGeo10, accentMat);
  box53.position.set(-0.8437, 0.58, 4.7175);
  box53.rotation.set(deg(-21.2218), deg(17.3826), deg(-173.3828));
  body.add(box53);
  const box54 = new THREE.Mesh(boxGeo11, accentMat);
  box54.position.set(-0.5625, 0.58, 4.795);
  box54.rotation.set(deg(-27.5814), deg(7.7259), deg(-175.983));
  body.add(box54);
  const box55 = new THREE.Mesh(boxGeo12, accentMat);
  box55.position.set(-0.2812, 0.58, 4.8725);
  box55.rotation.set(deg(-33.9857), deg(2.76), deg(-178.1407));
  body.add(box55);
  const box56 = new THREE.Mesh(new THREE.BoxGeometry(0.07, 1.2496, 0.05), accentMat);
  box56.position.set(0, 0.58, 4.95);
  box56.rotation.set(deg(-39.8056), 0, deg(-180));
  body.add(box56);
  const box57 = new THREE.Mesh(boxGeo12, accentMat);
  box57.position.set(0.2813, 0.58, 4.8725);
  box57.rotation.set(deg(-33.9857), deg(-2.76), deg(178.1407));
  body.add(box57);
  const box58 = new THREE.Mesh(boxGeo11, accentMat);
  box58.position.set(0.5625, 0.58, 4.795);
  box58.rotation.set(deg(-27.5814), deg(-7.7259), deg(175.983));
  body.add(box58);
  const box59 = new THREE.Mesh(boxGeo10, accentMat);
  box59.position.set(0.8438, 0.58, 4.7175);
  box59.rotation.set(deg(-21.2218), deg(-17.3826), deg(173.3828));
  body.add(box59);
  const box60 = new THREE.Mesh(boxGeo9, accentMat);
  box60.position.set(1.125, 0.58, 4.64);
  box60.rotation.set(deg(-17.6255), deg(-38.4571), deg(168.8228));
  body.add(box60);
  const box61 = new THREE.Mesh(boxGeo13, blackMat);
  box61.position.set(0.56, 0.1, 5.025);
  box61.rotation.set(deg(-90), 0, deg(120.129));
  body.add(box61);
  const box62 = new THREE.Mesh(boxGeo14, blackMat);
  box62.position.set(0.625, 1.06, 4.585);
  box62.rotation.set(deg(-90), 0, deg(93.2052));
  body.add(box62);
  const box63 = new THREE.Mesh(boxGeo13, blackMat);
  box63.position.set(-0.56, 0.1, 5.025);
  box63.rotation.set(deg(-90), 0, deg(-120.129));
  body.add(box63);
  const box64 = new THREE.Mesh(boxGeo14, blackMat);
  box64.position.set(-0.625, 1.06, 4.585);
  box64.rotation.set(deg(-90), 0, deg(-93.2052));
  body.add(box64);
  const firebox = new THREE.Mesh(new THREE.BoxGeometry(1.5, 1.1, 1.5), blackMat);
  firebox.name = 'firebox';
  firebox.position.set(0, 2.07, -1.7);
  body.add(firebox);
  const cabFloor = new THREE.Mesh(new THREE.BoxGeometry(2.85, 0.08, 2.1), blackMat);
  cabFloor.name = 'cabFloor';
  cabFloor.position.set(0, 1.62, -1.95);
  body.add(cabFloor);
  const cabSideL = new THREE.Mesh(extrudeGeo, paintMat);
  cabSideL.name = 'cabSideL';
  cabSideL.position.set(1.36, 0, 0);
  cabSideL.rotation.set(0, deg(-90), 0);
  body.add(cabSideL);
  const box68 = new THREE.Mesh(boxGeo15, glassMat);
  box68.position.set(1.33, 3.1, -1.825);
  body.add(box68);
  const box69 = new THREE.Mesh(boxGeo16, brassMat);
  box69.position.set(1.41, 2.6, -1.95);
  body.add(box69);
  const box70 = new THREE.Mesh(boxGeo17, glassMat);
  box70.position.set(1.02, 3.2, -0.9);
  body.add(box70);
  const cabSideR = new THREE.Mesh(extrudeGeo, paintMat);
  cabSideR.name = 'cabSideR';
  cabSideR.position.set(-1.36, 0, 0);
  cabSideR.rotation.set(0, deg(-90), 0);
  body.add(cabSideR);
  const box72 = new THREE.Mesh(boxGeo15, glassMat);
  box72.position.set(-1.33, 3.1, -1.825);
  body.add(box72);
  const box73 = new THREE.Mesh(boxGeo16, brassMat);
  box73.position.set(-1.41, 2.6, -1.95);
  body.add(box73);
  const box74 = new THREE.Mesh(boxGeo17, glassMat);
  box74.position.set(-1.02, 3.2, -0.9);
  body.add(box74);
  const cabFront = new THREE.Mesh(extrude([[-1.4, 1.66], [1.4, 1.66], [1.4, 3.72], [-1.4, 3.72]], 0.07, [[[-1.25, 2.95], [-0.78, 2.95], [-0.78, 3.42], [-1.25, 3.42]], [[0.78, 2.95], [1.25, 2.95], [1.25, 3.42], [0.78, 3.42]]]), paintMat);
  cabFront.name = 'cabFront';
  cabFront.position.set(0, 0, -0.95);
  body.add(cabFront);
  const cabRoof = new THREE.Mesh(extrude([[-1.62, 0], [-1.215, 0.07], [-0.81, 0.12], [-0.405, 0.15], [0, 0.16], [0.405, 0.15], [0.81, 0.12], [1.215, 0.07], [1.62, 0], [1.62, 0.07], [1.215, 0.14], [0.81, 0.19], [0.405, 0.22], [0, 0.23], [-0.405, 0.22], [-0.81, 0.19], [-1.215, 0.14], [-1.62, 0.07]], 2.5), blackMat);
  cabRoof.name = 'cabRoof';
  cabRoof.position.set(0, 3.72, -1.95);
  body.add(cabRoof);
  const backhead = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.9, 0.2), blackMat);
  backhead.name = 'backhead';
  backhead.position.set(0, 2.45, -1);
  body.add(backhead);
  const cylinder78 = new THREE.Mesh(cylinderGeo6, brassMat);
  cylinder78.position.set(-0.35, 2.75, -1.12);
  cylinder78.rotation.set(deg(90), 0, 0);
  body.add(cylinder78);
  const cylinder79 = new THREE.Mesh(cylinderGeo6, brassMat);
  cylinder79.position.set(0, 2.75, -1.12);
  cylinder79.rotation.set(deg(90), 0, 0);
  body.add(cylinder79);
  const cylinder80 = new THREE.Mesh(cylinderGeo6, brassMat);
  cylinder80.position.set(0.35, 2.75, -1.12);
  cylinder80.rotation.set(deg(90), 0, 0);
  body.add(cylinder80);
  const wheels = new THREE.Group();
  wheels.name = 'wheels';
  root.add(wheels);
  const driverL1 = new THREE.Group();
  driverL1.name = 'driverL1';
  driverL1.position.set(0.76, 0.78, 1.75);
  wheels.add(driverL1);
  const tire = new THREE.Mesh(latheGeo, accentMat);
  tire.name = 'tire';
  tire.rotation.set(0, 0, deg(90));
  driverL1.add(tire);
  const hub = new THREE.Mesh(cylinderGeo7, accentMat);
  hub.name = 'hub';
  hub.rotation.set(0, 0, deg(90));
  driverL1.add(hub);
  const box85 = new THREE.Mesh(boxGeo18, accentMat);
  box85.position.set(0, 0.4, 0);
  driverL1.add(box85);
  const box86 = new THREE.Mesh(boxGeo18, accentMat);
  box86.position.set(0, 0.3064, 0.2571);
  box86.rotation.set(deg(40), 0, 0);
  driverL1.add(box86);
  const box87 = new THREE.Mesh(boxGeo18, accentMat);
  box87.position.set(0, 0.0695, 0.3939);
  box87.rotation.set(deg(80), 0, 0);
  driverL1.add(box87);
  const box88 = new THREE.Mesh(boxGeo18, accentMat);
  box88.position.set(0, -0.2, 0.3464);
  box88.rotation.set(deg(120), 0, 0);
  driverL1.add(box88);
  const box89 = new THREE.Mesh(boxGeo18, accentMat);
  box89.position.set(0, -0.3759, 0.1368);
  box89.rotation.set(deg(160), 0, 0);
  driverL1.add(box89);
  const box90 = new THREE.Mesh(boxGeo18, accentMat);
  box90.position.set(0, -0.3759, -0.1368);
  box90.rotation.set(deg(200), 0, 0);
  driverL1.add(box90);
  const box91 = new THREE.Mesh(boxGeo18, accentMat);
  box91.position.set(0, -0.2, -0.3464);
  box91.rotation.set(deg(240), 0, 0);
  driverL1.add(box91);
  const box92 = new THREE.Mesh(boxGeo18, accentMat);
  box92.position.set(0, 0.0695, -0.3939);
  box92.rotation.set(deg(280), 0, 0);
  driverL1.add(box92);
  const box93 = new THREE.Mesh(boxGeo18, accentMat);
  box93.position.set(0, 0.3064, -0.2571);
  box93.rotation.set(deg(320), 0, 0);
  driverL1.add(box93);
  const crankPin = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin.name = 'crankPin';
  crankPin.position.set(0.14, 0, 0.32);
  crankPin.rotation.set(0, 0, deg(90));
  driverL1.add(crankPin);
  const counterweight = new THREE.Mesh(extrudeGeo2, accentMat);
  counterweight.name = 'counterweight';
  counterweight.position.set(0.01, 0, 0);
  counterweight.rotation.set(0, deg(-90), 0);
  driverL1.add(counterweight);
  const driverL2 = new THREE.Group();
  driverL2.name = 'driverL2';
  driverL2.position.set(0.76, 0.78, 0.15);
  wheels.add(driverL2);
  const tire2 = new THREE.Mesh(latheGeo, accentMat);
  tire2.name = 'tire';
  tire2.rotation.set(0, 0, deg(90));
  driverL2.add(tire2);
  const hub2 = new THREE.Mesh(cylinderGeo7, accentMat);
  hub2.name = 'hub';
  hub2.rotation.set(0, 0, deg(90));
  driverL2.add(hub2);
  const box99 = new THREE.Mesh(boxGeo18, accentMat);
  box99.position.set(0, 0.4, 0);
  driverL2.add(box99);
  const box100 = new THREE.Mesh(boxGeo18, accentMat);
  box100.position.set(0, 0.3064, 0.2571);
  box100.rotation.set(deg(40), 0, 0);
  driverL2.add(box100);
  const box101 = new THREE.Mesh(boxGeo18, accentMat);
  box101.position.set(0, 0.0695, 0.3939);
  box101.rotation.set(deg(80), 0, 0);
  driverL2.add(box101);
  const box102 = new THREE.Mesh(boxGeo18, accentMat);
  box102.position.set(0, -0.2, 0.3464);
  box102.rotation.set(deg(120), 0, 0);
  driverL2.add(box102);
  const box103 = new THREE.Mesh(boxGeo18, accentMat);
  box103.position.set(0, -0.3759, 0.1368);
  box103.rotation.set(deg(160), 0, 0);
  driverL2.add(box103);
  const box104 = new THREE.Mesh(boxGeo18, accentMat);
  box104.position.set(0, -0.3759, -0.1368);
  box104.rotation.set(deg(200), 0, 0);
  driverL2.add(box104);
  const box105 = new THREE.Mesh(boxGeo18, accentMat);
  box105.position.set(0, -0.2, -0.3464);
  box105.rotation.set(deg(240), 0, 0);
  driverL2.add(box105);
  const box106 = new THREE.Mesh(boxGeo18, accentMat);
  box106.position.set(0, 0.0695, -0.3939);
  box106.rotation.set(deg(280), 0, 0);
  driverL2.add(box106);
  const box107 = new THREE.Mesh(boxGeo18, accentMat);
  box107.position.set(0, 0.3064, -0.2571);
  box107.rotation.set(deg(320), 0, 0);
  driverL2.add(box107);
  const crankPin2 = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin2.name = 'crankPin';
  crankPin2.position.set(0.14, 0, 0.32);
  crankPin2.rotation.set(0, 0, deg(90));
  driverL2.add(crankPin2);
  const counterweight2 = new THREE.Mesh(extrudeGeo2, accentMat);
  counterweight2.name = 'counterweight';
  counterweight2.position.set(0.01, 0, 0);
  counterweight2.rotation.set(0, deg(-90), 0);
  driverL2.add(counterweight2);
  const driverL3 = new THREE.Group();
  driverL3.name = 'driverL3';
  driverL3.position.set(0.76, 0.78, -1.45);
  wheels.add(driverL3);
  const tire3 = new THREE.Mesh(latheGeo, accentMat);
  tire3.name = 'tire';
  tire3.rotation.set(0, 0, deg(90));
  driverL3.add(tire3);
  const hub3 = new THREE.Mesh(cylinderGeo7, accentMat);
  hub3.name = 'hub';
  hub3.rotation.set(0, 0, deg(90));
  driverL3.add(hub3);
  const box113 = new THREE.Mesh(boxGeo18, accentMat);
  box113.position.set(0, 0.4, 0);
  driverL3.add(box113);
  const box114 = new THREE.Mesh(boxGeo18, accentMat);
  box114.position.set(0, 0.3064, 0.2571);
  box114.rotation.set(deg(40), 0, 0);
  driverL3.add(box114);
  const box115 = new THREE.Mesh(boxGeo18, accentMat);
  box115.position.set(0, 0.0695, 0.3939);
  box115.rotation.set(deg(80), 0, 0);
  driverL3.add(box115);
  const box116 = new THREE.Mesh(boxGeo18, accentMat);
  box116.position.set(0, -0.2, 0.3464);
  box116.rotation.set(deg(120), 0, 0);
  driverL3.add(box116);
  const box117 = new THREE.Mesh(boxGeo18, accentMat);
  box117.position.set(0, -0.3759, 0.1368);
  box117.rotation.set(deg(160), 0, 0);
  driverL3.add(box117);
  const box118 = new THREE.Mesh(boxGeo18, accentMat);
  box118.position.set(0, -0.3759, -0.1368);
  box118.rotation.set(deg(200), 0, 0);
  driverL3.add(box118);
  const box119 = new THREE.Mesh(boxGeo18, accentMat);
  box119.position.set(0, -0.2, -0.3464);
  box119.rotation.set(deg(240), 0, 0);
  driverL3.add(box119);
  const box120 = new THREE.Mesh(boxGeo18, accentMat);
  box120.position.set(0, 0.0695, -0.3939);
  box120.rotation.set(deg(280), 0, 0);
  driverL3.add(box120);
  const box121 = new THREE.Mesh(boxGeo18, accentMat);
  box121.position.set(0, 0.3064, -0.2571);
  box121.rotation.set(deg(320), 0, 0);
  driverL3.add(box121);
  const crankPin3 = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin3.name = 'crankPin';
  crankPin3.position.set(0.14, 0, 0.32);
  crankPin3.rotation.set(0, 0, deg(90));
  driverL3.add(crankPin3);
  const counterweight3 = new THREE.Mesh(extrudeGeo2, accentMat);
  counterweight3.name = 'counterweight';
  counterweight3.position.set(0.01, 0, 0);
  counterweight3.rotation.set(0, deg(-90), 0);
  driverL3.add(counterweight3);
  const ponyL = new THREE.Group();
  ponyL.name = 'ponyL';
  ponyL.position.set(0.76, 0.48, 3.85);
  wheels.add(ponyL);
  const tire4 = new THREE.Mesh(latheGeo2, accentMat);
  tire4.name = 'tire';
  tire4.rotation.set(0, 0, deg(90));
  ponyL.add(tire4);
  const disc = new THREE.Mesh(cylinderGeo9, blackMat);
  disc.name = 'disc';
  disc.rotation.set(0, 0, deg(90));
  ponyL.add(disc);
  const driverR1 = new THREE.Group();
  driverR1.name = 'driverR1';
  driverR1.position.set(-0.76, 0.78, 1.75);
  wheels.add(driverR1);
  const tire5 = new THREE.Mesh(latheGeo, accentMat);
  tire5.name = 'tire';
  tire5.rotation.set(0, 0, deg(-90));
  driverR1.add(tire5);
  const hub4 = new THREE.Mesh(cylinderGeo7, accentMat);
  hub4.name = 'hub';
  hub4.rotation.set(0, 0, deg(90));
  driverR1.add(hub4);
  const box130 = new THREE.Mesh(boxGeo18, accentMat);
  box130.position.set(0, 0.4, 0);
  driverR1.add(box130);
  const box131 = new THREE.Mesh(boxGeo18, accentMat);
  box131.position.set(0, 0.3064, 0.2571);
  box131.rotation.set(deg(40), 0, 0);
  driverR1.add(box131);
  const box132 = new THREE.Mesh(boxGeo18, accentMat);
  box132.position.set(0, 0.0695, 0.3939);
  box132.rotation.set(deg(80), 0, 0);
  driverR1.add(box132);
  const box133 = new THREE.Mesh(boxGeo18, accentMat);
  box133.position.set(0, -0.2, 0.3464);
  box133.rotation.set(deg(120), 0, 0);
  driverR1.add(box133);
  const box134 = new THREE.Mesh(boxGeo18, accentMat);
  box134.position.set(0, -0.3759, 0.1368);
  box134.rotation.set(deg(160), 0, 0);
  driverR1.add(box134);
  const box135 = new THREE.Mesh(boxGeo18, accentMat);
  box135.position.set(0, -0.3759, -0.1368);
  box135.rotation.set(deg(200), 0, 0);
  driverR1.add(box135);
  const box136 = new THREE.Mesh(boxGeo18, accentMat);
  box136.position.set(0, -0.2, -0.3464);
  box136.rotation.set(deg(240), 0, 0);
  driverR1.add(box136);
  const box137 = new THREE.Mesh(boxGeo18, accentMat);
  box137.position.set(0, 0.0695, -0.3939);
  box137.rotation.set(deg(280), 0, 0);
  driverR1.add(box137);
  const box138 = new THREE.Mesh(boxGeo18, accentMat);
  box138.position.set(0, 0.3064, -0.2571);
  box138.rotation.set(deg(320), 0, 0);
  driverR1.add(box138);
  const crankPin4 = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin4.name = 'crankPin';
  crankPin4.position.set(-0.14, 0.32, 0);
  crankPin4.rotation.set(0, 0, deg(90));
  driverR1.add(crankPin4);
  const counterweight4 = new THREE.Mesh(extrudeGeo3, accentMat);
  counterweight4.name = 'counterweight';
  counterweight4.position.set(-0.01, 0, 0);
  counterweight4.rotation.set(0, deg(-90), 0);
  driverR1.add(counterweight4);
  const driverR2 = new THREE.Group();
  driverR2.name = 'driverR2';
  driverR2.position.set(-0.76, 0.78, 0.15);
  wheels.add(driverR2);
  const tire6 = new THREE.Mesh(latheGeo, accentMat);
  tire6.name = 'tire';
  tire6.rotation.set(0, 0, deg(-90));
  driverR2.add(tire6);
  const hub5 = new THREE.Mesh(cylinderGeo7, accentMat);
  hub5.name = 'hub';
  hub5.rotation.set(0, 0, deg(90));
  driverR2.add(hub5);
  const box144 = new THREE.Mesh(boxGeo18, accentMat);
  box144.position.set(0, 0.4, 0);
  driverR2.add(box144);
  const box145 = new THREE.Mesh(boxGeo18, accentMat);
  box145.position.set(0, 0.3064, 0.2571);
  box145.rotation.set(deg(40), 0, 0);
  driverR2.add(box145);
  const box146 = new THREE.Mesh(boxGeo18, accentMat);
  box146.position.set(0, 0.0695, 0.3939);
  box146.rotation.set(deg(80), 0, 0);
  driverR2.add(box146);
  const box147 = new THREE.Mesh(boxGeo18, accentMat);
  box147.position.set(0, -0.2, 0.3464);
  box147.rotation.set(deg(120), 0, 0);
  driverR2.add(box147);
  const box148 = new THREE.Mesh(boxGeo18, accentMat);
  box148.position.set(0, -0.3759, 0.1368);
  box148.rotation.set(deg(160), 0, 0);
  driverR2.add(box148);
  const box149 = new THREE.Mesh(boxGeo18, accentMat);
  box149.position.set(0, -0.3759, -0.1368);
  box149.rotation.set(deg(200), 0, 0);
  driverR2.add(box149);
  const box150 = new THREE.Mesh(boxGeo18, accentMat);
  box150.position.set(0, -0.2, -0.3464);
  box150.rotation.set(deg(240), 0, 0);
  driverR2.add(box150);
  const box151 = new THREE.Mesh(boxGeo18, accentMat);
  box151.position.set(0, 0.0695, -0.3939);
  box151.rotation.set(deg(280), 0, 0);
  driverR2.add(box151);
  const box152 = new THREE.Mesh(boxGeo18, accentMat);
  box152.position.set(0, 0.3064, -0.2571);
  box152.rotation.set(deg(320), 0, 0);
  driverR2.add(box152);
  const crankPin5 = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin5.name = 'crankPin';
  crankPin5.position.set(-0.14, 0.32, 0);
  crankPin5.rotation.set(0, 0, deg(90));
  driverR2.add(crankPin5);
  const counterweight5 = new THREE.Mesh(extrudeGeo3, accentMat);
  counterweight5.name = 'counterweight';
  counterweight5.position.set(-0.01, 0, 0);
  counterweight5.rotation.set(0, deg(-90), 0);
  driverR2.add(counterweight5);
  const driverR3 = new THREE.Group();
  driverR3.name = 'driverR3';
  driverR3.position.set(-0.76, 0.78, -1.45);
  wheels.add(driverR3);
  const tire7 = new THREE.Mesh(latheGeo, accentMat);
  tire7.name = 'tire';
  tire7.rotation.set(0, 0, deg(-90));
  driverR3.add(tire7);
  const hub6 = new THREE.Mesh(cylinderGeo7, accentMat);
  hub6.name = 'hub';
  hub6.rotation.set(0, 0, deg(90));
  driverR3.add(hub6);
  const box158 = new THREE.Mesh(boxGeo18, accentMat);
  box158.position.set(0, 0.4, 0);
  driverR3.add(box158);
  const box159 = new THREE.Mesh(boxGeo18, accentMat);
  box159.position.set(0, 0.3064, 0.2571);
  box159.rotation.set(deg(40), 0, 0);
  driverR3.add(box159);
  const box160 = new THREE.Mesh(boxGeo18, accentMat);
  box160.position.set(0, 0.0695, 0.3939);
  box160.rotation.set(deg(80), 0, 0);
  driverR3.add(box160);
  const box161 = new THREE.Mesh(boxGeo18, accentMat);
  box161.position.set(0, -0.2, 0.3464);
  box161.rotation.set(deg(120), 0, 0);
  driverR3.add(box161);
  const box162 = new THREE.Mesh(boxGeo18, accentMat);
  box162.position.set(0, -0.3759, 0.1368);
  box162.rotation.set(deg(160), 0, 0);
  driverR3.add(box162);
  const box163 = new THREE.Mesh(boxGeo18, accentMat);
  box163.position.set(0, -0.3759, -0.1368);
  box163.rotation.set(deg(200), 0, 0);
  driverR3.add(box163);
  const box164 = new THREE.Mesh(boxGeo18, accentMat);
  box164.position.set(0, -0.2, -0.3464);
  box164.rotation.set(deg(240), 0, 0);
  driverR3.add(box164);
  const box165 = new THREE.Mesh(boxGeo18, accentMat);
  box165.position.set(0, 0.0695, -0.3939);
  box165.rotation.set(deg(280), 0, 0);
  driverR3.add(box165);
  const box166 = new THREE.Mesh(boxGeo18, accentMat);
  box166.position.set(0, 0.3064, -0.2571);
  box166.rotation.set(deg(320), 0, 0);
  driverR3.add(box166);
  const crankPin6 = new THREE.Mesh(cylinderGeo8, steelMat);
  crankPin6.name = 'crankPin';
  crankPin6.position.set(-0.14, 0.32, 0);
  crankPin6.rotation.set(0, 0, deg(90));
  driverR3.add(crankPin6);
  const counterweight6 = new THREE.Mesh(extrudeGeo3, accentMat);
  counterweight6.name = 'counterweight';
  counterweight6.position.set(-0.01, 0, 0);
  counterweight6.rotation.set(0, deg(-90), 0);
  driverR3.add(counterweight6);
  const ponyR = new THREE.Group();
  ponyR.name = 'ponyR';
  ponyR.position.set(-0.76, 0.48, 3.85);
  wheels.add(ponyR);
  const tire8 = new THREE.Mesh(latheGeo2, accentMat);
  tire8.name = 'tire';
  tire8.rotation.set(0, 0, deg(-90));
  ponyR.add(tire8);
  const disc2 = new THREE.Mesh(cylinderGeo9, blackMat);
  disc2.name = 'disc';
  disc2.rotation.set(0, 0, deg(90));
  ponyR.add(disc2);

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

export default createSteamLocomotive;

Ratings & comments

—
No ratings yet — be the first.
5
0
4
0
3
0
2
0
1
0

Sign in to rate and comment.

0 comments

No comments yet. Share how you used this model or what could be better.

Related models

Same category or similar tags