forked from phenom/healer-man
36 lines
2.1 KiB
JavaScript
36 lines
2.1 KiB
JavaScript
import { sourceTerrainToThreeMatrix } from '../sand-vortex/terrain-geometry.mjs';
|
|
import { Vector3 } from 'three';
|
|
|
|
const BOX_FACES = [
|
|
[0, 3, 2], [0, 2, 1], [4, 5, 6], [4, 6, 7],
|
|
[0, 1, 5], [0, 5, 4], [1, 2, 6], [1, 6, 5],
|
|
[2, 3, 7], [2, 7, 6], [3, 0, 4], [3, 4, 7],
|
|
];
|
|
|
|
/** Match the native ROS exporter: inverse primary TRS followed by reflected Z. */
|
|
export function sourceAnchorSupportGeometry(points, placement, {
|
|
halfExtent = 60, thickness = 3, metersPerSourceUnit = 1, omitPointIndices = [],
|
|
} = {}) {
|
|
if (!Array.isArray(points) || !Number.isFinite(halfExtent) || halfExtent <= 0
|
|
|| !Number.isFinite(thickness) || thickness <= 0) throw new Error('Invalid source-anchor support dimensions.');
|
|
const transform = sourceTerrainToThreeMatrix(placement, metersPerSourceUnit);
|
|
if (!Array.isArray(omitPointIndices) || new Set(omitPointIndices).size !== omitPointIndices.length
|
|
|| omitPointIndices.some(i => !Number.isInteger(i) || i < 0 || i >= points.length)) throw new Error('Invalid source-anchor support omissions.');
|
|
const omitted = new Set(omitPointIndices);
|
|
const faces = transform.determinant() < 0 ? BOX_FACES.map(([a, b, c]) => [a, c, b]) : BOX_FACES;
|
|
const positions = [], indices = [], navigationPositions = [];
|
|
for (const [pointIndex, point] of points.entries()) {
|
|
if (omitted.has(pointIndex)) continue;
|
|
if (!Array.isArray(point) || point.length !== 3 || !point.every(Number.isFinite)) throw new Error('Invalid source-anchor support point.');
|
|
const [x, y, z] = point, h = halfExtent;
|
|
const vertices = [[x-h,y,z-h],[x+h,y,z-h],[x+h,y,z+h],[x-h,y,z+h],
|
|
[x-h,y-thickness,z-h],[x+h,y-thickness,z-h],[x+h,y-thickness,z+h],[x-h,y-thickness,z+h]]
|
|
.map(p => new Vector3(...p).applyMatrix4(transform).toArray());
|
|
const offset = positions.length / 3;
|
|
positions.push(...vertices.flat());
|
|
for (const face of faces) indices.push(...face.map(i => offset + i));
|
|
for (const face of faces.slice(0, 2)) for (const i of face) navigationPositions.push(...vertices[i]);
|
|
}
|
|
return { positions, indices, navigationPositions };
|
|
}
|