@ifc-lite/renderer 1.17.0 → 1.20.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.
Files changed (75) hide show
  1. package/dist/deviation/deviation-pipeline.d.ts +48 -0
  2. package/dist/deviation/deviation-pipeline.d.ts.map +1 -0
  3. package/dist/deviation/deviation-pipeline.js +163 -0
  4. package/dist/deviation/deviation-pipeline.js.map +1 -0
  5. package/dist/deviation/deviation-shader.wgsl.d.ts +23 -0
  6. package/dist/deviation/deviation-shader.wgsl.d.ts.map +1 -0
  7. package/dist/deviation/deviation-shader.wgsl.js +237 -0
  8. package/dist/deviation/deviation-shader.wgsl.js.map +1 -0
  9. package/dist/deviation/triangle-bvh.d.ts +58 -0
  10. package/dist/deviation/triangle-bvh.d.ts.map +1 -0
  11. package/dist/deviation/triangle-bvh.js +255 -0
  12. package/dist/deviation/triangle-bvh.js.map +1 -0
  13. package/dist/device.d.ts +3 -0
  14. package/dist/device.d.ts.map +1 -1
  15. package/dist/device.js +10 -0
  16. package/dist/device.js.map +1 -1
  17. package/dist/edl-pass.d.ts +52 -0
  18. package/dist/edl-pass.d.ts.map +1 -0
  19. package/dist/edl-pass.js +204 -0
  20. package/dist/edl-pass.js.map +1 -0
  21. package/dist/index.d.ts +175 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +676 -110
  24. package/dist/index.js.map +1 -1
  25. package/dist/picker.d.ts +40 -3
  26. package/dist/picker.d.ts.map +1 -1
  27. package/dist/picker.js +211 -59
  28. package/dist/picker.js.map +1 -1
  29. package/dist/picking-manager.d.ts +32 -1
  30. package/dist/picking-manager.d.ts.map +1 -1
  31. package/dist/picking-manager.js +53 -1
  32. package/dist/picking-manager.js.map +1 -1
  33. package/dist/point-picker.d.ts +61 -0
  34. package/dist/point-picker.d.ts.map +1 -0
  35. package/dist/point-picker.js +223 -0
  36. package/dist/point-picker.js.map +1 -0
  37. package/dist/pointcloud/point-cloud-node.d.ts +63 -0
  38. package/dist/pointcloud/point-cloud-node.d.ts.map +1 -0
  39. package/dist/pointcloud/point-cloud-node.js +149 -0
  40. package/dist/pointcloud/point-cloud-node.js.map +1 -0
  41. package/dist/pointcloud/point-cloud-renderer.d.ts +166 -0
  42. package/dist/pointcloud/point-cloud-renderer.d.ts.map +1 -0
  43. package/dist/pointcloud/point-cloud-renderer.js +293 -0
  44. package/dist/pointcloud/point-cloud-renderer.js.map +1 -0
  45. package/dist/pointcloud/point-cloud-uniforms.d.ts +36 -0
  46. package/dist/pointcloud/point-cloud-uniforms.d.ts.map +1 -0
  47. package/dist/pointcloud/point-cloud-uniforms.js +89 -0
  48. package/dist/pointcloud/point-cloud-uniforms.js.map +1 -0
  49. package/dist/pointcloud/point-pipeline.d.ts +27 -0
  50. package/dist/pointcloud/point-pipeline.d.ts.map +1 -0
  51. package/dist/pointcloud/point-pipeline.js +126 -0
  52. package/dist/pointcloud/point-pipeline.js.map +1 -0
  53. package/dist/pointcloud/point-shader.wgsl.d.ts +22 -0
  54. package/dist/pointcloud/point-shader.wgsl.d.ts.map +1 -0
  55. package/dist/pointcloud/point-shader.wgsl.js +288 -0
  56. package/dist/pointcloud/point-shader.wgsl.js.map +1 -0
  57. package/dist/scene.d.ts +11 -0
  58. package/dist/scene.d.ts.map +1 -1
  59. package/dist/scene.js +21 -0
  60. package/dist/scene.js.map +1 -1
  61. package/dist/section-2d-overlay.d.ts +24 -5
  62. package/dist/section-2d-overlay.d.ts.map +1 -1
  63. package/dist/section-2d-overlay.js +42 -13
  64. package/dist/section-2d-overlay.js.map +1 -1
  65. package/dist/section-plane-basis.d.ts +64 -0
  66. package/dist/section-plane-basis.d.ts.map +1 -0
  67. package/dist/section-plane-basis.js +86 -0
  68. package/dist/section-plane-basis.js.map +1 -0
  69. package/dist/section-plane.d.ts +18 -0
  70. package/dist/section-plane.d.ts.map +1 -1
  71. package/dist/section-plane.js +89 -6
  72. package/dist/section-plane.js.map +1 -1
  73. package/dist/types.d.ts +35 -4
  74. package/dist/types.d.ts.map +1 -1
  75. package/package.json +3 -3
