- ground-model.ts: read schema 2 terrain_grid (origin, step, nx, ny, z), checked the same way as the stored project form; schema 1 is still read. - view/terrain.ts: the grid as a mesh in pier-scene coordinates (x = E − pivot E, z = −(N − pivot N), y = EL), same as the pier frame. Cells with a missing corner are not drawn. - scene.ts: draws the terrain in place of the 60 m plane when the model has a grid; the camera fits the members, not the terrain. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
38 lines
1.5 KiB
TypeScript
38 lines
1.5 KiB
TypeScript
import * as THREE from 'three';
|
||
import type { TerrainGrid } from '../core/ground-model';
|
||
|
||
/**
|
||
* Terrain grid → mesh in scene coordinates. The scene origin is the pier centre (pivot), with y up:
|
||
* x = X − pivot.e, y = EL, z = −(Y − pivot.n). This is the straight-frame matrix of the pier scene (stretchMatrix, k = 0),
|
||
* so the terrain lines up with the footings and copings. A cell is drawn only when its four corners have data.
|
||
*/
|
||
export function terrainGeometry(grid: TerrainGrid, pivot: { e: number; n: number }): THREE.BufferGeometry {
|
||
const { origin, step, nx, ny, z } = grid;
|
||
const positions: number[] = [];
|
||
const index: number[] = [];
|
||
const vertexOf = new Int32Array(nx * ny).fill(-1);
|
||
for (let j = 0; j < ny; j++) {
|
||
for (let i = 0; i < nx; i++) {
|
||
const h = z[j * nx + i];
|
||
if (h === null) continue;
|
||
vertexOf[j * nx + i] = positions.length / 3;
|
||
positions.push(origin[0] + i * step - pivot.e, h, -(origin[1] + j * step - pivot.n));
|
||
}
|
||
}
|
||
for (let j = 0; j < ny - 1; j++) {
|
||
for (let i = 0; i < nx - 1; i++) {
|
||
const a = vertexOf[j * nx + i];
|
||
const b = vertexOf[j * nx + i + 1];
|
||
const c = vertexOf[(j + 1) * nx + i];
|
||
const d = vertexOf[(j + 1) * nx + i + 1];
|
||
if (a < 0 || b < 0 || c < 0 || d < 0) continue;
|
||
index.push(a, c, b, b, c, d);
|
||
}
|
||
}
|
||
const geometry = new THREE.BufferGeometry();
|
||
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
||
geometry.setIndex(index);
|
||
geometry.computeVertexNormals();
|
||
return geometry;
|
||
}
|