Codels
608 tris0,51 × 0,95 × 0,44 m
Módulo ES autocontido — depende apenas do three. Chame a factory e adicione o grupo à sua cena.
/**
 * Nightstand — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 608 · Size (W × H × D): 0.51 × 0.95 × 0.44 m
 *
 * Usage:
 *   import { createNightstand } from './nightstand.js';
 *   
 *   const model = createNightstand();
 *   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 createNightstand() {
  const root = new THREE.Group();
  root.name = 'Nightstand';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x9a6338, roughness: 0.8, flatShading: true });
  const panelMat = new THREE.MeshStandardMaterial({ name: 'panel', color: 0xa67650, roughness: 0.75, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x593920, roughness: 0.95, flatShading: true });
  const brassMat = new THREE.MeshStandardMaterial({ name: 'brass', color: 0xd4a84e, roughness: 0.35, metalness: 0.5, flatShading: true });
  const ceramicMat = new THREE.MeshStandardMaterial({ name: 'ceramic', color: 0x5f86a3, roughness: 0.35, flatShading: true });
  const shadeMat = new THREE.MeshStandardMaterial({ name: 'shade', color: 0xefdcb4, roughness: 1, emissive: 0xd7c6a2, emissiveIntensity: 0.45, flatShading: true, side: THREE.DoubleSide });
  const bulbMat = new THREE.MeshStandardMaterial({ name: 'bulb', color: 0xfff4d6, roughness: 0.8, emissive: 0xffd27a, emissiveIntensity: 1.2, flatShading: true });
  const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xa3413a, roughness: 0.85, flatShading: true });
  const greenMat = new THREE.MeshStandardMaterial({ name: 'green', color: 0x4b6b4a, roughness: 0.85, flatShading: true });
  const paperMat = new THREE.MeshStandardMaterial({ name: 'paper', color: 0xefe7d2, roughness: 1, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.024, 0.0156, 0.11, 4);
  const boxGeo = new THREE.BoxGeometry(0.02, 0.454, 0.4);

  // Parts
  const leg = new THREE.Mesh(cylinderGeo, woodMat);
  leg.name = 'leg';
  leg.position.set(-0.21, 0.055, -0.17);
  leg.rotation.set(0, deg(45), 0);
  root.add(leg);
  const leg2 = new THREE.Mesh(cylinderGeo, woodMat);
  leg2.name = 'leg';
  leg2.position.set(-0.21, 0.055, 0.17);
  leg2.rotation.set(0, deg(45), 0);
  root.add(leg2);
  const leg3 = new THREE.Mesh(cylinderGeo, woodMat);
  leg3.name = 'leg';
  leg3.position.set(0.21, 0.055, -0.17);
  leg3.rotation.set(0, deg(45), 0);
  root.add(leg3);
  const leg4 = new THREE.Mesh(cylinderGeo, woodMat);
  leg4.name = 'leg';
  leg4.position.set(0.21, 0.055, 0.17);
  leg4.rotation.set(0, deg(45), 0);
  root.add(leg4);
  const side = new THREE.Mesh(boxGeo, woodMat);
  side.name = 'side';
  side.position.set(-0.23, 0.327, 0);
  root.add(side);
  const side2 = new THREE.Mesh(boxGeo, woodMat);
  side2.name = 'side';
  side2.position.set(0.23, 0.327, 0);
  root.add(side2);
  const bottom = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.02, 0.4), woodMat);
  bottom.name = 'bottom';
  bottom.position.set(0, 0.11, 0);
  root.add(bottom);
  const backPanel = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.454, 0.012), darkMat);
  backPanel.name = 'backPanel';
  backPanel.position.set(0, 0.327, -0.194);
  root.add(backPanel);
  const skirt = new THREE.Mesh(new THREE.BoxGeometry(0.47, 0.03, 0.02), woodMat);
  skirt.name = 'skirt';
  skirt.position.set(0, 0.103, 0.188);
  root.add(skirt);
  const top = new THREE.Mesh(extrude([[0.247, 0.1919], [0.2369, 0.202], [-0.2369, 0.202], [-0.247, 0.1919], [-0.247, -0.1919], [-0.2369, -0.202], [0.2369, -0.202], [0.247, -0.1919]], 0.01, [], [0.008, 0.008, 1]), woodMat);
  top.name = 'top';
  top.position.set(0, 0.567, 0.005);
  top.rotation.set(deg(-90), 0, 0);
  root.add(top);
  const drawer = new THREE.Mesh(extrude([[0.219, 0.0451], [0.211, 0.053], [-0.211, 0.053], [-0.219, 0.0451], [-0.219, -0.0451], [-0.211, -0.053], [0.211, -0.053], [0.219, -0.0451]], 0.008, [], [0.006, 0.006, 1]), panelMat);
  drawer.name = 'drawer';
  drawer.position.set(0, 0.485, 0.196);
  root.add(drawer);
  const knob = new THREE.Group();
  knob.name = 'knob';
  knob.position.set(0, 0.485, 0.206);
  root.add(knob);
  const knobStem = new THREE.Mesh(new THREE.CylinderGeometry(0.0063, 0.0084, 0.0126, 6), brassMat);
  knobStem.name = 'knobStem';
  knobStem.position.set(0, 0, 0.0063);
  knobStem.rotation.set(deg(90), 0, 0);
  knob.add(knobStem);
  const knobHead = new THREE.Mesh(new THREE.SphereGeometry(0.014, 6, 4), brassMat);
  knobHead.name = 'knobHead';
  knobHead.position.set(0, 0, 0.0175);
  knobHead.scale.set(1, 1, 0.7);
  knob.add(knobHead);
  const drawerShelf = new THREE.Mesh(new THREE.BoxGeometry(0.44, 0.016, 0.38), woodMat);
  drawerShelf.name = 'drawerShelf';
  drawerShelf.position.set(0, 0.42, 0);
  root.add(drawerShelf);
  const book = new THREE.Mesh(new THREE.BoxGeometry(0.03, 0.16, 0.13), redMat);
  book.name = 'book';
  book.position.set(-0.165, 0.2, 0.02);
  root.add(book);
  const book2 = new THREE.Mesh(new THREE.BoxGeometry(0.025, 0.15, 0.13), greenMat);
  book2.name = 'book';
  book2.position.set(-0.1335, 0.195, 0.02);
  root.add(book2);
  const book3 = new THREE.Mesh(new THREE.BoxGeometry(0.035, 0.17, 0.13), paperMat);
  book3.name = 'book';
  book3.position.set(-0.0995, 0.205, 0.02);
  root.add(book3);
  const book4 = new THREE.Mesh(new THREE.BoxGeometry(0.025, 0.15, 0.12), redMat);
  book4.name = 'book';
  book4.position.set(-0.043, 0.195, 0.02);
  book4.rotation.set(0, 0, deg(-22));
  root.add(book4);
  const lampBase = new THREE.Mesh(lathe([[0.001, 0], [0.045, 0], [0.052, 0.012], [0.064, 0.05], [0.06, 0.1], [0.044, 0.14], [0.018, 0.165], [0.012, 0.18], [0.001, 0.18]], 8), ceramicMat);
  lampBase.name = 'lampBase';
  lampBase.position.set(-0.08, 0.58, -0.05);
  root.add(lampBase);
  const lampStem = new THREE.Mesh(new THREE.CylinderGeometry(0.007, 0.007, 0.09, 5), brassMat);
  lampStem.name = 'lampStem';
  lampStem.position.set(-0.08, 0.805, -0.05);
  root.add(lampStem);
  const bulb = new THREE.Mesh(new THREE.SphereGeometry(0.03, 6, 4), bulbMat);
  bulb.name = 'bulb';
  bulb.position.set(-0.08, 0.85, -0.05);
  root.add(bulb);
  const lampShade = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.115, 0.15, 10, 1, true), shadeMat);
  lampShade.name = 'lampShade';
  lampShade.position.set(-0.08, 0.865, -0.05);
  root.add(lampShade);
  const finial = new THREE.Mesh(new THREE.SphereGeometry(0.008, 4, 3), brassMat);
  finial.name = 'finial';
  finial.position.set(-0.08, 0.945, -0.05);
  root.add(finial);
  const bedsideBook = new THREE.Group();
  bedsideBook.name = 'bedsideBook';
  bedsideBook.position.set(0.11, 0.58, 0.06);
  bedsideBook.rotation.set(0, deg(-18), 0);
  root.add(bedsideBook);
  const cover = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.03, 0.21), greenMat);
  cover.name = 'cover';
  cover.position.set(0, 0.015, 0);
  bedsideBook.add(cover);
  const pages = new THREE.Mesh(new THREE.BoxGeometry(0.14, 0.022, 0.01), paperMat);
  pages.name = 'pages';
  pages.position.set(0, 0.015, 0.1);
  bedsideBook.add(pages);

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

export default createNightstand;

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