Codels
500 ポリゴン0.04 × 0.04 × 0.05 m
自己完結型の ES モジュールで、依存先は three のみです。ファクトリー関数を呼び出し、返された group をシーンに追加してください。
/**
 * Strawberry — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 500 · Size (W × H × D): 0.04 × 0.04 × 0.04 m
 *
 * Usage:
 *   import { createStrawberry } from './strawberry.js';
 *   
 *   const model = createStrawberry();
 *   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 createStrawberry() {
  const root = new THREE.Group();
  root.name = 'Strawberry';

  // Materials
  const berryMat = new THREE.MeshStandardMaterial({ name: 'berry', color: 0xe0283a, roughness: 0.35 });
  const seedMat = new THREE.MeshStandardMaterial({ name: 'seed', color: 0xf6d76a, roughness: 0.5, flatShading: true });
  const leafMat = new THREE.MeshStandardMaterial({ name: 'leaf', color: 0x4fa032, roughness: 0.7, flatShading: true });
  const stemMat = new THREE.MeshStandardMaterial({ name: 'stem', color: 0x3f7a26, roughness: 0.8, flatShading: true });

  // Shared geometries
  const tetrahedronGeo = new THREE.TetrahedronGeometry(0.028, 0);
  const extrudeGeo = extrude([[0, -0.06], [0.14, -0.085], [0.3, -0.055], [0.46, 0], [0.3, 0.055], [0.14, 0.085], [0, 0.06]], 0.024);

  // Parts
  const berry1 = new THREE.Group();
  berry1.name = 'berry1';
  berry1.position.set(0, 0.0167, 0);
  berry1.rotation.set(0, deg(62), deg(72));
  berry1.scale.setScalar(0.045);
  root.add(berry1);
  const berry1Core = new THREE.Group();
  berry1Core.name = 'berry1Core';
  berry1Core.position.set(0, -0.5, 0);
  berry1.add(berry1Core);
  const berry1Body = new THREE.Mesh(lathe([[0, 0], [0.08, 0.04], [0.2, 0.16], [0.31, 0.32], [0.39, 0.5], [0.425, 0.66], [0.41, 0.8], [0.34, 0.9], [0.2, 0.96], [0, 0.97]], 12), berryMat);
  berry1Body.name = 'berry1Body';
  berry1Body.rotation.set(0, deg(13), 0);
  berry1Core.add(berry1Body);
  const berry1Seed11 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed11.name = 'berry1Seed1_1';
  berry1Seed11.position.set(0.1481, 0.14, 0.0951);
  berry1Seed11.rotation.set(deg(61.6175), deg(36.5133), deg(-22.2578));
  berry1Seed11.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed11);
  const berry1Seed12 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed12.name = 'berry1Seed1_2';
  berry1Seed12.position.set(0.0083, 0.14, -0.1758);
  berry1Seed12.rotation.set(deg(134.9681), deg(1.9118), deg(-4.6098));
  berry1Seed12.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed12);
  const berry1Seed13 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed13.name = 'berry1Seed1_3';
  berry1Seed13.position.set(-0.1564, 0.14, 0.0807);
  berry1Seed13.rotation.set(deg(65.3646), deg(-38.9301), deg(25.551));
  berry1Seed13.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed13);
  const berry1Seed21 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed21.name = 'berry1Seed2_1';
  berry1Seed21.position.set(0.2889, 0.305, -0.063);
  berry1Seed21.rotation.set(deg(107.2108), deg(53.6237), deg(-68.872));
  berry1Seed21.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed21);
  const berry1Seed22 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed22.name = 'berry1Seed2_2';
  berry1Seed22.position.set(-0.063, 0.305, -0.2889);
  berry1Seed22.rotation.set(deg(144.8682), deg(-10.107), deg(31.2146));
  berry1Seed22.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed22);
  const berry1Seed23 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed23.name = 'berry1Seed2_3';
  berry1Seed23.position.set(-0.2889, 0.305, 0.063);
  berry1Seed23.rotation.set(deg(72.7892), deg(-53.6237), deg(40.8644));
  berry1Seed23.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed23);
  const berry1Seed24 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed24.name = 'berry1Seed2_4';
  berry1Seed24.position.set(0.063, 0.305, 0.2889);
  berry1Seed24.rotation.set(deg(35.1318), deg(10.107), deg(-3.207));
  berry1Seed24.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed24);
  const berry1Seed31 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed31.name = 'berry1Seed3_1';
  berry1Seed31.position.set(0.3136, 0.47, 0.2014);
  berry1Seed31.rotation.set(deg(39.4402), deg(50.2593), deg(-19.0884));
  berry1Seed31.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed31);
  const berry1Seed32 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed32.name = 'berry1Seed3_2';
  berry1Seed32.position.set(0.2884, 0.47, -0.236);
  berry1Seed32.rotation.set(deg(144.9402), deg(45.0065), deg(-105.3517));
  berry1Seed32.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed32);
  const berry1Seed33 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed33.name = 'berry1Seed3_3';
  berry1Seed33.position.set(-0.1353, 0.47, -0.3472);
  berry1Seed33.rotation.set(deg(154.4981), deg(-19.383), deg(74.0823));
  berry1Seed33.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed33);
  const berry1Seed34 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed34.name = 'berry1Seed3_4';
  berry1Seed34.position.set(-0.3721, 0.47, 0.0214);
  berry1Seed34.rotation.set(deg(82.6295), deg(-65.8252), deg(59.272));
  berry1Seed34.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed34);
  const berry1Seed35 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed35.name = 'berry1Seed3_5';
  berry1Seed35.position.set(-0.0946, 0.47, 0.3605);
  berry1Seed35.rotation.set(deg(24.6785), deg(-13.412), deg(2.9467));
  berry1Seed35.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed35);
  const berry1Seed41 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed41.name = 'berry1Seed4_1';
  berry1Seed41.position.set(0.4151, 0.635, 0.0196);
  berry1Seed41.rotation.set(deg(77.8289), deg(77.3726), deg(-65.7624));
  berry1Seed41.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed41);
  const berry1Seed42 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed42.name = 'berry1Seed4_2';
  berry1Seed42.position.set(0.2245, 0.635, -0.3497);
  berry1Seed42.rotation.set(deg(165.4279), deg(31.8584), deg(-131.7376));
  berry1Seed42.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed42);
  const berry1Seed43 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed43.name = 'berry1Seed4_3';
  berry1Seed43.position.set(-0.1906, 0.635, -0.3693);
  berry1Seed43.rotation.set(deg(166.171), deg(-26.6148), deg(125.7106));
  berry1Seed43.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed43);
  const berry1Seed44 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed44.name = 'berry1Seed4_4';
  berry1Seed44.position.set(-0.4151, 0.635, -0.0196);
  berry1Seed44.rotation.set(deg(102.1711), deg(-77.3726), deg(89.5328));
  berry1Seed44.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed44);
  const berry1Seed45 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed45.name = 'berry1Seed4_5';
  berry1Seed45.position.set(-0.2245, 0.635, 0.3497);
  berry1Seed45.rotation.set(deg(14.5721), deg(-31.8584), deg(4.1797));
  berry1Seed45.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed45);
  const berry1Seed46 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed46.name = 'berry1Seed4_6';
  berry1Seed46.position.set(0.1906, 0.635, 0.3693);
  berry1Seed46.rotation.set(deg(13.829), deg(26.6148), deg(-3.286));
  berry1Seed46.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed46);
  const berry1Seed51 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed51.name = 'berry1Seed5_1';
  berry1Seed51.position.set(0.3416, 0.8, 0.2194);
  berry1Seed51.rotation.set(deg(-11.2163), deg(56.7914), deg(6.0773));
  berry1Seed51.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed51);
  const berry1Seed52 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed52.name = 'berry1Seed5_2';
  berry1Seed52.position.set(0.3608, 0.8, -0.1862);
  berry1Seed52.rotation.set(deg(-166.8494), deg(62.079), deg(158.3141));
  berry1Seed52.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed52);
  const berry1Seed53 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed53.name = 'berry1Seed5_3';
  berry1Seed53.position.set(0.0192, 0.8, -0.4055);
  berry1Seed53.rotation.set(deg(-173.8777), deg(2.6888), deg(47.3885));
  berry1Seed53.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed53);
  const berry1Seed54 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed54.name = 'berry1Seed5_4';
  berry1Seed54.position.set(-0.3416, 0.8, -0.2194);
  berry1Seed54.rotation.set(deg(-168.7837), deg(-56.7914), deg(-159.4101));
  berry1Seed54.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed54);
  const berry1Seed55 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed55.name = 'berry1Seed5_5';
  berry1Seed55.position.set(-0.3608, 0.8, 0.1862);
  berry1Seed55.rotation.set(deg(-13.1506), deg(-62.079), deg(-7.9362));
  berry1Seed55.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed55);
  const berry1Seed56 = new THREE.Mesh(tetrahedronGeo, seedMat);
  berry1Seed56.name = 'berry1Seed5_6';
  berry1Seed56.position.set(-0.0192, 0.8, 0.4055);
  berry1Seed56.rotation.set(deg(-6.1223), deg(-2.6888), deg(-0.1438));
  berry1Seed56.scale.set(0.7, 0.7, 0.45);
  berry1Core.add(berry1Seed56);
  const berry1SepalMount1 = new THREE.Group();
  berry1SepalMount1.name = 'berry1SepalMount1';
  berry1SepalMount1.position.set(0, 0.995, 0);
  berry1SepalMount1.rotation.set(0, deg(20), 0);
  berry1Core.add(berry1SepalMount1);
  const berry1Sepal1 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal1.name = 'berry1Sepal1';
  berry1Sepal1.rotation.set(deg(90), deg(-13), 0);
  berry1SepalMount1.add(berry1Sepal1);
  const berry1SepalMount2 = new THREE.Group();
  berry1SepalMount2.name = 'berry1SepalMount2';
  berry1SepalMount2.position.set(0, 0.995, 0);
  berry1SepalMount2.rotation.set(0, deg(80), 0);
  berry1Core.add(berry1SepalMount2);
  const berry1Sepal2 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal2.name = 'berry1Sepal2';
  berry1Sepal2.rotation.set(deg(90), deg(-20), 0);
  berry1SepalMount2.add(berry1Sepal2);
  const berry1SepalMount3 = new THREE.Group();
  berry1SepalMount3.name = 'berry1SepalMount3';
  berry1SepalMount3.position.set(0, 0.995, 0);
  berry1SepalMount3.rotation.set(0, deg(140), 0);
  berry1Core.add(berry1SepalMount3);
  const berry1Sepal3 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal3.name = 'berry1Sepal3';
  berry1Sepal3.rotation.set(deg(90), deg(-13), 0);
  berry1SepalMount3.add(berry1Sepal3);
  const berry1SepalMount4 = new THREE.Group();
  berry1SepalMount4.name = 'berry1SepalMount4';
  berry1SepalMount4.position.set(0, 0.995, 0);
  berry1SepalMount4.rotation.set(0, deg(200), 0);
  berry1Core.add(berry1SepalMount4);
  const berry1Sepal4 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal4.name = 'berry1Sepal4';
  berry1Sepal4.rotation.set(deg(90), deg(-20), 0);
  berry1SepalMount4.add(berry1Sepal4);
  const berry1SepalMount5 = new THREE.Group();
  berry1SepalMount5.name = 'berry1SepalMount5';
  berry1SepalMount5.position.set(0, 0.995, 0);
  berry1SepalMount5.rotation.set(0, deg(260), 0);
  berry1Core.add(berry1SepalMount5);
  const berry1Sepal5 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal5.name = 'berry1Sepal5';
  berry1Sepal5.rotation.set(deg(90), deg(-13), 0);
  berry1SepalMount5.add(berry1Sepal5);
  const berry1SepalMount6 = new THREE.Group();
  berry1SepalMount6.name = 'berry1SepalMount6';
  berry1SepalMount6.position.set(0, 0.995, 0);
  berry1SepalMount6.rotation.set(0, deg(320), 0);
  berry1Core.add(berry1SepalMount6);
  const berry1Sepal6 = new THREE.Mesh(extrudeGeo, leafMat);
  berry1Sepal6.name = 'berry1Sepal6';
  berry1Sepal6.rotation.set(deg(90), deg(-20), 0);
  berry1SepalMount6.add(berry1Sepal6);
  const berry1Calyx = new THREE.Mesh(new THREE.CylinderGeometry(0.07, 0.12, 0.05, 6), leafMat);
  berry1Calyx.name = 'berry1Calyx';
  berry1Calyx.position.set(0, 0.99, 0);
  berry1Core.add(berry1Calyx);
  const berry1Stem = new THREE.Mesh(new THREE.CylinderGeometry(0.022, 0.03, 0.16, 5), stemMat);
  berry1Stem.name = 'berry1Stem';
  berry1Stem.position.set(0.01, 1.08, 0);
  berry1Stem.rotation.set(0, 0, deg(14));
  berry1Core.add(berry1Stem);

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

export default createStrawberry;

評価とコメント

—
まだ評価はありません。最初の評価をしてみましょう。
5
0
4
0
3
0
2
0
1
0

評価やコメントをするにはログインしてください。

0 件のコメント

まだコメントはありません。このモデルの使い方や改善できる点を共有しましょう。

関連モデル

同じカテゴリまたは似たタグ