1 k tris1,41 × 2,00 × 0,61 m
Utiliser dans le code
Remixer dans l’éditeurscarecrow.js · 354 lignes
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
* 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;
Notes et commentaires
0 commentaire
Aucun commentaire pour l’instant. Dites comment vous avez utilisé ce modèle ou ce qui pourrait être amélioré.
Modèles similaires
Même catégorie ou étiquettes proches









