204 tris1,16 × 3,19 × 0,63 m
Utiliser dans le code
Remixer dans l’éditeurstanding-stone.js · 124 lignes
Module ES autonome — ne dépend que de three. Appelez la fonction factory et ajoutez le groupe à votre scène.
/**
* Standing Stone — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 204 · Size (W × H × D): 1.16 × 3.19 × 0.63 m
*
* Usage:
* import { createStandingStone } from './standing-stone.js';
*
* const model = createStandingStone();
* 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 createStandingStone() {
const root = new THREE.Group();
root.name = 'StandingStone';
// Materials
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x77756f, roughness: 0.95, flatShading: true });
const runeMat = new THREE.MeshStandardMaterial({ name: 'rune', color: 0x4fd4ff, roughness: 0.4, emissive: 0x4fd4ff, emissiveIntensity: 1.4, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.2831, 0.0389, 0.03);
const boxGeo2 = new THREE.BoxGeometry(0.4277, 0.0389, 0.03);
const boxGeo3 = new THREE.BoxGeometry(0.2458, 0.0389, 0.03);
const boxGeo4 = new THREE.BoxGeometry(0.2591, 0.0389, 0.03);
// Parts
const menhir = new THREE.Group();
menhir.name = 'menhir';
menhir.position.set(0, 0.0733, 0);
menhir.rotation.set(0, 0, deg(-2.7367));
root.add(menhir);
const slab = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.3456, 0.5616, 3, 6, 4), 0.0648, 548), stoneMat);
slab.name = 'slab';
slab.position.set(0, 1.5, 0);
slab.rotation.set(0, deg(90), 0);
slab.scale.set(0.6, 1, 1);
menhir.add(slab);
const crown = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2916, 0), 0.027, 708), stoneMat);
crown.name = 'crown';
crown.position.set(0.0329, 2.9784, 0);
crown.rotation.set(0, deg(90), 0);
crown.scale.set(0.58, 0.5, 1);
menhir.add(crown);
const rune1s1 = new THREE.Mesh(boxGeo, runeMat);
rune1s1.name = 'rune1s1';
rune1s1.position.set(0.0007, 2.1458, 0.229);
rune1s1.rotation.set(deg(2.7309), deg(6.4925), deg(-142.9201));
menhir.add(rune1s1);
const rune1s2 = new THREE.Mesh(new THREE.BoxGeometry(0.2545, 0.0389, 0.03), runeMat);
rune1s2.name = 'rune1s2';
rune1s2.position.set(0.0007, 2.0253, 0.2232);
rune1s2.rotation.set(deg(2.7309), deg(6.4925), deg(-25.7959));
menhir.add(rune1s2);
const rune1s3 = new THREE.Mesh(boxGeo, runeMat);
rune1s3.name = 'rune1s3';
rune1s3.position.set(-0.0003, 1.9054, 0.2188);
rune1s3.rotation.set(deg(-2.7774), deg(-2.4116), deg(-142.8236));
menhir.add(rune1s3);
const rune2s1 = new THREE.Mesh(boxGeo2, runeMat);
rune2s1.name = 'rune2s1';
rune2s1.position.set(-0.078, 1.4813, 0.2349);
rune2s1.rotation.set(deg(-0.603), deg(-2.4371), deg(89.9872));
menhir.add(rune2s1);
const rune2s2 = new THREE.Mesh(boxGeo3, runeMat);
rune2s2.name = 'rune2s2';
rune2s2.position.set(0.0153, 1.6118, 0.2337);
rune2s2.rotation.set(deg(-2.7774), deg(-2.4116), deg(25.5437));
menhir.add(rune2s2);
const rune2s3 = new THREE.Mesh(boxGeo3, runeMat);
rune2s3.name = 'rune2s3';
rune2s3.position.set(0.0153, 1.5066, 0.2386);
rune2s3.rotation.set(deg(-0.603), deg(-2.4371), deg(25.5894));
menhir.add(rune2s3);
const rune3s1 = new THREE.Mesh(boxGeo2, runeMat);
rune3s1.name = 'rune3s1';
rune3s1.position.set(-0.0001, 0.9369, 0.2399);
rune3s1.rotation.set(deg(0.5273), deg(-0.7508), deg(90.0035));
menhir.add(rune3s1);
const rune3s2 = new THREE.Mesh(boxGeo4, runeMat);
rune3s2.name = 'rune3s2';
rune3s2.position.set(-0.074, 1.0186, 0.2397);
rune3s2.rotation.set(deg(0.5273), deg(-0.7508), deg(132.141));
menhir.add(rune3s2);
const rune3s3 = new THREE.Mesh(boxGeo4, runeMat);
rune3s3.name = 'rune3s3';
rune3s3.position.set(0.0738, 1.0186, 0.2416);
rune3s3.rotation.set(deg(0.5273), deg(-0.7508), deg(47.8659));
menhir.add(rune3s3);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createStandingStone;
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









