696 Tris6,11 × 5,61 × 3,35 m
Im Code verwenden
Im Editor remixencliff-wall.js · 169 Zeilen
Eigenständiges ES-Modul — hängt nur von three ab. Ruf die Factory auf und füge die Gruppe deiner Szene hinzu.
/**
* Cliff Wall — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 696 · Size (W × H × D): 6.11 × 5.61 × 3.35 m
*
* Usage:
* import { createCliffWall } from './cliff-wall.js';
*
* const model = createCliffWall();
* 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;
}
// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
const options = bevel
? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
: { depth, bevelEnabled: false };
return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}
export function createCliffWall() {
const root = new THREE.Group();
root.name = 'CliffWall';
// Materials
const stoneMat = new THREE.MeshStandardMaterial({ name: 'stone', color: 0x9a8470, roughness: 0.92, flatShading: true });
const stoneLightMat = new THREE.MeshStandardMaterial({ name: 'stoneLight', color: 0xac9b85, roughness: 0.9, flatShading: true });
const stoneDarkMat = new THREE.MeshStandardMaterial({ name: 'stoneDark', color: 0x786457, roughness: 0.95, flatShading: true });
const stoneWarmMat = new THREE.MeshStandardMaterial({ name: 'stoneWarm', color: 0xa28e72, roughness: 0.92, flatShading: true });
const grassMat = new THREE.MeshStandardMaterial({ name: 'grass', color: 0x58833a, roughness: 0.95, flatShading: true });
const grassDarkMat = new THREE.MeshStandardMaterial({ name: 'grassDark', color: 0x47702f, roughness: 1, flatShading: true });
// Parts
const cliff = new THREE.Group();
cliff.name = 'cliff';
cliff.position.set(0, 0.0566, 0);
root.add(cliff);
const stratum1 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -1.4882], [2.5567, -1.5524], [1.8758, -1.6237], [1.1078, -1.6113], [0.6875, -1.5653], [-0.176, -1.519], [-0.6323, -1.5178], [-1.1795, -1.4863], [-1.6981, -1.0908], [-2.4269, -1.0537], [-3, -1.3992]], 1.0821), 0.0649, 217), stoneWarmMat);
stratum1.name = 'stratum1';
stratum1.position.set(0, 0.541, 0);
stratum1.rotation.set(deg(-90), 0, 0);
cliff.add(stratum1);
const stratum2 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -1.275], [2.5567, -1.391], [1.8758, -1.5027], [1.1078, -1.2853], [0.6875, -1.4531], [-0.176, -1.3579], [-0.6323, -1.5031], [-1.1795, -1.283], [-1.6981, -1.0177], [-2.4269, -0.9103], [-3, -1.0696]], 0.8873), 0.0532, 218), stoneLightMat);
stratum2.name = 'stratum2';
stratum2.position.set(0, 1.5257, 0);
stratum2.rotation.set(deg(-90), 0, 0);
cliff.add(stratum2);
const stratum3 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -0.8778], [2.5567, -1.0941], [1.8758, -1.2291], [1.1078, -1.1454], [0.6875, -0.9087], [-0.176, -1.1725], [-0.6323, -1.168], [-1.1795, -0.9633], [-1.6981, -0.7049], [-2.4269, -0.5579], [-3, -0.8934]], 0.5347), 0.0321, 219), stoneMat);
stratum3.name = 'stratum3';
stratum3.position.set(0, 2.2366, 0);
stratum3.rotation.set(deg(-90), 0, 0);
cliff.add(stratum3);
const stratum4 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -0.879], [2.5567, -0.9653], [1.8758, -0.9533], [1.1078, -0.9355], [0.6875, -0.8393], [-0.176, -1.0715], [-0.6323, -0.9541], [-1.1795, -0.7952], [-1.6981, -0.6488], [-2.4269, -0.5143], [-3, -0.5727]], 0.8727), 0.0524, 220), stoneDarkMat);
stratum4.name = 'stratum4';
stratum4.position.set(0, 2.9403, 0);
stratum4.rotation.set(deg(-90), 0, 0);
cliff.add(stratum4);
const stratum5 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -1.2996], [2.5567, -1.3665], [1.8758, -1.4197], [1.1078, -1.2248], [0.6875, -1.3594], [-0.176, -1.3022], [-0.6323, -1.4103], [-1.1795, -1.1084], [-1.6981, -0.9899], [-2.4269, -0.7586], [-3, -1.1111]], 0.8831), 0.053, 221), stoneWarmMat);
stratum5.name = 'stratum5';
stratum5.position.set(0, 3.8182, 0);
stratum5.rotation.set(deg(-90), 0, 0);
cliff.add(stratum5);
const stratum6 = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -0.817], [2.5567, -1.1111], [1.8758, -1.0332], [1.1078, -1.0456], [0.6875, -0.8499], [-0.176, -0.8983], [-0.6323, -1.0613], [-1.1795, -0.7787], [-1.6981, -0.6481], [-2.4269, -0.5142], [-3, -0.8274]], 0.7402), 0.0444, 222), stoneMat);
stratum6.name = 'stratum6';
stratum6.position.set(0, 4.6299, 0);
stratum6.rotation.set(deg(-90), 0, 0);
cliff.add(stratum6);
const boulder1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.542, 0), 0.0813, 49), stoneLightMat);
boulder1.name = 'boulder1';
boulder1.position.set(-1.1795, 1.3105, 1.246);
boulder1.rotation.set(deg(70.3431), deg(252.3563), 0);
boulder1.scale.set(1.2, 0.8, 0.8);
cliff.add(boulder1);
const boulder2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.5743, 0), 0.0861, 50), stoneDarkMat);
boulder2.name = 'boulder2';
boulder2.position.set(0.6875, 1.8469, 1.194);
boulder2.rotation.set(deg(59.3889), deg(51.3757), 0);
boulder2.scale.set(1.2, 0.8, 0.8);
cliff.add(boulder2);
const grassTop = new THREE.Mesh(jitter(extrude([[-3, 1.35], [3, 1.35], [3, -0.777], [2.5567, -1.0711], [1.8758, -0.9932], [1.1078, -1.0056], [0.6875, -0.8099], [-0.176, -0.8583], [-0.6323, -1.0213], [-1.1795, -0.7387], [-1.6981, -0.6081], [-2.4269, -0.4742], [-3, -0.7874]], 0.16), 0.03, 7), grassMat);
grassTop.name = 'grassTop';
grassTop.position.set(0, 5.06, 0);
grassTop.rotation.set(deg(-90), 0, 0);
cliff.add(grassTop);
const bush1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2639, 0), 0.0317, 77), grassDarkMat);
bush1.name = 'bush1';
bush1.position.set(-1.9805, 5.2387, -0.8059);
bush1.rotation.set(deg(16.2333), deg(101.9843), 0);
bush1.scale.set(1, 0.7, 1);
cliff.add(bush1);
const bush2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.3768, 0), 0.0452, 78), grassMat);
bush2.name = 'bush2';
bush2.position.set(0.1712, 5.2896, -0.4049);
bush2.rotation.set(deg(28.3234), deg(341.7536), 0);
bush2.scale.set(1, 0.7, 1);
cliff.add(bush2);
const bush3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2605, 0), 0.0313, 79), grassDarkMat);
bush3.name = 'bush3';
bush3.position.set(2.2031, 5.2372, -0.095);
bush3.rotation.set(deg(57.6155), deg(336.1826), 0);
bush3.scale.set(1, 0.7, 1);
cliff.add(bush3);
const rubble1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2275, 0), 0.0341, 119), stoneMat);
rubble1.name = 'rubble1';
rubble1.position.set(-2.3957, 0.1588, 1.6322);
rubble1.rotation.set(deg(26.2946), deg(27.8798), 0);
rubble1.scale.set(1, 0.65, 1);
cliff.add(rubble1);
const rubble2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2527, 0), 0.0379, 120), stoneDarkMat);
rubble2.name = 'rubble2';
rubble2.position.set(-1.4102, 0.1766, 1.6459);
rubble2.rotation.set(deg(2.5141), deg(187.0549), 0);
rubble2.scale.set(1, 0.65, 1);
cliff.add(rubble2);
const rubble3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2828, 0), 0.0424, 121), stoneMat);
rubble3.name = 'rubble3';
rubble3.position.set(-0.3755, 0.2025, 1.7087);
rubble3.rotation.set(deg(30.4868), deg(132.2735), 0);
rubble3.scale.set(1, 0.65, 1);
cliff.add(rubble3);
const rubble4 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2196, 0), 0.0329, 122), stoneDarkMat);
rubble4.name = 'rubble4';
rubble4.position.set(1.0895, 0.1916, 1.6106);
rubble4.rotation.set(deg(76.7033), deg(33.0454), 0);
rubble4.scale.set(1, 0.65, 1);
cliff.add(rubble4);
const rubble5 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2325, 0), 0.0349, 123), stoneMat);
rubble5.name = 'rubble5';
rubble5.position.set(2.3383, 0.1705, 1.6147);
rubble5.rotation.set(deg(23.2269), deg(100.1775), 0);
rubble5.scale.set(1, 0.65, 1);
cliff.add(rubble5);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createCliffWall;
Bewertungen & Kommentare
—
Noch keine Bewertungen — gib die erste ab.
5
0
4
0
3
0
2
0
1
0
Melde dich an, um zu bewerten und zu kommentieren.
0 Kommentare
Noch keine Kommentare. Erzähl, wie du dieses Modell genutzt hast oder was besser sein könnte.
Ähnliche Modelle
Gleiche Kategorie oder ähnliche Tags









