1376 三角面1.03 × 2.04 × 1.03 m
在代码中使用
在编辑器中改编fire-trap.js · 335 行
自包含的 ES 模块,仅依赖 three。调用工厂函数,然后把返回的 group 添加到场景中。
/**
* Fire Trap — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,376 · Size (W × H × D): 1.03 × 2.04 × 1.03 m
*
* Usage:
* import { createFireTrap } from './fire-trap.js';
*
* const model = createFireTrap();
* model.position.set(0, 0, 0);
* scene.add(model);
*/
import * as THREE from 'three';
const deg = THREE.MathUtils.degToRad;
// Deterministic vertex displacement (organic low-poly look).
function jitter(geometry, amount, seed) {
const pos = geometry.attributes.position;
const h = (a, b, c, s) => {
let x = Math.imul(a, 73856093) ^ Math.imul(b, 19349663) ^ Math.imul(c, 83492791) ^ Math.imul(s, 2654435761);
x = Math.imul(x ^ (x >>> 16), 2246822507);
x = Math.imul(x ^ (x >>> 13), 3266489909);
return ((x ^ (x >>> 16)) >>> 0) / 4294967295 - 0.5;
};
for (let i = 0; i < pos.count; i++) {
const x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i);
const qx = Math.round(x * 1000), qy = Math.round(y * 1000), qz = Math.round(z * 1000);
pos.setXYZ(i, x + h(qx, qy, qz, seed) * 2 * amount, y + h(qx, qy, qz, seed + 1) * 2 * amount, z + h(qx, qy, qz, seed + 2) * 2 * amount);
}
pos.needsUpdate = true;
geometry.computeVertexNormals();
return geometry;
}
// 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 createFireTrap() {
const root = new THREE.Group();
root.name = 'FireTrap';
// Materials
const plateMat = new THREE.MeshStandardMaterial({ name: 'plate', color: 0x3a4252, roughness: 0.6, metalness: 0.35, flatShading: true });
const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x1c1f26, roughness: 0.8, metalness: 0.2, flatShading: true });
const hazardMat = new THREE.MeshStandardMaterial({ name: 'hazard', color: 0xf5c02a, roughness: 0.55, flatShading: true });
const stripeMat = new THREE.MeshStandardMaterial({ name: 'stripe', color: 0x1d1f25, roughness: 0.7, flatShading: true });
const steelMat = new THREE.MeshStandardMaterial({ name: 'steel', color: 0xaeb6c2, roughness: 0.3, metalness: 0.75, flatShading: true });
const ventMat = new THREE.MeshStandardMaterial({ name: 'vent', color: 0xff5a12, roughness: 0.6, emissive: 0xff5a12, emissiveIntensity: 0.9, flatShading: true });
const outerMat = new THREE.MeshStandardMaterial({ name: 'outer', color: 0xf54b14, roughness: 0.6, emissive: 0xf54b14, emissiveIntensity: 0.9, flatShading: true });
const midMat = new THREE.MeshStandardMaterial({ name: 'mid', color: 0xff6a1a, roughness: 0.5, emissive: 0xff6a1a, flatShading: true });
const coreMat = new THREE.MeshStandardMaterial({ name: 'core', color: 0xffd38b, roughness: 0.4, emissive: 0xffc161, emissiveIntensity: 1.1, flatShading: true });
// Shared geometries
const extrudeGeo = extrude([[-0.51, 0.025], [-0.51, -0.025], [-0.49, -0.025], [-0.44, 0.025]], 0.006);
const extrudeGeo2 = extrude([[-0.42, -0.025], [-0.35, -0.025], [-0.3, 0.025], [-0.37, 0.025]], 0.006);
const extrudeGeo3 = extrude([[-0.28, -0.025], [-0.21, -0.025], [-0.16, 0.025], [-0.23, 0.025]], 0.006);
const extrudeGeo4 = extrude([[-0.14, -0.025], [-0.07, -0.025], [-0.02, 0.025], [-0.09, 0.025]], 0.006);
const extrudeGeo5 = extrude([[0, -0.025], [0.07, -0.025], [0.12, 0.025], [0.05, 0.025]], 0.006);
const extrudeGeo6 = extrude([[0.14, -0.025], [0.21, -0.025], [0.26, 0.025], [0.19, 0.025]], 0.006);
const extrudeGeo7 = extrude([[0.28, -0.025], [0.35, -0.025], [0.4, 0.025], [0.33, 0.025]], 0.006);
const extrudeGeo8 = extrude([[0.42, -0.025], [0.49, -0.025], [0.51, -0.005], [0.51, 0.025], [0.47, 0.025]], 0.006);
const boxGeo = new THREE.BoxGeometry(1, 0.035, 0.09);
const boxGeo2 = new THREE.BoxGeometry(0.09, 0.035, 0.82);
const cylinderGeo = new THREE.CylinderGeometry(0.025, 0.025, 0.02, 6);
const boxGeo3 = new THREE.BoxGeometry(0.82, 0.03, 0.045);
// Parts
const band = new THREE.Mesh(new THREE.BoxGeometry(1.02, 0.05, 1.02), hazardMat);
band.name = 'band';
band.position.set(0, 0.025, 0);
root.add(band);
const stripesFront = new THREE.Group();
stripesFront.name = 'stripesFront';
stripesFront.position.set(0, 0.025, 0.51);
root.add(stripesFront);
const extrude3 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude3.position.set(0, 0, 0.003);
stripesFront.add(extrude3);
const extrude4 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude4.position.set(0, 0, 0.003);
stripesFront.add(extrude4);
const extrude5 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude5.position.set(0, 0, 0.003);
stripesFront.add(extrude5);
const extrude6 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude6.position.set(0, 0, 0.003);
stripesFront.add(extrude6);
const extrude7 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude7.position.set(0, 0, 0.003);
stripesFront.add(extrude7);
const extrude8 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude8.position.set(0, 0, 0.003);
stripesFront.add(extrude8);
const extrude9 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude9.position.set(0, 0, 0.003);
stripesFront.add(extrude9);
const extrude10 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude10.position.set(0, 0, 0.003);
stripesFront.add(extrude10);
const stripesRight = new THREE.Group();
stripesRight.name = 'stripesRight';
stripesRight.position.set(0.51, 0.025, 0);
stripesRight.rotation.set(0, deg(90), 0);
root.add(stripesRight);
const extrude12 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude12.position.set(0, 0, 0.003);
stripesRight.add(extrude12);
const extrude13 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude13.position.set(0, 0, 0.003);
stripesRight.add(extrude13);
const extrude14 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude14.position.set(0, 0, 0.003);
stripesRight.add(extrude14);
const extrude15 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude15.position.set(0, 0, 0.003);
stripesRight.add(extrude15);
const extrude16 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude16.position.set(0, 0, 0.003);
stripesRight.add(extrude16);
const extrude17 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude17.position.set(0, 0, 0.003);
stripesRight.add(extrude17);
const extrude18 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude18.position.set(0, 0, 0.003);
stripesRight.add(extrude18);
const extrude19 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude19.position.set(0, 0, 0.003);
stripesRight.add(extrude19);
const stripesBack = new THREE.Group();
stripesBack.name = 'stripesBack';
stripesBack.position.set(0, 0.025, -0.51);
stripesBack.rotation.set(0, deg(180), 0);
root.add(stripesBack);
const extrude21 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude21.position.set(0, 0, 0.003);
stripesBack.add(extrude21);
const extrude22 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude22.position.set(0, 0, 0.003);
stripesBack.add(extrude22);
const extrude23 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude23.position.set(0, 0, 0.003);
stripesBack.add(extrude23);
const extrude24 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude24.position.set(0, 0, 0.003);
stripesBack.add(extrude24);
const extrude25 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude25.position.set(0, 0, 0.003);
stripesBack.add(extrude25);
const extrude26 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude26.position.set(0, 0, 0.003);
stripesBack.add(extrude26);
const extrude27 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude27.position.set(0, 0, 0.003);
stripesBack.add(extrude27);
const extrude28 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude28.position.set(0, 0, 0.003);
stripesBack.add(extrude28);
const stripesLeft = new THREE.Group();
stripesLeft.name = 'stripesLeft';
stripesLeft.position.set(-0.51, 0.025, 0);
stripesLeft.rotation.set(0, deg(-90), 0);
root.add(stripesLeft);
const extrude30 = new THREE.Mesh(extrudeGeo, stripeMat);
extrude30.position.set(0, 0, 0.003);
stripesLeft.add(extrude30);
const extrude31 = new THREE.Mesh(extrudeGeo2, stripeMat);
extrude31.position.set(0, 0, 0.003);
stripesLeft.add(extrude31);
const extrude32 = new THREE.Mesh(extrudeGeo3, stripeMat);
extrude32.position.set(0, 0, 0.003);
stripesLeft.add(extrude32);
const extrude33 = new THREE.Mesh(extrudeGeo4, stripeMat);
extrude33.position.set(0, 0, 0.003);
stripesLeft.add(extrude33);
const extrude34 = new THREE.Mesh(extrudeGeo5, stripeMat);
extrude34.position.set(0, 0, 0.003);
stripesLeft.add(extrude34);
const extrude35 = new THREE.Mesh(extrudeGeo6, stripeMat);
extrude35.position.set(0, 0, 0.003);
stripesLeft.add(extrude35);
const extrude36 = new THREE.Mesh(extrudeGeo7, stripeMat);
extrude36.position.set(0, 0, 0.003);
stripesLeft.add(extrude36);
const extrude37 = new THREE.Mesh(extrudeGeo8, stripeMat);
extrude37.position.set(0, 0, 0.003);
stripesLeft.add(extrude37);
const plate = new THREE.Mesh(new THREE.BoxGeometry(1, 0.07, 1), plateMat);
plate.name = 'plate';
plate.position.set(0, 0.085, 0);
root.add(plate);
const box39 = new THREE.Mesh(boxGeo, plateMat);
box39.position.set(0, 0.1375, -0.455);
root.add(box39);
const box40 = new THREE.Mesh(boxGeo2, plateMat);
box40.position.set(-0.455, 0.1375, 0);
root.add(box40);
const box41 = new THREE.Mesh(boxGeo, plateMat);
box41.position.set(0, 0.1375, 0.455);
root.add(box41);
const box42 = new THREE.Mesh(boxGeo2, plateMat);
box42.position.set(0.455, 0.1375, 0);
root.add(box42);
const cylinder43 = new THREE.Mesh(cylinderGeo, steelMat);
cylinder43.position.set(-0.455, 0.165, -0.455);
root.add(cylinder43);
const cylinder44 = new THREE.Mesh(cylinderGeo, steelMat);
cylinder44.position.set(0.455, 0.165, -0.455);
root.add(cylinder44);
const cylinder45 = new THREE.Mesh(cylinderGeo, steelMat);
cylinder45.position.set(0.455, 0.165, 0.455);
root.add(cylinder45);
const cylinder46 = new THREE.Mesh(cylinderGeo, steelMat);
cylinder46.position.set(-0.455, 0.165, 0.455);
root.add(cylinder46);
const ventGlow = new THREE.Mesh(new THREE.BoxGeometry(0.82, 0.012, 0.82), ventMat);
ventGlow.name = 'ventGlow';
ventGlow.position.set(0, 0.126, 0);
root.add(ventGlow);
const box48 = new THREE.Mesh(boxGeo3, darkMat);
box48.position.set(0, 0.14, -0.3514);
root.add(box48);
const box49 = new THREE.Mesh(boxGeo3, darkMat);
box49.position.set(0, 0.14, -0.2343);
root.add(box49);
const box50 = new THREE.Mesh(boxGeo3, darkMat);
box50.position.set(0, 0.14, -0.1171);
root.add(box50);
const box51 = new THREE.Mesh(boxGeo3, darkMat);
box51.position.set(0, 0.14, 0);
root.add(box51);
const box52 = new THREE.Mesh(boxGeo3, darkMat);
box52.position.set(0, 0.14, 0.1171);
root.add(box52);
const box53 = new THREE.Mesh(boxGeo3, darkMat);
box53.position.set(0, 0.14, 0.2343);
root.add(box53);
const box54 = new THREE.Mesh(boxGeo3, darkMat);
box54.position.set(0, 0.14, 0.3514);
root.add(box54);
const nozzle1 = new THREE.Mesh(new THREE.CylinderGeometry(0.11, 0.13, 0.07, 10), steelMat);
nozzle1.name = 'nozzle1';
nozzle1.position.set(0, 0.155, 0);
root.add(nozzle1);
const nozzleGlow1 = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.07, 0.012, 10), ventMat);
nozzleGlow1.name = 'nozzleGlow1';
nozzleGlow1.position.set(0, 0.192, 0);
root.add(nozzleGlow1);
const flames = new THREE.Group();
flames.name = 'flames';
root.add(flames);
const flame1 = new THREE.Group();
flame1.name = 'flame1';
flame1.position.set(0, 0.19, 0);
flames.add(flame1);
const lathe59 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.0376], [0.15, 0.1631], [0.1275, 0.3137], [0.0675, 0.4894], [0, 0.6274]], 6), 0.015, 30), outerMat);
lathe59.position.set(0.0597, 0, 0.006);
lathe59.rotation.set(deg(1.1002), deg(-0.1069), deg(-11.104));
flame1.add(lathe59);
const lathe60 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.0429], [0.15, 0.1858], [0.1275, 0.3573], [0.0675, 0.5574], [0, 0.7146]], 6), 0.015, 31), outerMat);
lathe60.position.set(0.0266, 0, 0.0538);
lathe60.rotation.set(deg(6.5614), deg(-0.1857), deg(-3.2381));
flame1.add(lathe60);
const lathe61 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.0473], [0.15, 0.2049], [0.1275, 0.394], [0.0675, 0.6146], [0, 0.7879]], 6), 0.015, 32), outerMat);
lathe61.position.set(-0.0358, 0, 0.0482);
lathe61.rotation.set(deg(7.5459), deg(0.3694), deg(5.5974));
flame1.add(lathe61);
const lathe62 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.045], [0.15, 0.1948], [0.1275, 0.3747], [0.0675, 0.5845], [0, 0.7493]], 6), 0.015, 33), outerMat);
lathe62.position.set(-0.0594, 0, 0.0085);
lathe62.rotation.set(deg(1.5714), deg(0.1525), deg(11.0854));
flame1.add(lathe62);
const lathe63 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.0411], [0.15, 0.1781], [0.1275, 0.3425], [0.0675, 0.5342], [0, 0.6849]], 6), 0.015, 34), outerMat);
lathe63.position.set(-0.0255, 0, -0.0543);
lathe63.rotation.set(deg(-6.2603), deg(-0.1608), deg(2.9391));
flame1.add(lathe63);
const lathe64 = new THREE.Mesh(jitter(lathe([[0, 0], [0.105, 0.0386], [0.15, 0.1673], [0.1275, 0.3217], [0.0675, 0.5019], [0, 0.6434]], 6), 0.015, 35), outerMat);
lathe64.position.set(0.0244, 0, -0.0548);
lathe64.rotation.set(deg(-10.8034), deg(0.4532), deg(-4.7902));
flame1.add(lathe64);
const lathe65 = new THREE.Mesh(jitter(lathe([[0, 0], [0.126, 0.0827], [0.18, 0.3584], [0.153, 0.6892], [0.081, 1.0751], [0, 1.3783]], 6), 0.02, 40), midMat);
lathe65.position.set(0.0306, 0.02, 0.0257);
lathe65.rotation.set(deg(2.2063), deg(-0.0506), deg(-2.6297));
flame1.add(lathe65);
const lathe66 = new THREE.Mesh(jitter(lathe([[0, 0], [0.126, 0.0822], [0.18, 0.3563], [0.153, 0.6852], [0.081, 1.0688], [0, 1.3703]], 6), 0.02, 41), midMat);
lathe66.position.set(-0.0376, 0.02, 0.0137);
lathe66.rotation.set(deg(1.1738), deg(0.0331), deg(3.2263));
flame1.add(lathe66);
const lathe67 = new THREE.Mesh(jitter(lathe([[0, 0], [0.126, 0.0751], [0.18, 0.3255], [0.153, 0.626], [0.081, 0.9765], [0, 1.2519]], 6), 0.02, 42), midMat);
lathe67.position.set(0.0069, 0.02, -0.0394);
lathe67.rotation.set(deg(-3.3814), deg(0.0176), deg(-0.5959));
flame1.add(lathe67);
const core = new THREE.Mesh(jitter(lathe([[0, 0], [0.084, 0.108], [0.12, 0.468], [0.102, 0.9], [0.054, 1.404], [0, 1.8]], 6), 0.015, 50), coreMat);
core.name = 'core';
core.position.set(0, 0.04, 0);
flame1.add(core);
const octahedron69 = new THREE.Mesh(new THREE.OctahedronGeometry(0.0205, 0), midMat);
octahedron69.position.set(0.2294, 1.2354, 0.0275);
octahedron69.rotation.set(deg(11.0936), deg(42.307), 0);
flame1.add(octahedron69);
const octahedron70 = new THREE.Mesh(new THREE.OctahedronGeometry(0.019, 0), coreMat);
octahedron70.position.set(0.1542, 1.7537, -0.0081);
octahedron70.rotation.set(deg(28.5322), deg(36.6806), 0);
flame1.add(octahedron70);
const octahedron71 = new THREE.Mesh(new THREE.OctahedronGeometry(0.0226, 0), midMat);
octahedron71.position.set(0.1574, 1.1855, -0.0141);
octahedron71.rotation.set(deg(78.2302), deg(65.0125), 0);
flame1.add(octahedron71);
const octahedron72 = new THREE.Mesh(new THREE.OctahedronGeometry(0.0277, 0), coreMat);
octahedron72.position.set(0.1387, 1.5742, -0.1322);
octahedron72.rotation.set(deg(12.5667), deg(57.2443), 0);
flame1.add(octahedron72);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createFireTrap;
评分与评论
0 条评论
暂无评论。分享一下你是如何使用这个模型的,或者有哪些可以改进的地方。
相关模型
同一分类或相似标签









