932 üçgen5,39 × 1,99 × 5,95 m
Kodda kullan
Editörde remix’lehill.js · 391 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.
/**
* Grassy Hill — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 932 · Size (W × H × D): 5.39 × 1.99 × 5.95 m
*
* Usage:
* import { createHill } from './hill.js';
*
* const model = createHill();
* 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 createHill() {
const root = new THREE.Group();
root.name = 'Hill';
// Materials
const grassMat = new THREE.MeshStandardMaterial({ name: 'grass', color: 0x6aae45, roughness: 0.9, flatShading: true });
const grassLightMat = new THREE.MeshStandardMaterial({ name: 'grassLight', color: 0x6eb856, roughness: 0.9, flatShading: true });
const grassDarkMat = new THREE.MeshStandardMaterial({ name: 'grassDark', color: 0x5b8836, roughness: 0.9, flatShading: true });
const rockMat = new THREE.MeshStandardMaterial({ name: 'rock', color: 0x95918a, roughness: 0.9, flatShading: true });
const rockDarkMat = new THREE.MeshStandardMaterial({ name: 'rockDark', color: 0x77736c, roughness: 0.95, flatShading: true });
const petalMat = new THREE.MeshStandardMaterial({ name: 'petal', color: 0xfff3c4, roughness: 0.7, flatShading: true });
const petalBlueMat = new THREE.MeshStandardMaterial({ name: 'petalBlue', color: 0x8fb4f5, roughness: 0.7, flatShading: true });
// Shared geometries
const cylinderGeo = new THREE.CylinderGeometry(0.012, 0.016, 0.2112, 4);
const dodecahedronGeo = new THREE.DodecahedronGeometry(0.0549, 0);
const coneGeo = new THREE.ConeGeometry(0.0338, 0.0845, 3);
// Parts
const hill = new THREE.Group();
hill.name = 'hill';
hill.position.set(0, 0.0589, 0);
hill.rotation.set(0, deg(81.9581), 0);
root.add(hill);
const mound = new THREE.Mesh(jitter(lathe([[0, 0], [1, 0], [0.8571, 0.1048], [0.7143, 0.2972], [0.5714, 0.5107], [0.4286, 0.7082], [0.2857, 0.8652], [0.1429, 0.9656], [0, 1]], 14), 0.035, 3), grassMat);
mound.name = 'mound';
mound.scale.set(3, 1.8, 2.5094);
hill.add(mound);
const shoulder = new THREE.Mesh(jitter(lathe([[0, 0], [1, 0], [0.8, 0.1761], [0.6, 0.4683], [0.4, 0.7435], [0.2, 0.933], [0, 1]], 11), 0.05, 10), grassMat);
shoulder.name = 'shoulder';
shoulder.position.set(0.1688, 0, 1.2187);
shoulder.scale.set(1.6904, 1.2571, 1.4369);
hill.add(shoulder);
const dressing = new THREE.Group();
dressing.name = 'dressing';
root.add(dressing);
const tuft1 = new THREE.Group();
tuft1.name = 'tuft1';
tuft1.position.set(0.4813, 1.7038, -0.1137);
dressing.add(tuft1);
const cone6 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2945, 3), grassDarkMat);
cone6.position.set(0.0621, 0.1272, -0.0039);
cone6.rotation.set(deg(1.5887), deg(11.1348), deg(-11.9651));
cone6.scale.set(1, 1, 0.45);
tuft1.add(cone6);
const cone7 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2642, 3), grassMat);
cone7.position.set(-0.0168, 0.1121, 0.0599);
cone7.rotation.set(deg(14.543), deg(20.4617), deg(4.7895));
cone7.scale.set(1, 1, 0.45);
tuft1.add(cone7);
const cone8 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2776, 3), grassLightMat);
cone8.position.set(-0.0622, 0.1188, 0.0025);
cone8.rotation.set(deg(-10.2058), deg(32.4381), deg(19.731));
cone8.scale.set(1, 1, 0.45);
tuft1.add(cone8);
const cone9 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2817, 3), grassDarkMat);
cone9.position.set(0.0225, 0.1209, -0.058);
cone9.rotation.set(deg(-12.4737), deg(10.3569), deg(-5.2197));
cone9.scale.set(1, 1, 0.45);
tuft1.add(cone9);
const tuft2 = new THREE.Group();
tuft2.name = 'tuft2';
tuft2.position.set(-0.6252, 1.5092, 0.5015);
dressing.add(tuft2);
const cone11 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2423, 3), grassDarkMat);
cone11.position.set(0.0618, 0.1011, -0.0068);
cone11.rotation.set(deg(2.353), deg(12.3675), deg(-20.9773));
cone11.scale.set(1, 1, 0.45);
tuft2.add(cone11);
const cone12 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2816, 3), grassMat);
cone12.position.set(-0.0319, 0.1208, 0.0534);
cone12.rotation.set(deg(17.5024), deg(4.8767), deg(10.7155));
cone12.scale.set(1, 1, 0.45);
tuft2.add(cone12);
const cone13 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3215, 3), grassLightMat);
cone13.position.set(-0.0378, 0.1407, -0.0494);
cone13.rotation.set(deg(-174.0467), deg(62.3921), deg(159.4077));
cone13.scale.set(1, 1, 0.45);
tuft2.add(cone13);
const tuft3 = new THREE.Group();
tuft3.name = 'tuft3';
tuft3.position.set(-0.0065, 1.5397, -0.9354);
dressing.add(tuft3);
const cone15 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.247, 3), grassDarkMat);
cone15.position.set(0.0612, 0.1035, -0.0114);
cone15.rotation.set(deg(157.1232), deg(59.4813), deg(-156.3594));
cone15.scale.set(1, 1, 0.45);
tuft3.add(cone15);
const cone16 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3437, 3), grassMat);
cone16.position.set(-0.0422, 0.1518, 0.0457);
cone16.rotation.set(deg(-144.1052), deg(63.925), deg(154.0345));
cone16.scale.set(1, 1, 0.45);
tuft3.add(cone16);
const cone17 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3281, 3), grassLightMat);
cone17.position.set(-0.0303, 0.1441, -0.0543);
cone17.rotation.set(deg(-173.0964), deg(67.9314), deg(154.0671));
cone17.scale.set(1, 1, 0.45);
tuft3.add(cone17);
const flower4 = new THREE.Group();
flower4.name = 'flower4';
flower4.position.set(0.811, 1.2064, 0.8745);
dressing.add(flower4);
const cylinder19 = new THREE.Mesh(cylinderGeo, grassDarkMat);
cylinder19.position.set(0, 0.0856, 0);
flower4.add(cylinder19);
const dodecahedron20 = new THREE.Mesh(dodecahedronGeo, petalBlueMat);
dodecahedron20.position.set(0, 0.2012, 0);
dodecahedron20.scale.set(1, 0.6, 1);
flower4.add(dodecahedron20);
const cone21 = new THREE.Mesh(coneGeo, grassDarkMat);
cone21.position.set(0.0169, 0.0296, 0);
cone21.rotation.set(0, deg(122.6426), deg(-40));
cone21.scale.set(1, 1, 0.4);
flower4.add(cone21);
const tuft5 = new THREE.Group();
tuft5.name = 'tuft5';
tuft5.position.set(-1.4964, 0.808, 0.0906);
dressing.add(tuft5);
const cone23 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3189, 3), grassDarkMat);
cone23.position.set(0.06, 0.1395, -0.0163);
cone23.rotation.set(deg(23.5823), deg(53.5592), deg(-34.7649));
cone23.scale.set(1, 1, 0.45);
tuft5.add(cone23);
const cone24 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2552, 3), grassMat);
cone24.position.set(-0.0123, 0.1076, 0.061);
cone24.rotation.set(deg(18.2013), deg(14.4551), deg(3.923));
cone24.scale.set(1, 1, 0.45);
tuft5.add(cone24);
const cone25 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2677, 3), grassLightMat);
cone25.position.set(-0.059, 0.1138, -0.0198);
cone25.rotation.set(deg(-20.6286), deg(40.4996), deg(22.2075));
cone25.scale.set(1, 1, 0.45);
tuft5.add(cone25);
const cone26 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3143, 3), grassDarkMat);
cone26.position.set(-0.0158, 0.1372, -0.0602);
cone26.rotation.set(deg(-174.2442), deg(78.2899), deg(153.2604));
cone26.scale.set(1, 1, 0.45);
tuft5.add(cone26);
const tuft6 = new THREE.Group();
tuft6.name = 'tuft6';
tuft6.position.set(1.2717, 0.8772, -0.8907);
dressing.add(tuft6);
const cone28 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2999, 3), grassDarkMat);
cone28.position.set(0.06, 0.13, -0.0164);
cone28.rotation.set(deg(13.1808), deg(45.904), deg(-24.1273));
cone28.scale.set(1, 1, 0.45);
tuft6.add(cone28);
const cone29 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3501, 3), grassMat);
cone29.position.set(-0.0389, 0.155, 0.0486);
cone29.rotation.set(deg(-139.856), deg(62.1964), deg(152.8815));
cone29.scale.set(1, 1, 0.45);
tuft6.add(cone29);
const cone30 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2918, 3), grassLightMat);
cone30.position.set(-0.0081, 0.1259, -0.0617);
cone30.rotation.set(deg(-26.9797), deg(78.6867), deg(10.8422));
cone30.scale.set(1, 1, 0.45);
tuft6.add(cone30);
const tuft7 = new THREE.Group();
tuft7.name = 'tuft7';
tuft7.position.set(-0.5133, 1.0798, 1.4459);
dressing.add(tuft7);
const cone32 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2828, 3), grassDarkMat);
cone32.position.set(0.061, 0.1214, 0.0121);
cone32.rotation.set(deg(17.4346), deg(48.0361), deg(-19.5777));
cone32.scale.set(1, 1, 0.45);
tuft7.add(cone32);
const cone33 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2659, 3), grassMat);
cone33.position.set(-0.02, 0.113, 0.0589);
cone33.rotation.set(deg(16.7145), deg(30.5895), deg(8.017));
cone33.scale.set(1, 1, 0.45);
tuft7.add(cone33);
const cone34 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3016, 3), grassLightMat);
cone34.position.set(-0.0591, 0.1308, 0.0194);
cone34.rotation.set(deg(-95.487), deg(73.3761), deg(100.5457));
cone34.scale.set(1, 1, 0.45);
tuft7.add(cone34);
const cone35 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2893, 3), grassDarkMat);
cone35.position.set(0.0168, 0.1247, -0.0599);
cone35.rotation.set(deg(-13.7255), deg(43.6867), deg(-7.066));
cone35.scale.set(1, 1, 0.45);
tuft7.add(cone35);
const flower8 = new THREE.Group();
flower8.name = 'flower8';
flower8.position.set(-1.1403, 0.7735, -1.3096);
dressing.add(flower8);
const cylinder37 = new THREE.Mesh(cylinderGeo, grassDarkMat);
cylinder37.position.set(0, 0.0856, 0);
flower8.add(cylinder37);
const dodecahedron38 = new THREE.Mesh(dodecahedronGeo, petalMat);
dodecahedron38.position.set(0, 0.2012, 0);
dodecahedron38.scale.set(1, 0.6, 1);
flower8.add(dodecahedron38);
const cone39 = new THREE.Mesh(coneGeo, grassDarkMat);
cone39.position.set(0.0169, 0.0296, 0);
cone39.rotation.set(0, deg(238.7538), deg(-40));
cone39.scale.set(1, 1, 0.4);
flower8.add(cone39);
const tuft9 = new THREE.Group();
tuft9.name = 'tuft9';
tuft9.position.set(1.9049, 0.4961, 0.6603);
dressing.add(tuft9);
const cone41 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2432, 3), grassDarkMat);
cone41.position.set(0.0613, 0.1016, -0.0108);
cone41.rotation.set(deg(139.2174), deg(64.6924), deg(-139.3171));
cone41.scale.set(1, 1, 0.45);
tuft9.add(cone41);
const cone42 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3456, 3), grassMat);
cone42.position.set(-0.0076, 0.1528, 0.0617);
cone42.rotation.set(deg(12.1417), deg(35.7519), deg(2.0084));
cone42.scale.set(1, 1, 0.45);
tuft9.add(cone42);
const cone43 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2852, 3), grassLightMat);
cone43.position.set(-0.0599, 0.1226, 0.0168);
cone43.rotation.set(deg(-132.2155), deg(73.9152), deg(134.3254));
cone43.scale.set(1, 1, 0.45);
tuft9.add(cone43);
const cone44 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2547, 3), grassDarkMat);
cone44.position.set(-0.0018, 0.1074, -0.0622);
cone44.rotation.set(deg(-170.0229), deg(89.0312), deg(156.3655));
cone44.scale.set(1, 1, 0.45);
tuft9.add(cone44);
const tuft10 = new THREE.Group();
tuft10.name = 'tuft10';
tuft10.position.set(-1.7511, 0.3784, 1.086);
dressing.add(tuft10);
const cone46 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3388, 3), grassDarkMat);
cone46.position.set(0.0555, 0.1494, 0.0281);
cone46.rotation.set(deg(8.8138), deg(1.1926), deg(-16.2381));
cone46.scale.set(1, 1, 0.45);
tuft10.add(cone46);
const cone47 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3345, 3), grassMat);
cone47.position.set(-0.0285, 0.1472, 0.0553);
cone47.rotation.set(deg(11.9676), deg(1.8131), deg(6.2051));
cone47.scale.set(1, 1, 0.45);
tuft10.add(cone47);
const cone48 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3253, 3), grassLightMat);
cone48.position.set(-0.0616, 0.1426, 0.0086);
cone48.rotation.set(deg(-82.7502), deg(75.5375), deg(84.9613));
cone48.scale.set(1, 1, 0.45);
tuft10.add(cone48);
const cone49 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.284, 3), grassDarkMat);
cone49.position.set(-0.0237, 0.122, -0.0575);
cone49.rotation.set(deg(-23.9666), deg(72.3857), deg(14.2003));
cone49.scale.set(1, 1, 0.45);
tuft10.add(cone49);
const tuft11 = new THREE.Group();
tuft11.name = 'tuft11';
tuft11.position.set(0.8196, 0.6473, -1.7902);
dressing.add(tuft11);
const cone51 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2598, 3), grassDarkMat);
cone51.position.set(0.0591, 0.1099, 0.0193);
cone51.rotation.set(deg(80.3364), deg(69.7829), deg(-74.6527));
cone51.scale.set(1, 1, 0.45);
tuft11.add(cone51);
const cone52 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.326, 3), grassMat);
cone52.position.set(0.0037, 0.143, 0.0621);
cone52.rotation.set(deg(16.0906), deg(2.8814), deg(-0.9512));
cone52.scale.set(1, 1, 0.45);
tuft11.add(cone52);
const cone53 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.244, 3), grassLightMat);
cone53.position.set(-0.0606, 0.102, -0.014);
cone53.rotation.set(deg(-141.966), deg(74.6174), deg(138.5629));
cone53.scale.set(1, 1, 0.45);
tuft11.add(cone53);
const cone54 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3364, 3), grassDarkMat);
cone54.position.set(0.0119, 0.1482, -0.0611);
cone54.rotation.set(deg(-9.2186), deg(46.8251), deg(-3.2677));
cone54.scale.set(1, 1, 0.45);
tuft11.add(cone54);
const flower12 = new THREE.Group();
flower12.name = 'flower12';
flower12.position.set(0.9295, 0.5226, 1.8494);
dressing.add(flower12);
const cylinder56 = new THREE.Mesh(cylinderGeo, grassDarkMat);
cylinder56.position.set(0, 0.0856, 0);
flower12.add(cylinder56);
const dodecahedron57 = new THREE.Mesh(dodecahedronGeo, petalBlueMat);
dodecahedron57.position.set(0, 0.2012, 0);
dodecahedron57.scale.set(1, 0.6, 1);
flower12.add(dodecahedron57);
const cone58 = new THREE.Mesh(coneGeo, grassDarkMat);
cone58.position.set(0.0169, 0.0296, 0);
cone58.rotation.set(0, deg(30.0281), deg(-40));
cone58.scale.set(1, 1, 0.4);
flower12.add(cone58);
const tuft13 = new THREE.Group();
tuft13.name = 'tuft13';
tuft13.position.set(-2.049, 0.0927, -1.1988);
dressing.add(tuft13);
const cone60 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3532, 3), grassDarkMat);
cone60.position.set(0.0601, 0.1566, 0.0161);
cone60.rotation.set(deg(146.4695), deg(69.352), deg(-141.1442));
cone60.scale.set(1, 1, 0.45);
tuft13.add(cone60);
const cone61 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.2447, 3), grassMat);
cone61.position.set(0.0291, 0.1023, 0.055);
cone61.rotation.set(deg(124.0359), deg(82.3858), deg(-110.1582));
cone61.scale.set(1, 1, 0.45);
tuft13.add(cone61);
const cone62 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3596, 3), grassLightMat);
cone62.position.set(-0.0616, 0.1598, -0.0087);
cone62.rotation.set(deg(-15.57), deg(39.2519), deg(20.4655));
cone62.scale.set(1, 1, 0.45);
tuft13.add(cone62);
const cone63 = new THREE.Mesh(new THREE.ConeGeometry(0.0691, 0.3653, 3), grassDarkMat);
cone63.position.set(-0.0142, 0.1626, -0.0606);
cone63.rotation.set(deg(-29.4695), deg(63.6155), deg(10.4257));
cone63.scale.set(1, 1, 0.45);
tuft13.add(cone63);
const rock1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2157, 0), 0.0388, 381), rockMat);
rock1.name = 'rock1';
rock1.position.set(1.5083, 0.7935, -0.8617);
rock1.rotation.set(deg(-7.1934), deg(12.1483), deg(-4.429));
rock1.scale.set(1.0407, 0.6209, 1);
dressing.add(rock1);
const rock2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2855, 0), 0.0514, 376), rockDarkMat);
rock2.name = 'rock2';
rock2.position.set(0.4331, 1.4334, 1.0493);
rock2.rotation.set(deg(-5.7611), deg(286.7857), deg(-2.4723));
rock2.scale.set(1.0804, 0.5755, 1);
dressing.add(rock2);
const rock3 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.2467, 0), 0.0444, 382), rockMat);
rock3.name = 'rock3';
rock3.position.set(0.9087, 1.0423, 1.2752);
rock3.rotation.set(deg(5.4397), deg(74.5639), deg(4.4835));
rock3.scale.set(1.1813, 0.5928, 1);
dressing.add(rock3);
const footStone1 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.14, 0), 0.0252, 145), rockMat);
footStone1.name = 'footStone1';
footStone1.position.set(-2.614, 0.0743, -1.3306);
footStone1.rotation.set(deg(-6.4402), deg(345.3177), deg(-2.8507));
footStone1.scale.set(1.2113, 0.5484, 1);
dressing.add(footStone1);
const footStone2 = new THREE.Mesh(jitter(new THREE.DodecahedronGeometry(0.14, 0), 0.0252, 467), rockMat);
footStone2.name = 'footStone2';
footStone2.position.set(2.4746, 0.0758, -1.5057);
footStone2.rotation.set(deg(-3.4121), deg(261.4087), deg(4.0205));
footStone2.scale.set(1.1825, 0.507, 1);
dressing.add(footStone2);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createHill;
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









