2108 三角面1.86 × 1.44 × 4.46 m
在代码中使用
在编辑器中改编sedan.js · 290 行
自包含的 ES 模块,仅依赖 three。调用工厂函数,然后把返回的 group 添加到场景中。
/**
* Sedan — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 2,108 · Size (W × H × D): 1.86 × 1.44 × 4.46 m
*
* Usage:
* import { createSedan } from './sedan.js';
*
* const model = createSedan();
* 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 createSedan() {
const root = new THREE.Group();
root.name = 'Sedan';
// Materials
const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0x3f78c0, roughness: 0.42, metalness: 0.15, flatShading: true });
const glassMat = new THREE.MeshStandardMaterial({ name: 'glass', color: 0x2a3644, roughness: 0.2, metalness: 0.3, flatShading: true });
const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0x2a2c31, roughness: 0.8, flatShading: true });
const chromeMat = new THREE.MeshStandardMaterial({ name: 'chrome', color: 0xc9cdd3, roughness: 0.3, metalness: 0.65, 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.8004, 0.99], [0.3225, 1.33], [-0.12, 1.33], [-0.12, 0.99]], 0.02);
const extrudeGeo2 = extrude([[-0.22, 0.99], [-0.22, 1.33], [-0.6526, 1.33], [-0.9852, 0.99]], 0.02);
const boxGeo = new THREE.BoxGeometry(0.36, 0.12, 0.06);
const boxGeo2 = new THREE.BoxGeometry(0.34, 0.11, 0.06);
const boxGeo3 = new THREE.BoxGeometry(0.13, 0.09, 0.13);
const boxGeo4 = new THREE.BoxGeometry(0.006, 0.52, 0.014);
const boxGeo5 = new THREE.BoxGeometry(0.02, 0.03, 0.13);
const boxGeo6 = new THREE.BoxGeometry(0.05, 0.1, 1.7);
const boxGeo7 = new THREE.BoxGeometry(1.86, 0.16, 0.24);
const boxGeo8 = new THREE.BoxGeometry(0.36, 0.11, 0.02);
const latheGeo = lathe([[0.2139, -0.095], [0.2139, -0.12], [0.3, -0.12], [0.345, -0.07], [0.345, 0.07], [0.3, 0.12], [0.2139, 0.12], [0.2139, 0.095]], 14);
const cylinderGeo = new THREE.CylinderGeometry(0.2139, 0.2139, 0.19, 14);
const cylinderGeo2 = new THREE.CylinderGeometry(0.1754, 0.2096, 0.03, 14);
const cylinderGeo3 = new THREE.CylinderGeometry(0.0535, 0.0684, 0.03, 8);
// Parts
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const lowerBody = new THREE.Mesh(extrude([[2.02, 0.24], [2.11, 0.34], [2.12, 0.62], [2, 0.79], [1.5, 0.88], [1, 0.93], [-1.05, 0.935], [-1.88, 0.945], [-2.1, 0.88], [-2.12, 0.44], [-2.02, 0.24], [-1.7773, 0.24], [-1.7802, 0.4376], [-1.6963, 0.6165], [-1.5425, 0.7406], [-1.35, 0.785], [-1.1575, 0.7406], [-1.0037, 0.6165], [-0.9198, 0.4376], [-0.9227, 0.24], [0.9227, 0.24], [0.9198, 0.4376], [1.0037, 0.6165], [1.1575, 0.7406], [1.35, 0.785], [1.5425, 0.7406], [1.6963, 0.6165], [1.7802, 0.4376], [1.7773, 0.24]], 1.73, [], [0.035, 0.035, 2]), paintMat);
lowerBody.name = 'lowerBody';
lowerBody.rotation.set(0, deg(-90), 0);
body.add(lowerBody);
const chassis = new THREE.Mesh(new THREE.BoxGeometry(1.24, 0.5, 3.9), trimMat);
chassis.name = 'chassis';
chassis.position.set(0, 0.55, 0);
body.add(chassis);
const cabin = new THREE.Mesh(extrude([[1.12, 0.84], [0.3, 1.4], [-0.66, 1.4], [-1.22, 0.86]], 1.42, [], [0.05, 0.05, 2]), paintMat);
cabin.name = 'cabin';
cabin.rotation.set(0, deg(-90), 0);
body.add(cabin);
const windowFL = new THREE.Mesh(extrudeGeo, glassMat);
windowFL.name = 'windowFL';
windowFL.position.set(0.765, 0, 0);
windowFL.rotation.set(0, deg(-90), 0);
body.add(windowFL);
const windowRL = new THREE.Mesh(extrudeGeo2, glassMat);
windowRL.name = 'windowRL';
windowRL.position.set(0.765, 0, 0);
windowRL.rotation.set(0, deg(-90), 0);
body.add(windowRL);
const windowFR = new THREE.Mesh(extrudeGeo, glassMat);
windowFR.name = 'windowFR';
windowFR.position.set(-0.765, 0, 0);
windowFR.rotation.set(0, deg(-90), 0);
body.add(windowFR);
const windowRR = new THREE.Mesh(extrudeGeo2, glassMat);
windowRR.name = 'windowRR';
windowRR.position.set(-0.765, 0, 0);
windowRR.rotation.set(0, deg(-90), 0);
body.add(windowRR);
const windshield = new THREE.Mesh(new THREE.BoxGeometry(1.3, 0.02, 0.6206), glassMat);
windshield.name = 'windshield';
windshield.position.set(0, 1.2079, 0.6948);
windshield.rotation.set(deg(-145.6698), 0, 0);
body.add(windshield);
const rearWindow = new THREE.Mesh(new THREE.BoxGeometry(1.3, 0.02, 0.4898), glassMat);
rearWindow.name = 'rearWindow';
rearWindow.position.set(0, 1.2161, -0.9429);
rearWindow.rotation.set(deg(136.0416), 0, 0);
body.add(rearWindow);
const headlightL = new THREE.Mesh(boxGeo, headlightMat);
headlightL.name = 'headlightL';
headlightL.position.set(0.57, 0.6, 2.155);
body.add(headlightL);
const taillightL = new THREE.Mesh(boxGeo2, taillightMat);
taillightL.name = 'taillightL';
taillightL.position.set(0.58, 0.74, -2.155);
body.add(taillightL);
const mirrorL = new THREE.Mesh(boxGeo3, paintMat);
mirrorL.name = 'mirrorL';
mirrorL.position.set(0.83, 1.03, 0.76);
body.add(mirrorL);
const box14 = new THREE.Mesh(boxGeo4, trimMat);
box14.position.set(0.903, 0.6, 0.86);
body.add(box14);
const box15 = new THREE.Mesh(boxGeo4, trimMat);
box15.position.set(0.903, 0.6, -0.12);
body.add(box15);
const box16 = new THREE.Mesh(boxGeo4, trimMat);
box16.position.set(0.903, 0.6, -0.88);
body.add(box16);
const box17 = new THREE.Mesh(boxGeo5, trimMat);
box17.position.set(0.91, 0.8, 0.36);
body.add(box17);
const box18 = new THREE.Mesh(boxGeo5, trimMat);
box18.position.set(0.91, 0.8, -0.56);
body.add(box18);
const skirtL = new THREE.Mesh(boxGeo6, trimMat);
skirtL.name = 'skirtL';
skirtL.position.set(0.89, 0.26, 0);
body.add(skirtL);
const headlightR = new THREE.Mesh(boxGeo, headlightMat);
headlightR.name = 'headlightR';
headlightR.position.set(-0.57, 0.6, 2.155);
body.add(headlightR);
const taillightR = new THREE.Mesh(boxGeo2, taillightMat);
taillightR.name = 'taillightR';
taillightR.position.set(-0.58, 0.74, -2.155);
body.add(taillightR);
const mirrorR = new THREE.Mesh(boxGeo3, paintMat);
mirrorR.name = 'mirrorR';
mirrorR.position.set(-0.83, 1.03, 0.76);
body.add(mirrorR);
const box23 = new THREE.Mesh(boxGeo4, trimMat);
box23.position.set(-0.903, 0.6, 0.86);
body.add(box23);
const box24 = new THREE.Mesh(boxGeo4, trimMat);
box24.position.set(-0.903, 0.6, -0.12);
body.add(box24);
const box25 = new THREE.Mesh(boxGeo4, trimMat);
box25.position.set(-0.903, 0.6, -0.88);
body.add(box25);
const box26 = new THREE.Mesh(boxGeo5, trimMat);
box26.position.set(-0.91, 0.8, 0.36);
body.add(box26);
const box27 = new THREE.Mesh(boxGeo5, trimMat);
box27.position.set(-0.91, 0.8, -0.56);
body.add(box27);
const skirtR = new THREE.Mesh(boxGeo6, trimMat);
skirtR.name = 'skirtR';
skirtR.position.set(-0.89, 0.26, 0);
body.add(skirtR);
const grille = new THREE.Mesh(new THREE.BoxGeometry(0.72, 0.13, 0.04), trimMat);
grille.name = 'grille';
grille.position.set(0, 0.58, 2.16);
body.add(grille);
const bumperFront = new THREE.Mesh(boxGeo7, trimMat);
bumperFront.name = 'bumperFront';
bumperFront.position.set(0, 0.33, 2.1);
body.add(bumperFront);
const bumperRear = new THREE.Mesh(boxGeo7, trimMat);
bumperRear.name = 'bumperRear';
bumperRear.position.set(0, 0.34, -2.1);
body.add(bumperRear);
const plateFront = new THREE.Mesh(boxGeo8, chromeMat);
plateFront.name = 'plateFront';
plateFront.position.set(0, 0.34, 2.23);
body.add(plateFront);
const plateRear = new THREE.Mesh(boxGeo8, chromeMat);
plateRear.name = 'plateRear';
plateRear.position.set(0, 0.5, -2.167);
body.add(plateRear);
const wheels = new THREE.Group();
wheels.name = 'wheels';
root.add(wheels);
const wheelFL = new THREE.Group();
wheelFL.name = 'wheelFL';
wheelFL.position.set(0.765, 0.345, 1.35);
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(cylinderGeo, chromeMat);
rim.name = 'rim';
rim.rotation.set(0, 0, deg(90));
wheelFL.add(rim);
const hubcap = new THREE.Mesh(cylinderGeo2, chromeMat);
hubcap.name = 'hubcap';
hubcap.position.set(0.11, 0, 0);
hubcap.rotation.set(0, 0, deg(-90));
wheelFL.add(hubcap);
const centerCap = new THREE.Mesh(cylinderGeo3, trimMat);
centerCap.name = 'centerCap';
centerCap.position.set(0.135, 0, 0);
centerCap.rotation.set(0, 0, deg(-90));
wheelFL.add(centerCap);
const wheelFR = new THREE.Group();
wheelFR.name = 'wheelFR';
wheelFR.position.set(-0.765, 0.345, 1.35);
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(cylinderGeo, chromeMat);
rim2.name = 'rim';
rim2.rotation.set(0, 0, deg(90));
wheelFR.add(rim2);
const hubcap2 = new THREE.Mesh(cylinderGeo2, chromeMat);
hubcap2.name = 'hubcap';
hubcap2.position.set(-0.11, 0, 0);
hubcap2.rotation.set(0, 0, deg(90));
wheelFR.add(hubcap2);
const centerCap2 = new THREE.Mesh(cylinderGeo3, trimMat);
centerCap2.name = 'centerCap';
centerCap2.position.set(-0.135, 0, 0);
centerCap2.rotation.set(0, 0, deg(90));
wheelFR.add(centerCap2);
const wheelRL = new THREE.Group();
wheelRL.name = 'wheelRL';
wheelRL.position.set(0.765, 0.345, -1.35);
wheels.add(wheelRL);
const tire3 = new THREE.Mesh(latheGeo, trimMat);
tire3.name = 'tire';
tire3.rotation.set(0, 0, deg(90));
wheelRL.add(tire3);
const rim3 = new THREE.Mesh(cylinderGeo, chromeMat);
rim3.name = 'rim';
rim3.rotation.set(0, 0, deg(90));
wheelRL.add(rim3);
const hubcap3 = new THREE.Mesh(cylinderGeo2, chromeMat);
hubcap3.name = 'hubcap';
hubcap3.position.set(0.11, 0, 0);
hubcap3.rotation.set(0, 0, deg(-90));
wheelRL.add(hubcap3);
const centerCap3 = new THREE.Mesh(cylinderGeo3, trimMat);
centerCap3.name = 'centerCap';
centerCap3.position.set(0.135, 0, 0);
centerCap3.rotation.set(0, 0, deg(-90));
wheelRL.add(centerCap3);
const wheelRR = new THREE.Group();
wheelRR.name = 'wheelRR';
wheelRR.position.set(-0.765, 0.345, -1.35);
wheels.add(wheelRR);
const tire4 = new THREE.Mesh(latheGeo, trimMat);
tire4.name = 'tire';
tire4.rotation.set(0, 0, deg(90));
wheelRR.add(tire4);
const rim4 = new THREE.Mesh(cylinderGeo, chromeMat);
rim4.name = 'rim';
rim4.rotation.set(0, 0, deg(90));
wheelRR.add(rim4);
const hubcap4 = new THREE.Mesh(cylinderGeo2, chromeMat);
hubcap4.name = 'hubcap';
hubcap4.position.set(-0.11, 0, 0);
hubcap4.rotation.set(0, 0, deg(90));
wheelRR.add(hubcap4);
const centerCap4 = new THREE.Mesh(cylinderGeo3, trimMat);
centerCap4.name = 'centerCap';
centerCap4.position.set(-0.135, 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 createSedan;
评分与评论
0 条评论
暂无评论。分享一下你是如何使用这个模型的,或者有哪些可以改进的地方。
相关模型
同一分类或相似标签









