@ifc-lite/geometry 1.19.0 → 2.0.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 (66) hide show
  1. package/dist/geometry-coordinate.d.ts +0 -5
  2. package/dist/geometry-coordinate.d.ts.map +1 -1
  3. package/dist/geometry-coordinate.js +0 -19
  4. package/dist/geometry-coordinate.js.map +1 -1
  5. package/dist/geometry-parallel.d.ts +4 -26
  6. package/dist/geometry-parallel.d.ts.map +1 -1
  7. package/dist/geometry-parallel.js +5 -23
  8. package/dist/geometry-parallel.js.map +1 -1
  9. package/dist/geometry.worker.d.ts +0 -1
  10. package/dist/geometry.worker.d.ts.map +1 -1
  11. package/dist/geometry.worker.js.map +1 -1
  12. package/dist/ifc-lite-bridge.d.ts +2 -58
  13. package/dist/ifc-lite-bridge.d.ts.map +1 -1
  14. package/dist/ifc-lite-bridge.js +5 -127
  15. package/dist/ifc-lite-bridge.js.map +1 -1
  16. package/dist/index.d.ts +17 -46
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +100 -293
  19. package/dist/index.js.map +1 -1
  20. package/dist/platform-bridge.d.ts +6 -3
  21. package/dist/platform-bridge.d.ts.map +1 -1
  22. package/dist/platform-bridge.js +7 -7
  23. package/dist/platform-bridge.js.map +1 -1
  24. package/dist/progressive-loader.d.ts +5 -56
  25. package/dist/progressive-loader.d.ts.map +1 -1
  26. package/dist/progressive-loader.js +7 -132
  27. package/dist/progressive-loader.js.map +1 -1
  28. package/dist/types.d.ts +0 -29
  29. package/dist/types.d.ts.map +1 -1
  30. package/package.json +5 -14
  31. package/dist/default-materials.d.ts +0 -22
  32. package/dist/default-materials.d.ts.map +0 -1
  33. package/dist/default-materials.js +0 -124
  34. package/dist/default-materials.js.map +0 -1
  35. package/dist/geometry-controller.worker.d.ts +0 -4
  36. package/dist/geometry-controller.worker.d.ts.map +0 -1
  37. package/dist/geometry-controller.worker.js +0 -402
  38. package/dist/geometry-controller.worker.js.map +0 -1
  39. package/dist/geometry-deduplicator.d.ts +0 -42
  40. package/dist/geometry-deduplicator.d.ts.map +0 -1
  41. package/dist/geometry-deduplicator.js +0 -80
  42. package/dist/geometry-deduplicator.js.map +0 -1
  43. package/dist/ifc-lite-mesh-collector.d.ts +0 -111
  44. package/dist/ifc-lite-mesh-collector.d.ts.map +0 -1
  45. package/dist/ifc-lite-mesh-collector.js +0 -455
  46. package/dist/ifc-lite-mesh-collector.js.map +0 -1
  47. package/dist/lod.d.ts +0 -60
  48. package/dist/lod.d.ts.map +0 -1
  49. package/dist/lod.js +0 -113
  50. package/dist/lod.js.map +0 -1
  51. package/dist/style-cache.d.ts +0 -36
  52. package/dist/style-cache.d.ts.map +0 -1
  53. package/dist/style-cache.js +0 -127
  54. package/dist/style-cache.js.map +0 -1
  55. package/dist/wasm-bridge.d.ts +0 -22
  56. package/dist/wasm-bridge.d.ts.map +0 -1
  57. package/dist/wasm-bridge.js +0 -120
  58. package/dist/wasm-bridge.js.map +0 -1
  59. package/dist/wasm-memory-manager.d.ts +0 -178
  60. package/dist/wasm-memory-manager.d.ts.map +0 -1
  61. package/dist/wasm-memory-manager.js +0 -86
  62. package/dist/wasm-memory-manager.js.map +0 -1
  63. package/dist/zero-copy-collector.d.ts +0 -158
  64. package/dist/zero-copy-collector.d.ts.map +0 -1
  65. package/dist/zero-copy-collector.js +0 -224
  66. package/dist/zero-copy-collector.js.map +0 -1
