Codels
삼각형 1.5천개0.30 × 0.02 × 0.30 m

코드에서 사용하기

에디터에서 리믹스
독립형 ES 모듈이에요 — three에만 의존해요. 팩토리 함수를 호출하고 그룹을 씬에 추가하세요.
/**
 * Pizza — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,456 · Size (W × H × D): 0.30 × 0.02 × 0.30 m
 *
 * Usage:
 *   import { createPizza } from './pizza.js';
 *   
 *   const model = createPizza();
 *   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 createPizza() {
  const root = new THREE.Group();
  root.name = 'Pizza';

  // Materials
  const doughMat = new THREE.MeshStandardMaterial({ name: 'dough', color: 0xe3a85c, roughness: 0.8, flatShading: true });
  const crustMat = new THREE.MeshStandardMaterial({ name: 'crust', color: 0xc7792f, roughness: 0.75, flatShading: true });
  const sauceMat = new THREE.MeshStandardMaterial({ name: 'sauce', color: 0xc8321f, roughness: 0.6, flatShading: true });
  const cheeseMat = new THREE.MeshStandardMaterial({ name: 'cheese', color: 0xffc53d, roughness: 0.55, flatShading: true });
  const pepperoniMat = new THREE.MeshStandardMaterial({ name: 'pepperoni', color: 0xb3261e, roughness: 0.55, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[0.0072, 0.003], [0.48, 0.003], [0.4708, 0.0936], [0.4435, 0.1837], [0.3991, 0.2667], [0.3415, 0.3373]], 0.022);
  const extrudeGeo2 = extrude([[0.0266, 0.011], [0.4499, 0.011], [0.4414, 0.0878], [0.4157, 0.1722], [0.3742, 0.25], [0.3259, 0.3103]], 0.008);
  const extrudeGeo3 = extrude([[0.041, 0.017], [0.4247, 0.017], [0.4168, 0.0829], [0.3926, 0.1626], [0.3534, 0.2361], [0.3123, 0.2883]], 0.01);
  const torusGeo = new THREE.TorusGeometry(0.458, 0.036, 5, 5, 0.771);
  const cylinderGeo = new THREE.CylinderGeometry(0.042, 0.042, 0.008, 9);

  // Parts
  const pizza = new THREE.Group();
  pizza.name = 'pizza';
  pizza.scale.setScalar(0.3);
  root.add(pizza);
  const slice1 = new THREE.Group();
  slice1.name = 'slice1';
  pizza.add(slice1);
  const dough = new THREE.Mesh(extrudeGeo, doughMat);
  dough.name = 'dough';
  dough.position.set(0, 0.011, 0);
  dough.rotation.set(deg(-90), 0, 0);
  slice1.add(dough);
  const sauce = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce.name = 'sauce';
  sauce.position.set(0, 0.024, 0);
  sauce.rotation.set(deg(-90), 0, 0);
  slice1.add(sauce);
  const cheese = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese.name = 'cheese';
  cheese.position.set(0, 0.027, 0);
  cheese.rotation.set(deg(-90), 0, 0);
  slice1.add(cheese);
  const crust = new THREE.Mesh(torusGeo, crustMat);
  crust.name = 'crust';
  crust.position.set(0, 0.037, 0);
  crust.rotation.set(deg(-90), 0, deg(0.4125));
  slice1.add(crust);
  const cylinder7 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder7.position.set(0.1533, 0.034, -0.059);
  slice1.add(cylinder7);
  const cylinder8 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder8.position.set(0.2886, 0.034, -0.1845);
  slice1.add(cylinder8);
  const slice2 = new THREE.Group();
  slice2.name = 'slice2';
  slice2.rotation.set(0, deg(45), 0);
  pizza.add(slice2);
  const dough2 = new THREE.Mesh(extrudeGeo, doughMat);
  dough2.name = 'dough';
  dough2.position.set(0, 0.011, 0);
  dough2.rotation.set(deg(-90), 0, 0);
  slice2.add(dough2);
  const sauce2 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce2.name = 'sauce';
  sauce2.position.set(0, 0.024, 0);
  sauce2.rotation.set(deg(-90), 0, 0);
  slice2.add(sauce2);
  const cheese2 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese2.name = 'cheese';
  cheese2.position.set(0, 0.027, 0);
  cheese2.rotation.set(deg(-90), 0, 0);
  slice2.add(cheese2);
  const crust2 = new THREE.Mesh(torusGeo, crustMat);
  crust2.name = 'crust';
  crust2.position.set(0, 0.037, 0);
  crust2.rotation.set(deg(-90), 0, deg(0.4125));
  slice2.add(crust2);
  const cylinder14 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder14.position.set(0.2032, 0.034, -0.0747);
  slice2.add(cylinder14);
  const cylinder15 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder15.position.set(0.3284, 0.034, -0.1369);
  slice2.add(cylinder15);
  const slice3 = new THREE.Group();
  slice3.name = 'slice3';
  slice3.rotation.set(0, deg(90), 0);
  pizza.add(slice3);
  const dough3 = new THREE.Mesh(extrudeGeo, doughMat);
  dough3.name = 'dough';
  dough3.position.set(0, 0.011, 0);
  dough3.rotation.set(deg(-90), 0, 0);
  slice3.add(dough3);
  const sauce3 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce3.name = 'sauce';
  sauce3.position.set(0, 0.024, 0);
  sauce3.rotation.set(deg(-90), 0, 0);
  slice3.add(sauce3);
  const cheese3 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese3.name = 'cheese';
  cheese3.position.set(0, 0.027, 0);
  cheese3.rotation.set(deg(-90), 0, 0);
  slice3.add(cheese3);
  const crust3 = new THREE.Mesh(torusGeo, crustMat);
  crust3.name = 'crust';
  crust3.position.set(0, 0.037, 0);
  crust3.rotation.set(deg(-90), 0, deg(0.4125));
  slice3.add(crust3);
  const cylinder21 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder21.position.set(0.1672, 0.034, -0.0693);
  slice3.add(cylinder21);
  const cylinder22 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder22.position.set(0.3103, 0.034, -0.1878);
  slice3.add(cylinder22);
  const slice4 = new THREE.Group();
  slice4.name = 'slice4';
  slice4.rotation.set(0, deg(135), 0);
  pizza.add(slice4);
  const dough4 = new THREE.Mesh(extrudeGeo, doughMat);
  dough4.name = 'dough';
  dough4.position.set(0, 0.011, 0);
  dough4.rotation.set(deg(-90), 0, 0);
  slice4.add(dough4);
  const sauce4 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce4.name = 'sauce';
  sauce4.position.set(0, 0.024, 0);
  sauce4.rotation.set(deg(-90), 0, 0);
  slice4.add(sauce4);
  const cheese4 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese4.name = 'cheese';
  cheese4.position.set(0, 0.027, 0);
  cheese4.rotation.set(deg(-90), 0, 0);
  slice4.add(cheese4);
  const crust4 = new THREE.Mesh(torusGeo, crustMat);
  crust4.name = 'crust';
  crust4.position.set(0, 0.037, 0);
  crust4.rotation.set(deg(-90), 0, deg(0.4125));
  slice4.add(crust4);
  const cylinder28 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder28.position.set(0.1386, 0.034, -0.0643);
  slice4.add(cylinder28);
  const cylinder29 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder29.position.set(0.3463, 0.034, -0.1069);
  slice4.add(cylinder29);
  const slice5 = new THREE.Group();
  slice5.name = 'slice5';
  slice5.rotation.set(0, deg(180), 0);
  pizza.add(slice5);
  const dough5 = new THREE.Mesh(extrudeGeo, doughMat);
  dough5.name = 'dough';
  dough5.position.set(0, 0.011, 0);
  dough5.rotation.set(deg(-90), 0, 0);
  slice5.add(dough5);
  const sauce5 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce5.name = 'sauce';
  sauce5.position.set(0, 0.024, 0);
  sauce5.rotation.set(deg(-90), 0, 0);
  slice5.add(sauce5);
  const cheese5 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese5.name = 'cheese';
  cheese5.position.set(0, 0.027, 0);
  cheese5.rotation.set(deg(-90), 0, 0);
  slice5.add(cheese5);
  const crust5 = new THREE.Mesh(torusGeo, crustMat);
  crust5.name = 'crust';
  crust5.position.set(0, 0.037, 0);
  crust5.rotation.set(deg(-90), 0, deg(0.4125));
  slice5.add(crust5);
  const cylinder35 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder35.position.set(0.1729, 0.034, -0.0535);
  slice5.add(cylinder35);
  const cylinder36 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder36.position.set(0.346, 0.034, -0.1181);
  slice5.add(cylinder36);
  const slice6 = new THREE.Group();
  slice6.name = 'slice6';
  slice6.rotation.set(0, deg(225), 0);
  pizza.add(slice6);
  const dough6 = new THREE.Mesh(extrudeGeo, doughMat);
  dough6.name = 'dough';
  dough6.position.set(0, 0.011, 0);
  dough6.rotation.set(deg(-90), 0, 0);
  slice6.add(dough6);
  const sauce6 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce6.name = 'sauce';
  sauce6.position.set(0, 0.024, 0);
  sauce6.rotation.set(deg(-90), 0, 0);
  slice6.add(sauce6);
  const cheese6 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese6.name = 'cheese';
  cheese6.position.set(0, 0.027, 0);
  cheese6.rotation.set(deg(-90), 0, 0);
  slice6.add(cheese6);
  const crust6 = new THREE.Mesh(torusGeo, crustMat);
  crust6.name = 'crust';
  crust6.position.set(0, 0.037, 0);
  crust6.rotation.set(deg(-90), 0, deg(0.4125));
  slice6.add(crust6);
  const cylinder42 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder42.position.set(0.1445, 0.034, -0.0641);
  slice6.add(cylinder42);
  const cylinder43 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder43.position.set(0.3396, 0.034, -0.1314);
  slice6.add(cylinder43);
  const slice7 = new THREE.Group();
  slice7.name = 'slice7';
  slice7.rotation.set(0, deg(270), 0);
  pizza.add(slice7);
  const dough7 = new THREE.Mesh(extrudeGeo, doughMat);
  dough7.name = 'dough';
  dough7.position.set(0, 0.011, 0);
  dough7.rotation.set(deg(-90), 0, 0);
  slice7.add(dough7);
  const sauce7 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce7.name = 'sauce';
  sauce7.position.set(0, 0.024, 0);
  sauce7.rotation.set(deg(-90), 0, 0);
  slice7.add(sauce7);
  const cheese7 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese7.name = 'cheese';
  cheese7.position.set(0, 0.027, 0);
  cheese7.rotation.set(deg(-90), 0, 0);
  slice7.add(cheese7);
  const crust7 = new THREE.Mesh(torusGeo, crustMat);
  crust7.name = 'crust';
  crust7.position.set(0, 0.037, 0);
  crust7.rotation.set(deg(-90), 0, deg(0.4125));
  slice7.add(crust7);
  const cylinder49 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder49.position.set(0.1788, 0.034, -0.0794);
  slice7.add(cylinder49);
  const cylinder50 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder50.position.set(0.2886, 0.034, -0.1696);
  slice7.add(cylinder50);
  const slice8 = new THREE.Group();
  slice8.name = 'slice8';
  slice8.rotation.set(0, deg(315), 0);
  pizza.add(slice8);
  const dough8 = new THREE.Mesh(extrudeGeo, doughMat);
  dough8.name = 'dough';
  dough8.position.set(0, 0.011, 0);
  dough8.rotation.set(deg(-90), 0, 0);
  slice8.add(dough8);
  const sauce8 = new THREE.Mesh(extrudeGeo2, sauceMat);
  sauce8.name = 'sauce';
  sauce8.position.set(0, 0.024, 0);
  sauce8.rotation.set(deg(-90), 0, 0);
  slice8.add(sauce8);
  const cheese8 = new THREE.Mesh(extrudeGeo3, cheeseMat);
  cheese8.name = 'cheese';
  cheese8.position.set(0, 0.027, 0);
  cheese8.rotation.set(deg(-90), 0, 0);
  slice8.add(cheese8);
  const crust8 = new THREE.Mesh(torusGeo, crustMat);
  crust8.name = 'crust';
  crust8.position.set(0, 0.037, 0);
  crust8.rotation.set(deg(-90), 0, deg(0.4125));
  slice8.add(crust8);
  const cylinder56 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder56.position.set(0.1693, 0.034, -0.069);
  slice8.add(cylinder56);
  const cylinder57 = new THREE.Mesh(cylinderGeo, pepperoniMat);
  cylinder57.position.set(0.3061, 0.034, -0.2002);
  slice8.add(cylinder57);

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

export default createPizza;

평점 및 댓글

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

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

댓글 0개

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

관련 모델

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