912 tris2,52 × 2,32 × 1,06 m
Utiliser dans le code
Remixer dans l’éditeurgolem.js · 306 lignes
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
* Stone Golem — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 912 · Size (W × H × D): 2.52 × 2.32 × 1.06 m
*
* Usage:
* import { createGolem } from './golem.js';
*
* const model = createGolem();
* 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 createGolem() {
const root = new THREE.Group();
root.name = 'Golem';
// Materials
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x858a93, roughness: 0.95, flatShading: true });
const stoneDarkMat = new THREE.MeshStandardMaterial({ name: 'stoneDark', color: 0x686c73, roughness: 0.95, flatShading: true });
const stoneLightMat = new THREE.MeshStandardMaterial({ name: 'stoneLight', color: 0x9498a0, roughness: 0.95, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x46dcff, roughness: 0.3, emissive: 0x46dcff, emissiveIntensity: 1.1, flatShading: true });
const mossMat = new THREE.MeshStandardMaterial({ name: 'moss', color: 0x6b9a3e, roughness: 1, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.2016, 0.0364, 0.02);
const octahedronGeo = new THREE.OctahedronGeometry(0.085, 0);
const boxGeo2 = new THREE.BoxGeometry(0.0648, 0.018, 0.02);
const boxGeo3 = new THREE.BoxGeometry(0.018, 0.135, 0.02);
const boxGeo4 = new THREE.BoxGeometry(0.045, 0.018, 0.02);
const boxGeo5 = new THREE.BoxGeometry(0.11, 0.055, 0.03);
// Parts
const legL = new THREE.Group();
legL.name = 'legL';
legL.position.set(0.3, 0.72, 0);
root.add(legL);
const thighL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.25, 0), 0.035, 3), stoneDarkMat);
thighL.name = 'thighL';
thighL.position.set(0, -0.14, 0);
legL.add(thighL);
const footL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.3, 0), 0.03, 5), stoneMat);
footL.name = 'footL';
footL.position.set(0, -0.5313, 0.06);
footL.scale.set(1.05, 0.62, 1.25);
legL.add(footL);
const legR = new THREE.Group();
legR.name = 'legR';
legR.position.set(-0.3, 0.72, 0);
root.add(legR);
const thighR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.25, 0), 0.035, 4), stoneDarkMat);
thighR.name = 'thighR';
thighR.position.set(0, -0.14, 0);
legR.add(thighR);
const footR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.3, 0), 0.03, 6), stoneMat);
footR.name = 'footR';
footR.position.set(0, -0.5445, 0.06);
footR.scale.set(1.05, 0.62, 1.25);
legR.add(footR);
const body = new THREE.Group();
body.name = 'body';
root.add(body);
const pelvis = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.4, 0), 0.04, 8), stoneDarkMat);
pelvis.name = 'pelvis';
pelvis.position.set(0, 0.84, 0);
pelvis.scale.set(1.25, 0.7, 0.9);
body.add(pelvis);
const torso = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.62, 0), 0.06, 2), stoneMat);
torso.name = 'torso';
torso.position.set(0, 1.4, 0);
torso.scale.set(1.2, 0.95, 0.85);
body.add(torso);
const chestRune = new THREE.Group();
chestRune.name = 'chestRune';
chestRune.position.set(-0.0045, 1.4814, 0.4943);
chestRune.rotation.set(deg(-7.2582), deg(-22.2077), deg(-1.4263));
body.add(chestRune);
const runeEdge = new THREE.Mesh(boxGeo, glowMat);
runeEdge.name = 'runeEdge';
runeEdge.position.set(-0.07, 0.07, 0);
runeEdge.rotation.set(0, 0, deg(45));
chestRune.add(runeEdge);
const runeEdge2 = new THREE.Mesh(boxGeo, glowMat);
runeEdge2.name = 'runeEdge';
runeEdge2.position.set(0.07, 0.07, 0);
runeEdge2.rotation.set(0, 0, deg(-45));
chestRune.add(runeEdge2);
const runeEdge3 = new THREE.Mesh(boxGeo, glowMat);
runeEdge3.name = 'runeEdge';
runeEdge3.position.set(-0.07, -0.07, 0);
runeEdge3.rotation.set(0, 0, deg(-45));
chestRune.add(runeEdge3);
const runeEdge4 = new THREE.Mesh(boxGeo, glowMat);
runeEdge4.name = 'runeEdge';
runeEdge4.position.set(0.07, -0.07, 0);
runeEdge4.rotation.set(0, 0, deg(45));
chestRune.add(runeEdge4);
const runeStroke = new THREE.Mesh(new THREE.BoxGeometry(0.0364, 0.42, 0.02), glowMat);
runeStroke.name = 'runeStroke';
chestRune.add(runeStroke);
const runeBar = new THREE.Mesh(new THREE.BoxGeometry(0.14, 0.0364, 0.02), glowMat);
runeBar.name = 'runeBar';
runeBar.position.set(0, -0.07, 0);
chestRune.add(runeBar);
const mossBack = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.26, 0), 0.03, 21), mossMat);
mossBack.name = 'mossBack';
mossBack.position.set(-0.22, 1.9532, -0.05);
mossBack.scale.set(1.1, 0.28, 0.9);
body.add(mossBack);
const backCrystal1 = new THREE.Mesh(octahedronGeo, glowMat);
backCrystal1.name = 'backCrystal1';
backCrystal1.position.set(-0.25, 1.62, -0.3526);
backCrystal1.rotation.set(deg(-43.8302), deg(-10.4646), deg(25.6471));
backCrystal1.scale.set(0.8, 2.2, 0.8);
body.add(backCrystal1);
const backCrystal2 = new THREE.Mesh(octahedronGeo, glowMat);
backCrystal2.name = 'backCrystal2';
backCrystal2.position.set(0.05, 1.72, -0.2488);
backCrystal2.rotation.set(deg(-38.5378), deg(1.5622), deg(-4.4667));
backCrystal2.scale.set(0.8, 2.2, 0.8);
body.add(backCrystal2);
const backCrystal3 = new THREE.Mesh(octahedronGeo, glowMat);
backCrystal3.name = 'backCrystal3';
backCrystal3.position.set(0.3, 1.55, -0.2999);
backCrystal3.rotation.set(deg(-44.8632), deg(13.4762), deg(-31.9421));
backCrystal3.scale.set(0.8, 2.2, 0.8);
body.add(backCrystal3);
const armL = new THREE.Group();
armL.name = 'armL';
armL.position.set(0.74, 1.74, 0);
armL.rotation.set(deg(-6), 0, deg(9));
root.add(armL);
const shoulderL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.35, 0), 0.04, 31), stoneLightMat);
shoulderL.name = 'shoulderL';
armL.add(shoulderL);
const upperArmL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.21, 0), 0.025, 33), stoneDarkMat);
upperArmL.name = 'upperArmL';
upperArmL.position.set(0, -0.4, 0);
armL.add(upperArmL);
const forearmL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.25, 0), 0.03, 35), stoneMat);
forearmL.name = 'forearmL';
forearmL.position.set(0, -0.76, 0.04);
forearmL.scale.set(1, 1.25, 1);
armL.add(forearmL);
const fistL = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.33, 0), 0.04, 37), stoneLightMat);
fistL.name = 'fistL';
fistL.position.set(0, -1.18, 0.07);
armL.add(fistL);
const forearmRuneL = new THREE.Group();
forearmRuneL.name = 'forearmRuneL';
forearmRuneL.position.set(0.0579, -0.7793, 0.2378);
forearmRuneL.rotation.set(deg(-4.3648), deg(41.2508), deg(1.6435));
armL.add(forearmRuneL);
const runeEdge5 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge5.name = 'runeEdge';
runeEdge5.position.set(-0.0225, 0.0225, 0);
runeEdge5.rotation.set(0, 0, deg(45));
forearmRuneL.add(runeEdge5);
const runeEdge6 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge6.name = 'runeEdge';
runeEdge6.position.set(0.0225, 0.0225, 0);
runeEdge6.rotation.set(0, 0, deg(-45));
forearmRuneL.add(runeEdge6);
const runeEdge7 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge7.name = 'runeEdge';
runeEdge7.position.set(-0.0225, -0.0225, 0);
runeEdge7.rotation.set(0, 0, deg(-45));
forearmRuneL.add(runeEdge7);
const runeEdge8 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge8.name = 'runeEdge';
runeEdge8.position.set(0.0225, -0.0225, 0);
runeEdge8.rotation.set(0, 0, deg(45));
forearmRuneL.add(runeEdge8);
const runeStroke2 = new THREE.Mesh(boxGeo3, glowMat);
runeStroke2.name = 'runeStroke';
forearmRuneL.add(runeStroke2);
const runeBar2 = new THREE.Mesh(boxGeo4, glowMat);
runeBar2.name = 'runeBar';
runeBar2.position.set(0, -0.0225, 0);
forearmRuneL.add(runeBar2);
const mossShoulder = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.2, 0), 0.025, 41), mossMat);
mossShoulder.name = 'mossShoulder';
mossShoulder.position.set(0.02, 0.31, -0.02);
mossShoulder.scale.set(1, 0.3, 1);
armL.add(mossShoulder);
const armR = new THREE.Group();
armR.name = 'armR';
armR.position.set(-0.74, 1.74, 0);
armR.rotation.set(deg(-6), 0, deg(-9));
root.add(armR);
const shoulderR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.35, 0), 0.04, 32), stoneLightMat);
shoulderR.name = 'shoulderR';
armR.add(shoulderR);
const upperArmR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.21, 0), 0.025, 34), stoneDarkMat);
upperArmR.name = 'upperArmR';
upperArmR.position.set(0, -0.4, 0);
armR.add(upperArmR);
const forearmR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.25, 0), 0.03, 36), stoneMat);
forearmR.name = 'forearmR';
forearmR.position.set(0, -0.76, 0.04);
forearmR.scale.set(1, 1.25, 1);
armR.add(forearmR);
const fistR = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.33, 0), 0.04, 38), stoneLightMat);
fistR.name = 'fistR';
fistR.position.set(0, -1.18, 0.07);
armR.add(fistR);
const forearmRuneR = new THREE.Group();
forearmRuneR.name = 'forearmRuneR';
forearmRuneR.position.set(-0.0569, -0.7806, 0.2372);
forearmRuneR.rotation.set(deg(3.4854), deg(-35.3884), deg(1.1123));
armR.add(forearmRuneR);
const runeEdge9 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge9.name = 'runeEdge';
runeEdge9.position.set(-0.0225, 0.0225, 0);
runeEdge9.rotation.set(0, 0, deg(45));
forearmRuneR.add(runeEdge9);
const runeEdge10 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge10.name = 'runeEdge';
runeEdge10.position.set(0.0225, 0.0225, 0);
runeEdge10.rotation.set(0, 0, deg(-45));
forearmRuneR.add(runeEdge10);
const runeEdge11 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge11.name = 'runeEdge';
runeEdge11.position.set(-0.0225, -0.0225, 0);
runeEdge11.rotation.set(0, 0, deg(-45));
forearmRuneR.add(runeEdge11);
const runeEdge12 = new THREE.Mesh(boxGeo2, glowMat);
runeEdge12.name = 'runeEdge';
runeEdge12.position.set(0.0225, -0.0225, 0);
runeEdge12.rotation.set(0, 0, deg(45));
forearmRuneR.add(runeEdge12);
const runeStroke3 = new THREE.Mesh(boxGeo3, glowMat);
runeStroke3.name = 'runeStroke';
forearmRuneR.add(runeStroke3);
const runeBar3 = new THREE.Mesh(boxGeo4, glowMat);
runeBar3.name = 'runeBar';
runeBar3.position.set(0, -0.0225, 0);
forearmRuneR.add(runeBar3);
const head = new THREE.Group();
head.name = 'head';
head.position.set(0, 1.92, 0.12);
root.add(head);
const skull = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.31, 0), 0.03, 51), stoneMat);
skull.name = 'skull';
skull.position.set(0, 0.15, 0.06);
skull.scale.set(1.12, 0.85, 1);
head.add(skull);
const brow = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.17, 0), 0.015, 52), stoneDarkMat);
brow.name = 'brow';
brow.position.set(0, 0.25, 0.2);
brow.scale.set(1.75, 0.42, 0.7);
head.add(brow);
const eyeL = new THREE.Mesh(boxGeo5, glowMat);
eyeL.name = 'eyeL';
eyeL.position.set(0.11, 0.15, 0.2711);
eyeL.rotation.set(deg(8.2871), deg(18.1187), deg(-13.3236));
head.add(eyeL);
const eyeR = new THREE.Mesh(boxGeo5, glowMat);
eyeR.name = 'eyeR';
eyeR.position.set(-0.11, 0.15, 0.2782);
eyeR.rotation.set(deg(4.8602), deg(-28.7519), deg(13.2464));
head.add(eyeR);
const mouth = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.035, 0.03), stoneDarkMat);
mouth.name = 'mouth';
mouth.position.set(0, 0.03, 0.2563);
mouth.rotation.set(deg(53.6954), deg(-1.8448), deg(0.9339));
head.add(mouth);
const mossHead = new THREE.Mesh(jitter(new THREE.IcosahedronGeometry(0.17, 0), 0.02, 61), mossMat);
mossHead.name = 'mossHead';
mossHead.position.set(-0.05, 0.35, 0);
mossHead.scale.set(1, 0.3, 1);
head.add(mossHead);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createGolem;
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









