2,6 k tris0,70 × 1,13 × 2,04 m
Utiliser dans le code
Remixer dans l’éditeurmotorcycle.js · 384 lignes
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
* Motorcycle — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 2,644 · Size (W × H × D): 0.70 × 1.13 × 2.04 m
*
* Usage:
* import { createMotorcycle } from './motorcycle.js';
*
* const model = createMotorcycle();
* 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);
}
// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}
export function createMotorcycle() {
const root = new THREE.Group();
root.name = 'Motorcycle';
// Materials
const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xd22f2f, roughness: 0.3, metalness: 0.25, flatShading: true });
const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xf2f2ee, roughness: 0.45, flatShading: true });
const tireMat = new THREE.MeshStandardMaterial({ name: 'tire', color: 0x222326, roughness: 0.85, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2c2e33, roughness: 0.7, flatShading: true });
const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x6d7279, roughness: 0.45, metalness: 0.6, flatShading: true });
const chromeMat = new THREE.MeshStandardMaterial({ name: 'chrome', color: 0xd4d8dd, roughness: 0.2, metalness: 0.85, flatShading: true });
const rimMat = new THREE.MeshStandardMaterial({ name: 'rim', color: 0xe2a72e, roughness: 0.3, metalness: 0.6, flatShading: true });
const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x2a3644, roughness: 0.2, metalness: 0.3, flatShading: true });
const headlightMat = new THREE.MeshStandardMaterial({ name: 'headlight', color: 0xfff4d6, roughness: 0.3, emissive: 0xffe2a0, emissiveIntensity: 0.9, flatShading: true });
const taillightMat = new THREE.MeshStandardMaterial({ name: 'taillight', color: 0xd81e28, roughness: 0.3, emissive: 0xff2020, emissiveIntensity: 0.7, flatShading: true });
// Shared geometries
const extrudeGeo = extrude([[0.4, 0.6], [0.3, 0.9], [0.02, 0.84], [-0.04, 0.62], [0.12, 0.44], [0.36, 0.42]], 0.02, [], [0.015, 0.015, 2]);
const extrudeGeo2 = extrude([[0.36, 0.62], [0.28, 0.82], [0.12, 0.78], [0.2, 0.6]], 0.006, [], [0.004, 0.004, 2]);
const boxGeo = new THREE.BoxGeometry(0.02, 0.012, 0.3);
const cylinderGeo = new THREE.CylinderGeometry(0.008, 0.008, 0.102, 4);
const boxGeo2 = new THREE.BoxGeometry(0.09, 0.05, 0.03);
const cylinderGeo2 = new THREE.CylinderGeometry(0.014, 0.014, 0.2375, 6);
const cylinderGeo3 = new THREE.CylinderGeometry(0.02, 0.02, 0.1095, 6);
const cylinderGeo4 = new THREE.CylinderGeometry(0.03, 0.03, 0.6, 8);
const cylinderGeo5 = new THREE.CylinderGeometry(0.024, 0.024, 0.18, 8);
const cylinderGeo6 = new THREE.CylinderGeometry(0.012, 0.012, 0.1, 5);
const boxGeo3 = new THREE.BoxGeometry(0.04, 0.6367, 0.08);
const boxGeo4 = new THREE.BoxGeometry(0.04, 0.5404, 0.09);
const boxGeo5 = new THREE.BoxGeometry(0.1, 0.055, 0.02);
const boxGeo6 = new THREE.BoxGeometry(0.24, 0.05, 0.1);
const boxGeo7 = new THREE.BoxGeometry(0.022, 0.155, 0.03);
const cylinderGeo7 = new THREE.CylinderGeometry(0.1548, 0.1548, 0.008, 16);
const boxGeo8 = new THREE.BoxGeometry(0.022, 0.156, 0.03);
// Parts
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const noseFairing = new THREE.Mesh(extrude([[0.36, 0.56], [0.58, 0.66], [0.8, 0.79], [0.79, 0.85], [0.62, 0.97], [0.46, 1.03], [0.34, 1], [0.3, 0.7]], 0.28, [], [0.05, 0.05, 2]), paintMat);
noseFairing.name = 'noseFairing';
noseFairing.rotation.set(0, deg(-90), 0);
body.add(noseFairing);
const tank = new THREE.Mesh(extrude([[0.32, 0.88], [0.3, 1], [0.15, 1.06], [-0.04, 1.03], [-0.14, 0.95], [-0.14, 0.83], [0.2, 0.8]], 0.26, [], [0.05, 0.05, 2]), paintMat);
tank.name = 'tank';
tank.rotation.set(0, deg(-90), 0);
body.add(tank);
const seat = new THREE.Mesh(extrude([[-0.12, 0.88], [-0.12, 0.96], [-0.45, 0.93], [-0.5, 0.88]], 0.24, [], [0.03, 0.03, 2]), darkMat);
seat.name = 'seat';
seat.rotation.set(0, deg(-90), 0);
body.add(seat);
const tail = new THREE.Mesh(extrude([[-0.42, 0.82], [-0.48, 0.95], [-0.86, 1.06], [-0.94, 1.02], [-0.78, 0.84]], 0.18, [], [0.03, 0.03, 2]), paintMat);
tail.name = 'tail';
tail.rotation.set(0, deg(-90), 0);
body.add(tail);
const pillion = new THREE.Mesh(extrude([[-0.6, 0.98], [-0.62, 1.02], [-0.78, 1.06], [-0.8, 1.02]], 0.14, [], [0.02, 0.02, 2]), darkMat);
pillion.name = 'pillion';
pillion.rotation.set(0, deg(-90), 0);
body.add(pillion);
const sidePanelL = new THREE.Mesh(extrudeGeo, paintMat);
sidePanelL.name = 'sidePanelL';
sidePanelL.position.set(0.18, 0, 0);
sidePanelL.rotation.set(0, deg(-90), 0);
body.add(sidePanelL);
const stripeL = new THREE.Mesh(extrudeGeo2, whiteMat);
stripeL.name = 'stripeL';
stripeL.position.set(0.207, 0, 0);
stripeL.rotation.set(0, deg(-90), 0);
body.add(stripeL);
const box9 = new THREE.Mesh(boxGeo, whiteMat);
box9.position.set(0.12, 1, -0.7);
box9.rotation.set(deg(-15), 0, 0);
body.add(box9);
const cylinder10 = new THREE.Mesh(cylinderGeo, darkMat);
cylinder10.position.set(0.2, 1.01, 0.51);
cylinder10.rotation.set(deg(-11.3641), deg(5.5583), deg(-52.0149));
body.add(cylinder10);
const mirrorL = new THREE.Mesh(boxGeo2, darkMat);
mirrorL.name = 'mirrorL';
mirrorL.position.set(0.26, 1.05, 0.5);
body.add(mirrorL);
const cylinder12 = new THREE.Mesh(cylinderGeo2, metalMat);
cylinder12.position.set(0.19, 0.9626, 0.3427);
cylinder12.rotation.set(deg(-21.3104), deg(22.0405), deg(-91.9766));
body.add(cylinder12);
const gripL = new THREE.Mesh(cylinderGeo3, darkMat);
gripL.name = 'gripL';
gripL.position.set(0.29, 0.9476, 0.3027);
gripL.rotation.set(deg(-23.5725), deg(24.0657), deg(-91.2212));
body.add(gripL);
const cylinder14 = new THREE.Mesh(cylinderGeo4, rimMat);
cylinder14.position.set(0.09, 0.5741, 0.578);
cylinder14.rotation.set(deg(-24), 0, 0);
body.add(cylinder14);
const cylinder15 = new THREE.Mesh(cylinderGeo5, chromeMat);
cylinder15.position.set(0.09, 0.9303, 0.4194);
cylinder15.rotation.set(deg(-24), 0, 0);
body.add(cylinder15);
const cylinder16 = new THREE.Mesh(cylinderGeo6, metalMat);
cylinder16.position.set(0.22, 0.44, -0.28);
cylinder16.rotation.set(0, 0, deg(90));
body.add(cylinder16);
const swingarmL = new THREE.Mesh(boxGeo3, metalMat);
swingarmL.name = 'swingarmL';
swingarmL.position.set(0.12, 0.3875, -0.41);
swingarmL.rotation.set(deg(-103.1632), 0, 0);
body.add(swingarmL);
const frameSparL = new THREE.Mesh(boxGeo4, metalMat);
frameSparL.name = 'frameSparL';
frameSparL.position.set(0.14, 0.67, 0.09);
frameSparL.rotation.set(deg(-128.991), 0, 0);
body.add(frameSparL);
const headlightL = new THREE.Mesh(boxGeo5, headlightMat);
headlightL.name = 'headlightL';
headlightL.position.set(0.075, 0.952, 0.742);
headlightL.rotation.set(deg(-55.9925), 0, 0);
body.add(headlightL);
const sidePanelR = new THREE.Mesh(extrudeGeo, paintMat);
sidePanelR.name = 'sidePanelR';
sidePanelR.position.set(-0.18, 0, 0);
sidePanelR.rotation.set(0, deg(-90), 0);
body.add(sidePanelR);
const stripeR = new THREE.Mesh(extrudeGeo2, whiteMat);
stripeR.name = 'stripeR';
stripeR.position.set(-0.207, 0, 0);
stripeR.rotation.set(0, deg(-90), 0);
body.add(stripeR);
const box22 = new THREE.Mesh(boxGeo, whiteMat);
box22.position.set(-0.12, 1, -0.7);
box22.rotation.set(deg(-15), 0, 0);
body.add(box22);
const cylinder23 = new THREE.Mesh(cylinderGeo, darkMat);
cylinder23.position.set(-0.2, 1.01, 0.51);
cylinder23.rotation.set(deg(-11.3641), deg(-5.5583), deg(52.0149));
body.add(cylinder23);
const mirrorR = new THREE.Mesh(boxGeo2, darkMat);
mirrorR.name = 'mirrorR';
mirrorR.position.set(-0.26, 1.05, 0.5);
body.add(mirrorR);
const cylinder25 = new THREE.Mesh(cylinderGeo2, metalMat);
cylinder25.position.set(-0.19, 0.9626, 0.3427);
cylinder25.rotation.set(deg(-21.3104), deg(-22.0405), deg(91.9766));
body.add(cylinder25);
const gripR = new THREE.Mesh(cylinderGeo3, darkMat);
gripR.name = 'gripR';
gripR.position.set(-0.29, 0.9476, 0.3027);
gripR.rotation.set(deg(-23.5725), deg(-24.0657), deg(91.2212));
body.add(gripR);
const cylinder27 = new THREE.Mesh(cylinderGeo4, rimMat);
cylinder27.position.set(-0.09, 0.5741, 0.578);
cylinder27.rotation.set(deg(-24), 0, 0);
body.add(cylinder27);
const cylinder28 = new THREE.Mesh(cylinderGeo5, chromeMat);
cylinder28.position.set(-0.09, 0.9303, 0.4194);
cylinder28.rotation.set(deg(-24), 0, 0);
body.add(cylinder28);
const cylinder29 = new THREE.Mesh(cylinderGeo6, metalMat);
cylinder29.position.set(-0.22, 0.44, -0.28);
cylinder29.rotation.set(0, 0, deg(90));
body.add(cylinder29);
const swingarmR = new THREE.Mesh(boxGeo3, metalMat);
swingarmR.name = 'swingarmR';
swingarmR.position.set(-0.12, 0.3875, -0.41);
swingarmR.rotation.set(deg(-103.1632), 0, 0);
body.add(swingarmR);
const frameSparR = new THREE.Mesh(boxGeo4, metalMat);
frameSparR.name = 'frameSparR';
frameSparR.position.set(-0.14, 0.67, 0.09);
frameSparR.rotation.set(deg(-128.991), 0, 0);
body.add(frameSparR);
const headlightR = new THREE.Mesh(boxGeo5, headlightMat);
headlightR.name = 'headlightR';
headlightR.position.set(-0.075, 0.952, 0.742);
headlightR.rotation.set(deg(-55.9925), 0, 0);
body.add(headlightR);
const ramAir = new THREE.Mesh(boxGeo2, darkMat);
ramAir.name = 'ramAir';
ramAir.position.set(0, 0.8, 0.86);
body.add(ramAir);
const topClamp = new THREE.Mesh(boxGeo6, metalMat);
topClamp.name = 'topClamp';
topClamp.position.set(0, 1.0126, 0.3827);
topClamp.rotation.set(deg(-24), 0, 0);
body.add(topClamp);
const box35 = new THREE.Mesh(boxGeo6, metalMat);
box35.position.set(0, 0.9681, 0.406);
box35.rotation.set(deg(-24), 0, 0);
body.add(box35);
const windscreen = new THREE.Mesh(new THREE.BoxGeometry(0.26, 0.012, 0.22), glassMat);
windscreen.name = 'windscreen';
windscreen.position.set(0, 1.07, 0.42);
windscreen.rotation.set(deg(32), 0, 0);
body.add(windscreen);
const crankcase = new THREE.Mesh(new THREE.BoxGeometry(0.34, 0.26, 0.42), metalMat);
crankcase.name = 'crankcase';
crankcase.position.set(0, 0.42, 0.08);
body.add(crankcase);
const cylinders = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.3, 0.2), darkMat);
cylinders.name = 'cylinders';
cylinders.position.set(0, 0.64, 0.2);
cylinders.rotation.set(deg(-28), 0, 0);
body.add(cylinders);
const radiator = new THREE.Mesh(new THREE.BoxGeometry(0.38, 0.3, 0.04), darkMat);
radiator.name = 'radiator';
radiator.position.set(0, 0.66, 0.38);
radiator.rotation.set(deg(-20), 0, 0);
body.add(radiator);
const header = new THREE.Mesh(tube([[-0.06, 0.5, 0.36], [-0.08, 0.3, 0.34], [-0.1, 0.24, 0.1], [-0.14, 0.3, -0.2], [-0.17, 0.4, -0.32]], 0.025, 12, 5), chromeMat);
header.name = 'header';
body.add(header);
const muffler = new THREE.Mesh(new THREE.CylinderGeometry(0.06, 0.055, 0.38, 8), metalMat);
muffler.name = 'muffler';
muffler.position.set(-0.18, 0.5, -0.48);
muffler.rotation.set(deg(-63.4349), 0, 0);
body.add(muffler);
const cylinder42 = new THREE.Mesh(new THREE.CylinderGeometry(0.045, 0.045, 0.02, 8), darkMat);
cylinder42.position.set(-0.18, 0.6, -0.66);
cylinder42.rotation.set(deg(-63.4349), 0, 0);
body.add(cylinder42);
const rearShock = new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.03, 0.3454, 6), rimMat);
rearShock.name = 'rearShock';
rearShock.position.set(0, 0.66, -0.385);
rearShock.rotation.set(deg(-22.1094), 0, 0);
body.add(rearShock);
const taillight = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.04, 0.03), taillightMat);
taillight.name = 'taillight';
taillight.position.set(0, 1.02, -0.95);
body.add(taillight);
const cylinder45 = new THREE.Mesh(new THREE.CylinderGeometry(0.012, 0.012, 0.1844, 4), darkMat);
cylinder45.position.set(0, 0.79, -0.88);
cylinder45.rotation.set(deg(-139.3987), 0, 0);
body.add(cylinder45);
const plate = new THREE.Mesh(new THREE.BoxGeometry(0.18, 0.12, 0.01), whiteMat);
plate.name = 'plate';
plate.position.set(0, 0.68, -0.96);
plate.rotation.set(deg(-20), 0, 0);
body.add(plate);
const frontFender = new THREE.Mesh(extrude([[0.2944, 0.17], [0.2546, 0.2253], [0.2046, 0.2715], [0.1464, 0.3069], [0.0823, 0.3299], [0.0148, 0.3397], [-0.0532, 0.3358], [-0.1191, 0.3185], [-0.1802, 0.2883], [-0.234, 0.2466], [-0.2785, 0.195], [-0.2662, 0.1864], [-0.2237, 0.2357], [-0.1722, 0.2756], [-0.1138, 0.3044], [-0.0508, 0.321], [0.0142, 0.3247], [0.0786, 0.3153], [0.1399, 0.2933], [0.1956, 0.2596], [0.2434, 0.2154], [0.2815, 0.1625]], 0.12), paintMat);
frontFender.name = 'frontFender';
frontFender.position.set(0, 0.3, 0.7);
frontFender.rotation.set(0, deg(-90), 0);
body.add(frontFender);
const wheels = new THREE.Group();
wheels.name = 'wheels';
root.add(wheels);
const wheelF = new THREE.Group();
wheelF.name = 'wheelF';
wheelF.position.set(0, 0.3, 0.7);
wheels.add(wheelF);
const tire = new THREE.Mesh(lathe([[0.215, -0.042], [0.215, -0.051], [0.246, -0.06], [0.282, -0.045], [0.3, -0.012], [0.3, 0.012], [0.282, 0.045], [0.246, 0.06], [0.215, 0.051], [0.215, 0.042]], 16, 0, Math.PI * 2), tireMat);
tire.name = 'tire';
tire.rotation.set(0, 0, deg(90));
wheelF.add(tire);
const rim = new THREE.Mesh(lathe([[0.19, -0.036], [0.219, -0.045], [0.219, 0.045], [0.19, 0.036], [0.19, -0.036]], 16), rimMat);
rim.name = 'rim';
rim.rotation.set(0, 0, deg(90));
wheelF.add(rim);
const hub = new THREE.Mesh(new THREE.CylinderGeometry(0.045, 0.045, 0.12, 8), metalMat);
hub.name = 'hub';
hub.rotation.set(0, 0, deg(90));
wheelF.add(hub);
const box53 = new THREE.Mesh(boxGeo7, rimMat);
box53.position.set(0, 0.1225, 0);
wheelF.add(box53);
const box54 = new THREE.Mesh(boxGeo7, rimMat);
box54.position.set(0, 0.0379, 0.1165);
box54.rotation.set(deg(72), 0, 0);
wheelF.add(box54);
const box55 = new THREE.Mesh(boxGeo7, rimMat);
box55.position.set(0, -0.0991, 0.072);
box55.rotation.set(deg(144), 0, 0);
wheelF.add(box55);
const box56 = new THREE.Mesh(boxGeo7, rimMat);
box56.position.set(0, -0.0991, -0.072);
box56.rotation.set(deg(216), 0, 0);
wheelF.add(box56);
const box57 = new THREE.Mesh(boxGeo7, rimMat);
box57.position.set(0, 0.0379, -0.1165);
box57.rotation.set(deg(288), 0, 0);
wheelF.add(box57);
const brakeDisc1 = new THREE.Mesh(cylinderGeo7, metalMat);
brakeDisc1.name = 'brakeDisc1';
brakeDisc1.position.set(0.033, 0, 0);
brakeDisc1.rotation.set(0, 0, deg(90));
wheelF.add(brakeDisc1);
const brakeDisc2 = new THREE.Mesh(cylinderGeo7, metalMat);
brakeDisc2.name = 'brakeDisc2';
brakeDisc2.position.set(-0.033, 0, 0);
brakeDisc2.rotation.set(0, 0, deg(90));
wheelF.add(brakeDisc2);
const wheelR = new THREE.Group();
wheelR.name = 'wheelR';
wheelR.position.set(0, 0.315, -0.72);
wheels.add(wheelR);
const tire2 = new THREE.Mesh(lathe([[0.216, -0.063], [0.216, -0.0765], [0.234, -0.09], [0.288, -0.0675], [0.315, -0.018], [0.315, 0.018], [0.288, 0.0675], [0.234, 0.09], [0.216, 0.0765], [0.216, 0.063]], 16, 0, Math.PI * 2), tireMat);
tire2.name = 'tire';
tire2.rotation.set(0, 0, deg(90));
wheelR.add(tire2);
const rim2 = new THREE.Mesh(lathe([[0.191, -0.054], [0.22, -0.0675], [0.22, 0.0675], [0.191, 0.054], [0.191, -0.054]], 16), rimMat);
rim2.name = 'rim';
rim2.rotation.set(0, 0, deg(90));
wheelR.add(rim2);
const hub2 = new THREE.Mesh(new THREE.CylinderGeometry(0.045, 0.045, 0.144, 8), metalMat);
hub2.name = 'hub';
hub2.rotation.set(0, 0, deg(90));
wheelR.add(hub2);
const box64 = new THREE.Mesh(boxGeo8, rimMat);
box64.position.set(0, 0.123, 0);
wheelR.add(box64);
const box65 = new THREE.Mesh(boxGeo8, rimMat);
box65.position.set(0, 0.038, 0.117);
box65.rotation.set(deg(72), 0, 0);
wheelR.add(box65);
const box66 = new THREE.Mesh(boxGeo8, rimMat);
box66.position.set(0, -0.0995, 0.0723);
box66.rotation.set(deg(144), 0, 0);
wheelR.add(box66);
const box67 = new THREE.Mesh(boxGeo8, rimMat);
box67.position.set(0, -0.0995, -0.0723);
box67.rotation.set(deg(216), 0, 0);
wheelR.add(box67);
const box68 = new THREE.Mesh(boxGeo8, rimMat);
box68.position.set(0, 0.038, -0.117);
box68.rotation.set(deg(288), 0, 0);
wheelR.add(box68);
const brakeDisc12 = new THREE.Mesh(new THREE.CylinderGeometry(0.1555, 0.1555, 0.008, 16), metalMat);
brakeDisc12.name = 'brakeDisc1';
brakeDisc12.position.set(0.0495, 0, 0);
brakeDisc12.rotation.set(0, 0, deg(90));
wheelR.add(brakeDisc12);
const sprocket = new THREE.Mesh(new THREE.CylinderGeometry(0.1188, 0.1188, 0.01, 16), darkMat);
sprocket.name = 'sprocket';
sprocket.position.set(0.045, 0, 0);
sprocket.rotation.set(0, 0, deg(90));
wheelR.add(sprocket);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createMotorcycle;
Notes et commentaires
0 commentaire
Aucun commentaire pour l’instant. Dites comment vous avez utilisé ce modèle ou ce qui pourrait être amélioré.
Modèles similaires
Même catégorie ou étiquettes proches









