1,4 k tris0,78 × 0,87 × 1,18 m
Utiliser dans le code
Remixer dans l’éditeursheep.js · 233 lignes
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
* Sheep — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,404 · Size (W × H × D): 0.78 × 0.87 × 1.18 m
*
* Usage:
* import { createSheep } from './sheep.js';
*
* const model = createSheep();
* 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 createSheep() {
const root = new THREE.Group();
root.name = 'Sheep';
// Materials
const woolMat = new THREE.MeshStandardMaterial({ name: 'wool', color: 0xede6d8, roughness: 1, flatShading: true });
const faceMat = new THREE.MeshStandardMaterial({ name: 'face', color: 0x3a3231, roughness: 0.85, flatShading: true });
const hoofMat = new THREE.MeshStandardMaterial({ name: 'hoof', color: 0x231d1c, roughness: 0.7, flatShading: true });
const eyeWhiteMat = new THREE.MeshStandardMaterial({ name: 'eyeWhite', color: 0xfbfaf6, roughness: 0.5, flatShading: true });
const pupilMat = new THREE.MeshStandardMaterial({ name: 'pupil', color: 0x141112, roughness: 0.3, flatShading: true });
const noseMat = new THREE.MeshStandardMaterial({ name: 'nose', color: 0xd98c8c, roughness: 0.6, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.1, 0.22, 0.1);
const boxGeo2 = new THREE.BoxGeometry(0.11, 0.05, 0.115);
const boxGeo3 = new THREE.BoxGeometry(0.08, 0.085, 0.012);
const boxGeo4 = new THREE.BoxGeometry(0.04, 0.055, 0.01);
const boxGeo5 = new THREE.BoxGeometry(0.13, 0.05, 0.08);
// Parts
const legFL = new THREE.Group();
legFL.name = 'legFL';
legFL.position.set(0.13, 0.27, 0.17);
root.add(legFL);
const legFLUpper = new THREE.Mesh(boxGeo, faceMat);
legFLUpper.name = 'legFLUpper';
legFLUpper.position.set(0, -0.11, 0);
legFL.add(legFLUpper);
const legFLHoof = new THREE.Mesh(boxGeo2, hoofMat);
legFLHoof.name = 'legFLHoof';
legFLHoof.position.set(0, -0.245, 0.005);
legFL.add(legFLHoof);
const legFR = new THREE.Group();
legFR.name = 'legFR';
legFR.position.set(-0.13, 0.27, 0.17);
root.add(legFR);
const legFRUpper = new THREE.Mesh(boxGeo, faceMat);
legFRUpper.name = 'legFRUpper';
legFRUpper.position.set(0, -0.11, 0);
legFR.add(legFRUpper);
const legFRHoof = new THREE.Mesh(boxGeo2, hoofMat);
legFRHoof.name = 'legFRHoof';
legFRHoof.position.set(0, -0.245, 0.005);
legFR.add(legFRHoof);
const legBL = new THREE.Group();
legBL.name = 'legBL';
legBL.position.set(0.13, 0.27, -0.19);
root.add(legBL);
const legBLUpper = new THREE.Mesh(boxGeo, faceMat);
legBLUpper.name = 'legBLUpper';
legBLUpper.position.set(0, -0.11, 0);
legBL.add(legBLUpper);
const legBLHoof = new THREE.Mesh(boxGeo2, hoofMat);
legBLHoof.name = 'legBLHoof';
legBLHoof.position.set(0, -0.245, 0.005);
legBL.add(legBLHoof);
const legBR = new THREE.Group();
legBR.name = 'legBR';
legBR.position.set(-0.13, 0.27, -0.19);
root.add(legBR);
const legBRUpper = new THREE.Mesh(boxGeo, faceMat);
legBRUpper.name = 'legBRUpper';
legBRUpper.position.set(0, -0.11, 0);
legBR.add(legBRUpper);
const legBRHoof = new THREE.Mesh(boxGeo2, hoofMat);
legBRHoof.name = 'legBRHoof';
legBRHoof.position.set(0, -0.245, 0.005);
legBR.add(legBRHoof);
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const woolCore = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.3, 1), 0.02, 3), woolMat);
woolCore.name = 'woolCore';
woolCore.position.set(0, 0.49, -0.02);
woolCore.scale.set(0.95, 0.82, 1.18);
body.add(woolCore);
const puff1 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.16, 1), 0.022, 11), woolMat);
puff1.name = 'puff1';
puff1.position.set(0, 0.69, 0.12);
body.add(puff1);
const puff2 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.17, 1), 0.022, 12), woolMat);
puff2.name = 'puff2';
puff2.position.set(0, 0.7, -0.14);
puff2.rotation.set(deg(37), deg(53), 0);
body.add(puff2);
const puff3 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.15, 1), 0.022, 13), woolMat);
puff3.name = 'puff3';
puff3.position.set(0.15, 0.64, 0);
puff3.rotation.set(deg(74), deg(106), 0);
body.add(puff3);
const puff4 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.15, 1), 0.022, 14), woolMat);
puff4.name = 'puff4';
puff4.position.set(-0.15, 0.64, -0.06);
puff4.rotation.set(deg(111), deg(159), 0);
body.add(puff4);
const puff5 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.14, 1), 0.022, 15), woolMat);
puff5.name = 'puff5';
puff5.position.set(0.22, 0.49, 0.14);
puff5.rotation.set(deg(148), deg(212), 0);
body.add(puff5);
const puff6 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.15, 1), 0.022, 16), woolMat);
puff6.name = 'puff6';
puff6.position.set(0.23, 0.47, -0.18);
puff6.rotation.set(deg(185), deg(265), 0);
body.add(puff6);
const puff7 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.14, 1), 0.022, 17), woolMat);
puff7.name = 'puff7';
puff7.position.set(-0.22, 0.49, 0.12);
puff7.rotation.set(deg(222), deg(318), 0);
body.add(puff7);
const puff8 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.15, 1), 0.022, 18), woolMat);
puff8.name = 'puff8';
puff8.position.set(-0.23, 0.47, -0.19);
puff8.rotation.set(deg(259), deg(371), 0);
body.add(puff8);
const puff9 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.15, 1), 0.022, 19), woolMat);
puff9.name = 'puff9';
puff9.position.set(0, 0.45, 0.27);
puff9.rotation.set(deg(296), deg(424), 0);
body.add(puff9);
const puff10 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.14, 1), 0.022, 20), woolMat);
puff10.name = 'puff10';
puff10.position.set(0, 0.51, -0.35);
puff10.rotation.set(deg(333), deg(477), 0);
body.add(puff10);
const puff11 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.14, 1), 0.022, 21), woolMat);
puff11.name = 'puff11';
puff11.position.set(0.1, 0.37, -0.02);
puff11.rotation.set(deg(370), deg(530), 0);
body.add(puff11);
const puff12 = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.14, 1), 0.022, 22), woolMat);
puff12.name = 'puff12';
puff12.position.set(-0.1, 0.37, -0.02);
puff12.rotation.set(deg(407), deg(583), 0);
body.add(puff12);
const tail = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.07, 1), 0.012, 41), woolMat);
tail.name = 'tail';
tail.position.set(0, 0.57, -0.44);
body.add(tail);
const head = new THREE.Group();
head.name = 'head';
head.position.set(0, 0.56, 0.4);
root.add(head);
const face = new THREE.Mesh(new THREE.BoxGeometry(0.25, 0.28, 0.24), faceMat);
face.name = 'face';
face.position.set(0, -0.02, 0.1);
head.add(face);
const muzzle = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.07, 0.05), faceMat);
muzzle.name = 'muzzle';
muzzle.position.set(0, -0.11, 0.24);
head.add(muzzle);
const nose = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.03, 0.01), noseMat);
nose.name = 'nose';
nose.position.set(0, -0.095, 0.27);
head.add(nose);
const eyeL = new THREE.Mesh(boxGeo3, eyeWhiteMat);
eyeL.name = 'eyeL';
eyeL.position.set(0.062, 0.015, 0.226);
head.add(eyeL);
const pupilL = new THREE.Mesh(boxGeo4, pupilMat);
pupilL.name = 'pupilL';
pupilL.position.set(0.056, 0.01, 0.235);
head.add(pupilL);
const eyeR = new THREE.Mesh(boxGeo3, eyeWhiteMat);
eyeR.name = 'eyeR';
eyeR.position.set(-0.062, 0.015, 0.226);
head.add(eyeR);
const pupilR = new THREE.Mesh(boxGeo4, pupilMat);
pupilR.name = 'pupilR';
pupilR.position.set(-0.056, 0.01, 0.235);
head.add(pupilR);
const earL = new THREE.Mesh(boxGeo5, faceMat);
earL.name = 'earL';
earL.position.set(0.175, 0.04, 0.08);
earL.rotation.set(0, 0, deg(-28));
head.add(earL);
const earR = new THREE.Mesh(boxGeo5, faceMat);
earR.name = 'earR';
earR.position.set(-0.175, 0.04, 0.08);
earR.rotation.set(0, 0, deg(28));
head.add(earR);
const topknot = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.12, 1), 0.016, 7), woolMat);
topknot.name = 'topknot';
topknot.position.set(0, 0.14, 0.07);
topknot.scale.set(1.1, 0.8, 1);
head.add(topknot);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createSheep;
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









