1 B üçgen2,05 × 2,23 × 1,78 m
Kodda kullan
Editörde remix’lestalagmite.js · 146 satır
Bağımsız bir ES modülü — yalnızca three paketine bağımlıdır. Fabrika fonksiyonunu çağırıp dönen grubu sahnene ekle.
/**
* Stalagmite Cluster — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,008 · Size (W × H × D): 2.05 × 2.23 × 1.78 m
*
* Usage:
* import { createStalagmite } from './stalagmite.js';
*
* const model = createStalagmite();
* 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;
}
// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}
export function createStalagmite() {
const root = new THREE.Group();
root.name = 'Stalagmite';
// Materials
const rockMat = new THREE.MeshStandardMaterial({ name: 'rock', color: 0xb09a7e, roughness: 0.85, flatShading: true });
const rockAltMat = new THREE.MeshStandardMaterial({ name: 'rockAlt', color: 0x8a7e74, roughness: 0.9, flatShading: true });
const rockDarkMat = new THREE.MeshStandardMaterial({ name: 'rockDark', color: 0x655c51, roughness: 0.95, flatShading: true });
const tipMat = new THREE.MeshStandardMaterial({ name: 'tip', color: 0xc5bcb2, roughness: 0.35, flatShading: true });
// Parts
const cluster = new THREE.Group();
cluster.name = 'cluster';
cluster.position.set(0, 0.0651, 0);
root.add(cluster);
const spire1 = new THREE.Group();
spire1.name = 'spire1';
spire1.position.set(0, -0.0351, 0);
spire1.rotation.set(deg(0.3132), deg(104.4596), deg(2.4458));
cluster.add(spire1);
const body = new THREE.Mesh(jitter(lathe([[0, 0], [0.4387, 0], [0.3948, 0.11], [0.3244, 0.3394], [0.2634, 0.5689], [0.2541, 0.7983], [0.2067, 1.0277], [0.1401, 1.2571], [0.1079, 1.4866], [0.0771, 1.716]], 7), 0.0219, 39), rockMat);
body.name = 'body';
spire1.add(body);
const tip = new THREE.Mesh(lathe([[0, 1.705], [0.0834, 1.705], [0.0746, 1.826], [0.0439, 2.046], [0, 2.2]], 7), tipMat);
tip.name = 'tip';
spire1.add(tip);
const spire2 = new THREE.Group();
spire2.name = 'spire2';
spire2.position.set(-0.6572, -0.0186, -0.1027);
spire2.rotation.set(deg(-1.2191), deg(265.2578), deg(7.799));
cluster.add(spire2);
const body2 = new THREE.Mesh(jitter(lathe([[0, 0], [0.2329, 0], [0.2096, 0.0574], [0.164, 0.1772], [0.146, 0.297], [0.1387, 0.4167], [0.1043, 0.5365], [0.0737, 0.6563], [0.0606, 0.776], [0.0404, 0.8958]], 7), 0.0116, 40), rockAltMat);
body2.name = 'body';
spire2.add(body2);
const tip2 = new THREE.Mesh(lathe([[0, 0.8901], [0.0443, 0.8901], [0.0396, 0.9532], [0.0233, 1.0681], [0, 1.1485]], 7), tipMat);
tip2.name = 'tip';
spire2.add(tip2);
const spire3 = new THREE.Group();
spire3.name = 'spire3';
spire3.position.set(0.755, -0.02, -0.1099);
spire3.rotation.set(deg(-1.1902), deg(305.4421), deg(-8.1752));
cluster.add(spire3);
const body3 = new THREE.Mesh(jitter(lathe([[0, 0], [0.2495, 0], [0.2245, 0.0635], [0.1858, 0.1958], [0.1493, 0.3281], [0.1438, 0.4605], [0.1182, 0.5928], [0.08, 0.7251], [0.0609, 0.8575], [0.0438, 0.9898]], 7), 0.0125, 41), rockMat);
body3.name = 'body';
spire3.add(body3);
const tip3 = new THREE.Mesh(lathe([[0, 0.9835], [0.0474, 0.9835], [0.0424, 1.0533], [0.0249, 1.1802], [0, 1.269]], 7), tipMat);
tip3.name = 'tip';
spire3.add(tip3);
const spire4 = new THREE.Group();
spire4.name = 'spire4';
spire4.position.set(-0.787, -0.0137, -0.1521);
spire4.rotation.set(deg(-1.8478), deg(176.5189), deg(9.5602));
cluster.add(spire4);
const body4 = new THREE.Mesh(jitter(lathe([[0, 0], [0.1712, 0], [0.1541, 0.042], [0.1322, 0.1295], [0.1016, 0.217], [0.0955, 0.3046], [0.0827, 0.3921], [0.0564, 0.4796], [0.0404, 0.5672], [0.0297, 0.6547]], 7), 0.0086, 42), rockAltMat);
body4.name = 'body';
spire4.add(body4);
const tip4 = new THREE.Mesh(lathe([[0, 0.6505], [0.0325, 0.6505], [0.0291, 0.6967], [0.0171, 0.7806], [0, 0.8394]], 7), tipMat);
tip4.name = 'tip';
spire4.add(tip4);
const spire5 = new THREE.Group();
spire5.name = 'spire5';
spire5.position.set(0.8594, -0.0153, 0.126);
spire5.rotation.set(deg(1.4017), deg(121.4567), deg(-9.5564));
cluster.add(spire5);
const body5 = new THREE.Mesh(jitter(lathe([[0, 0], [0.1914, 0], [0.1723, 0.047], [0.1419, 0.1449], [0.1361, 0.2429], [0.1035, 0.3409], [0.0782, 0.4388], [0.0696, 0.5368], [0.0514, 0.6348], [0.0286, 0.7327]], 7), 0.0096, 43), rockMat);
body5.name = 'body';
spire5.add(body5);
const tip5 = new THREE.Mesh(lathe([[0, 0.728], [0.0364, 0.728], [0.0325, 0.7797], [0.0191, 0.8736], [0, 0.9394]], 7), tipMat);
tip5.name = 'tip';
spire5.add(tip5);
const flowstone = new THREE.Mesh(jitter(new THREE.SphereGeometry(1.007, 10, 3, 0, Math.PI * 2, 0, Math.PI / 2), 0.0604, 3), rockDarkMat);
flowstone.name = 'flowstone';
flowstone.scale.set(1, 0.3496, 0.9);
cluster.add(flowstone);
const nub1 = new THREE.Mesh(jitter(new THREE.ConeGeometry(0.1134, 0.2519, 6), 0.0126, 87), rockAltMat);
nub1.name = 'nub1';
nub1.position.set(0.5438, 0.126, -0.7357);
nub1.rotation.set(deg(-4.8505), deg(145.322), deg(4.2362));
cluster.add(nub1);
const nub2 = new THREE.Mesh(jitter(new THREE.ConeGeometry(0.1043, 0.2319, 6), 0.0116, 88), rockAltMat);
nub2.name = 'nub2';
nub2.position.set(-0.7489, 0.116, -0.3439);
nub2.rotation.set(deg(8.3396), deg(27.0106), deg(-7.3671));
cluster.add(nub2);
const nub3 = new THREE.Mesh(jitter(new THREE.ConeGeometry(0.1147, 0.2548, 6), 0.0127, 89), rockAltMat);
nub3.name = 'nub3';
nub3.position.set(-0.7039, 0.1274, -0.4375);
nub3.rotation.set(deg(7.6159), deg(215.2691), deg(4.8426));
cluster.add(nub3);
const nub4 = new THREE.Mesh(jitter(new THREE.ConeGeometry(0.0726, 0.1614, 6), 0.0081, 90), rockAltMat);
nub4.name = 'nub4';
nub4.position.set(0.8483, 0.0807, -0.2927);
nub4.rotation.set(deg(-5.0622), deg(244.7684), deg(-0.1702));
cluster.add(nub4);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createStalagmite;
Puanlar ve yorumlar
0 yorum
Henüz yorum yok. Bu modeli nasıl kullandığını ya da neyin daha iyi olabileceğini paylaş.
Benzer modeller
Aynı kategori ya da benzer etiketler









