928 üçgen4,00 × 2,82 × 3,00 m
Kodda kullan
Editörde remix’legrass-platform.js · 365 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.
/**
* Grass Platform — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 928 · Size (W × H × D): 4.00 × 2.82 × 3.00 m
*
* Usage:
* import { createGrassPlatform } from './grass-platform.js';
*
* const model = createGrassPlatform();
* 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 createGrassPlatform() {
const root = new THREE.Group();
root.name = 'GrassPlatform';
// Materials
const grassMat = new THREE.MeshStandardMaterial({ name: 'grass', color: 0x63c74a, roughness: 0.85, flatShading: true });
const tuftMat = new THREE.MeshStandardMaterial({ name: 'tuft', color: 0x4ba13a, roughness: 0.9, flatShading: true });
const dirtMat = new THREE.MeshStandardMaterial({ name: 'dirt', color: 0x9a6440, roughness: 0.95, flatShading: true });
const rockMat = new THREE.MeshStandardMaterial({ name: 'rock', color: 0xa39482, roughness: 0.95, flatShading: true });
const rockDarkMat = new THREE.MeshStandardMaterial({ name: 'rockDark', color: 0x877a6a, roughness: 0.95, flatShading: true });
const petalMat = new THREE.MeshStandardMaterial({ name: 'petal', color: 0xfff1b8, roughness: 0.7, flatShading: true });
const petalPinkMat = new THREE.MeshStandardMaterial({ name: 'petalPink', color: 0xff8fb3, roughness: 0.7, flatShading: true });
// Shared geometries
const cylinderGeo = new THREE.CylinderGeometry(0.016, 0.02, 0.22, 4);
const sphereGeo = new THREE.SphereGeometry(0.075, 6, 4);
// Parts
const grassTop = new THREE.Mesh(new THREE.BoxGeometry(4, 0.3, 3), grassMat);
grassTop.name = 'grassTop';
grassTop.position.set(0, 2.35, 0);
root.add(grassTop);
const earth = new THREE.Mesh(new THREE.BoxGeometry(3.92, 0.6, 2.92), dirtMat);
earth.name = 'earth';
earth.position.set(0, 1.95, 0);
root.add(earth);
const fringe = new THREE.Group();
fringe.name = 'fringe';
root.add(fringe);
const box4 = new THREE.Mesh(new THREE.BoxGeometry(0.2692, 0.2881, 0.06), grassMat);
box4.position.set(-1.706, 2.0759, 1.464);
fringe.add(box4);
const box5 = new THREE.Mesh(new THREE.BoxGeometry(0.1978, 0.2025, 0.06), grassMat);
box5.position.set(-1.2489, 2.1188, 1.464);
fringe.add(box5);
const box6 = new THREE.Mesh(new THREE.BoxGeometry(0.2621, 0.2696, 0.06), grassMat);
box6.position.set(-0.8576, 2.0852, 1.464);
fringe.add(box6);
const box7 = new THREE.Mesh(new THREE.BoxGeometry(0.2003, 0.1595, 0.06), grassMat);
box7.position.set(-0.4062, 2.1402, 1.464);
fringe.add(box7);
const box8 = new THREE.Mesh(new THREE.BoxGeometry(0.2134, 0.136, 0.06), grassMat);
box8.position.set(-0.0083, 2.152, 1.464);
fringe.add(box8);
const box9 = new THREE.Mesh(new THREE.BoxGeometry(0.2223, 0.1933, 0.06), grassMat);
box9.position.set(0.4473, 2.1234, 1.464);
fringe.add(box9);
const box10 = new THREE.Mesh(new THREE.BoxGeometry(0.2254, 0.2128, 0.06), grassMat);
box10.position.set(0.853, 2.1136, 1.464);
fringe.add(box10);
const box11 = new THREE.Mesh(new THREE.BoxGeometry(0.2932, 0.2664, 0.06), grassMat);
box11.position.set(1.2579, 2.0868, 1.464);
fringe.add(box11);
const box12 = new THREE.Mesh(new THREE.BoxGeometry(0.3011, 0.1794, 0.06), grassMat);
box12.position.set(1.7208, 2.1303, 1.464);
fringe.add(box12);
const box13 = new THREE.Mesh(new THREE.BoxGeometry(0.2327, 0.2483, 0.06), grassMat);
box13.position.set(-1.6902, 2.0959, -1.464);
fringe.add(box13);
const box14 = new THREE.Mesh(new THREE.BoxGeometry(0.2091, 0.2317, 0.06), grassMat);
box14.position.set(-1.2866, 2.1042, -1.464);
fringe.add(box14);
const box15 = new THREE.Mesh(new THREE.BoxGeometry(0.2884, 0.2954, 0.06), grassMat);
box15.position.set(-0.8604, 2.0723, -1.464);
fringe.add(box15);
const box16 = new THREE.Mesh(new THREE.BoxGeometry(0.2001, 0.2461, 0.06), grassMat);
box16.position.set(-0.4492, 2.097, -1.464);
fringe.add(box16);
const box17 = new THREE.Mesh(new THREE.BoxGeometry(0.3052, 0.2196, 0.06), grassMat);
box17.position.set(-0.0023, 2.1102, -1.464);
fringe.add(box17);
const box18 = new THREE.Mesh(new THREE.BoxGeometry(0.2381, 0.2101, 0.06), grassMat);
box18.position.set(0.4115, 2.115, -1.464);
fringe.add(box18);
const box19 = new THREE.Mesh(new THREE.BoxGeometry(0.2496, 0.1668, 0.06), grassMat);
box19.position.set(0.8867, 2.1366, -1.464);
fringe.add(box19);
const box20 = new THREE.Mesh(new THREE.BoxGeometry(0.2937, 0.2221, 0.06), grassMat);
box20.position.set(1.3107, 2.109, -1.464);
fringe.add(box20);
const box21 = new THREE.Mesh(new THREE.BoxGeometry(0.2209, 0.1935, 0.06), grassMat);
box21.position.set(1.6933, 2.1233, -1.464);
fringe.add(box21);
const box22 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.2584, 0.2464), grassMat);
box22.position.set(1.964, 2.0908, -1.1918);
fringe.add(box22);
const box23 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.2334, 0.2576), grassMat);
box23.position.set(1.964, 2.1033, -0.8121);
fringe.add(box23);
const box24 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1804, 0.2542), grassMat);
box24.position.set(1.964, 2.1298, -0.4134);
fringe.add(box24);
const box25 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1209, 0.2447), grassMat);
box25.position.set(1.964, 2.1596, -0.0312);
fringe.add(box25);
const box26 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.271, 0.2245), grassMat);
box26.position.set(1.964, 2.0845, 0.4042);
fringe.add(box26);
const box27 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1616, 0.2299), grassMat);
box27.position.set(1.964, 2.1392, 0.817);
fringe.add(box27);
const box28 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.224, 0.189), grassMat);
box28.position.set(1.964, 2.108, 1.2155);
fringe.add(box28);
const box29 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.2212, 0.2547), grassMat);
box29.position.set(-1.964, 2.1094, -1.1865);
fringe.add(box29);
const box30 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1474, 0.2318), grassMat);
box30.position.set(-1.964, 2.1463, -0.7795);
fringe.add(box30);
const box31 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1605, 0.1986), grassMat);
box31.position.set(-1.964, 2.1398, -0.4364);
fringe.add(box31);
const box32 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.2068, 0.2004), grassMat);
box32.position.set(-1.964, 2.1166, 0.0249);
fringe.add(box32);
const box33 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1637, 0.1844), grassMat);
box33.position.set(-1.964, 2.1381, 0.4225);
fringe.add(box33);
const box34 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.2366, 0.1984), grassMat);
box34.position.set(-1.964, 2.1017, 0.8361);
fringe.add(box34);
const box35 = new THREE.Mesh(new THREE.BoxGeometry(0.06, 0.1726, 0.2424), grassMat);
box35.position.set(-1.964, 2.1337, 1.2494);
fringe.add(box35);
const underside = new THREE.Group();
underside.name = 'underside';
underside.scale.set(3.9, 1, 2.9);
root.add(underside);
const rockBody = new THREE.Mesh(jitter(new THREE.CylinderGeometry(0.6859, 0.297, 1.073, 4, 3), 0.035, 5), rockMat);
rockBody.name = 'rockBody';
rockBody.position.set(0, 1.1635, 0);
rockBody.rotation.set(0, deg(45), 0);
underside.add(rockBody);
const tip = new THREE.Mesh(new THREE.ConeGeometry(0.6, 1.0025, 5), rockDarkMat);
tip.name = 'tip';
tip.position.set(0, 0.5013, 0);
tip.rotation.set(deg(180), deg(52.3075), 0);
root.add(tip);
const stalactite1 = new THREE.Mesh(new THREE.ConeGeometry(0.372, 0.3333, 5), rockDarkMat);
stalactite1.name = 'stalactite1';
stalactite1.position.set(0.7367, 0.7822, 0.1905);
stalactite1.rotation.set(deg(180), deg(3.242), 0);
root.add(stalactite1);
const stalactite2 = new THREE.Mesh(new THREE.ConeGeometry(0.3831, 0.5308, 5), rockMat);
stalactite2.name = 'stalactite2';
stalactite2.position.set(-0.1318, 0.6835, 0.5717);
stalactite2.rotation.set(deg(180), deg(24.0697), 0);
root.add(stalactite2);
const stalactite3 = new THREE.Mesh(new THREE.ConeGeometry(0.3366, 0.5336, 5), rockDarkMat);
stalactite3.name = 'stalactite3';
stalactite3.position.set(-0.3429, 0.6821, -0.5209);
stalactite3.rotation.set(deg(180), deg(42.4591), 0);
root.add(stalactite3);
const boulder1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.32, 0), 0.0384, 20), rockDarkMat);
boulder1.name = 'boulder1';
boulder1.position.set(1.4953, 1.4562, -0.1806);
root.add(boulder1);
const boulder2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.32, 0), 0.0384, 21), rockDarkMat);
boulder2.name = 'boulder2';
boulder2.position.set(-1.3801, 1.4142, -0.4029);
root.add(boulder2);
const tuft1 = new THREE.Group();
tuft1.name = 'tuft1';
tuft1.position.set(-0.8231, 2.5, -0.5925);
root.add(tuft1);
const cone45 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3368, 4), tuftMat);
cone45.position.set(0.0699, 0.1384, 0.0029);
cone45.rotation.set(deg(0.5873), deg(4.3031), deg(-13.9877));
tuft1.add(cone45);
const cone46 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3461, 4), tuftMat);
cone46.position.set(-0.0316, 0.1431, 0.0625);
cone46.rotation.set(deg(12.4903), deg(22.2316), deg(6.3239));
tuft1.add(cone46);
const cone47 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3384, 4), tuftMat);
cone47.position.set(-0.0317, 0.1392, -0.0624);
cone47.rotation.set(deg(-12.4845), deg(4.5793), deg(6.3355));
tuft1.add(cone47);
const tuft2 = new THREE.Group();
tuft2.name = 'tuft2';
tuft2.position.set(-0.8622, 2.5, 0.609);
root.add(tuft2);
const cone49 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3117, 4), tuftMat);
cone49.position.set(0.0684, 0.1259, 0.0148);
cone49.rotation.set(deg(2.9506), deg(28.3553), deg(-13.6855));
tuft2.add(cone49);
const cone50 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3053, 4), tuftMat);
cone50.position.set(-0.0158, 0.1227, 0.0682);
cone50.rotation.set(deg(13.6373), deg(27.7775), deg(3.1661));
tuft2.add(cone50);
const cone51 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2609, 4), tuftMat);
cone51.position.set(-0.049, 0.1005, -0.05);
cone51.rotation.set(deg(-9.9981), deg(41.9708), deg(9.7999));
tuft2.add(cone51);
const tuft3 = new THREE.Group();
tuft3.name = 'tuft3';
tuft3.position.set(-0.8815, 2.5, 1.1204);
root.add(tuft3);
const cone53 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3223, 4), tuftMat);
cone53.position.set(0.0662, 0.1312, 0.0226);
cone53.rotation.set(deg(4.5289), deg(36.0245), deg(-13.2472));
tuft3.add(cone53);
const cone54 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2232, 4), tuftMat);
cone54.position.set(-0.0251, 0.0816, 0.0653);
cone54.rotation.set(deg(13.0655), deg(18.5439), deg(5.0291));
tuft3.add(cone54);
const cone55 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2324, 4), tuftMat);
cone55.position.set(-0.0195, 0.0862, -0.0672);
cone55.rotation.set(deg(-13.4442), deg(8.0463), deg(3.9054));
tuft3.add(cone55);
const tuft4 = new THREE.Group();
tuft4.name = 'tuft4';
tuft4.position.set(1.7782, 2.5, 1.167);
root.add(tuft4);
const cone57 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3133, 4), tuftMat);
cone57.position.set(0.0629, 0.1267, -0.0307);
cone57.rotation.set(deg(-6.1346), deg(84.4887), deg(-12.5844));
tuft4.add(cone57);
const cone58 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2395, 4), tuftMat);
cone58.position.set(-0.0311, 0.0898, 0.0627);
cone58.rotation.set(deg(12.5451), deg(84.4965), deg(6.2145));
tuft4.add(cone58);
const cone59 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.34, 4), tuftMat);
cone59.position.set(-0.0331, 0.14, -0.0617);
cone59.rotation.set(deg(-12.3401), deg(56.3412), deg(6.6123));
tuft4.add(cone59);
const tuft5 = new THREE.Group();
tuft5.name = 'tuft5';
tuft5.position.set(0.7444, 2.5, 0.7846);
root.add(tuft5);
const cone61 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2302, 4), tuftMat);
cone61.position.set(0.0697, 0.0851, -0.0068);
cone61.rotation.set(deg(-1.3508), deg(7.2705), deg(-13.9347));
tuft5.add(cone61);
const cone62 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3239, 4), tuftMat);
cone62.position.set(-0.0217, 0.132, 0.0666);
cone62.rotation.set(deg(13.3133), deg(3.6086), deg(4.3307));
tuft5.add(cone62);
const cone63 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2621, 4), tuftMat);
cone63.position.set(-0.051, 0.1011, -0.048);
cone63.rotation.set(deg(-9.5984), deg(23.7475), deg(10.1917));
tuft5.add(cone63);
const tuft6 = new THREE.Group();
tuft6.name = 'tuft6';
tuft6.position.set(-1.0249, 2.5, -0.3635);
root.add(tuft6);
const cone65 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3035, 4), tuftMat);
cone65.position.set(0.0685, 0.1218, 0.0145);
cone65.rotation.set(deg(2.9003), deg(83.9748), deg(-13.6963));
tuft6.add(cone65);
const cone66 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2858, 4), tuftMat);
cone66.position.set(-0.0554, 0.1129, 0.0429);
cone66.rotation.set(deg(8.5702), deg(73.2091), deg(11.0703));
tuft6.add(cone66);
const cone67 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2387, 4), tuftMat);
cone67.position.set(-0.0407, 0.0894, -0.057);
cone67.rotation.set(deg(-11.3937), deg(68.0117), deg(8.1354));
tuft6.add(cone67);
const tuft7 = new THREE.Group();
tuft7.name = 'tuft7';
tuft7.position.set(-1.4803, 2.5, -0.18);
root.add(tuft7);
const cone69 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2969, 4), tuftMat);
cone69.position.set(0.0676, 0.1185, -0.0183);
cone69.rotation.set(deg(-3.6551), deg(82.0903), deg(-13.5144));
tuft7.add(cone69);
const cone70 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.3562, 4), tuftMat);
cone70.position.set(-0.0573, 0.1481, 0.0401);
cone70.rotation.set(deg(8.0292), deg(66.6529), deg(11.4687));
tuft7.add(cone70);
const cone71 = new THREE.Mesh(new THREE.ConeGeometry(0.065, 0.2319, 4), tuftMat);
cone71.position.set(-0.0359, 0.086, -0.0601);
cone71.rotation.set(deg(-12.0189), deg(70.6536), deg(7.1796));
tuft7.add(cone71);
const flower1 = new THREE.Group();
flower1.name = 'flower1';
flower1.position.set(1.7318, 2.5, 0.3789);
root.add(flower1);
const cylinder73 = new THREE.Mesh(cylinderGeo, tuftMat);
cylinder73.position.set(0, 0.09, 0);
flower1.add(cylinder73);
const sphere74 = new THREE.Mesh(sphereGeo, petalMat);
sphere74.position.set(0, 0.21, 0);
sphere74.scale.set(1, 0.7, 1);
flower1.add(sphere74);
const flower2 = new THREE.Group();
flower2.name = 'flower2';
flower2.position.set(-0.3844, 2.5, 0.1216);
root.add(flower2);
const cylinder76 = new THREE.Mesh(cylinderGeo, tuftMat);
cylinder76.position.set(0, 0.09, 0);
flower2.add(cylinder76);
const sphere77 = new THREE.Mesh(sphereGeo, petalMat);
sphere77.position.set(0, 0.21, 0);
sphere77.scale.set(1, 0.7, 1);
flower2.add(sphere77);
const flower3 = new THREE.Group();
flower3.name = 'flower3';
flower3.position.set(0.7658, 2.5, -0.0129);
root.add(flower3);
const cylinder79 = new THREE.Mesh(cylinderGeo, tuftMat);
cylinder79.position.set(0, 0.09, 0);
flower3.add(cylinder79);
const sphere80 = new THREE.Mesh(sphereGeo, petalPinkMat);
sphere80.position.set(0, 0.21, 0);
sphere80.scale.set(1, 0.7, 1);
flower3.add(sphere80);
const flower4 = new THREE.Group();
flower4.name = 'flower4';
flower4.position.set(0.1232, 2.5, 0.75);
root.add(flower4);
const cylinder82 = new THREE.Mesh(cylinderGeo, tuftMat);
cylinder82.position.set(0, 0.09, 0);
flower4.add(cylinder82);
const sphere83 = new THREE.Mesh(sphereGeo, petalMat);
sphere83.position.set(0, 0.21, 0);
sphere83.scale.set(1, 0.7, 1);
flower4.add(sphere83);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createGrassPlatform;
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









