| 30 | */ |
| 31 | |
| 32 | export function createEnvironment() { |
| 33 | |
| 34 | const environment = new Group(); |
| 35 | const material = new MeshStandardMaterial({ |
| 36 | color: 0xc1c1c1, |
| 37 | roughness: 0.0, |
| 38 | metalness: 1.0 |
| 39 | }); |
| 40 | |
| 41 | const m = new Matrix4(); |
| 42 | const s = new Vector3(); |
| 43 | const p = new Vector3(); |
| 44 | const q = new Quaternion(); |
| 45 | |
| 46 | q.identity(); |
| 47 | |
| 48 | // Total instances = n * n * 2 * 16 |
| 49 | // Total triangles = instances * 12 |
| 50 | |
| 51 | const n = 12; |
| 52 | const clusterSizeXZ = 24; |
| 53 | const instanceSizeXZ = clusterSizeXZ / n; |
| 54 | const instanceHeight = 10; |
| 55 | const clearance = 0.3; |
| 56 | |
| 57 | const geometry = new BoxGeometry(1, 1, 1); |
| 58 | geometry.boundingSphere = new Sphere(); |
| 59 | geometry.boundingBox = new Box3(); |
| 60 | geometry.boundingBox.min.set(0, -instanceHeight, 0); |
| 61 | geometry.boundingBox.max.set(clusterSizeXZ, instanceHeight, clusterSizeXZ); |
| 62 | geometry.boundingBox.getBoundingSphere(geometry.boundingSphere); |
| 63 | |
| 64 | // 4x4 instance clusters |
| 65 | for(let i = -2; i < 2; ++i) { |
| 66 | |
| 67 | for(let j = -2; j < 2; ++j) { |
| 68 | |
| 69 | const mesh = new InstancedMesh(geometry, material, n ** 2 * 2); |
| 70 | |
| 71 | // nx2xn instances |
| 72 | for(let k = 0, x = 0; x < n; ++x) { |
| 73 | |
| 74 | for(let y = -1; y < 1; ++y) { |
| 75 | |
| 76 | for(let z = 0; z < n; ++z) { |
| 77 | |
| 78 | s.set(instanceSizeXZ, Math.random() * (instanceHeight - clearance), instanceSizeXZ); |
| 79 | p.set(x * instanceSizeXZ, (y + 0.5) * instanceHeight, z * instanceSizeXZ); |
| 80 | mesh.setMatrixAt(k++, m.compose(p, q, s)); |
| 81 | |
| 82 | } |
| 83 | |
| 84 | } |
| 85 | |
| 86 | } |
| 87 | |
| 88 | mesh.position.set(clusterSizeXZ * i, 0, clusterSizeXZ * j); |
| 89 | mesh.instanceMatrix.needsUpdate = true; |