Codels
1016 ポリゴン1.41 × 2.00 × 0.61 m
自己完結型の ES モジュールで、依存先は three のみです。ファクトリー関数を呼び出し、返された group をシーンに追加してください。
/**
 * Scarecrow — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,016 · Size (W × H × D): 1.41 × 2.00 × 0.61 m
 *
 * Usage:
 *   import { createScarecrow } from './scarecrow.js';
 *   
 *   const model = createScarecrow();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Deterministic vertex displacement (organic low-poly look).
function jitter(geometry, amount, seed) {
  const pos = geometry.attributes.position;
  const h = (a, b, c, s) => {
    let x = Math.imul(a, 73856093) ^ Math.imul(b, 19349663) ^ Math.imul(c, 83492791) ^ Math.imul(s, 2654435761);
    x = Math.imul(x ^ (x >>> 16), 2246822507);
    x = Math.imul(x ^ (x >>> 13), 3266489909);
    return ((x ^ (x >>> 16)) >>> 0) / 4294967295 - 0.5;
  };
  for (let i = 0; i < pos.count; i++) {
    const x = pos.getX(i), y = pos.getY(i), z = pos.getZ(i);
    const qx = Math.round(x * 1000), qy = Math.round(y * 1000), qz = Math.round(z * 1000);
    pos.setXYZ(i, x + h(qx, qy, qz, seed) * 2 * amount, y + h(qx, qy, qz, seed + 1) * 2 * amount, z + h(qx, qy, qz, seed + 2) * 2 * amount);
  }
  pos.needsUpdate = true;
  geometry.computeVertexNormals();
  return geometry;
}

export function createScarecrow() {
  const root = new THREE.Group();
  root.name = 'Scarecrow';

  // Materials
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x7a5634, roughness: 0.9, flatShading: true });
  const dirtMat = new THREE.MeshStandardMaterial({ name: 'dirt', color: 0x5e4129, roughness: 1, flatShading: true });
  const strawMat = new THREE.MeshStandardMaterial({ name: 'straw', color: 0xe0be5c, roughness: 0.9, flatShading: true });
  const shirtMat = new THREE.MeshStandardMaterial({ name: 'shirt', color: 0xb4483a, roughness: 0.95, flatShading: true });
  const pantsMat = new THREE.MeshStandardMaterial({ name: 'pants', color: 0x4a5f86, roughness: 0.95, flatShading: true });
  const burlapMat = new THREE.MeshStandardMaterial({ name: 'burlap', color: 0xc4a274, roughness: 1, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x24211f, roughness: 0.8, flatShading: true });
  const pumpkinMat = new THREE.MeshStandardMaterial({ name: 'pumpkin', color: 0xe5791f, roughness: 0.75, flatShading: true });

  // Shared geometries
  const cylinderGeo = new THREE.CylinderGeometry(0.014, 0.014, 0.008, 6);
  const boxGeo = new THREE.BoxGeometry(0.05, 0.012, 0.006);
  const boxGeo2 = new THREE.BoxGeometry(0.007, 0.032, 0.006);
  const boxGeo3 = new THREE.BoxGeometry(0.008, 0.03, 0.012);

  // Parts
  const mound = new THREE.Mesh(jitter(new THREE.SphereGeometry(0.3, 8, 3, 0, Math.PI * 2, 0, Math.PI / 2), 0.02, 3), dirtMat);
  mound.name = 'mound';
  mound.scale.set(1, 0.28, 1);
  root.add(mound);
  const post = new THREE.Mesh(new THREE.BoxGeometry(0.07, 1.8, 0.07), woodMat);
  post.name = 'post';
  post.position.set(0, 0.9, 0);
  root.add(post);
  const crossbar = new THREE.Mesh(new THREE.BoxGeometry(1.36, 0.06, 0.06), woodMat);
  crossbar.name = 'crossbar';
  crossbar.position.set(0, 1.42, 0);
  crossbar.rotation.set(0, 0, deg(2));
  root.add(crossbar);
  const shirt = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.22, 0.19, 0.56, 7), 0.012, 4), shirtMat);
  shirt.name = 'shirt';
  shirt.position.set(0, 1.2, 0);
  shirt.scale.set(1, 1, 0.62);
  root.add(shirt);
  const sleeve = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.072, 0.088, 0.42, 6), 0.01, 5), shirtMat);
  sleeve.name = 'sleeve';
  sleeve.position.set(0.35, 1.4325, 0);
  sleeve.rotation.set(0, 0, deg(-89.3179));
  root.add(sleeve);
  const straw = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1435, 4), strawMat);
  straw.name = 'straw';
  straw.position.set(0.6312, 1.4112, 0.0105);
  straw.rotation.set(deg(11.0113), deg(-16.2092), deg(-111.8137));
  root.add(straw);
  const straw2 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1404, 4), strawMat);
  straw2.name = 'straw';
  straw2.position.set(0.6318, 1.4173, -0.0123);
  straw2.rotation.set(deg(-13.2326), deg(17.1648), deg(-104.9113));
  root.add(straw2);
  const straw3 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1568, 4), strawMat);
  straw3.name = 'straw';
  straw3.position.set(0.6361, 1.4072, 0.0041);
  straw3.rotation.set(deg(3.7235), deg(-5.9561), deg(-116.0044));
  root.add(straw3);
  const straw4 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1209, 4), strawMat);
  straw4.name = 'straw';
  straw4.position.set(0.6238, 1.4193, 0.0134);
  straw4.rotation.set(deg(17.3391), deg(-21.7494), deg(-103.1225));
  root.add(straw4);
  const sleeve2 = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.072, 0.088, 0.4207, 6), 0.01, 6), shirtMat);
  sleeve2.name = 'sleeve';
  sleeve2.position.set(-0.35, 1.4175, 0);
  sleeve2.rotation.set(0, 0, deg(93.4064));
  root.add(sleeve2);
  const straw5 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1323, 4), strawMat);
  straw5.name = 'straw';
  straw5.position.set(-0.6264, 1.3796, -0.0001);
  straw5.rotation.set(deg(-0.1552), deg(-0.262), deg(118.7127));
  root.add(straw5);
  const straw6 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1428, 4), strawMat);
  straw6.name = 'straw';
  straw6.position.set(-0.6209, 1.3661, 0.0088);
  straw6.rotation.set(deg(9.4319), deg(20.1907), deg(130.2793));
  root.add(straw6);
  const straw7 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1529, 4), strawMat);
  straw7.name = 'straw';
  straw7.position.set(-0.6367, 1.3968, 0.0213);
  straw7.rotation.set(deg(22.0119), deg(21.8734), deg(89.6293));
  root.add(straw7);
  const straw8 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1155, 4), strawMat);
  straw8.name = 'straw';
  straw8.position.set(-0.6237, 1.3911, -0.0055);
  straw8.rotation.set(deg(-6.9057), deg(-9.2498), deg(106.5647));
  root.add(straw8);
  const straw9 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.0801, 4), strawMat);
  straw9.name = 'straw';
  straw9.position.set(0.005, 1.5306, 0.0482);
  straw9.rotation.set(deg(14.8484), deg(-1.1686), deg(-8.9499));
  root.add(straw9);
  const straw10 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.0952, 4), strawMat);
  straw10.name = 'straw';
  straw10.position.set(0.0085, 1.5294, 0.0627);
  straw10.rotation.set(deg(36.667), deg(-4.2775), deg(-12.8603));
  root.add(straw10);
  const straw11 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1037, 4), strawMat);
  straw11.name = 'straw';
  straw11.position.set(0.012, 1.5223, 0.0729);
  straw11.rotation.set(deg(53.2936), deg(-8.5558), deg(-16.9576));
  root.add(straw11);
  const shirtPatch = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.09, 0.008), pantsMat);
  shirtPatch.name = 'shirtPatch';
  shirtPatch.position.set(0.0911, 1.2398, 0.1086);
  shirtPatch.rotation.set(deg(2.306), deg(16.1074), deg(7.6737));
  root.add(shirtPatch);
  const button = new THREE.Mesh(cylinderGeo, darkMat);
  button.name = 'button';
  button.position.set(-0.0212, 1.3599, 0.1301);
  button.rotation.set(deg(86.1674), deg(17.2521), deg(18.4266));
  root.add(button);
  const button2 = new THREE.Mesh(cylinderGeo, darkMat);
  button2.name = 'button';
  button2.position.set(-0.0212, 1.2199, 0.1256);
  button2.rotation.set(deg(86.1674), deg(17.2521), deg(18.4266));
  root.add(button2);
  const button3 = new THREE.Mesh(cylinderGeo, darkMat);
  button3.name = 'button';
  button3.position.set(-0.0212, 1.0799, 0.1212);
  button3.rotation.set(deg(86.1674), deg(17.2521), deg(18.4266));
  root.add(button3);
  const ropeBelt = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.2, 0.04, 7), strawMat);
  ropeBelt.name = 'ropeBelt';
  ropeBelt.position.set(0, 0.95, 0);
  ropeBelt.scale.set(1, 1, 0.66);
  root.add(ropeBelt);
  const trousersTop = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.2, 0.21, 0.16, 7), 0.008, 7), pantsMat);
  trousersTop.name = 'trousersTop';
  trousersTop.position.set(0, 0.88, 0);
  trousersTop.scale.set(1, 1, 0.66);
  root.add(trousersTop);
  const trouserLeg = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.078, 0.088, 0.4614, 6), 0.01, 8), pantsMat);
  trouserLeg.name = 'trouserLeg';
  trouserLeg.position.set(0.115, 0.63, 0.01);
  trouserLeg.rotation.set(deg(6.4144), deg(-67.1708), deg(-170.3529));
  root.add(trouserLeg);
  const straw12 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1462, 4), strawMat);
  straw12.name = 'straw';
  straw12.position.set(0.1333, 0.323, 0.0075);
  straw12.rotation.set(deg(-165.8543), deg(28.9681), deg(-3.6715));
  root.add(straw12);
  const straw13 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1296, 4), strawMat);
  straw13.name = 'straw';
  straw13.position.set(0.1402, 0.3296, 0.0133);
  straw13.rotation.set(deg(-17.6791), deg(64.8005), deg(-152.462));
  root.add(straw13);
  const straw14 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1072, 4), strawMat);
  straw14.name = 'straw';
  straw14.position.set(0.1424, 0.3396, 0.027);
  straw14.rotation.set(deg(17.0032), deg(-56.0951), deg(-148.6551));
  root.add(straw14);
  const straw15 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.126, 4), strawMat);
  straw15.name = 'straw';
  straw15.position.set(0.1369, 0.3386, 0.0479);
  straw15.rotation.set(deg(142.244), deg(-25.1131), deg(-8.7107));
  root.add(straw15);
  const trouserLeg2 = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.078, 0.088, 0.4614, 6), 0.01, 9), pantsMat);
  trouserLeg2.name = 'trouserLeg';
  trouserLeg2.position.set(-0.115, 0.63, 0.01);
  trouserLeg2.rotation.set(deg(6.4144), deg(67.1708), deg(170.3529));
  root.add(trouserLeg2);
  const straw16 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1409, 4), strawMat);
  straw16.name = 'straw';
  straw16.position.set(-0.1408, 0.3271, 0.0038);
  straw16.rotation.set(deg(-140.1125), deg(-63.3403), deg(25.2348));
  root.add(straw16);
  const straw17 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1322, 4), strawMat);
  straw17.name = 'straw';
  straw17.position.set(-0.1486, 0.3309, 0.0134);
  straw17.rotation.set(deg(-9.0434), deg(-37.4345), deg(153.7237));
  root.add(straw17);
  const straw18 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1108, 4), strawMat);
  straw18.name = 'straw';
  straw18.position.set(-0.1499, 0.3428, 0.0064);
  straw18.rotation.set(deg(-36.2587), deg(-58.8349), deg(119.7161));
  root.add(straw18);
  const straw19 = new THREE.Mesh(new THREE.ConeGeometry(0.028, 0.1231, 4), strawMat);
  straw19.name = 'straw';
  straw19.position.set(-0.1337, 0.3332, 0.0053);
  straw19.rotation.set(deg(-160.3141), deg(-27.7692), deg(4.9116));
  root.add(straw19);
  const kneePatch = new THREE.Mesh(new THREE.BoxGeometry(0.08, 0.08, 0.008), shirtMat);
  kneePatch.name = 'kneePatch';
  kneePatch.position.set(-0.1171, 0.5603, 0.1002);
  kneePatch.rotation.set(deg(-4.7693), deg(-32.038), deg(-11.37));
  root.add(kneePatch);
  const sackNeck = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.06, 0.1, 0.1, 7), 0.006, 2), burlapMat);
  sackNeck.name = 'sackNeck';
  sackNeck.position.set(0, 1.52, 0);
  root.add(sackNeck);
  const neckRope = new THREE.Mesh(new THREE.CylinderGeometry(0.068, 0.068, 0.028, 7), strawMat);
  neckRope.name = 'neckRope';
  neckRope.position.set(0, 1.544, 0);
  root.add(neckRope);
  const sackHead = new THREE.Mesh(jitter(new THREE.SphereGeometry(0.16, 8, 6), 0.012, 12), burlapMat);
  sackHead.name = 'sackHead';
  sackHead.position.set(0, 1.69, 0);
  sackHead.scale.set(1, 1.12, 0.95);
  root.add(sackHead);
  const eyeStitch = new THREE.Mesh(boxGeo, darkMat);
  eyeStitch.name = 'eyeStitch';
  eyeStitch.position.set(0.0594, 1.7309, 0.1184);
  eyeStitch.rotation.set(deg(-14.0106), deg(21.1865), deg(47.633));
  root.add(eyeStitch);
  const eyeStitch2 = new THREE.Mesh(boxGeo, darkMat);
  eyeStitch2.name = 'eyeStitch';
  eyeStitch2.position.set(0.0594, 1.7309, 0.1184);
  eyeStitch2.rotation.set(deg(-14.0106), deg(21.1865), deg(-42.367));
  root.add(eyeStitch2);
  const eyeStitch3 = new THREE.Mesh(boxGeo, darkMat);
  eyeStitch3.name = 'eyeStitch';
  eyeStitch3.position.set(-0.0589, 1.7309, 0.1222);
  eyeStitch3.rotation.set(deg(-12.9914), deg(-13.4616), deg(43.4603));
  root.add(eyeStitch3);
  const eyeStitch4 = new THREE.Mesh(boxGeo, darkMat);
  eyeStitch4.name = 'eyeStitch';
  eyeStitch4.position.set(-0.0589, 1.7309, 0.1222);
  eyeStitch4.rotation.set(deg(-12.9914), deg(-13.4616), deg(-46.5397));
  root.add(eyeStitch4);
  const mouthStitch = new THREE.Mesh(new THREE.BoxGeometry(0.12, 0.009, 0.006), darkMat);
  mouthStitch.name = 'mouthStitch';
  mouthStitch.position.set(-0.0009, 1.6241, 0.1349);
  mouthStitch.rotation.set(deg(13.4726), deg(-12.8393), deg(-2.4772));
  root.add(mouthStitch);
  const mouthTick = new THREE.Mesh(boxGeo2, darkMat);
  mouthTick.name = 'mouthTick';
  mouthTick.position.set(-0.0491, 1.6218, 0.1223);
  mouthTick.rotation.set(deg(17.6124), deg(-15.3553), deg(-1.6072));
  root.add(mouthTick);
  const mouthTick2 = new THREE.Mesh(boxGeo2, darkMat);
  mouthTick2.name = 'mouthTick';
  mouthTick2.position.set(-0.0249, 1.6231, 0.1291);
  mouthTick2.rotation.set(deg(13.4726), deg(-12.8393), deg(-2.4772));
  root.add(mouthTick2);
  const mouthTick3 = new THREE.Mesh(boxGeo2, darkMat);
  mouthTick3.name = 'mouthTick';
  mouthTick3.position.set(-0.0009, 1.6241, 0.1349);
  mouthTick3.rotation.set(deg(13.4726), deg(-12.8393), deg(-2.4772));
  root.add(mouthTick3);
  const mouthTick4 = new THREE.Mesh(boxGeo2, darkMat);
  mouthTick4.name = 'mouthTick';
  mouthTick4.position.set(0.025, 1.6251, 0.1331);
  mouthTick4.rotation.set(deg(13.7943), deg(15.2058), deg(-5.8501));
  root.add(mouthTick4);
  const mouthTick5 = new THREE.Mesh(boxGeo2, darkMat);
  mouthTick5.name = 'mouthTick';
  mouthTick5.position.set(0.049, 1.6261, 0.1266);
  mouthTick5.rotation.set(deg(13.7943), deg(15.2058), deg(-5.8501));
  root.add(mouthTick5);
  const hat = new THREE.Group();
  hat.name = 'hat';
  hat.position.set(0, 1.82, 0);
  hat.rotation.set(deg(-6), 0, deg(-9));
  root.add(hat);
  const hatBrim = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.3, 0.3, 0.018, 10), 0.006, 21), strawMat);
  hatBrim.name = 'hatBrim';
  hatBrim.position.set(0, 0.009, 0);
  hat.add(hatBrim);
  const hatCrown = new THREE.Mesh(new THREE.CylinderGeometry(0.13, 0.155, 0.14, 8), strawMat);
  hatCrown.name = 'hatCrown';
  hatCrown.position.set(0, 0.082, 0);
  hat.add(hatCrown);
  const hatBand = new THREE.Mesh(new THREE.CylinderGeometry(0.158, 0.158, 0.032, 8), pantsMat);
  hatBand.name = 'hatBand';
  hatBand.position.set(0, 0.03, 0);
  hat.add(hatBand);
  const hatStraw = new THREE.Mesh(new THREE.ConeGeometry(0.03, 0.09, 4), strawMat);
  hatStraw.name = 'hatStraw';
  hatStraw.position.set(0.12, 0.04, 0.12);
  hatStraw.rotation.set(deg(70), 0, deg(-20));
  hat.add(hatStraw);
  const crow = new THREE.Group();
  crow.name = 'crow';
  crow.position.set(0.47, 1.5, 0);
  crow.rotation.set(0, deg(35), 0);
  crow.scale.setScalar(1.5);
  root.add(crow);
  const crowBody = new THREE.Mesh(new THREE.SphereGeometry(0.055, 7, 5), darkMat);
  crowBody.name = 'crowBody';
  crowBody.position.set(0, 0.055, 0);
  crowBody.scale.set(0.78, 0.82, 1.3);
  crow.add(crowBody);
  const crowHead = new THREE.Mesh(new THREE.SphereGeometry(0.036, 7, 5), darkMat);
  crowHead.name = 'crowHead';
  crowHead.position.set(0, 0.11, 0.06);
  crow.add(crowHead);
  const crowBeak = new THREE.Mesh(new THREE.ConeGeometry(0.013, 0.045, 4), pumpkinMat);
  crowBeak.name = 'crowBeak';
  crowBeak.position.set(0, 0.105, 0.11);
  crowBeak.rotation.set(deg(90), 0, 0);
  crow.add(crowBeak);
  const crowTail = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.012, 0.09), darkMat);
  crowTail.name = 'crowTail';
  crowTail.position.set(0, 0.045, -0.09);
  crowTail.rotation.set(deg(-25), 0, 0);
  crow.add(crowTail);
  const crowLeg = new THREE.Mesh(boxGeo3, pumpkinMat);
  crowLeg.name = 'crowLeg';
  crowLeg.position.set(0.016, 0.015, 0);
  crow.add(crowLeg);
  const crowLeg2 = new THREE.Mesh(boxGeo3, pumpkinMat);
  crowLeg2.name = 'crowLeg';
  crowLeg2.position.set(-0.016, 0.015, 0);
  crow.add(crowLeg2);

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

export default createScarecrow;

評価とコメント

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

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

0 件のコメント

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

関連モデル

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