@ifc-lite/renderer 1.39.0 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deviation/deviation-pipeline.d.ts +8 -0
- package/dist/deviation/deviation-pipeline.d.ts.map +1 -1
- package/dist/deviation/deviation-pipeline.js +20 -9
- package/dist/deviation/deviation-pipeline.js.map +1 -1
- package/dist/deviation/deviation-shader.wgsl.d.ts +1 -1
- package/dist/deviation/deviation-shader.wgsl.d.ts.map +1 -1
- package/dist/deviation/deviation-shader.wgsl.js +11 -3
- package/dist/deviation/deviation-shader.wgsl.js.map +1 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -3
- package/dist/index.js.map +1 -1
- package/dist/picker.d.ts +9 -0
- package/dist/picker.d.ts.map +1 -1
- package/dist/picker.js +84 -2
- package/dist/picker.js.map +1 -1
- package/dist/picking-manager.d.ts +33 -5
- package/dist/picking-manager.d.ts.map +1 -1
- package/dist/picking-manager.js +162 -101
- package/dist/picking-manager.js.map +1 -1
- package/dist/pointcloud/point-cloud-node.d.ts +46 -0
- package/dist/pointcloud/point-cloud-node.d.ts.map +1 -1
- package/dist/pointcloud/point-cloud-node.js +71 -0
- package/dist/pointcloud/point-cloud-node.js.map +1 -1
- package/dist/pointcloud/point-cloud-ray-transform.d.ts +66 -0
- package/dist/pointcloud/point-cloud-ray-transform.d.ts.map +1 -0
- package/dist/pointcloud/point-cloud-ray-transform.js +172 -0
- package/dist/pointcloud/point-cloud-ray-transform.js.map +1 -0
- package/dist/pointcloud/point-cloud-renderer.d.ts +24 -0
- package/dist/pointcloud/point-cloud-renderer.d.ts.map +1 -1
- package/dist/pointcloud/point-cloud-renderer.js +46 -13
- package/dist/pointcloud/point-cloud-renderer.js.map +1 -1
- package/dist/pointcloud/point-cloud-spatial-index.d.ts +188 -0
- package/dist/pointcloud/point-cloud-spatial-index.d.ts.map +1 -0
- package/dist/pointcloud/point-cloud-spatial-index.js +536 -0
- package/dist/pointcloud/point-cloud-spatial-index.js.map +1 -0
- package/dist/pointcloud/point-cloud-uniforms.d.ts.map +1 -1
- package/dist/pointcloud/point-cloud-uniforms.js +14 -6
- package/dist/pointcloud/point-cloud-uniforms.js.map +1 -1
- package/dist/raycast-engine.d.ts +8 -0
- package/dist/raycast-engine.d.ts.map +1 -1
- package/dist/raycast-engine.js +68 -23
- package/dist/raycast-engine.js.map +1 -1
- package/dist/raycast-point-cloud-query.d.ts +122 -0
- package/dist/raycast-point-cloud-query.d.ts.map +1 -0
- package/dist/raycast-point-cloud-query.js +145 -0
- package/dist/raycast-point-cloud-query.js.map +1 -0
- package/dist/scene-rect-select.d.ts +51 -0
- package/dist/scene-rect-select.d.ts.map +1 -0
- package/dist/scene-rect-select.js +207 -0
- package/dist/scene-rect-select.js.map +1 -0
- package/dist/scene.d.ts +15 -0
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +115 -46
- package/dist/scene.js.map +1 -1
- package/dist/snap-detector.d.ts +12 -1
- package/dist/snap-detector.d.ts.map +1 -1
- package/dist/snap-detector.js +9 -1
- package/dist/snap-detector.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { PointCloudAsset } from '@ifc-lite/geometry';
|
|
9
9
|
import type { PointRenderPipeline } from './point-pipeline.js';
|
|
10
|
+
import { PointCloudSpatialIndex } from './point-cloud-spatial-index.js';
|
|
10
11
|
export interface PointCloudGpuChunk {
|
|
11
12
|
vertexBuffer: GPUBuffer;
|
|
12
13
|
/**
|
|
@@ -52,7 +53,52 @@ export interface PointCloudNode {
|
|
|
52
53
|
max: [number, number, number];
|
|
53
54
|
};
|
|
54
55
|
pointCount: number;
|
|
56
|
+
/**
|
|
57
|
+
* CPU spatial index over this node's points (issue #1860), so the
|
|
58
|
+
* measure tool can snap to real scan points even though `chunks`
|
|
59
|
+
* above holds only opaque GPU buffers. Built incrementally in
|
|
60
|
+
* `appendChunkToNode`, alongside the GPU upload.
|
|
61
|
+
*/
|
|
62
|
+
spatialIndex: PointCloudSpatialIndex;
|
|
63
|
+
/**
|
|
64
|
+
* Optional per-asset GPU model matrix (column-major, 16 floats),
|
|
65
|
+
* applied in the vertex shader as `uniforms.model * vec4(position, 1)`
|
|
66
|
+
* before `viewProj` (issue #1804: aligns a georeferenced point cloud
|
|
67
|
+
* with the IFC model's `IfcMapConversion`). `undefined` → identity,
|
|
68
|
+
* written by `writePointCloudUniforms`.
|
|
69
|
+
*/
|
|
70
|
+
model?: Float32Array;
|
|
55
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Transform an AABB through a column-major 4x4 model matrix and return
|
|
74
|
+
* the axis-aligned box of the result (standard 8-corner fold). Used so
|
|
75
|
+
* `PointCloudRenderer.getBounds()` reports WORLD-space extents when a
|
|
76
|
+
* node carries a per-asset model matrix (issue #1804) — the height-ramp
|
|
77
|
+
* colour mode and the viewer's scene-bounds/framing consume those
|
|
78
|
+
* extents and must agree with where the shader actually places points.
|
|
79
|
+
* Returns the input box unchanged for a missing/malformed matrix
|
|
80
|
+
* (mirrors `writePointCloudUniforms`' identity fallback).
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* True when `model` is a usable 4x4: exactly 16 entries, all finite.
|
|
84
|
+
*
|
|
85
|
+
* Single-sourced so the two consumers of `PointCloudNode.model` — the AABB
|
|
86
|
+
* fold below and `writePointCloudUniforms`' GPU write — accept exactly the
|
|
87
|
+
* same matrices. When they disagree, a matrix one accepts and the other
|
|
88
|
+
* rejects puts the reported bounds in a different frame from the rendered
|
|
89
|
+
* points, which is the precise failure this transform exists to prevent.
|
|
90
|
+
* The finiteness check matters because a single NaN propagates to every
|
|
91
|
+
* corner of the box (and to every point on the GPU), so a degenerate matrix
|
|
92
|
+
* must fall back to identity rather than poison the result.
|
|
93
|
+
*/
|
|
94
|
+
export declare function isUsableModelMatrix(model: Float32Array | undefined): model is Float32Array;
|
|
95
|
+
export declare function transformAabb(bounds: {
|
|
96
|
+
min: [number, number, number];
|
|
97
|
+
max: [number, number, number];
|
|
98
|
+
}, model: Float32Array | undefined): {
|
|
99
|
+
min: [number, number, number];
|
|
100
|
+
max: [number, number, number];
|
|
101
|
+
};
|
|
56
102
|
/** Build an empty node — chunks are appended via `appendChunkToNode`. */
|
|
57
103
|
export declare function createNode(device: GPUDevice, pipeline: PointRenderPipeline, meta: PointCloudNodeMeta): PointCloudNode;
|
|
58
104
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point-cloud-node.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-node.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"point-cloud-node.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,65 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
import { POINT_VERTEX_BYTES } from './point-pipeline.js';
|
|
5
|
+
import { PointCloudSpatialIndex } from './point-cloud-spatial-index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Transform an AABB through a column-major 4x4 model matrix and return
|
|
8
|
+
* the axis-aligned box of the result (standard 8-corner fold). Used so
|
|
9
|
+
* `PointCloudRenderer.getBounds()` reports WORLD-space extents when a
|
|
10
|
+
* node carries a per-asset model matrix (issue #1804) — the height-ramp
|
|
11
|
+
* colour mode and the viewer's scene-bounds/framing consume those
|
|
12
|
+
* extents and must agree with where the shader actually places points.
|
|
13
|
+
* Returns the input box unchanged for a missing/malformed matrix
|
|
14
|
+
* (mirrors `writePointCloudUniforms`' identity fallback).
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* True when `model` is a usable 4x4: exactly 16 entries, all finite.
|
|
18
|
+
*
|
|
19
|
+
* Single-sourced so the two consumers of `PointCloudNode.model` — the AABB
|
|
20
|
+
* fold below and `writePointCloudUniforms`' GPU write — accept exactly the
|
|
21
|
+
* same matrices. When they disagree, a matrix one accepts and the other
|
|
22
|
+
* rejects puts the reported bounds in a different frame from the rendered
|
|
23
|
+
* points, which is the precise failure this transform exists to prevent.
|
|
24
|
+
* The finiteness check matters because a single NaN propagates to every
|
|
25
|
+
* corner of the box (and to every point on the GPU), so a degenerate matrix
|
|
26
|
+
* must fall back to identity rather than poison the result.
|
|
27
|
+
*/
|
|
28
|
+
export function isUsableModelMatrix(model) {
|
|
29
|
+
if (!model || model.length !== 16)
|
|
30
|
+
return false;
|
|
31
|
+
for (let i = 0; i < 16; i++) {
|
|
32
|
+
if (!Number.isFinite(model[i]))
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
export function transformAabb(bounds, model) {
|
|
38
|
+
if (!isUsableModelMatrix(model))
|
|
39
|
+
return bounds;
|
|
40
|
+
const min = [Infinity, Infinity, Infinity];
|
|
41
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
42
|
+
for (let c = 0; c < 8; c++) {
|
|
43
|
+
const x = (c & 1) === 0 ? bounds.min[0] : bounds.max[0];
|
|
44
|
+
const y = (c & 2) === 0 ? bounds.min[1] : bounds.max[1];
|
|
45
|
+
const z = (c & 4) === 0 ? bounds.min[2] : bounds.max[2];
|
|
46
|
+
const tx = model[0] * x + model[4] * y + model[8] * z + model[12];
|
|
47
|
+
const ty = model[1] * x + model[5] * y + model[9] * z + model[13];
|
|
48
|
+
const tz = model[2] * x + model[6] * y + model[10] * z + model[14];
|
|
49
|
+
if (tx < min[0])
|
|
50
|
+
min[0] = tx;
|
|
51
|
+
if (ty < min[1])
|
|
52
|
+
min[1] = ty;
|
|
53
|
+
if (tz < min[2])
|
|
54
|
+
min[2] = tz;
|
|
55
|
+
if (tx > max[0])
|
|
56
|
+
max[0] = tx;
|
|
57
|
+
if (ty > max[1])
|
|
58
|
+
max[1] = ty;
|
|
59
|
+
if (tz > max[2])
|
|
60
|
+
max[2] = tz;
|
|
61
|
+
}
|
|
62
|
+
return { min, max };
|
|
63
|
+
}
|
|
5
64
|
/** Build an empty node — chunks are appended via `appendChunkToNode`. */
|
|
6
65
|
export function createNode(device, pipeline, meta) {
|
|
7
66
|
void device;
|
|
@@ -17,6 +76,7 @@ export function createNode(device, pipeline, meta) {
|
|
|
17
76
|
max: [-Infinity, -Infinity, -Infinity],
|
|
18
77
|
},
|
|
19
78
|
pointCount: 0,
|
|
79
|
+
spatialIndex: new PointCloudSpatialIndex(),
|
|
20
80
|
};
|
|
21
81
|
}
|
|
22
82
|
/**
|
|
@@ -44,6 +104,13 @@ export function appendChunkToNode(device, node, chunk) {
|
|
|
44
104
|
const total = chunk.pointCount;
|
|
45
105
|
if (total <= 0)
|
|
46
106
|
return;
|
|
107
|
+
// Index the whole chunk's points for measure-tool snapping (#1860),
|
|
108
|
+
// independent of how the GPU sub-buffer split below divides it up —
|
|
109
|
+
// the index doesn't care about buffer size limits, only world
|
|
110
|
+
// positions. Retains `chunk.positions` (and classifications, so the
|
|
111
|
+
// query can honour the class visibility mask #1783) by reference; see
|
|
112
|
+
// spatial index class docs. No-ops past the index's point cap.
|
|
113
|
+
node.spatialIndex.insertRange(chunk.positions, total, chunk.classifications ?? null);
|
|
47
114
|
// Honour BOTH the raw buffer cap and the storage-binding cap, with a 5%
|
|
48
115
|
// margin for safety against driver rounding.
|
|
49
116
|
const maxBytes = Math.min(device.limits.maxBufferSize, device.limits.maxStorageBufferBindingSize);
|
|
@@ -158,6 +225,10 @@ export function destroyNode(node) {
|
|
|
158
225
|
node.uniformBuffer.destroy();
|
|
159
226
|
node.chunks = [];
|
|
160
227
|
node.pointCount = 0;
|
|
228
|
+
// Drop the retained position arrays + grid buckets (#1860) — without
|
|
229
|
+
// this the spatial index would keep every chunk's Float32Array alive
|
|
230
|
+
// for the rest of the session even after the GPU buffers are freed.
|
|
231
|
+
node.spatialIndex.dispose();
|
|
161
232
|
}
|
|
162
233
|
function growBounds(bounds, bbox) {
|
|
163
234
|
if (bbox.min[0] < bounds.min[0])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point-cloud-node.js","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-node.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAY/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"point-cloud-node.js","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Vec3 } from '../raycaster.js';
|
|
2
|
+
/** The subset of a `PointCloudNode` the snap-source snapshot reads. */
|
|
3
|
+
export interface RayQueryNodeLike {
|
|
4
|
+
meta: {
|
|
5
|
+
expressId: number;
|
|
6
|
+
modelIndex?: number;
|
|
7
|
+
};
|
|
8
|
+
spatialIndex: {
|
|
9
|
+
pointCount: number;
|
|
10
|
+
};
|
|
11
|
+
model?: Float32Array;
|
|
12
|
+
}
|
|
13
|
+
/** One entry of the snapshot handed to `queryPointClouds`. */
|
|
14
|
+
export interface RayQuerySource<TNode extends RayQueryNodeLike> {
|
|
15
|
+
expressId: number;
|
|
16
|
+
modelIndex?: number;
|
|
17
|
+
index: TNode['spatialIndex'];
|
|
18
|
+
classMask: Uint32Array;
|
|
19
|
+
model?: Float32Array;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build the snap-query snapshot from live nodes.
|
|
23
|
+
*
|
|
24
|
+
* Pure and node-shaped rather than inlined in `PointCloudRenderer` so it is
|
|
25
|
+
* testable without a `GPUDevice`. That matters here specifically: the
|
|
26
|
+
* renderer-to-query wiring is exactly where the aligned-scan gap lived, and
|
|
27
|
+
* it went unnoticed because nothing could exercise it without a GPU. Empty
|
|
28
|
+
* nodes are skipped, mirroring `getPickNodes`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildRayQuerySources<TNode extends RayQueryNodeLike>(nodes: Iterable<TNode>, classMask: Uint32Array): Array<RayQuerySource<TNode>>;
|
|
31
|
+
/** A ray rewritten into a point cloud's local frame, plus the conversions
|
|
32
|
+
* needed to move distances and hit positions back out to world space. */
|
|
33
|
+
export interface LocalFrameRay {
|
|
34
|
+
origin: Vec3;
|
|
35
|
+
/** Unit-length in local space, so `queryRay`'s `t` stays a true distance. */
|
|
36
|
+
direction: Vec3;
|
|
37
|
+
/** World distance = local distance * this. 1 for an identity transform. */
|
|
38
|
+
distanceScale: number;
|
|
39
|
+
/** Map a local-space hit position back to world space. */
|
|
40
|
+
toWorld(p: Vec3): Vec3;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Uniform scale factor of a column-major 4x4's linear part.
|
|
44
|
+
*
|
|
45
|
+
* Exact for a similarity transform (every column has the same length);
|
|
46
|
+
* for a non-uniform matrix it returns the mean, which keeps snap
|
|
47
|
+
* tolerances in the right ballpark rather than exact. Returns 1 for a
|
|
48
|
+
* degenerate (~zero) matrix so callers never divide by zero.
|
|
49
|
+
*/
|
|
50
|
+
export declare function matrixUniformScale(m: Float32Array): number;
|
|
51
|
+
/**
|
|
52
|
+
* True when `m` is close enough to the identity that transforming through
|
|
53
|
+
* it is pure overhead. The overwhelmingly common case is an unaligned
|
|
54
|
+
* scan, and this keeps that path allocation-free.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isIdentityMatrix(m: Float32Array): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Rewrite a world-space ray into `model`'s local frame.
|
|
59
|
+
*
|
|
60
|
+
* Returns `null` when no transform is needed (absent, malformed, identity)
|
|
61
|
+
* or when the matrix is singular — callers should then query with the
|
|
62
|
+
* original world ray, which is the correct behaviour for an unaligned
|
|
63
|
+
* cloud and a safe fallback for a degenerate matrix.
|
|
64
|
+
*/
|
|
65
|
+
export declare function toLocalFrameRay(origin: Vec3, direction: Vec3, model: Float32Array | undefined): LocalFrameRay | null;
|
|
66
|
+
//# sourceMappingURL=point-cloud-ray-transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"point-cloud-ray-transform.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-ray-transform.ts"],"names":[],"mappings":"AA+EA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAG5C,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,YAAY,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,gBAAgB;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC7B,SAAS,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,gBAAgB,EACjE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,EACtB,SAAS,EAAE,WAAW,GACrB,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAgB9B;AAED;0EAC0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,CAAC;IACb,6EAA6E;IAC7E,SAAS,EAAE,IAAI,CAAC;IAChB,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,OAAO,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAM1D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAOzD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,IAAI,EACZ,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,YAAY,GAAG,SAAS,GAC9B,aAAa,GAAG,IAAI,CA6BtB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Ray <-> point-cloud local-frame conversion for snap queries.
|
|
6
|
+
*
|
|
7
|
+
* ## Why this exists
|
|
8
|
+
*
|
|
9
|
+
* Two features landed independently and left a gap between them:
|
|
10
|
+
*
|
|
11
|
+
* - #1804 gives each point-cloud node a per-asset model matrix
|
|
12
|
+
* (`PointCloudNode.model`) applied at RENDER time — the shader places
|
|
13
|
+
* points through it, and `transformAabb` folds it into reported bounds.
|
|
14
|
+
* - #1860 built the snap/measure spatial index, which stores RAW,
|
|
15
|
+
* untransformed chunk positions straight off the decoder.
|
|
16
|
+
*
|
|
17
|
+
* So for a georeferenced (aligned) scan the renderer draws points at
|
|
18
|
+
* aligned positions while the snap query walks an index of pre-alignment
|
|
19
|
+
* positions: a measurement snapped to where the point USED to be, not
|
|
20
|
+
* where the user can see it. Both features are individually correct; the
|
|
21
|
+
* defect only exists in their composition, which is why neither PR's tests
|
|
22
|
+
* caught it.
|
|
23
|
+
*
|
|
24
|
+
* ## Why the ray moves, not the points
|
|
25
|
+
*
|
|
26
|
+
* We inverse-transform the ray into the node's local frame rather than
|
|
27
|
+
* transforming candidate points into world space:
|
|
28
|
+
*
|
|
29
|
+
* - The index's cell keys are packed RELATIVE to the first indexed point
|
|
30
|
+
* and are only meaningful in local space — transforming points would
|
|
31
|
+
* invalidate the whole acceleration structure.
|
|
32
|
+
* - It is O(1) per node instead of O(points-examined).
|
|
33
|
+
*
|
|
34
|
+
* ## Distances stay in world units
|
|
35
|
+
*
|
|
36
|
+
* `queryRay` treats `t` as a distance along a UNIT direction and compares
|
|
37
|
+
* `toleranceAt(t)` as a perpendicular radius, both in the index's own
|
|
38
|
+
* space. Under a matrix with scale `s`, a world distance `d` is a local
|
|
39
|
+
* distance `d / s`. Every distance-valued quantity therefore has to be
|
|
40
|
+
* converted on the way in and back on the way out:
|
|
41
|
+
*
|
|
42
|
+
* maxDistance_local = maxDistance_world / s
|
|
43
|
+
* toleranceAt_local(t_local) = toleranceAt_world(t_local * s) / s
|
|
44
|
+
* distance_world = distance_local * s
|
|
45
|
+
*
|
|
46
|
+
* Get this wrong and the ~8px screen-space snap tolerance silently means
|
|
47
|
+
* something different on any scan whose CRS is not in metres (a foot-based
|
|
48
|
+
* CRS carries s = 0.3048), which would read as "snapping feels wrong on
|
|
49
|
+
* US survey-foot projects" — the sort of bug that is very hard to trace
|
|
50
|
+
* back to a matrix.
|
|
51
|
+
*
|
|
52
|
+
* The alignment matrices this handles are similarity transforms (uniform
|
|
53
|
+
* scale * rotation about Y, zero translation — see `pointCloudAlignment`),
|
|
54
|
+
* so a single scalar `s` is exact. `matrixUniformScale` falls back to the
|
|
55
|
+
* mean column length for anything else, which keeps a non-uniform matrix
|
|
56
|
+
* approximately right rather than wildly wrong.
|
|
57
|
+
*
|
|
58
|
+
* ## Known limit: long-range reach under a sub-unit scale
|
|
59
|
+
*
|
|
60
|
+
* `PointCloudSpatialIndex` caps its per-step dilation at
|
|
61
|
+
* `MAX_DILATION_RADIUS_CELLS * cellSize` = 2 LOCAL units, a deliberate
|
|
62
|
+
* bound on march cost. Because the tolerance is converted into local
|
|
63
|
+
* units, a matrix with `s < 1` tightens that cap in world terms: a
|
|
64
|
+
* foot-based CRS (`s = 0.3048`) caps the effective snap radius at
|
|
65
|
+
* `2 * 0.3048 = 0.61 m` rather than 2 m, so at long range a point inside
|
|
66
|
+
* the nominal ~8px tolerance can sit outside the searched cells and be
|
|
67
|
+
* missed.
|
|
68
|
+
*
|
|
69
|
+
* This is a reach limit, not a wrong answer: whatever the query returns is
|
|
70
|
+
* correctly placed, and near-to-mid range (where measuring actually
|
|
71
|
+
* happens) is unaffected. Restoring the full world-space reach means
|
|
72
|
+
* scaling the cap to `MAX_DILATION_RADIUS_CELLS / s` (~14 cells at
|
|
73
|
+
* s = 0.3048), which re-inflates the per-step probe cost that the
|
|
74
|
+
* leading-slab bound exists to contain — a perf trade that should be made
|
|
75
|
+
* deliberately, with a benchmark, rather than folded into this fix.
|
|
76
|
+
*/
|
|
77
|
+
import { MathUtils } from '../math.js';
|
|
78
|
+
import { isUsableModelMatrix } from './point-cloud-node.js';
|
|
79
|
+
/**
|
|
80
|
+
* Build the snap-query snapshot from live nodes.
|
|
81
|
+
*
|
|
82
|
+
* Pure and node-shaped rather than inlined in `PointCloudRenderer` so it is
|
|
83
|
+
* testable without a `GPUDevice`. That matters here specifically: the
|
|
84
|
+
* renderer-to-query wiring is exactly where the aligned-scan gap lived, and
|
|
85
|
+
* it went unnoticed because nothing could exercise it without a GPU. Empty
|
|
86
|
+
* nodes are skipped, mirroring `getPickNodes`.
|
|
87
|
+
*/
|
|
88
|
+
export function buildRayQuerySources(nodes, classMask) {
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const node of nodes) {
|
|
91
|
+
if (node.spatialIndex.pointCount === 0)
|
|
92
|
+
continue;
|
|
93
|
+
out.push({
|
|
94
|
+
expressId: node.meta.expressId,
|
|
95
|
+
modelIndex: node.meta.modelIndex,
|
|
96
|
+
index: node.spatialIndex,
|
|
97
|
+
// The index stores RAW decoder positions while the shader draws
|
|
98
|
+
// through `model` (#1804) — the query needs the matrix to reconcile
|
|
99
|
+
// the two, or an aligned scan snaps to pre-alignment coordinates.
|
|
100
|
+
model: node.model,
|
|
101
|
+
classMask,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Uniform scale factor of a column-major 4x4's linear part.
|
|
108
|
+
*
|
|
109
|
+
* Exact for a similarity transform (every column has the same length);
|
|
110
|
+
* for a non-uniform matrix it returns the mean, which keeps snap
|
|
111
|
+
* tolerances in the right ballpark rather than exact. Returns 1 for a
|
|
112
|
+
* degenerate (~zero) matrix so callers never divide by zero.
|
|
113
|
+
*/
|
|
114
|
+
export function matrixUniformScale(m) {
|
|
115
|
+
const cx = Math.hypot(m[0], m[1], m[2]);
|
|
116
|
+
const cy = Math.hypot(m[4], m[5], m[6]);
|
|
117
|
+
const cz = Math.hypot(m[8], m[9], m[10]);
|
|
118
|
+
const mean = (cx + cy + cz) / 3;
|
|
119
|
+
return mean > 1e-12 ? mean : 1;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* True when `m` is close enough to the identity that transforming through
|
|
123
|
+
* it is pure overhead. The overwhelmingly common case is an unaligned
|
|
124
|
+
* scan, and this keeps that path allocation-free.
|
|
125
|
+
*/
|
|
126
|
+
export function isIdentityMatrix(m) {
|
|
127
|
+
const EPS = 1e-6;
|
|
128
|
+
for (let i = 0; i < 16; i++) {
|
|
129
|
+
const expected = i % 5 === 0 ? 1 : 0;
|
|
130
|
+
if (Math.abs(m[i] - expected) > EPS)
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Rewrite a world-space ray into `model`'s local frame.
|
|
137
|
+
*
|
|
138
|
+
* Returns `null` when no transform is needed (absent, malformed, identity)
|
|
139
|
+
* or when the matrix is singular — callers should then query with the
|
|
140
|
+
* original world ray, which is the correct behaviour for an unaligned
|
|
141
|
+
* cloud and a safe fallback for a degenerate matrix.
|
|
142
|
+
*/
|
|
143
|
+
export function toLocalFrameRay(origin, direction, model) {
|
|
144
|
+
if (!isUsableModelMatrix(model) || isIdentityMatrix(model))
|
|
145
|
+
return null;
|
|
146
|
+
const inv = MathUtils.invert({ m: model });
|
|
147
|
+
if (!inv)
|
|
148
|
+
return null;
|
|
149
|
+
const i = inv.m;
|
|
150
|
+
const ox = i[0] * origin.x + i[4] * origin.y + i[8] * origin.z + i[12];
|
|
151
|
+
const oy = i[1] * origin.x + i[5] * origin.y + i[9] * origin.z + i[13];
|
|
152
|
+
const oz = i[2] * origin.x + i[6] * origin.y + i[10] * origin.z + i[14];
|
|
153
|
+
// Direction is a vector: no translation column.
|
|
154
|
+
const dx = i[0] * direction.x + i[4] * direction.y + i[8] * direction.z;
|
|
155
|
+
const dy = i[1] * direction.x + i[5] * direction.y + i[9] * direction.z;
|
|
156
|
+
const dz = i[2] * direction.x + i[6] * direction.y + i[10] * direction.z;
|
|
157
|
+
const len = Math.hypot(dx, dy, dz);
|
|
158
|
+
if (!(len > 1e-12))
|
|
159
|
+
return null;
|
|
160
|
+
const m = model;
|
|
161
|
+
return {
|
|
162
|
+
origin: { x: ox, y: oy, z: oz },
|
|
163
|
+
direction: { x: dx / len, y: dy / len, z: dz / len },
|
|
164
|
+
distanceScale: matrixUniformScale(m),
|
|
165
|
+
toWorld: (p) => ({
|
|
166
|
+
x: m[0] * p.x + m[4] * p.y + m[8] * p.z + m[12],
|
|
167
|
+
y: m[1] * p.x + m[5] * p.y + m[9] * p.z + m[13],
|
|
168
|
+
z: m[2] * p.x + m[6] * p.y + m[10] * p.z + m[14],
|
|
169
|
+
}),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=point-cloud-ray-transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"point-cloud-ray-transform.js","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-ray-transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { PointCloudAsset } from '@ifc-lite/geometry';
|
|
14
14
|
import { type PointCloudChunkInput, type PointCloudNode, type PointCloudNodeMeta } from './point-cloud-node.js';
|
|
15
|
+
import type { PointCloudSpatialIndex } from './point-cloud-spatial-index.js';
|
|
15
16
|
import { type PointColorMode, type PointSizeMode } from './point-cloud-uniforms.js';
|
|
16
17
|
export interface ResolvedSectionPlane {
|
|
17
18
|
normal: [number, number, number];
|
|
@@ -128,6 +129,14 @@ export declare class PointCloudRenderer {
|
|
|
128
129
|
* touching the per-vertex attributes.
|
|
129
130
|
*/
|
|
130
131
|
relabelAsset(handle: PointCloudAssetHandle, newExpressId: number): void;
|
|
132
|
+
/**
|
|
133
|
+
* Set (or clear) a streamed asset's per-vertex GPU model matrix
|
|
134
|
+
* (issue #1804: point-cloud ↔ `IfcMapConversion` alignment). Pass
|
|
135
|
+
* `null` to reset to identity. Takes effect on the next frame's
|
|
136
|
+
* uniform write — no GPU buffer rewrite needed, so toggling alignment
|
|
137
|
+
* on/off is cheap.
|
|
138
|
+
*/
|
|
139
|
+
setAssetTransform(handle: PointCloudAssetHandle, matrix: Float32Array | null): void;
|
|
131
140
|
clear(): void;
|
|
132
141
|
private clearOwner;
|
|
133
142
|
hasAssets(): boolean;
|
|
@@ -171,5 +180,20 @@ export declare class PointCloudRenderer {
|
|
|
171
180
|
pointCount: number;
|
|
172
181
|
}>;
|
|
173
182
|
}>;
|
|
183
|
+
/**
|
|
184
|
+
* Snapshot of every node's CPU spatial index (issue #1860), for the
|
|
185
|
+
* measure tool's ray-based point snapping (`RaycastEngine`). Skips
|
|
186
|
+
* empty nodes, mirroring `getPickNodes`. Each source carries the
|
|
187
|
+
* CURRENT class visibility bitmask so the query skips points the
|
|
188
|
+
* splat shader is hiding (#1783) — snapping to invisible scan data
|
|
189
|
+
* would otherwise silently corrupt measurements.
|
|
190
|
+
*/
|
|
191
|
+
getRayQuerySources(): Array<{
|
|
192
|
+
expressId: number;
|
|
193
|
+
modelIndex?: number;
|
|
194
|
+
index: PointCloudSpatialIndex;
|
|
195
|
+
classMask: Uint32Array;
|
|
196
|
+
model?: Float32Array;
|
|
197
|
+
}>;
|
|
174
198
|
}
|
|
175
199
|
//# sourceMappingURL=point-cloud-renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point-cloud-renderer.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-renderer.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,
|
|
1
|
+
{"version":3,"file":"point-cloud-renderer.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
import { PointRenderPipeline, POINT_QUAD_VERTS, POINT_UNIFORM_SIZE } from './point-pipeline.js';
|
|
5
|
-
import { appendChunkToNode, createNode, destroyNode, uploadAssetToGpu, } from './point-cloud-node.js';
|
|
5
|
+
import { appendChunkToNode, createNode, destroyNode, transformAabb, uploadAssetToGpu, } from './point-cloud-node.js';
|
|
6
|
+
import { buildRayQuerySources } from './point-cloud-ray-transform.js';
|
|
6
7
|
import { normalizeClassMask, writePointCloudUniforms, } from './point-cloud-uniforms.js';
|
|
7
8
|
export class PointCloudRenderer {
|
|
8
9
|
device;
|
|
@@ -126,6 +127,19 @@ export class PointCloudRenderer {
|
|
|
126
127
|
return;
|
|
127
128
|
node.meta.expressId = newExpressId >>> 0;
|
|
128
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Set (or clear) a streamed asset's per-vertex GPU model matrix
|
|
132
|
+
* (issue #1804: point-cloud ↔ `IfcMapConversion` alignment). Pass
|
|
133
|
+
* `null` to reset to identity. Takes effect on the next frame's
|
|
134
|
+
* uniform write — no GPU buffer rewrite needed, so toggling alignment
|
|
135
|
+
* on/off is cheap.
|
|
136
|
+
*/
|
|
137
|
+
setAssetTransform(handle, matrix) {
|
|
138
|
+
const node = this.nodes.get(handle.id);
|
|
139
|
+
if (!node)
|
|
140
|
+
return;
|
|
141
|
+
node.model = matrix ?? undefined;
|
|
142
|
+
}
|
|
129
143
|
// ─── lifecycle / queries ─────────────────────────────────────────────────
|
|
130
144
|
clear() {
|
|
131
145
|
for (const node of this.nodes.values()) {
|
|
@@ -177,18 +191,24 @@ export class PointCloudRenderer {
|
|
|
177
191
|
if (!Number.isFinite(node.bounds.min[0]))
|
|
178
192
|
continue;
|
|
179
193
|
any = true;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
194
|
+
// Report WORLD-space extents: fold the per-asset model matrix
|
|
195
|
+
// (issue #1804 IfcMapConversion alignment) into the chunk-space
|
|
196
|
+
// bounds, so the height-ramp min/max and the viewer's scene
|
|
197
|
+
// bounds/framing agree with where the vertex shader actually
|
|
198
|
+
// places the points. Identity/no-matrix nodes pass through as-is.
|
|
199
|
+
const b = transformAabb(node.bounds, node.model);
|
|
200
|
+
if (b.min[0] < minX)
|
|
201
|
+
minX = b.min[0];
|
|
202
|
+
if (b.min[1] < minY)
|
|
203
|
+
minY = b.min[1];
|
|
204
|
+
if (b.min[2] < minZ)
|
|
205
|
+
minZ = b.min[2];
|
|
206
|
+
if (b.max[0] > maxX)
|
|
207
|
+
maxX = b.max[0];
|
|
208
|
+
if (b.max[1] > maxY)
|
|
209
|
+
maxY = b.max[1];
|
|
210
|
+
if (b.max[2] > maxZ)
|
|
211
|
+
maxZ = b.max[2];
|
|
192
212
|
}
|
|
193
213
|
if (!any)
|
|
194
214
|
return null;
|
|
@@ -292,5 +312,18 @@ export class PointCloudRenderer {
|
|
|
292
312
|
}
|
|
293
313
|
return out;
|
|
294
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Snapshot of every node's CPU spatial index (issue #1860), for the
|
|
317
|
+
* measure tool's ray-based point snapping (`RaycastEngine`). Skips
|
|
318
|
+
* empty nodes, mirroring `getPickNodes`. Each source carries the
|
|
319
|
+
* CURRENT class visibility bitmask so the query skips points the
|
|
320
|
+
* splat shader is hiding (#1783) — snapping to invisible scan data
|
|
321
|
+
* would otherwise silently corrupt measurements.
|
|
322
|
+
*/
|
|
323
|
+
getRayQuerySources() {
|
|
324
|
+
// `classMask` is a live reference — read synchronously within one
|
|
325
|
+
// query, and `setOptions` replaces (never mutates in place) the array.
|
|
326
|
+
return buildRayQuerySources(this.nodes.values(), this.options.classMask);
|
|
327
|
+
}
|
|
295
328
|
}
|
|
296
329
|
//# sourceMappingURL=point-cloud-renderer.js.map
|