4.2K tris3.24 × 4.05 × 8.59 m
Use it in code
Remix in the editorsteam-locomotive.js · 769 lines
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
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