@@ -1,402 +0,0 @@
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
- * Single-controller geometry worker (Phase 2 of single-controller-rayon-design.md).
6
- *
7
- * Replaces the N-independent-Web-Workers pool. ONE WASM instance with
8
- * an internal rayon thread pool of (navigator.hardwareConcurrency - 1)
9
- * helper threads. All `processGeometryBatchParallel` work happens
10
- * inside this worker; rayon's `par_iter` distributes per-entity work
11
- * across the helpers via shared memory.
12
- *
13
- * Message protocol is INTENTIONALLY identical to `geometry.worker.ts`
14
- * so the host (`geometry-parallel.ts`) can swap implementations behind
15
- * a feature flag without changing the dispatch / event-collection
16
- * code. The controller accepts the same set: `init`, `stream-start`,
17
- * `stream-chunk`, `stream-end`, `set-styles`, `set-entity-index`.
18
- *
19
- * Why this matters: the per-worker entity-index FxHashMap (~600 MB
20
- * per worker on the 986 MB test file) was triplicated across 3
21
- * workers. Single controller holds ONE copy. Total peakWasm should
22
- * drop from ~5.3 GB to ~3 GB. Plus rayon work-stealing replaces
23
- * the contention pattern that capped useful workers at 3 even on
24
- * 10-core hosts.
25
- */
26
- // Import the THREADED bundle. The viewer's vite.config.ts maps
27
- // `@ifc-lite/wasm-threaded` to `packages/wasm-threaded/pkg/ifc-lite.js`
28
- // (see vite.config.ts alias added by Phase 2 wiring), so this static
29
- // specifier resolves naturally for the workspace source-alias build.
30
- //
31
- // Published-package contract (issue #676): `scripts/transform-controller-worker-dist.mjs`
32
- // runs after `tsc` and rewrites this single line in `dist/geometry-controller.worker.js`
33
- // into a lazy `await import(<runtime-built-specifier>)` so consumer bundlers
34
- // (Turbopack, webpack, esbuild) don't try to resolve `@ifc-lite/wasm-threaded`
35
- // at their build step — that package is workspace-only per
36
- // `packages/wasm-threaded/package.json` `_intent`. The
37
- // `geometry-controller-dist.test.ts` regression pins both halves of this
38
- // contract (no static import in dist, dynamic loader present).
39
- // Issue #676: scripts/transform-controller-worker-dist.mjs replaces the
40
- // source-level static import of '@ifc-lite/wasm-threaded' with this lazy
41
- // loader so consumer bundlers (Turbopack / webpack / esbuild) don't try
42
- // to resolve a package that is workspace-only by design. See the source
43
- // file for the full rationale.
44
- let init, initSync, IfcAPI, initThreadPool;
45
- let __threadedModulePromise = null;
46
- async function __loadThreadedModule() {
47
- if (__threadedModulePromise) return __threadedModulePromise;
48
- // Specifier built at call time so static-import scanners can't see it.
49
- const __specifier = ['@ifc-lite', 'wasm-threaded'].join('/');
50
- __threadedModulePromise = (async () => {
51
- try {
52
- const m = await import(/* webpackIgnore: true */ /* @vite-ignore */ __specifier);
53
- init = m.default;
54
- initSync = m.initSync;
55
- IfcAPI = m.IfcAPI;
56
- initThreadPool = m.initThreadPool;
57
- return m;
58
- } catch (err) {
59
- __threadedModulePromise = null;
60
- const detail = err instanceof Error ? err.message : String(err);
61
- throw new Error(
62
- '[controller] failed to load @ifc-lite/wasm-threaded (' + detail + '). ' +
63
- 'The single-controller path requires the threaded WASM bundle. ' +
64
- "Alias '@ifc-lite/wasm-threaded' to packages/wasm-threaded/pkg/ifc-lite.js " +
65
- "in your bundler config (see viewer's vite.config.ts Phase 2 wiring), " +
66
- 'or omit useSingleController to stay on the N-worker fallback.',
67
- );
68
- }
69
- })();
70
- return __threadedModulePromise;
71
- }
72
- let api = null;
73
- let threadPoolReady = false;
74
- /**
75
- * Captured at the explicit `init` message and forwarded to wasm-bindgen's
76
- * `init(url)` call. Mirrors `geometry.worker.ts`'s `cachedWasmUrl` — see
77
- * that file for the rationale. Defaults to undefined so wasm-bindgen
78
- * falls back to its `import.meta.url`-relative default resolution.
79
- */
80
- let cachedWasmUrl = undefined;
81
- /**
82
- * Cached merge-layers flag (issue #540). The host may post
83
- * `set-merge-layers` BEFORE `init`, so we remember the latest value
84
- * and re-apply once the threaded IfcAPI is constructed.
85
- */
86
- let mergeLayersFlag = false;
87
- let mergeLayersApplied = false;
88
- function applyMergeLayersToApi() {
89
- if (!api || mergeLayersApplied)
90
- return;
91
- const merging = api;
92
- if (typeof merging.setMergeLayers === 'function') {
93
- merging.setMergeLayers(mergeLayersFlag);
94
- }
95
- mergeLayersApplied = true;
96
- }
97
- let activeSession = null;
98
- function viewSharedBytes(sharedBuffer) {
99
- return new Uint8Array(sharedBuffer);
100
- }
101
- function materialiseSharedBytes(sharedBuffer) {
102
- const local = new Uint8Array(sharedBuffer.byteLength);
103
- local.set(new Uint8Array(sharedBuffer));
104
- return local;
105
- }
106
- function startSession(input) {
107
- return {
108
- sharedBuffer: input.sharedBuffer,
109
- localBytes: viewSharedBytes(input.sharedBuffer),
110
- sabFallbackTaken: false,
111
- unitScale: input.unitScale,
112
- rtcX: input.rtcX, rtcY: input.rtcY, rtcZ: input.rtcZ,
113
- needsShift: input.needsShift,
114
- voidKeys: input.voidKeys,
115
- voidCounts: input.voidCounts,
116
- voidValues: input.voidValues,
117
- styleIds: input.styleIds,
118
- styleColors: input.styleColors,
119
- pendingMeshes: [],
120
- pendingTransfers: [],
121
- totalMeshesEmitted: 0,
122
- cumulativeMeshBytes: 0,
123
- };
124
- }
125
- function flushPending(session) {
126
- if (session.pendingMeshes.length === 0)
127
- return;
128
- const meshes = session.pendingMeshes;
129
- const transfers = session.pendingTransfers;
130
- session.pendingMeshes = [];
131
- session.pendingTransfers = [];
132
- session.totalMeshesEmitted += meshes.length;
133
- self.postMessage({ type: 'batch', meshes }, transfers);
134
- }
135
- function collectMeshes(session, collection) {
136
- for (let i = 0; i < collection.length; i++) {
137
- const mesh = collection.get(i);
138
- if (!mesh)
139
- continue;
140
- const positions = new Float32Array(mesh.positions);
141
- const normals = new Float32Array(mesh.normals);
142
- const indices = new Uint32Array(mesh.indices);
143
- session.pendingMeshes.push({
144
- expressId: mesh.expressId,
145
- ifcType: mesh.ifcType,
146
- positions, normals, indices,
147
- color: [mesh.color[0], mesh.color[1], mesh.color[2], mesh.color[3]],
148
- });
149
- session.pendingTransfers.push(positions.buffer, normals.buffer, indices.buffer);
150
- session.cumulativeMeshBytes += positions.byteLength + normals.byteLength + indices.byteLength;
151
- mesh.free();
152
- }
153
- collection.free();
154
- }
155
- /**
156
- * Run one chunk through the rayon-parallel batch entry. Same binary-
157
- * split recovery as the N-worker path: if WASM rejects the whole slice
158
- * (typical: SAB-view incompatible with this runtime), fall back to a
159
- * materialised copy; on per-entity failure, halve and retry.
160
- */
161
- async function processBatchParallel(session, jobs) {
162
- const numJobs = Math.floor(jobs.length / 3);
163
- if (numJobs === 0)
164
- return;
165
- try {
166
- if (!api) {
167
- throw new Error('controller API not initialised before stream-chunk');
168
- }
169
- const collection = api.processGeometryBatchParallel(session.localBytes, jobs, session.unitScale, session.rtcX, session.rtcY, session.rtcZ, session.needsShift, session.voidKeys, session.voidCounts, session.voidValues, session.styleIds, session.styleColors);
170
- collectMeshes(session, collection);
171
- }
172
- catch (err) {
173
- const msg = err.message;
174
- if (!session.sabFallbackTaken && session.localBytes.buffer instanceof SharedArrayBuffer) {
175
- session.sabFallbackTaken = true;
176
- console.warn(`[controller] processGeometryBatchParallel rejected SAB view (${msg}), copying`);
177
- session.localBytes = materialiseSharedBytes(session.sharedBuffer);
178
- await processBatchParallel(session, jobs);
179
- return;
180
- }
181
- if (numJobs === 1) {
182
- console.warn(`[controller] skipping entity #${jobs[0]}: ${msg}`);
183
- return;
184
- }
185
- console.warn(`[controller] batch of ${numJobs} entities failed (${msg}), splitting…`);
186
- const mid = Math.floor(numJobs / 2) * 3;
187
- await processBatchParallel(session, jobs.slice(0, mid));
188
- await processBatchParallel(session, jobs.slice(mid));
189
- }
190
- }
191
- /**
192
- * Run a slice in STREAM_BATCH_SIZE chunks, flushing after each. Same
193
- * cadence as the N-worker path so downstream React/render code sees
194
- * familiar timing.
195
- */
196
- const STREAM_BATCH_SIZE = 1_000_000;
197
- async function processSliceStreaming(session, jobsFlat) {
198
- const totalJobs = Math.floor(jobsFlat.length / 3);
199
- for (let jobOffset = 0; jobOffset < totalJobs; jobOffset += STREAM_BATCH_SIZE) {
200
- const start = jobOffset * 3;
201
- const end = Math.min(start + STREAM_BATCH_SIZE * 3, jobsFlat.length);
202
- await processBatchParallel(session, jobsFlat.slice(start, end));
203
- flushPending(session);
204
- }
205
- }
206
- function emitSessionEnd(session) {
207
- flushPending(session);
208
- // Memory snapshot — single WASM heap (vs N-worker pool sums).
209
- let wasmHeapBytes = 0;
210
- try {
211
- const memJs = api?.getMemory();
212
- const buf = memJs?.buffer;
213
- wasmHeapBytes = buf?.byteLength ?? 0;
214
- }
215
- catch { /* memory probe is best-effort */ }
216
- self.postMessage({
217
- type: 'memory',
218
- wasmHeapBytes,
219
- meshBytes: session.cumulativeMeshBytes,
220
- });
221
- self.postMessage({
222
- type: 'complete',
223
- totalMeshes: session.totalMeshesEmitted,
224
- });
225
- }
226
- /**
227
- * Tail-promise serialiser — copied from `geometry.worker.ts`. Web
228
- * Worker `onmessage` is fire-and-forget; without serialisation, an
229
- * async handler for `stream-start` (which awaits init() + initThreadPool)
230
- * can be overtaken by a synchronous `stream-chunk` handler that
231
- * dispatches before the session is ready.
232
- */
233
- let messageTail = Promise.resolve();
234
- self.onmessage = (rawEvent) => {
235
- const e = rawEvent;
236
- messageTail = messageTail.then(async () => {
237
- try {
238
- if (e.data.type === 'init') {
239
- // Lazily resolve '@ifc-lite/wasm-threaded' before its bindings are used.
240
- await __loadThreadedModule();
241
- if (e.data.wasmUrl)
242
- cachedWasmUrl = e.data.wasmUrl;
243
- if (e.data.wasmModule) {
244
- initSync({ module_or_path: e.data.wasmModule });
245
- }
246
- else {
247
- await init(cachedWasmUrl);
248
- }
249
- api = new IfcAPI();
250
- mergeLayersApplied = false;
251
- applyMergeLayersToApi();
252
- // Spin up the rayon thread pool. Per the design (and upstream
253
- // guidance from issue #36), call from inside this worker (NOT
254
- // main thread) to dodge the Atomics.wait deadlock that fires
255
- // when initThreadPool runs on the main thread.
256
- //
257
- // Thread count: hardwareConcurrency - 1 to leave one core for
258
- // main-thread render. Wrap with retry-25ms-backoff x5 in case
259
- // we hit transient deadlocks anyway.
260
- const cores = (typeof navigator !== 'undefined'
261
- ? (navigator.hardwareConcurrency ?? 4)
262
- : 4);
263
- const targetThreads = Math.max(1, cores - 1);
264
- let lastInitErr = null;
265
- for (let attempt = 1; attempt <= 5; attempt++) {
266
- try {
267
- const t0 = performance.now();
268
- await initThreadPool(targetThreads);
269
- console.log(`[controller] rayon pool ready (${targetThreads} threads, attempt ${attempt}) @ ${Math.round(performance.now() - t0)}ms`);
270
- threadPoolReady = true;
271
- lastInitErr = null;
272
- break;
273
- }
274
- catch (err) {
275
- lastInitErr = err;
276
- console.warn(`[controller] initThreadPool attempt ${attempt} failed:`, err);
277
- if (attempt < 5) {
278
- await new Promise((r) => setTimeout(r, 25));
279
- }
280
- }
281
- }
282
- if (!threadPoolReady) {
283
- // Surface the failure as an error message back to the host
284
- // instead of silently posting `ready` and then hanging on
285
- // the first par_iter call. The host's processParallel will
286
- // see this and reject the load with a clear cause.
287
- const errMsg = lastInitErr instanceof Error
288
- ? lastInitErr.message
289
- : String(lastInitErr ?? 'unknown initThreadPool failure');
290
- self.postMessage({
291
- type: 'error',
292
- message: `controller: initThreadPool failed after 5 attempts: ${errMsg}`,
293
- });
294
- return;
295
- }
296
- // Phase 2 microbenchmark — run a CPU-pure parallel task to
297
- // measure rayon's actual speedup on this hardware. Helps
298
- // distinguish "rayon is broken" vs "our workload doesn't fit
299
- // rayon" when stream tail is slow.
300
- try {
301
- const benchApi = api;
302
- if (typeof benchApi.benchmarkPureCpuParallelism === 'function') {
303
- // 9 tasks → one per helper thread — best case for scaling.
304
- benchApi.benchmarkPureCpuParallelism(9);
305
- }
306
- }
307
- catch (err) {
308
- console.warn('[controller] microbench failed:', err);
309
- }
310
- self.postMessage({ type: 'ready' });
311
- return;
312
- }
313
- if (e.data.type === 'stream-start') {
314
- // The thread pool MUST be ready before we accept stream
315
- // messages — `processGeometryBatchParallel` calls par_iter
316
- // which would silently run on the calling thread (slow
317
- // serial fallback) if the pool isn't initialized. Refuse
318
- // and surface a clear error so the host can fall back.
319
- if (!api || !threadPoolReady) {
320
- throw new Error('controller: stream-start before init/threadPool ready — host must wait for {type:"ready"} before dispatching');
321
- }
322
- activeSession = startSession({
323
- sharedBuffer: e.data.sharedBuffer,
324
- unitScale: e.data.unitScale,
325
- rtcX: e.data.rtcX, rtcY: e.data.rtcY, rtcZ: e.data.rtcZ,
326
- needsShift: e.data.needsShift,
327
- voidKeys: e.data.voidKeys,
328
- voidCounts: e.data.voidCounts,
329
- voidValues: e.data.voidValues,
330
- styleIds: e.data.styleIds,
331
- styleColors: e.data.styleColors,
332
- });
333
- return;
334
- }
335
- if (e.data.type === 'stream-chunk') {
336
- if (!activeSession || !api || !threadPoolReady) {
337
- throw new Error('controller: stream-chunk before init/stream-start');
338
- }
339
- await processSliceStreaming(activeSession, e.data.jobsFlat);
340
- return;
341
- }
342
- if (e.data.type === 'stream-end') {
343
- if (!activeSession)
344
- return;
345
- emitSessionEnd(activeSession);
346
- activeSession = null;
347
- return;
348
- }
349
- if (e.data.type === 'set-styles') {
350
- if (!activeSession)
351
- return;
352
- activeSession.styleIds = e.data.styleIds;
353
- activeSession.styleColors = e.data.styleColors;
354
- activeSession.voidKeys = e.data.voidKeys;
355
- activeSession.voidCounts = e.data.voidCounts;
356
- activeSession.voidValues = e.data.voidValues;
357
- return;
358
- }
359
- if (e.data.type === 'set-merge-layers') {
360
- // Cache the requested merge-layers flag (issue #540). The
361
- // host may post this BEFORE `init` (rare but legal); if so
362
- // we just hold onto the value and the `init` branch above
363
- // applies it to the newly-constructed API.
364
- mergeLayersFlag = e.data.enabled === true;
365
- mergeLayersApplied = false;
366
- applyMergeLayersToApi();
367
- return;
368
- }
369
- if (e.data.type === 'set-entity-index') {
370
- if (!api) {
371
- // Should never happen — host always sends `init` first and
372
- // waits for `ready`. If we hit this, it indicates a host
373
- // sequencing bug; surface clearly rather than silently
374
- // initializing a fresh API (which would skip thread-pool
375
- // setup and break later par_iter calls).
376
- throw new Error('controller: set-entity-index before init — host must wait for {type:"ready"} before dispatching');
377
- }
378
- // Eager FxHashMap build — happens during the styles wait so
379
- // by the time stream-chunk arrives the cache is hot.
380
- api.setEntityIndex(e.data.ids, e.data.starts, e.data.lengths);
381
- return;
382
- }
383
- // process / prepass-* message types are NOT handled by the
384
- // controller path — those are pre-pass-only contracts that stay
385
- // on the existing pre-pass worker (geometry.worker.ts). The
386
- // controller is for stream-chunk dispatch only.
387
- console.warn(`[controller] ignoring unhandled message type: ${e.data.type}`);
388
- }
389
- catch (err) {
390
- const msg = err instanceof Error ? err.message : String(err);
391
- console.error('[controller] handler error:', err);
392
- self.postMessage({
393
- type: 'error',
394
- message: msg,
395
- });
396
- }
397
- });
398
- };
399
- // Mark threadPoolReady reachable to silence potential unused warning
400
- // when the future Phase 3 code references it for back-pressure.
401
- void threadPoolReady;
402
- //# sourceMappingURL=geometry-controller.worker.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"geometry-controller.worker.js","sourceRoot":"","sources":["../src/geometry-controller.worker.ts"],"names":[],"mappings":"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"}
@@ -1,42 +0,0 @@
1
- /**
2
- * Geometry Deduplicator - Groups identical meshes for GPU instancing
3
- *
4
- * Reduces draw calls from N individual meshes to M unique geometries with instances.
5
- * A typical building with 40,000 elements might have only 500-2000 unique geometries.
6
- */
7
- import type { MeshData } from './types.js';
8
- export interface InstancedMeshData {
9
- /** Unique hash for this geometry */
10
- geometryHash: string;
11
- /** Vertex positions (shared by all instances) */
12
- positions: Float32Array;
13
- /** Vertex normals (shared by all instances) */
14
- normals: Float32Array;
15
- /** Triangle indices (shared by all instances) */
16
- indices: Uint32Array;
17
- /** All instances of this geometry */
18
- instances: Array<{
19
- expressId: number;
20
- color: [number, number, number, number];
21
- }>;
22
- }
23
- /**
24
- * Deduplicate meshes by grouping identical geometries
25
- * Returns instanced mesh data that can be rendered with GPU instancing
26
- */
27
- export declare function deduplicateMeshes(meshes: MeshData[]): InstancedMeshData[];
28
- /**
29
- * Stats about deduplication results
30
- */
31
- export interface DeduplicationStats {
32
- inputMeshes: number;
33
- uniqueGeometries: number;
34
- deduplicationRatio: number;
35
- totalInstances: number;
36
- maxInstancesPerGeometry: number;
37
- }
38
- /**
39
- * Get statistics about deduplication results
40
- */
41
- export declare function getDeduplicationStats(instanced: InstancedMeshData[]): DeduplicationStats;
42
- //# sourceMappingURL=geometry-deduplicator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"geometry-deduplicator.d.ts","sourceRoot":"","sources":["../src/geometry-deduplicator.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,EAAE,YAAY,CAAC;IACxB,+CAA+C;IAC/C,OAAO,EAAE,YAAY,CAAC;IACtB,iDAAiD;IACjD,OAAO,EAAE,WAAW,CAAC;IACrB,qCAAqC;IACrC,SAAS,EAAE,KAAK,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;KAGzC,CAAC,CAAC;CACJ;AAqCD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,iBAAiB,EAAE,CA6BzE;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,EAAE,GAAG,kBAAkB,CAWxF"}
@@ -1,80 +0,0 @@
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
- * Fast hash for geometry data
6
- * Uses a subset of vertices for speed while maintaining uniqueness
7
- */
8
- function hashGeometry(positions, indices) {
9
- // Hash based on: vertex count, index count, first few vertices, first few indices
10
- const parts = [
11
- positions.length,
12
- indices.length,
13
- ];
14
- // Sample first 12 position values (4 vertices)
15
- const positionSamples = Math.min(12, positions.length);
16
- for (let i = 0; i < positionSamples; i++) {
17
- // Quantize to 3 decimal places for floating point stability
18
- parts.push(Math.round(positions[i] * 1000));
19
- }
20
- // Sample first 6 indices (2 triangles)
21
- const indexSamples = Math.min(6, indices.length);
22
- for (let i = 0; i < indexSamples; i++) {
23
- parts.push(indices[i]);
24
- }
25
- // Also sample from middle and end if we have enough data
26
- if (positions.length > 24) {
27
- const mid = Math.floor(positions.length / 2);
28
- for (let i = 0; i < 6; i++) {
29
- parts.push(Math.round(positions[mid + i] * 1000));
30
- }
31
- }
32
- return parts.join('_');
33
- }
34
- /**
35
- * Deduplicate meshes by grouping identical geometries
36
- * Returns instanced mesh data that can be rendered with GPU instancing
37
- */
38
- export function deduplicateMeshes(meshes) {
39
- const geometryGroups = new Map();
40
- for (const mesh of meshes) {
41
- const hash = hashGeometry(mesh.positions, mesh.indices);
42
- const existing = geometryGroups.get(hash);
43
- if (existing) {
44
- // Add as instance of existing geometry
45
- existing.instances.push({
46
- expressId: mesh.expressId,
47
- color: mesh.color,
48
- });
49
- }
50
- else {
51
- // First occurrence - create new geometry group
52
- geometryGroups.set(hash, {
53
- geometryHash: hash,
54
- positions: mesh.positions,
55
- normals: mesh.normals,
56
- indices: mesh.indices,
57
- instances: [{
58
- expressId: mesh.expressId,
59
- color: mesh.color,
60
- }],
61
- });
62
- }
63
- }
64
- return Array.from(geometryGroups.values());
65
- }
66
- /**
67
- * Get statistics about deduplication results
68
- */
69
- export function getDeduplicationStats(instanced) {
70
- const totalInstances = instanced.reduce((sum, g) => sum + g.instances.length, 0);
71
- const maxInstances = Math.max(...instanced.map(g => g.instances.length));
72
- return {
73
- inputMeshes: totalInstances,
74
- uniqueGeometries: instanced.length,
75
- deduplicationRatio: totalInstances / instanced.length,
76
- totalInstances,
77
- maxInstancesPerGeometry: maxInstances,
78
- };
79
- }
80
- //# sourceMappingURL=geometry-deduplicator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"geometry-deduplicator.js","sourceRoot":"","sources":["../src/geometry-deduplicator.ts"],"names":[],"mappings":"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"}
@@ -1,111 +0,0 @@
1
- import type { IfcAPI, InstancedGeometry } from '@ifc-lite/wasm';
2
- import type { MeshData } from './types.js';
3
- export interface StreamingProgress {
4
- percent: number;
5
- processed: number;
6
- total: number;
7
- phase: 'simple' | 'simple_complete' | 'complex';
8
- }
9
- export interface StreamingBatchEvent {
10
- type: 'batch';
11
- meshes: MeshData[];
12
- progress: StreamingProgress;
13
- }
14
- export interface StreamingCompleteEvent {
15
- type: 'complete';
16
- stats: {
17
- totalMeshes: number;
18
- totalVertices: number;
19
- totalTriangles: number;
20
- };
21
- }
22
- export interface StreamingColorUpdateEvent {
23
- type: 'colorUpdate';
24
- updates: Map<number, [number, number, number, number]>;
25
- }
26
- export interface StreamingRtcOffsetEvent {
27
- type: 'rtcOffset';
28
- /** RTC offset in IFC coordinates (before Z-up to Y-up conversion) */
29
- rtcOffset: {
30
- x: number;
31
- y: number;
32
- z: number;
33
- };
34
- hasRtc: boolean;
35
- }
36
- export type StreamingEvent = StreamingBatchEvent | StreamingCompleteEvent | StreamingColorUpdateEvent | StreamingRtcOffsetEvent;
37
- /**
38
- * Optional constructor options for the mesh collector. Currently used
39
- * to forward the Revit-style multilayer-wall merge flag from the
40
- * viewer's UI toggle (issue #540) down to the WASM API before the
41
- * first `parseMeshes*` call.
42
- */
43
- export interface IfcLiteMeshCollectorOptions {
44
- /**
45
- * When true, the WASM mesh emitters suppress `IfcBuildingElementPart`
46
- * meshes whose parent wall is sliceable. Default `false` keeps the
47
- * existing per-layer behaviour.
48
- */
49
- mergeLayers?: boolean;
50
- }
51
- export declare class IfcLiteMeshCollector {
52
- private ifcApi;
53
- private content;
54
- private _buildingRotation;
55
- private mergeLayers;
56
- private mergeLayersApplied;
57
- constructor(ifcApi: IfcAPI, content: string, options?: IfcLiteMeshCollectorOptions);
58
- /**
59
- * Forward the cached `mergeLayers` flag to the IfcAPI once per
60
- * collector instance. The Rust agent's contract is "state on the
61
- * IfcAPI carries forward to subsequent parseMeshes* calls", so we
62
- * only need to push the flag once before the first parse call.
63
- *
64
- * When the WASM build pre-dates the Rust agent's contract, the
65
- * method is missing — we tolerate that silently because the bridge
66
- * already logged a warning on its own `applyMergeLayers` path.
67
- */
68
- private ensureMergeLayersApplied;
69
- /**
70
- * Convert IFC Z-up coordinates to WebGL Y-up coordinates
71
- * IFC uses Z-up (Z points up), WebGL uses Y-up (Y points up)
72
- * Transformation: swap Y and Z, then negate new Z to maintain right-handedness
73
- */
74
- private convertZUpToYUp;
75
- /**
76
- * Reverse triangle winding order to correct for handedness flip.
77
- * The Z-up to Y-up conversion includes a reflection (Z negation),
78
- * which flips the handedness. This reverses winding to compensate,
79
- * ensuring triangles face the correct direction after transformation.
80
- */
81
- private reverseWindingOrder;
82
- /**
83
- * Collect all meshes from IFC-Lite
84
- * Much faster than web-ifc (~1.9x speedup)
85
- */
86
- collectMeshes(): MeshData[];
87
- /**
88
- * Get building rotation extracted from IfcSite placement
89
- */
90
- getBuildingRotation(): number | undefined;
91
- /**
92
- * Collect meshes incrementally, yielding batches for progressive rendering
93
- * Uses fast-first-frame streaming: simple geometry (walls, slabs) first
94
- * @param batchSize Number of meshes per batch (default: 25 for faster first frame)
95
- */
96
- collectMeshesStreaming(batchSize?: number): AsyncGenerator<MeshData[] | StreamingColorUpdateEvent | StreamingRtcOffsetEvent>;
97
- /**
98
- * Collect meshes with dynamic batch sizing (ramp-up approach)
99
- * Accumulates meshes from WASM and yields them in dynamically-sized batches
100
- * @param getBatchSize Function that returns batch size for current batch number
101
- */
102
- collectMeshesStreamingDynamic(getBatchSize: () => number): AsyncGenerator<MeshData[]>;
103
- /**
104
- * Collect instanced geometry incrementally, yielding batches for progressive rendering
105
- * Groups identical geometries by hash (before transformation) for GPU instancing
106
- * Uses fast-first-frame streaming: simple geometry (walls, slabs) first
107
- * @param batchSize Number of unique geometries per batch (default: 25)
108
- */
109
- collectInstancedGeometryStreaming(batchSize?: number): AsyncGenerator<InstancedGeometry[]>;
110
- }
111
- //# sourceMappingURL=ifc-lite-mesh-collector.d.ts.map