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

  // Materials
  const shellMat = new THREE.MeshStandardMaterial({ name: 'shell', color: 0xe2482f, roughness: 0.45, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0xa33422, roughness: 0.5, flatShading: true });
  const bellyMat = new THREE.MeshStandardMaterial({ name: 'belly', color: 0xf7c2ac, roughness: 0.6, flatShading: true });
  const eyeWhiteMat = new THREE.MeshStandardMaterial({ name: 'eyeWhite', color: 0xfbfaf6, roughness: 0.3, flatShading: true });
  const pupilMat = new THREE.MeshStandardMaterial({ name: 'pupil', color: 0x161317, roughness: 0.25, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.009, 0.012, 0.08, 5);
  const sphereGeo = new THREE.SphereGeometry(0.027, 8, 6);
  const sphereGeo2 = new THREE.SphereGeometry(0.014, 6, 4);
  const boxGeo = new THREE.BoxGeometry(0.006, 0.006, 0.003);
  const boxGeo2 = new THREE.BoxGeometry(0.028, 0.1257, 0.028);
  const boxGeo3 = new THREE.BoxGeometry(0.024, 0.1526, 0.024);
  const boxGeo4 = new THREE.BoxGeometry(0.028, 0.1261, 0.028);
  const boxGeo5 = new THREE.BoxGeometry(0.024, 0.153, 0.024);
  const boxGeo6 = new THREE.BoxGeometry(0.028, 0.1275, 0.028);
  const boxGeo7 = new THREE.BoxGeometry(0.024, 0.1578, 0.024);
  const boxGeo8 = new THREE.BoxGeometry(0.036, 0.119, 0.036);
  const boxGeo9 = new THREE.BoxGeometry(0.04, 0.121, 0.04);
  const extrudeGeo = extrude([[-0.035, -0.035], [0.04, -0.05], [0.11, -0.04], [0.16, -0.008], [0.12, -0.012], [0.075, -0.005], [0.05, 0.03], [0.01, 0.048], [-0.03, 0.035]], 0.034, [], [0.008, 0.008, 1]);
  const extrudeGeo2 = extrude([[0, -0.012], [0.04, 0.012], [0.085, 0.012], [0.115, -0.012], [0.075, -0.004], [0.035, -0.014]], 0.026, [], [0.008, 0.008, 1]);

  // Parts
  const crab = new THREE.Group();
  crab.name = 'crab';
  crab.scale.setScalar(0.6);
  root.add(crab);
  const body = new THREE.Group();
  body.name = 'body';
  crab.add(body);
  const shell = new THREE.Mesh(new THREE.SphereGeometry(1, 12, 7), shellMat);
  shell.name = 'shell';
  shell.position.set(0, 0.09, 0);
  shell.scale.set(0.15, 0.068, 0.115);
  body.add(shell);
  const underside = new THREE.Mesh(new THREE.SphereGeometry(1, 12, 5), bellyMat);
  underside.name = 'underside';
  underside.position.set(0, 0.068, 0.004);
  underside.scale.set(0.145, 0.05, 0.11);
  body.add(underside);
  const shellSpot = new THREE.Mesh(new THREE.SphereGeometry(0.022, 6, 3), darkMat);
  shellSpot.name = 'shellSpot';
  shellSpot.position.set(0.06, 0.1457, -0.03);
  shellSpot.scale.set(1, 0.3, 1);
  body.add(shellSpot);
  const shellSpot2 = new THREE.Mesh(new THREE.SphereGeometry(0.018, 6, 3), darkMat);
  shellSpot2.name = 'shellSpot';
  shellSpot2.position.set(-0.07, 0.145, -0.02);
  shellSpot2.scale.set(1, 0.3, 1);
  body.add(shellSpot2);
  const shellSpot3 = new THREE.Mesh(new THREE.SphereGeometry(0.016, 6, 3), darkMat);
  shellSpot3.name = 'shellSpot';
  shellSpot3.position.set(0, 0.1421, -0.065);
  shellSpot3.scale.set(1, 0.3, 1);
  body.add(shellSpot3);
  const shellSpot4 = new THREE.Mesh(new THREE.SphereGeometry(0.014, 6, 3), darkMat);
  shellSpot4.name = 'shellSpot';
  shellSpot4.position.set(-0.02, 0.151, 0.03);
  shellSpot4.scale.set(1, 0.3, 1);
  body.add(shellSpot4);
  const mouth = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.008, 0.008), pupilMat);
  mouth.name = 'mouth';
  mouth.position.set(0, 0.086, 0.112);
  body.add(mouth);
  const eyeStalkL = new THREE.Mesh(cylinderGeo, shellMat);
  eyeStalkL.name = 'eyeStalkL';
  eyeStalkL.position.set(0.042, 0.175, 0.07);
  eyeStalkL.rotation.set(deg(10), 0, deg(-8));
  body.add(eyeStalkL);
  const eyeL = new THREE.Mesh(sphereGeo, eyeWhiteMat);
  eyeL.name = 'eyeL';
  eyeL.position.set(0.048, 0.22, 0.077);
  body.add(eyeL);
  const pupilL = new THREE.Mesh(sphereGeo2, pupilMat);
  pupilL.name = 'pupilL';
  pupilL.position.set(0.046, 0.222, 0.1);
  pupilL.scale.set(1, 1.15, 0.5);
  body.add(pupilL);
  const eyeShineL = new THREE.Mesh(boxGeo, eyeWhiteMat);
  eyeShineL.name = 'eyeShineL';
  eyeShineL.position.set(0.051, 0.228, 0.107);
  body.add(eyeShineL);
  const eyeStalkR = new THREE.Mesh(cylinderGeo, shellMat);
  eyeStalkR.name = 'eyeStalkR';
  eyeStalkR.position.set(-0.042, 0.175, 0.07);
  eyeStalkR.rotation.set(deg(10), 0, deg(8));
  body.add(eyeStalkR);
  const eyeR = new THREE.Mesh(sphereGeo, eyeWhiteMat);
  eyeR.name = 'eyeR';
  eyeR.position.set(-0.048, 0.22, 0.077);
  body.add(eyeR);
  const pupilR = new THREE.Mesh(sphereGeo2, pupilMat);
  pupilR.name = 'pupilR';
  pupilR.position.set(-0.046, 0.222, 0.1);
  pupilR.scale.set(1, 1.15, 0.5);
  body.add(pupilR);
  const eyeShineR = new THREE.Mesh(boxGeo, eyeWhiteMat);
  eyeShineR.name = 'eyeShineR';
  eyeShineR.position.set(-0.041, 0.228, 0.107);
  body.add(eyeShineR);
  const legL1 = new THREE.Group();
  legL1.name = 'legL1';
  legL1.position.set(0.11, 0.09, 0.035);
  crab.add(legL1);
  const legUpper = new THREE.Mesh(boxGeo2, shellMat);
  legUpper.name = 'legUpper';
  legUpper.position.set(0.05, 0.0225, 0);
  legUpper.rotation.set(deg(-90), deg(-24.2277), deg(-90));
  legL1.add(legUpper);
  const legLower = new THREE.Mesh(boxGeo3, darkMat);
  legLower.name = 'legLower';
  legLower.position.set(0.1275, -0.0195, 0.005);
  legLower.rotation.set(deg(-67.5692), deg(64.5221), deg(-114.5731));
  legL1.add(legLower);
  const legL2 = new THREE.Group();
  legL2.name = 'legL2';
  legL2.position.set(0.11, 0.09, -0.02);
  crab.add(legL2);
  const legUpper2 = new THREE.Mesh(boxGeo4, shellMat);
  legUpper2.name = 'legUpper';
  legUpper2.position.set(0.05, 0.0225, -0.005);
  legUpper2.rotation.set(deg(-87.4489), deg(-23.994), deg(-83.7472));
  legL2.add(legUpper2);
  const legLower2 = new THREE.Mesh(boxGeo5, darkMat);
  legLower2.name = 'legLower';
  legLower2.position.set(0.1275, -0.0195, -0.0175);
  legLower2.rotation.set(deg(-120.7689), deg(61.9374), deg(-55.9922));
  legL2.add(legLower2);
  const legL3 = new THREE.Group();
  legL3.name = 'legL3';
  legL3.position.set(0.11, 0.09, -0.07);
  crab.add(legL3);
  const legUpper3 = new THREE.Mesh(boxGeo6, shellMat);
  legUpper3.name = 'legUpper';
  legUpper3.position.set(0.05, 0.0225, -0.01);
  legUpper3.rotation.set(deg(-85.054), deg(-23.32), deg(-77.6688));
  legL3.add(legUpper3);
  const legLower3 = new THREE.Mesh(boxGeo7, darkMat);
  legLower3.name = 'legLower';
  legLower3.position.set(0.1275, -0.0195, -0.04);
  legLower3.rotation.set(deg(-138.1296), deg(45.6766), deg(-32.6693));
  legL3.add(legLower3);
  const legR1 = new THREE.Group();
  legR1.name = 'legR1';
  legR1.position.set(-0.11, 0.09, 0.035);
  crab.add(legR1);
  const legUpper4 = new THREE.Mesh(boxGeo2, shellMat);
  legUpper4.name = 'legUpper';
  legUpper4.position.set(-0.05, 0.0225, 0);
  legUpper4.rotation.set(deg(-90), deg(24.2277), deg(90));
  legR1.add(legUpper4);
  const legLower4 = new THREE.Mesh(boxGeo3, darkMat);
  legLower4.name = 'legLower';
  legLower4.position.set(-0.1275, -0.0195, 0.005);
  legLower4.rotation.set(deg(-67.5692), deg(-64.5221), deg(114.5731));
  legR1.add(legLower4);
  const legR2 = new THREE.Group();
  legR2.name = 'legR2';
  legR2.position.set(-0.11, 0.09, -0.02);
  crab.add(legR2);
  const legUpper5 = new THREE.Mesh(boxGeo4, shellMat);
  legUpper5.name = 'legUpper';
  legUpper5.position.set(-0.05, 0.0225, -0.005);
  legUpper5.rotation.set(deg(-87.4489), deg(23.994), deg(83.7472));
  legR2.add(legUpper5);
  const legLower5 = new THREE.Mesh(boxGeo5, darkMat);
  legLower5.name = 'legLower';
  legLower5.position.set(-0.1275, -0.0195, -0.0175);
  legLower5.rotation.set(deg(-120.7689), deg(-61.9374), deg(55.9922));
  legR2.add(legLower5);
  const legR3 = new THREE.Group();
  legR3.name = 'legR3';
  legR3.position.set(-0.11, 0.09, -0.07);
  crab.add(legR3);
  const legUpper6 = new THREE.Mesh(boxGeo6, shellMat);
  legUpper6.name = 'legUpper';
  legUpper6.position.set(-0.05, 0.0225, -0.01);
  legUpper6.rotation.set(deg(-85.054), deg(23.32), deg(77.6688));
  legR3.add(legUpper6);
  const legLower6 = new THREE.Mesh(boxGeo7, darkMat);
  legLower6.name = 'legLower';
  legLower6.position.set(-0.1275, -0.0195, -0.04);
  legLower6.rotation.set(deg(-138.1296), deg(-45.6766), deg(32.6693));
  legR3.add(legLower6);
  const clawL = new THREE.Group();
  clawL.name = 'clawL';
  clawL.position.set(0.11, 0.1, 0.07);
  crab.add(clawL);
  const clawArmL = new THREE.Mesh(boxGeo8, shellMat);
  clawArmL.name = 'clawArmL';
  clawArmL.position.set(0.04, 0.015, 0.025);
  clawArmL.rotation.set(deg(-99.5667), deg(-14.8911), deg(-123.2585));
  clawL.add(clawArmL);
  const clawForearmL = new THREE.Mesh(boxGeo9, shellMat);
  clawForearmL.name = 'clawForearmL';
  clawForearmL.position.set(0.09, 0.065, 0.085);
  clawForearmL.rotation.set(deg(-132.7543), deg(-10.9767), deg(-168.3624));
  clawL.add(clawForearmL);
  const pincerL = new THREE.Group();
  pincerL.name = 'pincerL';
  pincerL.position.set(0.1, 0.1, 0.12);
  pincerL.rotation.set(deg(-38), deg(18), 0);
  clawL.add(pincerL);
  const clawPalmL = new THREE.Mesh(extrudeGeo, shellMat);
  clawPalmL.name = 'clawPalmL';
  clawPalmL.rotation.set(0, deg(-90), 0);
  pincerL.add(clawPalmL);
  const clawDactylL = new THREE.Group();
  clawDactylL.name = 'clawDactylL';
  clawDactylL.position.set(0, 0.03, 0.045);
  clawDactylL.rotation.set(deg(-26), 0, 0);
  pincerL.add(clawDactylL);
  const clawTipL = new THREE.Mesh(extrudeGeo2, darkMat);
  clawTipL.name = 'clawTipL';
  clawTipL.rotation.set(0, deg(-90), 0);
  clawDactylL.add(clawTipL);
  const clawR = new THREE.Group();
  clawR.name = 'clawR';
  clawR.position.set(-0.11, 0.1, 0.07);
  crab.add(clawR);
  const clawArmR = new THREE.Mesh(boxGeo8, shellMat);
  clawArmR.name = 'clawArmR';
  clawArmR.position.set(-0.04, 0.015, 0.025);
  clawArmR.rotation.set(deg(-99.5667), deg(14.8911), deg(123.2585));
  clawR.add(clawArmR);
  const clawForearmR = new THREE.Mesh(boxGeo9, shellMat);
  clawForearmR.name = 'clawForearmR';
  clawForearmR.position.set(-0.09, 0.065, 0.085);
  clawForearmR.rotation.set(deg(-132.7543), deg(10.9767), deg(168.3624));
  clawR.add(clawForearmR);
  const pincerR = new THREE.Group();
  pincerR.name = 'pincerR';
  pincerR.position.set(-0.1, 0.1, 0.12);
  pincerR.rotation.set(deg(-38), deg(-18), 0);
  clawR.add(pincerR);
  const clawPalmR = new THREE.Mesh(extrudeGeo, shellMat);
  clawPalmR.name = 'clawPalmR';
  clawPalmR.rotation.set(0, deg(-90), 0);
  pincerR.add(clawPalmR);
  const clawDactylR = new THREE.Group();
  clawDactylR.name = 'clawDactylR';
  clawDactylR.position.set(0, 0.03, 0.045);
  clawDactylR.rotation.set(deg(-26), 0, 0);
  pincerR.add(clawDactylR);
  const clawTipR = new THREE.Mesh(extrudeGeo2, darkMat);
  clawTipR.name = 'clawTipR';
  clawTipR.rotation.set(0, deg(-90), 0);
  clawDactylR.add(clawTipR);

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

export default createCrab;

評価とコメント

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

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

0 件のコメント

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

関連モデル

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