Codels
528 tris2,70 × 0,06 × 0,44 m
Módulo ES autocontido — depende apenas do three. Chame a factory e adicione o grupo à sua cena.
/**
 * Speed Bump — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 528 · Size (W × H × D): 2.70 × 0.06 × 0.44 m
 *
 * Usage:
 *   import { createSpeedBump } from './speed-bump.js';
 *   
 *   const model = createSpeedBump();
 *   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 createSpeedBump() {
  const root = new THREE.Group();
  root.name = 'SpeedBump';

  // Materials
  const yellowMat = new THREE.MeshStandardMaterial({ name: 'yellow', color: 0xf0c01c, roughness: 0.75, flatShading: true });
  const blackMat = new THREE.MeshStandardMaterial({ name: 'black', color: 0x26282b, roughness: 0.9, flatShading: true });
  const boltMat = new THREE.MeshStandardMaterial({ name: 'bolt', color: 0x8b9096, roughness: 0.4, metalness: 0.7, flatShading: true });
  const eyeMat = new THREE.MeshStandardMaterial({ name: 'eye', color: 0xf4f1e6, roughness: 0.2, metalness: 0.3, emissive: 0xfff4d6, emissiveIntensity: 0.6, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[-0.22, 0], [-0.165, 0.027], [-0.088, 0.0528], [0, 0.06], [0.088, 0.0528], [0.165, 0.027], [0.22, 0]], 0.446);
  const cylinderGeo = new THREE.CylinderGeometry(0.014, 0.016, 0.008, 6);
  const boxGeo = new THREE.BoxGeometry(0.09, 0.012, 0.03);

  // Parts
  const segment = new THREE.Mesh(extrudeGeo, yellowMat);
  segment.name = 'segment';
  segment.position.set(-0.904, 0, 0);
  segment.rotation.set(0, deg(90), 0);
  root.add(segment);
  const bolt = new THREE.Mesh(cylinderGeo, boltMat);
  bolt.name = 'bolt';
  bolt.position.set(-1.017, 0.06, 0);
  root.add(bolt);
  const bolt2 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt2.name = 'bolt';
  bolt2.position.set(-0.791, 0.06, 0);
  root.add(bolt2);
  const catEye = new THREE.Mesh(boxGeo, eyeMat);
  catEye.name = 'catEye';
  catEye.position.set(-0.904, 0.0439, -0.1265);
  catEye.rotation.set(deg(-18.5242), 0, 0);
  root.add(catEye);
  const catEye2 = new THREE.Mesh(boxGeo, eyeMat);
  catEye2.name = 'catEye';
  catEye2.position.set(-0.904, 0.0439, 0.1265);
  catEye2.rotation.set(deg(18.5242), 0, 0);
  root.add(catEye2);
  const segment2 = new THREE.Mesh(extrudeGeo, blackMat);
  segment2.name = 'segment';
  segment2.position.set(-0.452, 0, 0);
  segment2.rotation.set(0, deg(90), 0);
  root.add(segment2);
  const bolt3 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt3.name = 'bolt';
  bolt3.position.set(-0.565, 0.06, 0);
  root.add(bolt3);
  const bolt4 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt4.name = 'bolt';
  bolt4.position.set(-0.339, 0.06, 0);
  root.add(bolt4);
  const segment3 = new THREE.Mesh(extrudeGeo, yellowMat);
  segment3.name = 'segment';
  segment3.rotation.set(0, deg(90), 0);
  root.add(segment3);
  const bolt5 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt5.name = 'bolt';
  bolt5.position.set(-0.113, 0.06, 0);
  root.add(bolt5);
  const bolt6 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt6.name = 'bolt';
  bolt6.position.set(0.113, 0.06, 0);
  root.add(bolt6);
  const catEye3 = new THREE.Mesh(boxGeo, eyeMat);
  catEye3.name = 'catEye';
  catEye3.position.set(0, 0.0439, -0.1265);
  catEye3.rotation.set(deg(-18.5242), 0, 0);
  root.add(catEye3);
  const catEye4 = new THREE.Mesh(boxGeo, eyeMat);
  catEye4.name = 'catEye';
  catEye4.position.set(0, 0.0439, 0.1265);
  catEye4.rotation.set(deg(18.5242), 0, 0);
  root.add(catEye4);
  const segment4 = new THREE.Mesh(extrudeGeo, blackMat);
  segment4.name = 'segment';
  segment4.position.set(0.452, 0, 0);
  segment4.rotation.set(0, deg(90), 0);
  root.add(segment4);
  const bolt7 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt7.name = 'bolt';
  bolt7.position.set(0.339, 0.06, 0);
  root.add(bolt7);
  const bolt8 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt8.name = 'bolt';
  bolt8.position.set(0.565, 0.06, 0);
  root.add(bolt8);
  const segment5 = new THREE.Mesh(extrudeGeo, yellowMat);
  segment5.name = 'segment';
  segment5.position.set(0.904, 0, 0);
  segment5.rotation.set(0, deg(90), 0);
  root.add(segment5);
  const bolt9 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt9.name = 'bolt';
  bolt9.position.set(0.791, 0.06, 0);
  root.add(bolt9);
  const bolt10 = new THREE.Mesh(cylinderGeo, boltMat);
  bolt10.name = 'bolt';
  bolt10.position.set(1.017, 0.06, 0);
  root.add(bolt10);
  const catEye5 = new THREE.Mesh(boxGeo, eyeMat);
  catEye5.name = 'catEye';
  catEye5.position.set(0.904, 0.0439, -0.1265);
  catEye5.rotation.set(deg(-18.5242), 0, 0);
  root.add(catEye5);
  const catEye6 = new THREE.Mesh(boxGeo, eyeMat);
  catEye6.name = 'catEye';
  catEye6.position.set(0.904, 0.0439, 0.1265);
  catEye6.rotation.set(deg(18.5242), 0, 0);
  root.add(catEye6);
  const endCap = new THREE.Mesh(lathe([[0.22, 0], [0.165, 0.027], [0.088, 0.0528], [0, 0.06]], 8, 0, Math.PI), yellowMat);
  endCap.name = 'endCap';
  endCap.position.set(1.13, 0, 0);
  root.add(endCap);
  const endCap2 = new THREE.Mesh(lathe([[0.22, 0], [0.165, 0.027], [0.088, 0.0528], [0, 0.06]], 8, Math.PI, Math.PI), yellowMat);
  endCap2.name = 'endCap';
  endCap2.position.set(-1.13, 0, 0);
  root.add(endCap2);

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

export default createSpeedBump;

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