삼각형 632개0.15 × 0.14 × 0.04 m
코드에서 사용하기
에디터에서 리믹스watermelon.js · 149줄
독립형 ES 모듈이에요 — three에만 의존해요. 팩토리 함수를 호출하고 그룹을 씬에 추가하세요.
/**
* Watermelon — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 632 · Size (W × H × D): 0.15 × 0.14 × 0.04 m
*
* Usage:
* import { createWatermelon } from './watermelon.js';
*
* const model = createWatermelon();
* 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 createWatermelon() {
const root = new THREE.Group();
root.name = 'Watermelon';
// Materials
const skinMat = new THREE.MeshStandardMaterial({ name: 'skin', color: 0x2a7a30, roughness: 0.55, flatShading: true });
const rindMat = new THREE.MeshStandardMaterial({ name: 'rind', color: 0xe8f2c4, roughness: 0.7, flatShading: true });
const fleshMat = new THREE.MeshStandardMaterial({ name: 'flesh', color: 0xf2414f, roughness: 0.6, flatShading: true });
const seedMat = new THREE.MeshStandardMaterial({ name: 'seed', color: 0x241a14, roughness: 0.4, flatShading: true });
// Shared geometries
const sphereGeo = new THREE.SphereGeometry(0.0049, 5, 4);
// Parts
const slice = new THREE.Group();
slice.name = 'slice';
slice.position.set(0, 0.14, 0);
root.add(slice);
const flesh = new THREE.Mesh(extrude([[-0.0594, -0.095], [-0.0484, -0.101], [-0.0368, -0.1058], [-0.0248, -0.1092], [-0.0125, -0.1113], [0, -0.112], [0.0125, -0.1113], [0.0248, -0.1092], [0.0368, -0.1058], [0.0484, -0.101], [0.0594, -0.095], [0, 0]], 0.0392), fleshMat);
flesh.name = 'flesh';
slice.add(flesh);
const rind = new THREE.Mesh(extrude([[-0.0683, -0.1092], [-0.0557, -0.1162], [-0.0424, -0.1216], [-0.0285, -0.1256], [-0.0144, -0.128], [0, -0.1288], [0.0144, -0.128], [0.0285, -0.1256], [0.0424, -0.1216], [0.0557, -0.1162], [0.0683, -0.1092], [0.0594, -0.095], [0.0484, -0.101], [0.0368, -0.1058], [0.0248, -0.1092], [0.0125, -0.1113], [0, -0.112], [-0.0125, -0.1113], [-0.0248, -0.1092], [-0.0368, -0.1058], [-0.0484, -0.101], [-0.0594, -0.095]], 0.0392), rindMat);
rind.name = 'rind';
slice.add(rind);
const skin = new THREE.Mesh(extrude([[-0.0742, -0.1187], [-0.0605, -0.1263], [-0.046, -0.1322], [-0.031, -0.1365], [-0.0156, -0.1391], [0, -0.14], [0.0156, -0.1391], [0.031, -0.1365], [0.046, -0.1322], [0.0605, -0.1263], [0.0742, -0.1187], [0.0683, -0.1092], [0.0557, -0.1162], [0.0424, -0.1216], [0.0285, -0.1256], [0.0144, -0.128], [0, -0.1288], [-0.0144, -0.128], [-0.0285, -0.1256], [-0.0424, -0.1216], [-0.0557, -0.1162], [-0.0683, -0.1092]], 0.0392), skinMat);
skin.name = 'skin';
slice.add(skin);
const seedFront1 = new THREE.Mesh(sphereGeo, seedMat);
seedFront1.name = 'seedFront1';
seedFront1.position.set(-0.0127, -0.0848, 0.0196);
seedFront1.rotation.set(0, 0, deg(-8.4986));
seedFront1.scale.set(0.6, 1, 0.45);
slice.add(seedFront1);
const seedFront2 = new THREE.Mesh(sphereGeo, seedMat);
seedFront2.name = 'seedFront2';
seedFront2.position.set(-0.0151, -0.0481, 0.0196);
seedFront2.rotation.set(0, 0, deg(-17.4397));
seedFront2.scale.set(0.6, 1, 0.45);
slice.add(seedFront2);
const seedFront3 = new THREE.Mesh(sphereGeo, seedMat);
seedFront3.name = 'seedFront3';
seedFront3.position.set(0.0003, -0.051, 0.0196);
seedFront3.rotation.set(0, 0, deg(0.3567));
seedFront3.scale.set(0.6, 1, 0.45);
slice.add(seedFront3);
const seedFront4 = new THREE.Mesh(sphereGeo, seedMat);
seedFront4.name = 'seedFront4';
seedFront4.position.set(0.0133, -0.041, 0.0196);
seedFront4.rotation.set(0, 0, deg(17.9805));
seedFront4.scale.set(0.6, 1, 0.45);
slice.add(seedFront4);
const seedFront5 = new THREE.Mesh(sphereGeo, seedMat);
seedFront5.name = 'seedFront5';
seedFront5.position.set(0.0112, -0.0696, 0.0196);
seedFront5.rotation.set(0, 0, deg(9.1749));
seedFront5.scale.set(0.6, 1, 0.45);
slice.add(seedFront5);
const seedFront6 = new THREE.Mesh(sphereGeo, seedMat);
seedFront6.name = 'seedFront6';
seedFront6.position.set(-0.0088, -0.0774, 0.0196);
seedFront6.rotation.set(0, 0, deg(-6.4885));
seedFront6.scale.set(0.6, 1, 0.45);
slice.add(seedFront6);
const seedFront7 = new THREE.Mesh(sphereGeo, seedMat);
seedFront7.name = 'seedFront7';
seedFront7.position.set(0.0242, -0.0722, 0.0196);
seedFront7.rotation.set(0, 0, deg(18.5106));
seedFront7.scale.set(0.6, 1, 0.45);
slice.add(seedFront7);
const seedBack1 = new THREE.Mesh(sphereGeo, seedMat);
seedBack1.name = 'seedBack1';
seedBack1.position.set(-0.0127, -0.0848, -0.0196);
seedBack1.rotation.set(0, 0, deg(-8.4986));
seedBack1.scale.set(0.6, 1, 0.45);
slice.add(seedBack1);
const seedBack2 = new THREE.Mesh(sphereGeo, seedMat);
seedBack2.name = 'seedBack2';
seedBack2.position.set(-0.0151, -0.0481, -0.0196);
seedBack2.rotation.set(0, 0, deg(-17.4397));
seedBack2.scale.set(0.6, 1, 0.45);
slice.add(seedBack2);
const seedBack3 = new THREE.Mesh(sphereGeo, seedMat);
seedBack3.name = 'seedBack3';
seedBack3.position.set(0.0003, -0.051, -0.0196);
seedBack3.rotation.set(0, 0, deg(0.3567));
seedBack3.scale.set(0.6, 1, 0.45);
slice.add(seedBack3);
const seedBack4 = new THREE.Mesh(sphereGeo, seedMat);
seedBack4.name = 'seedBack4';
seedBack4.position.set(0.0133, -0.041, -0.0196);
seedBack4.rotation.set(0, 0, deg(17.9805));
seedBack4.scale.set(0.6, 1, 0.45);
slice.add(seedBack4);
const seedBack5 = new THREE.Mesh(sphereGeo, seedMat);
seedBack5.name = 'seedBack5';
seedBack5.position.set(0.0112, -0.0696, -0.0196);
seedBack5.rotation.set(0, 0, deg(9.1749));
seedBack5.scale.set(0.6, 1, 0.45);
slice.add(seedBack5);
const seedBack6 = new THREE.Mesh(sphereGeo, seedMat);
seedBack6.name = 'seedBack6';
seedBack6.position.set(-0.0088, -0.0774, -0.0196);
seedBack6.rotation.set(0, 0, deg(-6.4885));
seedBack6.scale.set(0.6, 1, 0.45);
slice.add(seedBack6);
const seedBack7 = new THREE.Mesh(sphereGeo, seedMat);
seedBack7.name = 'seedBack7';
seedBack7.position.set(0.0242, -0.0722, -0.0196);
seedBack7.rotation.set(0, 0, deg(18.5106));
seedBack7.scale.set(0.6, 1, 0.45);
slice.add(seedBack7);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createWatermelon;
평점 및 댓글
댓글 0개
아직 댓글이 없어요. 이 모델을 어떻게 사용했는지, 어떤 점이 더 나아질 수 있을지 공유해 주세요.
관련 모델
같은 카테고리 또는 비슷한 태그









