Codels
1,4 mil tris1,03 × 2,04 × 1,03 m
Módulo ES autocontido — depende apenas do three. Chame a factory e adicione o grupo à sua cena.
/**
 * 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;

Avaliações e comentários

—
Nenhuma avaliação ainda — seja o primeiro.
5
0
4
0
3
0
2
0
1
0

Entre para avaliar e comentar.

0 comentário

Nenhum comentário ainda. Conte como você usou este modelo ou o que poderia melhorar.

Modelos relacionados

Mesma categoria ou tags parecidas