Codels
2,2 k tris1,94 × 1,21 × 4,58 m

Utiliser dans le code

Remixer dans l’éditeur
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
 * Sports Car — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 2,212 · Size (W × H × D): 1.94 × 1.21 × 4.58 m
 *
 * Usage:
 *   import { createSportsCar } from './sports-car.js';
 *   
 *   const model = createSportsCar();
 *   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 createSportsCar() {
  const root = new THREE.Group();
  root.name = 'SportsCar';

  // Materials
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0xd63a2f, roughness: 0.35, metalness: 0.2, flatShading: true });
  const stripeMat = new THREE.MeshStandardMaterial({ name: 'stripe', color: 0xf4f1ea, roughness: 0.4, metalness: 0.1, flatShading: true });
  const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x26313d, roughness: 0.2, metalness: 0.3, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x24262a, roughness: 0.75, flatShading: true });
  const alloyMat = new THREE.MeshStandardMaterial({ name: 'alloy', color: 0xc3c7ce, roughness: 0.3, metalness: 0.7, flatShading: true });
  const headlightMat = new THREE.MeshStandardMaterial({ name: 'headlight', color: 0xf4f7ff, roughness: 0.3, emissive: 0xdfe9ff, emissiveIntensity: 0.9, flatShading: true });
  const taillightMat = new THREE.MeshStandardMaterial({ name: 'taillight', color: 0xe0202a, roughness: 0.3, emissive: 0xff1f2a, emissiveIntensity: 0.8, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0.4989, 0.93], [0.0467, 1.1], [-0.68, 1.1], [-1.01, 0.93]], 0.02);
  const boxGeo = new THREE.BoxGeometry(0.16, 0.01, 0.3413);
  const boxGeo2 = new THREE.BoxGeometry(0.16, 0.01, 0.9892);
  const boxGeo3 = new THREE.BoxGeometry(0.16, 0.01, 0.6);
  const boxGeo4 = new THREE.BoxGeometry(0.16, 0.01, 0.5025);
  const boxGeo5 = new THREE.BoxGeometry(0.42, 0.03, 0.1877);
  const boxGeo6 = new THREE.BoxGeometry(0.012, 0.16, 0.36);
  const boxGeo7 = new THREE.BoxGeometry(0.006, 0.42, 0.014);
  const boxGeo8 = new THREE.BoxGeometry(0.12, 0.08, 0.14);
  const cylinderGeo = new THREE.CylinderGeometry(0.055, 0.055, 0.2, 8);
  const boxGeo9 = new THREE.BoxGeometry(0.05, 0.22, 0.12);
  const boxGeo10 = new THREE.BoxGeometry(0.02, 0.14, 0.5);
  const latheGeo = lathe([[0.231, -0.1], [0.231, -0.125], [0.295, -0.125], [0.33, -0.085], [0.33, 0.085], [0.295, 0.125], [0.231, 0.125], [0.231, 0.1]], 14);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.231, 0.231, 0.2, 14);
  const boxGeo11 = new THREE.BoxGeometry(0.028, 0.06, 0.2171);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.0508, 0.0647, 0.05, 10);
  const latheGeo2 = lathe([[0.2485, -0.12], [0.2485, -0.145], [0.32, -0.145], [0.355, -0.105], [0.355, 0.105], [0.32, 0.145], [0.2485, 0.145], [0.2485, 0.12]], 14);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.2485, 0.2485, 0.24, 14);
  const boxGeo12 = new THREE.BoxGeometry(0.028, 0.06, 0.2336);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.0547, 0.0696, 0.05, 10);

  // Parts
  const body = new THREE.Group();
  body.name = 'body';
  root.add(body);
  const lowerBody = new THREE.Mesh(extrude([[2.1, 0.2], [2.22, 0.3], [2.24, 0.46], [1.95, 0.64], [0.95, 0.84], [-1.52, 0.88], [-2.02, 0.93], [-2.2, 0.9], [-2.23, 0.45], [-2.1, 0.2], [-1.7611, 0.2], [-1.7871, 0.4048], [-1.7146, 0.5982], [-1.5604, 0.7354], [-1.36, 0.785], [-1.1596, 0.7354], [-1.0054, 0.5982], [-0.9329, 0.4048], [-0.9589, 0.2], [1.0217, 0.2], [1.0042, 0.3876], [1.0744, 0.5624], [1.2169, 0.6856], [1.4, 0.73], [1.5831, 0.6856], [1.7256, 0.5624], [1.7958, 0.3876], [1.7783, 0.2]], 1.84, [], [0.04, 0.04, 2]), paintMat);
  lowerBody.name = 'lowerBody';
  lowerBody.rotation.set(0, deg(-90), 0);
  body.add(lowerBody);
  const chassis = new THREE.Mesh(extrude([[1.85, 0.28], [1.85, 0.6], [0.95, 0.78], [-1.85, 0.82], [-1.85, 0.28]], 1.22), trimMat);
  chassis.name = 'chassis';
  chassis.rotation.set(0, deg(-90), 0);
  body.add(chassis);
  const cabin = new THREE.Mesh(extrude([[0.98, 0.8], [-0.02, 1.16], [-0.62, 1.16], [-1.58, 0.84]], 1.3, [], [0.05, 0.05, 2]), paintMat);
  cabin.name = 'cabin';
  cabin.rotation.set(0, deg(-90), 0);
  body.add(cabin);
  const windowL = new THREE.Mesh(extrudeGeo, glassMat);
  windowL.name = 'windowL';
  windowL.position.set(0.705, 0, 0);
  windowL.rotation.set(0, deg(-90), 0);
  body.add(windowL);
  const windowR = new THREE.Mesh(extrudeGeo, glassMat);
  windowR.name = 'windowR';
  windowR.position.set(-0.705, 0, 0);
  windowR.rotation.set(0, deg(-90), 0);
  body.add(windowR);
  const windshield = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.02, 0.6495), glassMat);
  windshield.name = 'windshield';
  windshield.position.set(0, 1.0702, 0.4183);
  windshield.rotation.set(deg(-160.2011), 0, 0);
  body.add(windshield);
  const rearWindow = new THREE.Mesh(new THREE.BoxGeometry(1.16, 0.02, 0.6325), glassMat);
  rearWindow.name = 'rearWindow';
  rearWindow.position.set(0, 1.0807, -1.0602);
  rearWindow.rotation.set(deg(161.5651), 0, 0);
  body.add(rearWindow);
  const box9 = new THREE.Mesh(boxGeo, stripeMat);
  box9.position.set(0.15, 0.5899, 2.1198);
  box9.rotation.set(deg(-148.1726), 0, 0);
  body.add(box9);
  const box10 = new THREE.Mesh(boxGeo2, stripeMat);
  box10.position.set(0.15, 0.7831, 1.4742);
  box10.rotation.set(deg(-168.6901), 0, 0);
  body.add(box10);
  const box11 = new THREE.Mesh(boxGeo3, stripeMat);
  box11.position.set(0.15, 1.217, -0.32);
  box11.rotation.set(deg(-180), 0, 0);
  body.add(box11);
  const box12 = new THREE.Mesh(boxGeo4, stripeMat);
  box12.position.set(0.15, 0.9518, -1.7653);
  box12.rotation.set(deg(-174.2894), 0, 0);
  body.add(box12);
  const box13 = new THREE.Mesh(boxGeo, stripeMat);
  box13.position.set(-0.15, 0.5899, 2.1198);
  box13.rotation.set(deg(-148.1726), 0, 0);
  body.add(box13);
  const box14 = new THREE.Mesh(boxGeo2, stripeMat);
  box14.position.set(-0.15, 0.7831, 1.4742);
  box14.rotation.set(deg(-168.6901), 0, 0);
  body.add(box14);
  const box15 = new THREE.Mesh(boxGeo3, stripeMat);
  box15.position.set(-0.15, 1.217, -0.32);
  box15.rotation.set(deg(-180), 0, 0);
  body.add(box15);
  const box16 = new THREE.Mesh(boxGeo4, stripeMat);
  box16.position.set(-0.15, 0.9518, -1.7653);
  box16.rotation.set(deg(-174.2894), 0, 0);
  body.add(box16);
  const headlightL = new THREE.Mesh(boxGeo5, headlightMat);
  headlightL.name = 'headlightL';
  headlightL.position.set(0.62, 0.5837, 2.126);
  headlightL.rotation.set(deg(-148.1726), 0, 0);
  body.add(headlightL);
  const sideIntakeL = new THREE.Mesh(boxGeo6, trimMat);
  sideIntakeL.name = 'sideIntakeL';
  sideIntakeL.position.set(0.964, 0.62, -0.7);
  body.add(sideIntakeL);
  const box19 = new THREE.Mesh(boxGeo7, trimMat);
  box19.position.set(0.963, 0.58, 0.7);
  body.add(box19);
  const mirrorL = new THREE.Mesh(boxGeo8, paintMat);
  mirrorL.name = 'mirrorL';
  mirrorL.position.set(0.77, 0.92, 0.64);
  body.add(mirrorL);
  const exhaustL = new THREE.Mesh(cylinderGeo, alloyMat);
  exhaustL.name = 'exhaustL';
  exhaustL.position.set(0.38, 0.3, -2.2);
  exhaustL.rotation.set(deg(90), 0, 0);
  body.add(exhaustL);
  const headlightR = new THREE.Mesh(boxGeo5, headlightMat);
  headlightR.name = 'headlightR';
  headlightR.position.set(-0.62, 0.5837, 2.126);
  headlightR.rotation.set(deg(-148.1726), 0, 0);
  body.add(headlightR);
  const sideIntakeR = new THREE.Mesh(boxGeo6, trimMat);
  sideIntakeR.name = 'sideIntakeR';
  sideIntakeR.position.set(-0.964, 0.62, -0.7);
  body.add(sideIntakeR);
  const box24 = new THREE.Mesh(boxGeo7, trimMat);
  box24.position.set(-0.963, 0.58, 0.7);
  body.add(box24);
  const mirrorR = new THREE.Mesh(boxGeo8, paintMat);
  mirrorR.name = 'mirrorR';
  mirrorR.position.set(-0.77, 0.92, 0.64);
  body.add(mirrorR);
  const exhaustR = new THREE.Mesh(cylinderGeo, alloyMat);
  exhaustR.name = 'exhaustR';
  exhaustR.position.set(-0.38, 0.3, -2.2);
  exhaustR.rotation.set(deg(90), 0, 0);
  body.add(exhaustR);
  const taillightBar = new THREE.Mesh(new THREE.BoxGeometry(1.62, 0.07, 0.04), taillightMat);
  taillightBar.name = 'taillightBar';
  taillightBar.position.set(0, 0.8, -2.248);
  body.add(taillightBar);
  const frontIntake = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.09, 0.04), trimMat);
  frontIntake.name = 'frontIntake';
  frontIntake.position.set(0, 0.34, 2.26);
  body.add(frontIntake);
  const splitter = new THREE.Mesh(new THREE.BoxGeometry(1.94, 0.04, 0.3), trimMat);
  splitter.name = 'splitter';
  splitter.position.set(0, 0.2, 2.12);
  body.add(splitter);
  const diffuser = new THREE.Mesh(new THREE.BoxGeometry(1.5, 0.14, 0.3), trimMat);
  diffuser.name = 'diffuser';
  diffuser.position.set(0, 0.27, -2.08);
  body.add(diffuser);
  const spoiler = new THREE.Group();
  spoiler.name = 'spoiler';
  body.add(spoiler);
  const box32 = new THREE.Mesh(boxGeo9, trimMat);
  box32.position.set(-0.62, 1.04, -1.9);
  spoiler.add(box32);
  const box33 = new THREE.Mesh(boxGeo9, trimMat);
  box33.position.set(0.62, 1.04, -1.9);
  spoiler.add(box33);
  const wing = new THREE.Mesh(extrude([[0.2, 0], [0.16, 0.05], [-0.2, 0.06], [-0.24, 0.02]], 1.8), paintMat);
  wing.name = 'wing';
  wing.position.set(0, 1.14, -1.92);
  wing.rotation.set(0, deg(-90), 0);
  spoiler.add(wing);
  const box35 = new THREE.Mesh(boxGeo10, trimMat);
  box35.position.set(-0.92, 1.15, -1.94);
  spoiler.add(box35);
  const box36 = new THREE.Mesh(boxGeo10, trimMat);
  box36.position.set(0.92, 1.15, -1.94);
  spoiler.add(box36);
  const wheels = new THREE.Group();
  wheels.name = 'wheels';
  root.add(wheels);
  const wheelFL = new THREE.Group();
  wheelFL.name = 'wheelFL';
  wheelFL.position.set(0.79, 0.33, 1.4);
  wheels.add(wheelFL);
  const tire = new THREE.Mesh(latheGeo, trimMat);
  tire.name = 'tire';
  tire.rotation.set(0, 0, deg(90));
  wheelFL.add(tire);
  const rim = new THREE.Mesh(cylinderGeo2, trimMat);
  rim.name = 'rim';
  rim.rotation.set(0, 0, deg(90));
  wheelFL.add(rim);
  const spoke1 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke1.name = 'spoke1';
  spoke1.position.set(0.112, -0.0335, 0.1033);
  spoke1.rotation.set(deg(18), 0, 0);
  wheelFL.add(spoke1);
  const spoke2 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke2.name = 'spoke2';
  spoke2.position.set(0.112, -0.1086, 0);
  spoke2.rotation.set(deg(90), 0, 0);
  wheelFL.add(spoke2);
  const spoke3 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke3.name = 'spoke3';
  spoke3.position.set(0.112, -0.0335, -0.1033);
  spoke3.rotation.set(deg(162), 0, 0);
  wheelFL.add(spoke3);
  const spoke4 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke4.name = 'spoke4';
  spoke4.position.set(0.112, 0.0878, -0.0638);
  spoke4.rotation.set(deg(234), 0, 0);
  wheelFL.add(spoke4);
  const spoke5 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke5.name = 'spoke5';
  spoke5.position.set(0.112, 0.0878, 0.0638);
  spoke5.rotation.set(deg(306), 0, 0);
  wheelFL.add(spoke5);
  const centerCap = new THREE.Mesh(cylinderGeo3, alloyMat);
  centerCap.name = 'centerCap';
  centerCap.position.set(0.12, 0, 0);
  centerCap.rotation.set(0, 0, deg(-90));
  wheelFL.add(centerCap);
  const wheelFR = new THREE.Group();
  wheelFR.name = 'wheelFR';
  wheelFR.position.set(-0.79, 0.33, 1.4);
  wheels.add(wheelFR);
  const tire2 = new THREE.Mesh(latheGeo, trimMat);
  tire2.name = 'tire';
  tire2.rotation.set(0, 0, deg(90));
  wheelFR.add(tire2);
  const rim2 = new THREE.Mesh(cylinderGeo2, trimMat);
  rim2.name = 'rim';
  rim2.rotation.set(0, 0, deg(90));
  wheelFR.add(rim2);
  const spoke12 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke12.name = 'spoke1';
  spoke12.position.set(-0.112, -0.0335, 0.1033);
  spoke12.rotation.set(deg(18), 0, 0);
  wheelFR.add(spoke12);
  const spoke22 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke22.name = 'spoke2';
  spoke22.position.set(-0.112, -0.1086, 0);
  spoke22.rotation.set(deg(90), 0, 0);
  wheelFR.add(spoke22);
  const spoke32 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke32.name = 'spoke3';
  spoke32.position.set(-0.112, -0.0335, -0.1033);
  spoke32.rotation.set(deg(162), 0, 0);
  wheelFR.add(spoke32);
  const spoke42 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke42.name = 'spoke4';
  spoke42.position.set(-0.112, 0.0878, -0.0638);
  spoke42.rotation.set(deg(234), 0, 0);
  wheelFR.add(spoke42);
  const spoke52 = new THREE.Mesh(boxGeo11, alloyMat);
  spoke52.name = 'spoke5';
  spoke52.position.set(-0.112, 0.0878, 0.0638);
  spoke52.rotation.set(deg(306), 0, 0);
  wheelFR.add(spoke52);
  const centerCap2 = new THREE.Mesh(cylinderGeo3, alloyMat);
  centerCap2.name = 'centerCap';
  centerCap2.position.set(-0.12, 0, 0);
  centerCap2.rotation.set(0, 0, deg(90));
  wheelFR.add(centerCap2);
  const wheelRL = new THREE.Group();
  wheelRL.name = 'wheelRL';
  wheelRL.position.set(0.8, 0.355, -1.36);
  wheels.add(wheelRL);
  const tire3 = new THREE.Mesh(latheGeo2, trimMat);
  tire3.name = 'tire';
  tire3.rotation.set(0, 0, deg(90));
  wheelRL.add(tire3);
  const rim3 = new THREE.Mesh(cylinderGeo4, trimMat);
  rim3.name = 'rim';
  rim3.rotation.set(0, 0, deg(90));
  wheelRL.add(rim3);
  const spoke13 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke13.name = 'spoke1';
  spoke13.position.set(0.132, -0.0361, 0.1111);
  spoke13.rotation.set(deg(18), 0, 0);
  wheelRL.add(spoke13);
  const spoke23 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke23.name = 'spoke2';
  spoke23.position.set(0.132, -0.1168, 0);
  spoke23.rotation.set(deg(90), 0, 0);
  wheelRL.add(spoke23);
  const spoke33 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke33.name = 'spoke3';
  spoke33.position.set(0.132, -0.0361, -0.1111);
  spoke33.rotation.set(deg(162), 0, 0);
  wheelRL.add(spoke33);
  const spoke43 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke43.name = 'spoke4';
  spoke43.position.set(0.132, 0.0945, -0.0687);
  spoke43.rotation.set(deg(234), 0, 0);
  wheelRL.add(spoke43);
  const spoke53 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke53.name = 'spoke5';
  spoke53.position.set(0.132, 0.0945, 0.0687);
  spoke53.rotation.set(deg(306), 0, 0);
  wheelRL.add(spoke53);
  const centerCap3 = new THREE.Mesh(cylinderGeo5, alloyMat);
  centerCap3.name = 'centerCap';
  centerCap3.position.set(0.14, 0, 0);
  centerCap3.rotation.set(0, 0, deg(-90));
  wheelRL.add(centerCap3);
  const wheelRR = new THREE.Group();
  wheelRR.name = 'wheelRR';
  wheelRR.position.set(-0.8, 0.355, -1.36);
  wheels.add(wheelRR);
  const tire4 = new THREE.Mesh(latheGeo2, trimMat);
  tire4.name = 'tire';
  tire4.rotation.set(0, 0, deg(90));
  wheelRR.add(tire4);
  const rim4 = new THREE.Mesh(cylinderGeo4, trimMat);
  rim4.name = 'rim';
  rim4.rotation.set(0, 0, deg(90));
  wheelRR.add(rim4);
  const spoke14 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke14.name = 'spoke1';
  spoke14.position.set(-0.132, -0.0361, 0.1111);
  spoke14.rotation.set(deg(18), 0, 0);
  wheelRR.add(spoke14);
  const spoke24 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke24.name = 'spoke2';
  spoke24.position.set(-0.132, -0.1168, 0);
  spoke24.rotation.set(deg(90), 0, 0);
  wheelRR.add(spoke24);
  const spoke34 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke34.name = 'spoke3';
  spoke34.position.set(-0.132, -0.0361, -0.1111);
  spoke34.rotation.set(deg(162), 0, 0);
  wheelRR.add(spoke34);
  const spoke44 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke44.name = 'spoke4';
  spoke44.position.set(-0.132, 0.0945, -0.0687);
  spoke44.rotation.set(deg(234), 0, 0);
  wheelRR.add(spoke44);
  const spoke54 = new THREE.Mesh(boxGeo12, alloyMat);
  spoke54.name = 'spoke5';
  spoke54.position.set(-0.132, 0.0945, 0.0687);
  spoke54.rotation.set(deg(306), 0, 0);
  wheelRR.add(spoke54);
  const centerCap4 = new THREE.Mesh(cylinderGeo5, alloyMat);
  centerCap4.name = 'centerCap';
  centerCap4.position.set(-0.14, 0, 0);
  centerCap4.rotation.set(0, 0, deg(90));
  wheelRR.add(centerCap4);

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

export default createSportsCar;

Notes et commentaires

—
Aucune note pour l’instant — soyez le premier.
5
0
4
0
3
0
2
0
1
0

Connectez-vous pour noter et commenter.

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