Codels
삼각형 1.2천개0.98 × 1.22 × 0.98 m

코드에서 사용하기

에디터에서 리믹스
독립형 ES 모듈이에요 — three에만 의존해요. 팩토리 함수를 호출하고 그룹을 씬에 추가하세요.
/**
 * Cabinet — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,152 · Size (W × H × D): 0.98 × 1.22 × 0.97 m
 *
 * Usage:
 *   import { createCabinet } from './cabinet.js';
 *   
 *   const model = createCabinet();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// 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 createCabinet() {
  const root = new THREE.Group();
  root.name = 'Cabinet';

  // Materials
  const paintMat = new THREE.MeshStandardMaterial({ name: 'paint', color: 0x8fae9c, roughness: 0.6, flatShading: true });
  const trimMat = new THREE.MeshStandardMaterial({ name: 'trim', color: 0xa3bdae, roughness: 0.6, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x4f6056, roughness: 0.9, flatShading: true });
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0xc48a52, roughness: 0.8, flatShading: true });
  const chromeMat = new THREE.MeshStandardMaterial({ name: 'chrome', color: 0xc9ccd0, roughness: 0.25, metalness: 0.7, flatShading: true });
  const whiteMat = new THREE.MeshStandardMaterial({ name: 'white', color: 0xeeeee8, roughness: 0.5, flatShading: true });
  const redMat = new THREE.MeshStandardMaterial({ name: 'red', color: 0xc23b32, roughness: 0.6, flatShading: true });
  const amberMat = new THREE.MeshStandardMaterial({ name: 'amber', color: 0xa45a1c, roughness: 0.25, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.02, 0.76, 0.58);
  const boxGeo2 = new THREE.BoxGeometry(0.76, 0.02, 0.56);
  const boxGeo3 = new THREE.BoxGeometry(0.012, 0.012, 0.026);
  const boxGeo4 = new THREE.BoxGeometry(0.396, 0.578, 0.02);
  const boxGeo5 = new THREE.BoxGeometry(0.396, 0.07, 0.01);
  const boxGeo6 = new THREE.BoxGeometry(0.07, 0.438, 0.01);
  const cylinderGeo = new THREE.CylinderGeometry(0.006, 0.006, 0.12, 6);
  const cylinderGeo2 = new THREE.CylinderGeometry(0.007, 0.007, 0.26, 5);
  const sphereGeo = new THREE.SphereGeometry(0.025, 6, 4);
  const cylinderGeo3 = new THREE.CylinderGeometry(0.11, 0.09, 0.014, 10);
  const cylinderGeo4 = new THREE.CylinderGeometry(0.045, 0.045, 0.12, 7);
  const cylinderGeo5 = new THREE.CylinderGeometry(0.048, 0.048, 0.025, 7);

  // Parts
  const toeKick = new THREE.Mesh(new THREE.BoxGeometry(0.78, 0.1, 0.5), darkMat);
  toeKick.name = 'toeKick';
  toeKick.position.set(0, 0.05, -0.04);
  root.add(toeKick);
  const side = new THREE.Mesh(boxGeo, paintMat);
  side.name = 'side';
  side.position.set(-0.39, 0.48, 0);
  root.add(side);
  const side2 = new THREE.Mesh(boxGeo, paintMat);
  side2.name = 'side';
  side2.position.set(0.39, 0.48, 0);
  root.add(side2);
  const bottom = new THREE.Mesh(boxGeo2, paintMat);
  bottom.name = 'bottom';
  bottom.position.set(0, 0.11, 0.01);
  root.add(bottom);
  const backPanel = new THREE.Mesh(new THREE.BoxGeometry(0.76, 0.76, 0.012), darkMat);
  backPanel.name = 'backPanel';
  backPanel.position.set(0, 0.48, -0.284);
  root.add(backPanel);
  const rail = new THREE.Mesh(boxGeo2, paintMat);
  rail.name = 'rail';
  rail.position.set(0, 0.7, 0.01);
  root.add(rail);
  const topRail = new THREE.Mesh(boxGeo2, paintMat);
  topRail.name = 'topRail';
  topRail.position.set(0, 0.85, 0.01);
  root.add(topRail);
  const counter = new THREE.Mesh(new THREE.BoxGeometry(0.83, 0.04, 0.61), woodMat);
  counter.name = 'counter';
  counter.position.set(0, 0.88, 0.015);
  root.add(counter);
  const drawer = new THREE.Mesh(extrude([[0.388, 0.0523], [0.3788, 0.0615], [-0.3788, 0.0615], [-0.388, 0.0523], [-0.388, -0.0523], [-0.3788, -0.0615], [0.3788, -0.0615], [0.388, -0.0523]], 0.008, [], [0.006, 0.006, 1]), paintMat);
  drawer.name = 'drawer';
  drawer.position.set(0, 0.78, 0.3);
  root.add(drawer);
  const pull = new THREE.Group();
  pull.name = 'pull';
  pull.position.set(0, 0.785, 0.31);
  root.add(pull);
  const pullPost = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost.name = 'pullPost';
  pullPost.position.set(-0.074, 0, 0.013);
  pull.add(pullPost);
  const pullPost2 = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost2.name = 'pullPost';
  pullPost2.position.set(0.074, 0, 0.013);
  pull.add(pullPost2);
  const pullBar = new THREE.Mesh(new THREE.CylinderGeometry(0.006, 0.006, 0.16, 6), chromeMat);
  pullBar.name = 'pullBar';
  pullBar.position.set(0, 0, 0.026);
  pullBar.rotation.set(0, 0, deg(90));
  pull.add(pullBar);
  const doorLeft = new THREE.Group();
  doorLeft.name = 'doorLeft';
  doorLeft.position.set(-0.4, 0.106, 0.29);
  doorLeft.rotation.set(0, deg(-105), 0);
  root.add(doorLeft);
  const doorSlab = new THREE.Mesh(boxGeo4, paintMat);
  doorSlab.name = 'doorSlab';
  doorSlab.position.set(0.198, 0.289, 0.01);
  doorLeft.add(doorSlab);
  const doorRail = new THREE.Mesh(boxGeo5, trimMat);
  doorRail.name = 'doorRail';
  doorRail.position.set(0.198, 0.035, 0.025);
  doorLeft.add(doorRail);
  const doorRail2 = new THREE.Mesh(boxGeo5, trimMat);
  doorRail2.name = 'doorRail';
  doorRail2.position.set(0.198, 0.543, 0.025);
  doorLeft.add(doorRail2);
  const doorStile = new THREE.Mesh(boxGeo6, trimMat);
  doorStile.name = 'doorStile';
  doorStile.position.set(0.035, 0.289, 0.025);
  doorLeft.add(doorStile);
  const doorStile2 = new THREE.Mesh(boxGeo6, trimMat);
  doorStile2.name = 'doorStile';
  doorStile2.position.set(0.361, 0.289, 0.025);
  doorLeft.add(doorStile2);
  const pull2 = new THREE.Group();
  pull2.name = 'pull';
  pull2.position.set(0.361, 0.448, 0.03);
  pull2.rotation.set(0, 0, deg(90));
  doorLeft.add(pull2);
  const pullPost3 = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost3.name = 'pullPost';
  pullPost3.position.set(-0.054, 0, 0.013);
  pull2.add(pullPost3);
  const pullPost4 = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost4.name = 'pullPost';
  pullPost4.position.set(0.054, 0, 0.013);
  pull2.add(pullPost4);
  const pullBar2 = new THREE.Mesh(cylinderGeo, chromeMat);
  pullBar2.name = 'pullBar';
  pullBar2.position.set(0, 0, 0.026);
  pullBar2.rotation.set(0, 0, deg(90));
  pull2.add(pullBar2);
  const doorRight = new THREE.Group();
  doorRight.name = 'doorRight';
  doorRight.position.set(0.4, 0.106, 0.29);
  doorRight.rotation.set(0, deg(80), 0);
  root.add(doorRight);
  const doorSlab2 = new THREE.Mesh(boxGeo4, paintMat);
  doorSlab2.name = 'doorSlab';
  doorSlab2.position.set(-0.198, 0.289, 0.01);
  doorRight.add(doorSlab2);
  const doorRail3 = new THREE.Mesh(boxGeo5, trimMat);
  doorRail3.name = 'doorRail';
  doorRail3.position.set(-0.198, 0.035, 0.025);
  doorRight.add(doorRail3);
  const doorRail4 = new THREE.Mesh(boxGeo5, trimMat);
  doorRail4.name = 'doorRail';
  doorRail4.position.set(-0.198, 0.543, 0.025);
  doorRight.add(doorRail4);
  const doorStile3 = new THREE.Mesh(boxGeo6, trimMat);
  doorStile3.name = 'doorStile';
  doorStile3.position.set(-0.361, 0.289, 0.025);
  doorRight.add(doorStile3);
  const doorStile4 = new THREE.Mesh(boxGeo6, trimMat);
  doorStile4.name = 'doorStile';
  doorStile4.position.set(-0.035, 0.289, 0.025);
  doorRight.add(doorStile4);
  const pull3 = new THREE.Group();
  pull3.name = 'pull';
  pull3.position.set(-0.361, 0.448, 0.03);
  pull3.rotation.set(0, 0, deg(90));
  doorRight.add(pull3);
  const pullPost5 = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost5.name = 'pullPost';
  pullPost5.position.set(-0.054, 0, 0.013);
  pull3.add(pullPost5);
  const pullPost6 = new THREE.Mesh(boxGeo3, chromeMat);
  pullPost6.name = 'pullPost';
  pullPost6.position.set(0.054, 0, 0.013);
  pull3.add(pullPost6);
  const pullBar3 = new THREE.Mesh(cylinderGeo, chromeMat);
  pullBar3.name = 'pullBar';
  pullBar3.position.set(0, 0, 0.026);
  pullBar3.rotation.set(0, 0, deg(90));
  pull3.add(pullBar3);
  const crock = new THREE.Mesh(new THREE.CylinderGeometry(0.055, 0.05, 0.13, 8), whiteMat);
  crock.name = 'crock';
  crock.position.set(-0.24, 0.965, -0.14);
  root.add(crock);
  const crockOpening = new THREE.Mesh(new THREE.CylinderGeometry(0.048, 0.048, 0.005, 8), darkMat);
  crockOpening.name = 'crockOpening';
  crockOpening.position.set(-0.24, 1.0295, -0.14);
  root.add(crockOpening);
  const spoon = new THREE.Group();
  spoon.name = 'spoon';
  spoon.position.set(-0.252, 0.92, -0.13);
  spoon.rotation.set(deg(-6), 0, deg(-12));
  root.add(spoon);
  const spoonHandle = new THREE.Mesh(cylinderGeo2, woodMat);
  spoonHandle.name = 'spoonHandle';
  spoonHandle.position.set(0, 0.13, 0);
  spoon.add(spoonHandle);
  const spoonBowl = new THREE.Mesh(sphereGeo, woodMat);
  spoonBowl.name = 'spoonBowl';
  spoonBowl.position.set(0, 0.27, 0);
  spoonBowl.scale.set(1, 1.3, 0.45);
  spoon.add(spoonBowl);
  const spoon2 = new THREE.Group();
  spoon2.name = 'spoon';
  spoon2.position.set(-0.225, 0.92, -0.148);
  spoon2.rotation.set(deg(5), 0, deg(10));
  root.add(spoon2);
  const spoonHandle2 = new THREE.Mesh(cylinderGeo2, woodMat);
  spoonHandle2.name = 'spoonHandle';
  spoonHandle2.position.set(0, 0.13, 0);
  spoon2.add(spoonHandle2);
  const spoonBowl2 = new THREE.Mesh(sphereGeo, woodMat);
  spoonBowl2.name = 'spoonBowl';
  spoonBowl2.position.set(0, 0.27, 0);
  spoonBowl2.scale.set(1, 1.3, 0.45);
  spoon2.add(spoonBowl2);
  const cuttingBoard = new THREE.Mesh(new THREE.BoxGeometry(0.32, 0.022, 0.22), woodMat);
  cuttingBoard.name = 'cuttingBoard';
  cuttingBoard.position.set(0.14, 0.911, 0.04);
  cuttingBoard.rotation.set(0, deg(-10), 0);
  root.add(cuttingBoard);
  const tomato = new THREE.Mesh(new THREE.SphereGeometry(0.038, 7, 5), redMat);
  tomato.name = 'tomato';
  tomato.position.set(0.2, 0.954, 0.06);
  tomato.scale.set(1, 0.85, 1);
  root.add(tomato);
  const shelf = new THREE.Mesh(new THREE.BoxGeometry(0.76, 0.016, 0.5), paintMat);
  shelf.name = 'shelf';
  shelf.position.set(0, 0.408, -0.03);
  root.add(shelf);
  const plate = new THREE.Mesh(cylinderGeo3, whiteMat);
  plate.name = 'plate';
  plate.position.set(-0.17, 0.127, 0.02);
  root.add(plate);
  const plate2 = new THREE.Mesh(cylinderGeo3, whiteMat);
  plate2.name = 'plate';
  plate2.position.set(-0.17, 0.143, 0.02);
  root.add(plate2);
  const plate3 = new THREE.Mesh(cylinderGeo3, whiteMat);
  plate3.name = 'plate';
  plate3.position.set(-0.17, 0.159, 0.02);
  root.add(plate3);
  const plate4 = new THREE.Mesh(cylinderGeo3, whiteMat);
  plate4.name = 'plate';
  plate4.position.set(-0.17, 0.175, 0.02);
  root.add(plate4);
  const pot = new THREE.Mesh(new THREE.CylinderGeometry(0.12, 0.11, 0.15, 9), chromeMat);
  pot.name = 'pot';
  pot.position.set(0.17, 0.195, -0.02);
  root.add(pot);
  const potLid = new THREE.Mesh(new THREE.CylinderGeometry(0.125, 0.125, 0.012, 9), darkMat);
  potLid.name = 'potLid';
  potLid.position.set(0.17, 0.276, -0.02);
  root.add(potLid);
  const potKnob = new THREE.Mesh(new THREE.SphereGeometry(0.018, 5, 3), darkMat);
  potKnob.name = 'potKnob';
  potKnob.position.set(0.17, 0.29, -0.02);
  root.add(potKnob);
  const jar = new THREE.Mesh(cylinderGeo4, amberMat);
  jar.name = 'jar';
  jar.position.set(-0.25, 0.476, -0.06);
  root.add(jar);
  const jarLid = new THREE.Mesh(cylinderGeo5, whiteMat);
  jarLid.name = 'jarLid';
  jarLid.position.set(-0.25, 0.5485, -0.06);
  root.add(jarLid);
  const jar2 = new THREE.Mesh(cylinderGeo4, redMat);
  jar2.name = 'jar';
  jar2.position.set(-0.1, 0.476, -0.06);
  root.add(jar2);
  const jarLid2 = new THREE.Mesh(cylinderGeo5, whiteMat);
  jarLid2.name = 'jarLid';
  jarLid2.position.set(-0.1, 0.5485, -0.06);
  root.add(jarLid2);
  const jar3 = new THREE.Mesh(cylinderGeo4, woodMat);
  jar3.name = 'jar';
  jar3.position.set(0.06, 0.476, -0.06);
  root.add(jar3);
  const jarLid3 = new THREE.Mesh(cylinderGeo5, whiteMat);
  jarLid3.name = 'jarLid';
  jarLid3.position.set(0.06, 0.5485, -0.06);
  root.add(jarLid3);
  const jar4 = new THREE.Mesh(cylinderGeo4, amberMat);
  jar4.name = 'jar';
  jar4.position.set(0.22, 0.476, -0.06);
  root.add(jar4);
  const jarLid4 = new THREE.Mesh(cylinderGeo5, whiteMat);
  jarLid4.name = 'jarLid';
  jarLid4.position.set(0.22, 0.5485, -0.06);
  root.add(jarLid4);

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

export default createCabinet;

평점 및 댓글

—
아직 평점이 없어요 — 첫 평점을 남겨 보세요.
5
0
4
0
3
0
2
0
1
0

평점과 댓글을 남기려면 로그인하세요.

댓글 0개

아직 댓글이 없어요. 이 모델을 어떻게 사용했는지, 어떤 점이 더 나아질 수 있을지 공유해 주세요.

관련 모델

같은 카테고리 또는 비슷한 태그