@@ -0,0 +1,293 @@
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
+ import { PointRenderPipeline, POINT_QUAD_VERTS, POINT_UNIFORM_SIZE } from './point-pipeline.js';
5
+ import { appendChunkToNode, createNode, destroyNode, uploadAssetToGpu, } from './point-cloud-node.js';
6
+ import { writePointCloudUniforms, } from './point-cloud-uniforms.js';
7
+ export class PointCloudRenderer {
8
+ device;
9
+ pipeline;
10
+ nodes = new Map();
11
+ nodeOwners = new Map();
12
+ nextHandleId = 1;
13
+ uniformScratch = new Float32Array(POINT_UNIFORM_SIZE / 4);
14
+ uniformScratchU32 = new Uint32Array(this.uniformScratch.buffer);
15
+ options = {
16
+ colorMode: 'rgb',
17
+ fixedColor: [1, 1, 1, 1],
18
+ pointSize: 4,
19
+ sizeMode: 'attenuated',
20
+ worldRadius: 0.02,
21
+ roundShape: true,
22
+ classMask: 0xFFFFFFFF,
23
+ previewStride: 1,
24
+ deviationRange: { centerOffset: 0, halfRange: 0.05 },
25
+ };
26
+ constructor(device, colorFormat, depthFormat, sampleCount) {
27
+ this.device = device;
28
+ this.pipeline = new PointRenderPipeline(device, colorFormat, depthFormat, sampleCount);
29
+ }
30
+ setOptions(opts) {
31
+ if (opts.colorMode !== undefined)
32
+ this.options.colorMode = opts.colorMode;
33
+ if (opts.fixedColor !== undefined)
34
+ this.options.fixedColor = opts.fixedColor;
35
+ if (opts.pointSize !== undefined)
36
+ this.options.pointSize = opts.pointSize;
37
+ if (opts.sizeMode !== undefined)
38
+ this.options.sizeMode = opts.sizeMode;
39
+ if (opts.worldRadius !== undefined)
40
+ this.options.worldRadius = opts.worldRadius;
41
+ if (opts.roundShape !== undefined)
42
+ this.options.roundShape = opts.roundShape;
43
+ if (opts.classMask !== undefined)
44
+ this.options.classMask = opts.classMask >>> 0;
45
+ if (opts.previewStride !== undefined) {
46
+ // Clamp to a sane positive integer — stride 0 would divide by
47
+ // zero in the shader's modulo. >256 is silly but harmless.
48
+ const s = Math.max(1, Math.min(256, Math.floor(opts.previewStride) || 1));
49
+ this.options.previewStride = s;
50
+ }
51
+ if (opts.deviationRange !== undefined) {
52
+ const r = opts.deviationRange;
53
+ this.options.deviationRange = {
54
+ centerOffset: Number.isFinite(r.centerOffset) ? r.centerOffset : 0,
55
+ // halfRange = 0 would divide by zero in the shader; clamp to
56
+ // a tiny positive value so dragging the slider to the floor
57
+ // doesn't NaN the colour.
58
+ halfRange: Number.isFinite(r.halfRange) && r.halfRange > 0 ? r.halfRange : 1e-6,
59
+ };
60
+ }
61
+ }
62
+ getOptions() {
63
+ return this.options;
64
+ }
65
+ // ─── one-shot API (IFCx) ──────────────────────────────────────────────────
66
+ /**
67
+ * Replace every IFCx-owned asset with `assets`. Streamed assets are
68
+ * untouched. Use this from the viewer's IFCx sync hook.
69
+ */
70
+ setAssets(assets) {
71
+ this.clearOwner('ifcx');
72
+ for (const asset of assets) {
73
+ this.addAsset(asset);
74
+ }
75
+ }
76
+ addAsset(asset) {
77
+ const node = uploadAssetToGpu(this.device, this.pipeline, asset);
78
+ const id = this.nextHandleId++;
79
+ this.nodes.set(id, node);
80
+ this.nodeOwners.set(id, 'ifcx');
81
+ return { id };
82
+ }
83
+ // ─── streaming API (LAS / LAZ) ────────────────────────────────────────────
84
+ /** Open an empty asset that chunks will be appended to. */
85
+ beginAsset(meta) {
86
+ const node = createNode(this.device, this.pipeline, meta);
87
+ const id = this.nextHandleId++;
88
+ this.nodes.set(id, node);
89
+ this.nodeOwners.set(id, 'streamed');
90
+ return { id };
91
+ }
92
+ appendChunk(handle, chunk) {
93
+ const node = this.nodes.get(handle.id);
94
+ if (!node) {
95
+ console.warn(`[PointCloudRenderer] appendChunk: no node for handle ${handle.id}`);
96
+ return;
97
+ }
98
+ appendChunkToNode(this.device, node, chunk);
99
+ }
100
+ /** Mark streaming complete. No-op for now — kept for symmetry. */
101
+ endAsset(handle) {
102
+ void handle;
103
+ }
104
+ removeAsset(handle) {
105
+ const node = this.nodes.get(handle.id);
106
+ if (!node)
107
+ return;
108
+ destroyNode(node);
109
+ this.nodes.delete(handle.id);
110
+ this.nodeOwners.delete(handle.id);
111
+ }
112
+ /**
113
+ * Reassign a streamed asset's `expressId` after upload — used by
114
+ * `useIfcFederation` when the FederationRegistry hands out an
115
+ * `idOffset` for the model. The shader reads expressId from a
116
+ * per-asset uniform (flags.x), so this is just a metadata update;
117
+ * the next frame writes the new value into the GPU uniform without
118
+ * touching the per-vertex attributes.
119
+ */
120
+ relabelAsset(handle, newExpressId) {
121
+ const node = this.nodes.get(handle.id);
122
+ if (!node)
123
+ return;
124
+ node.meta.expressId = newExpressId >>> 0;
125
+ }
126
+ // ─── lifecycle / queries ─────────────────────────────────────────────────
127
+ clear() {
128
+ for (const node of this.nodes.values()) {
129
+ destroyNode(node);
130
+ }
131
+ this.nodes.clear();
132
+ this.nodeOwners.clear();
133
+ }
134
+ clearOwner(owner) {
135
+ for (const [id, ownerKind] of this.nodeOwners.entries()) {
136
+ if (ownerKind !== owner)
137
+ continue;
138
+ const node = this.nodes.get(id);
139
+ if (node)
140
+ destroyNode(node);
141
+ this.nodes.delete(id);
142
+ this.nodeOwners.delete(id);
143
+ }
144
+ }
145
+ hasAssets() {
146
+ return this.nodes.size > 0;
147
+ }
148
+ getNodeCount() {
149
+ return this.nodes.size;
150
+ }
151
+ /**
152
+ * Iterate every uploaded node. Exposed so the deviation compute
153
+ * pass can reach each node's vertex + deviation buffers without
154
+ * the renderer having to mirror its internal map.
155
+ */
156
+ getInternalNodes() {
157
+ return this.nodes.values();
158
+ }
159
+ /** Total number of points currently uploaded across all assets. */
160
+ getPointCount() {
161
+ let total = 0;
162
+ for (const node of this.nodes.values()) {
163
+ total += node.pointCount;
164
+ }
165
+ return total;
166
+ }
167
+ getBounds() {
168
+ if (this.nodes.size === 0)
169
+ return null;
170
+ let minX = Infinity, minY = Infinity, minZ = Infinity;
171
+ let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
172
+ let any = false;
173
+ for (const node of this.nodes.values()) {
174
+ if (!Number.isFinite(node.bounds.min[0]))
175
+ continue;
176
+ any = true;
177
+ if (node.bounds.min[0] < minX)
178
+ minX = node.bounds.min[0];
179
+ if (node.bounds.min[1] < minY)
180
+ minY = node.bounds.min[1];
181
+ if (node.bounds.min[2] < minZ)
182
+ minZ = node.bounds.min[2];
183
+ if (node.bounds.max[0] > maxX)
184
+ maxX = node.bounds.max[0];
185
+ if (node.bounds.max[1] > maxY)
186
+ maxY = node.bounds.max[1];
187
+ if (node.bounds.max[2] > maxZ)
188
+ maxZ = node.bounds.max[2];
189
+ }
190
+ if (!any)
191
+ return null;
192
+ return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
193
+ }
194
+ /**
195
+ * Issue draw calls into an already-open render pass. The caller owns
196
+ * the encoder/pass and is responsible for the depth attachment.
197
+ */
198
+ draw(pass, state) {
199
+ if (this.nodes.size === 0)
200
+ return;
201
+ pass.setPipeline(this.pipeline.getPipeline());
202
+ const sp = state.sectionPlane ?? null;
203
+ let normal;
204
+ let distance;
205
+ let enabled;
206
+ if (sp && sp.enabled) {
207
+ enabled = true;
208
+ if (sp.flipped) {
209
+ normal = [-sp.normal[0], -sp.normal[1], -sp.normal[2]];
210
+ distance = -sp.distance;
211
+ }
212
+ else {
213
+ normal = sp.normal;
214
+ distance = sp.distance;
215
+ }
216
+ }
217
+ else {
218
+ enabled = false;
219
+ normal = [0, 1, 0];
220
+ distance = 0;
221
+ }
222
+ const bounds = this.getBounds();
223
+ const heightMin = bounds ? bounds.min[1] : 0;
224
+ const heightMax = bounds ? bounds.max[1] : 1;
225
+ // Default to 1×1 if the caller didn't supply a viewport — keeps the
226
+ // shader from dividing by zero in adaptive-world mode and degrades
227
+ // gracefully to "all points the same fixed-px size".
228
+ const viewportW = Math.max(1, state.viewport?.width ?? 1);
229
+ const viewportH = Math.max(1, state.viewport?.height ?? 1);
230
+ for (const node of this.nodes.values()) {
231
+ writePointCloudUniforms(this.device, this.uniformScratch, this.uniformScratchU32, node, {
232
+ viewProj: state.viewProj,
233
+ fixedColor: this.options.fixedColor,
234
+ colorMode: this.options.colorMode,
235
+ sizeMode: this.options.sizeMode,
236
+ pointSize: this.options.pointSize,
237
+ worldRadius: this.options.worldRadius,
238
+ roundShape: this.options.roundShape,
239
+ sectionNormal: normal,
240
+ sectionDist: distance,
241
+ sectionEnabled: enabled,
242
+ heightMin,
243
+ heightMax,
244
+ viewportW,
245
+ viewportH,
246
+ classMask: this.options.classMask,
247
+ previewStride: this.options.previewStride,
248
+ deviationCenterOffset: this.options.deviationRange.centerOffset,
249
+ deviationHalfRange: this.options.deviationRange.halfRange,
250
+ });
251
+ pass.setBindGroup(0, node.bindGroup);
252
+ for (const chunk of node.chunks) {
253
+ pass.setVertexBuffer(0, chunk.vertexBuffer);
254
+ // 2nd buffer: per-point deviation float (location 4 in shader).
255
+ pass.setVertexBuffer(1, chunk.deviationBuffer);
256
+ // Six verts per splat, one instance per source point.
257
+ pass.draw(POINT_QUAD_VERTS, chunk.pointCount, 0, 0);
258
+ }
259
+ }
260
+ }
261
+ /**
262
+ * Resolve a packed objectId rgba8 sample back to the asset that owns it.
263
+ * Returns null when the sample doesn't match any asset's expressId.
264
+ */
265
+ resolvePick(expressId) {
266
+ for (const [id, node] of this.nodes.entries()) {
267
+ if ((node.meta.expressId >>> 0) === (expressId >>> 0)) {
268
+ return { handle: { id }, meta: node.meta };
269
+ }
270
+ }
271
+ return null;
272
+ }
273
+ /**
274
+ * Snapshot of nodes shaped for the picker — only the data the GPU
275
+ * picking pass actually needs (expressId, modelIndex, chunk vertex
276
+ * buffers + counts). Returns a fresh array; callers may iterate
277
+ * freely without worrying about mutation during a pick.
278
+ */
279
+ getPickNodes() {
280
+ const out = [];
281
+ for (const node of this.nodes.values()) {
282
+ if (node.pointCount === 0)
283
+ continue;
284
+ out.push({
285
+ expressId: node.meta.expressId,
286
+ modelIndex: node.meta.modelIndex,
287
+ chunks: node.chunks.map((c) => ({ vertexBuffer: c.vertexBuffer, pointCount: c.pointCount })),
288
+ });
289
+ }
290
+ return out;
291
+ }
292
+ }
293
+ //# sourceMappingURL=point-cloud-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-cloud-renderer.js","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { PointCloudNode } from './point-cloud-node.js';
2
+ export type PointColorMode = 'rgb' | 'classification' | 'intensity' | 'height' | 'fixed' | 'deviation';
3
+ export type PointSizeMode = 'fixed-px' | 'adaptive-world' | 'attenuated';
4
+ export declare const COLOR_MODE_INDEX: Record<PointColorMode, number>;
5
+ export declare const SIZE_MODE_INDEX: Record<PointSizeMode, number>;
6
+ export interface PointUniformInputs {
7
+ viewProj: Float32Array;
8
+ fixedColor: [number, number, number, number];
9
+ colorMode: PointColorMode;
10
+ sizeMode: PointSizeMode;
11
+ pointSize: number;
12
+ worldRadius: number;
13
+ roundShape: boolean;
14
+ sectionNormal: [number, number, number];
15
+ sectionDist: number;
16
+ sectionEnabled: boolean;
17
+ heightMin: number;
18
+ heightMax: number;
19
+ viewportW: number;
20
+ viewportH: number;
21
+ /** Per-ASPRS-class visibility bitmask (32 bits = LAS 1.4 classes). */
22
+ classMask: number;
23
+ /** Preview stride — 1 = full density, N = render every Nth point. */
24
+ previewStride: number;
25
+ /** BIM ↔ scan deviation heatmap range (metres). */
26
+ deviationCenterOffset: number;
27
+ deviationHalfRange: number;
28
+ }
29
+ /**
30
+ * Pack the per-asset point-cloud uniform block into `scratch` and copy
31
+ * it onto the GPU. The two scratch typed-arrays must alias the same
32
+ * underlying buffer so we can write floats and packed u32 flags in one
33
+ * pass.
34
+ */
35
+ export declare function writePointCloudUniforms(device: GPUDevice, scratch: Float32Array, scratchU32: Uint32Array, node: PointCloudNode, inputs: PointUniformInputs): void;
36
+ //# sourceMappingURL=point-cloud-uniforms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-cloud-uniforms.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-uniforms.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,gBAAgB,GAChB,WAAW,GACX,QAAQ,GACR,OAAO,GACP,WAAW,CAAC;AAEhB,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,gBAAgB,GAAG,YAAY,CAAC;AAEzE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAO3D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAIzD,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,SAAS,EAAE,cAAc,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,WAAW,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAwDN"}
@@ -0,0 +1,89 @@
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
+ * Uniform layout + writer for the point-cloud render pipeline.
6
+ *
7
+ * Extracted from `point-cloud-renderer.ts` to keep the orchestration
8
+ * class small. The layout matches `point-shader.wgsl.ts` byte-for-byte;
9
+ * any shader edit needs to come back here too.
10
+ */
11
+ import { POINT_UNIFORM_SIZE } from './point-pipeline.js';
12
+ export const COLOR_MODE_INDEX = {
13
+ rgb: 0,
14
+ classification: 1,
15
+ intensity: 2,
16
+ height: 3,
17
+ fixed: 4,
18
+ deviation: 5,
19
+ };
20
+ export const SIZE_MODE_INDEX = {
21
+ 'fixed-px': 0,
22
+ 'adaptive-world': 1,
23
+ 'attenuated': 2,
24
+ };
25
+ /**
26
+ * Pack the per-asset point-cloud uniform block into `scratch` and copy
27
+ * it onto the GPU. The two scratch typed-arrays must alias the same
28
+ * underlying buffer so we can write floats and packed u32 flags in one
29
+ * pass.
30
+ */
31
+ export function writePointCloudUniforms(device, scratch, scratchU32, node, inputs) {
32
+ const u = scratch;
33
+ const uU32 = scratchU32;
34
+ // viewProj — floats 0..15
35
+ u.set(inputs.viewProj.subarray(0, 16), 0);
36
+ // model — floats 16..31 (identity for now; per-asset transforms can be added later)
37
+ u.fill(0, 16, 32);
38
+ u[16] = 1;
39
+ u[21] = 1;
40
+ u[26] = 1;
41
+ u[31] = 1;
42
+ // colorOverride — floats 32..35
43
+ u[32] = inputs.fixedColor[0];
44
+ u[33] = inputs.fixedColor[1];
45
+ u[34] = inputs.fixedColor[2];
46
+ u[35] = inputs.fixedColor[3];
47
+ // colorModeAndExtras — floats 36..39 (mode, pointSize, heightMin, heightMax)
48
+ u[36] = COLOR_MODE_INDEX[inputs.colorMode];
49
+ u[37] = inputs.pointSize;
50
+ u[38] = inputs.heightMin;
51
+ u[39] = inputs.heightMax;
52
+ // sizing — floats 40..43 (sizeMode, worldRadius, viewportW, viewportH)
53
+ u[40] = SIZE_MODE_INDEX[inputs.sizeMode];
54
+ u[41] = inputs.worldRadius;
55
+ u[42] = inputs.viewportW;
56
+ u[43] = inputs.viewportH;
57
+ // sectionPlane — floats 44..47
58
+ u[44] = inputs.sectionNormal[0];
59
+ u[45] = inputs.sectionNormal[1];
60
+ u[46] = inputs.sectionNormal[2];
61
+ u[47] = inputs.sectionDist;
62
+ // flags (u32 view) — bytes 192..207 = u32 indices 48..51
63
+ // flags.x = the asset's CURRENT expressId. The shader uses this
64
+ // when non-zero so the federation registry can relabel a streamed
65
+ // asset post-upload (its per-vertex entityId attribute is baked
66
+ // at upload and would otherwise stay at the synthetic local ID).
67
+ // flags.w (u32 slot 51) = ASPRS class-visibility mask. Bit i set → class i shown.
68
+ uU32[48] = node.meta.expressId >>> 0;
69
+ uU32[49] = inputs.sectionEnabled ? 1 : 0;
70
+ uU32[50] = inputs.roundShape ? 1 : 0;
71
+ uU32[51] = inputs.classMask >>> 0;
72
+ // extras (u32 slots 52..55) — extras.x = previewStride, yzw reserved.
73
+ uU32[52] = inputs.previewStride >>> 0;
74
+ uU32[53] = 0;
75
+ uU32[54] = 0;
76
+ uU32[55] = 0;
77
+ // deviationRange (f32 slots 56..59) — center, halfRange, _, _.
78
+ u[56] = inputs.deviationCenterOffset;
79
+ u[57] = inputs.deviationHalfRange;
80
+ u[58] = 0;
81
+ u[59] = 0;
82
+ // Pass the typed array directly — TypeScript widens `.buffer` to
83
+ // `ArrayBufferLike` here (vs. `ArrayBuffer` on a class field), which
84
+ // doesn't satisfy `writeBuffer`'s parameter type. Slicing the typed
85
+ // array view to exactly the uniform size + 4 alignment is identical
86
+ // to the byteOffset/byteLength form on the buffer.
87
+ device.queue.writeBuffer(node.uniformBuffer, 0, u, 0, POINT_UNIFORM_SIZE / 4);
88
+ }
89
+ //# sourceMappingURL=point-cloud-uniforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-cloud-uniforms.js","sourceRoot":"","sources":["../../src/pointcloud/point-cloud-uniforms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Uniform block size in bytes. Layout (Float32 indices):
3
+ * [0..15] viewProj (mat4x4)
4
+ * [16..31] model (mat4x4)
5
+ * [32..35] colorOverride (vec4)
6
+ * [36..39] colorModeAndExtras (mode, pointSizePx, heightMin, heightMax)
7
+ * [40..43] sizing (sizeMode, worldRadius, viewportW, viewportH)
8
+ * [44..47] sectionPlane (nx, ny, nz, distance)
9
+ * [48..51] flags (u32 view: x=expressId, y=sectionEnabled, z=roundShape, w=classMask)
10
+ * [52..55] extras (u32 view: x=previewStride, yzw=unused)
11
+ * [56..59] deviationRange (centerOffset, halfRange, _, _)
12
+ */
13
+ export declare const POINT_UNIFORM_SIZE = 240;
14
+ export declare const POINT_VERTEX_BYTES = 24;
15
+ /** Number of vertices emitted per splat (two triangles forming a quad). */
16
+ export declare const POINT_QUAD_VERTS = 6;
17
+ export declare class PointRenderPipeline {
18
+ private device;
19
+ private pipeline;
20
+ private bindGroupLayout;
21
+ constructor(device: GPUDevice, colorFormat: GPUTextureFormat, depthFormat: GPUTextureFormat, sampleCount: number);
22
+ getPipeline(): GPURenderPipeline;
23
+ getBindGroupLayout(): GPUBindGroupLayout;
24
+ createUniformBuffer(): GPUBuffer;
25
+ createBindGroup(uniformBuffer: GPUBuffer): GPUBindGroup;
26
+ }
27
+ //# sourceMappingURL=point-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-pipeline.d.ts","sourceRoot":"","sources":["../../src/pointcloud/point-pipeline.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;;GAWG;AAKH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,eAAe,CAAqB;gBAG1C,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,gBAAgB,EAC7B,WAAW,EAAE,gBAAgB,EAC7B,WAAW,EAAE,MAAM;IAiErB,WAAW,IAAI,iBAAiB;IAIhC,kBAAkB,IAAI,kBAAkB;IAIxC,mBAAmB,IAAI,SAAS;IAOhC,eAAe,CAAC,aAAa,EAAE,SAAS,GAAG,YAAY;CAMxD"}
@@ -0,0 +1,126 @@
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
+ * WebGPU pipeline for point cloud splatting.
6
+ *
7
+ * Each point is drawn as an instanced 6-vertex quad (`triangle-list` with
8
+ * `stepMode: 'instance'` on the vertex buffer). The vertex shader picks
9
+ * a corner offset from `vertex_index` and inflates the clip-space
10
+ * position by the active size mode. Fragment discards out-of-disc
11
+ * corners so splats render as round dots, not squares.
12
+ *
13
+ * Color attachments must match RenderPipeline's main pipeline (color +
14
+ * objectId rgba8unorm) and depth/MSAA must match too — we render into
15
+ * the same render pass.
16
+ *
17
+ * Vertex layout (24 bytes/point, per-instance):
18
+ * 0..11 vec3<f32> position
19
+ * 12..15 unorm8x4 color (r, g, b, classification-as-byte)
20
+ * 16..19 uint32 intensity (low 16 bits, 0..65535)
21
+ * 20..23 uint32 entityId (federation-aware express id)
22
+ */
23
+ import { pointShaderSource } from './point-shader.wgsl.js';
24
+ /**
25
+ * Uniform block size in bytes. Layout (Float32 indices):
26
+ * [0..15] viewProj (mat4x4)
27
+ * [16..31] model (mat4x4)
28
+ * [32..35] colorOverride (vec4)
29
+ * [36..39] colorModeAndExtras (mode, pointSizePx, heightMin, heightMax)
30
+ * [40..43] sizing (sizeMode, worldRadius, viewportW, viewportH)
31
+ * [44..47] sectionPlane (nx, ny, nz, distance)
32
+ * [48..51] flags (u32 view: x=expressId, y=sectionEnabled, z=roundShape, w=classMask)
33
+ * [52..55] extras (u32 view: x=previewStride, yzw=unused)
34
+ * [56..59] deviationRange (centerOffset, halfRange, _, _)
35
+ */
36
+ // 15 vec4 slots × 16 bytes = 240. Was 208 before extras (PR-G's
37
+ // stride cull) and deviationRange (PR-H's BIM↔scan heatmap) both
38
+ // claimed their own slots — keeping them separate avoids overloading
39
+ // the flags / colourOverride slots and stays std140-friendly.
40
+ export const POINT_UNIFORM_SIZE = 240;
41
+ export const POINT_VERTEX_BYTES = 24;
42
+ /** Number of vertices emitted per splat (two triangles forming a quad). */
43
+ export const POINT_QUAD_VERTS = 6;
44
+ export class PointRenderPipeline {
45
+ device;
46
+ pipeline;
47
+ bindGroupLayout;
48
+ constructor(device, colorFormat, depthFormat, sampleCount) {
49
+ this.device = device;
50
+ this.bindGroupLayout = device.createBindGroupLayout({
51
+ entries: [
52
+ {
53
+ binding: 0,
54
+ visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
55
+ buffer: { type: 'uniform' },
56
+ },
57
+ ],
58
+ });
59
+ const layout = device.createPipelineLayout({
60
+ bindGroupLayouts: [this.bindGroupLayout],
61
+ });
62
+ const shader = device.createShaderModule({ code: pointShaderSource });
63
+ this.pipeline = device.createRenderPipeline({
64
+ layout,
65
+ vertex: {
66
+ module: shader,
67
+ entryPoint: 'vs_main',
68
+ buffers: [
69
+ {
70
+ arrayStride: POINT_VERTEX_BYTES,
71
+ // One source point feeds all 6 quad vertices: per-instance step.
72
+ stepMode: 'instance',
73
+ attributes: [
74
+ { shaderLocation: 0, offset: 0, format: 'float32x3' },
75
+ { shaderLocation: 1, offset: 12, format: 'unorm8x4' },
76
+ { shaderLocation: 2, offset: 16, format: 'uint32' },
77
+ { shaderLocation: 3, offset: 20, format: 'uint32' },
78
+ ],
79
+ },
80
+ {
81
+ // Per-point deviation float (BIM↔scan signed distance).
82
+ // Always present, zero when the user hasn't computed yet.
83
+ arrayStride: 4,
84
+ stepMode: 'instance',
85
+ attributes: [
86
+ { shaderLocation: 4, offset: 0, format: 'float32' },
87
+ ],
88
+ },
89
+ ],
90
+ },
91
+ fragment: {
92
+ module: shader,
93
+ entryPoint: 'fs_main',
94
+ targets: [{ format: colorFormat }, { format: 'rgba8unorm' }],
95
+ },
96
+ primitive: {
97
+ topology: 'triangle-list',
98
+ },
99
+ depthStencil: {
100
+ format: depthFormat,
101
+ depthWriteEnabled: true,
102
+ depthCompare: 'greater', // reverse-Z, matches RenderPipeline main pipeline
103
+ },
104
+ multisample: { count: sampleCount },
105
+ });
106
+ }
107
+ getPipeline() {
108
+ return this.pipeline;
109
+ }
110
+ getBindGroupLayout() {
111
+ return this.bindGroupLayout;
112
+ }
113
+ createUniformBuffer() {
114
+ return this.device.createBuffer({
115
+ size: POINT_UNIFORM_SIZE,
116
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
117
+ });
118
+ }
119
+ createBindGroup(uniformBuffer) {
120
+ return this.device.createBindGroup({
121
+ layout: this.bindGroupLayout,
122
+ entries: [{ binding: 0, resource: { buffer: uniformBuffer } }],
123
+ });
124
+ }
125
+ }
126
+ //# sourceMappingURL=point-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-pipeline.js","sourceRoot":"","sources":["../../src/pointcloud/point-pipeline.ts"],"names":[],"mappings":"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"}