@ifc-lite/renderer 1.50.0 → 2.0.1

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 (85) hide show
  1. package/README.md +4 -0
  2. package/dist/camera-animation.d.ts.map +1 -1
  3. package/dist/camera-animation.js +37 -27
  4. package/dist/camera-animation.js.map +1 -1
  5. package/dist/camera-controls.d.ts +26 -15
  6. package/dist/camera-controls.d.ts.map +1 -1
  7. package/dist/camera-controls.js +32 -18
  8. package/dist/camera-controls.js.map +1 -1
  9. package/dist/camera-framing.d.ts +60 -21
  10. package/dist/camera-framing.d.ts.map +1 -1
  11. package/dist/camera-framing.js +168 -131
  12. package/dist/camera-framing.js.map +1 -1
  13. package/dist/camera-preset-view.d.ts +2 -2
  14. package/dist/camera-preset-view.d.ts.map +1 -1
  15. package/dist/camera-preset-view.js +52 -42
  16. package/dist/camera-preset-view.js.map +1 -1
  17. package/dist/camera.d.ts +26 -6
  18. package/dist/camera.d.ts.map +1 -1
  19. package/dist/camera.js +41 -12
  20. package/dist/camera.js.map +1 -1
  21. package/dist/federation-registry.d.ts.map +1 -1
  22. package/dist/federation-registry.js +19 -2
  23. package/dist/federation-registry.js.map +1 -1
  24. package/dist/index.d.ts +42 -59
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +43 -73
  27. package/dist/index.js.map +1 -1
  28. package/dist/instanced-override-color.d.ts +17 -0
  29. package/dist/instanced-override-color.d.ts.map +1 -0
  30. package/dist/instanced-override-color.js +22 -0
  31. package/dist/instanced-override-color.js.map +1 -0
  32. package/dist/instanced-render.d.ts +10 -0
  33. package/dist/instanced-render.d.ts.map +1 -1
  34. package/dist/instanced-render.js +13 -3
  35. package/dist/instanced-render.js.map +1 -1
  36. package/dist/lod-simplify.d.ts.map +1 -1
  37. package/dist/lod-simplify.js +24 -2
  38. package/dist/lod-simplify.js.map +1 -1
  39. package/dist/pick-resolve.d.ts +125 -0
  40. package/dist/pick-resolve.d.ts.map +1 -0
  41. package/dist/pick-resolve.js +127 -0
  42. package/dist/pick-resolve.js.map +1 -0
  43. package/dist/picker.d.ts.map +1 -1
  44. package/dist/picker.js +20 -46
  45. package/dist/picker.js.map +1 -1
  46. package/dist/picking-manager.d.ts.map +1 -1
  47. package/dist/picking-manager.js +13 -1
  48. package/dist/picking-manager.js.map +1 -1
  49. package/dist/raycast-engine.d.ts +4 -4
  50. package/dist/raycast-engine.d.ts.map +1 -1
  51. package/dist/raycast-engine.js.map +1 -1
  52. package/dist/renderer-overlays.d.ts +3 -21
  53. package/dist/renderer-overlays.d.ts.map +1 -1
  54. package/dist/renderer-overlays.js +57 -85
  55. package/dist/renderer-overlays.js.map +1 -1
  56. package/dist/renderer-symbolic-overlays.d.ts +29 -2
  57. package/dist/renderer-symbolic-overlays.d.ts.map +1 -1
  58. package/dist/renderer-symbolic-overlays.js +61 -16
  59. package/dist/renderer-symbolic-overlays.js.map +1 -1
  60. package/dist/scene-contents.d.ts +132 -0
  61. package/dist/scene-contents.d.ts.map +1 -0
  62. package/dist/scene-contents.js +5 -0
  63. package/dist/scene-contents.js.map +1 -0
  64. package/dist/scene-raycaster.d.ts +14 -8
  65. package/dist/scene-raycaster.d.ts.map +1 -1
  66. package/dist/scene-raycaster.js +6 -2
  67. package/dist/scene-raycaster.js.map +1 -1
  68. package/dist/scene.d.ts.map +1 -1
  69. package/dist/scene.js +21 -7
  70. package/dist/scene.js.map +1 -1
  71. package/dist/section-2d-overlay.d.ts +52 -63
  72. package/dist/section-2d-overlay.d.ts.map +1 -1
  73. package/dist/section-2d-overlay.js +69 -130
  74. package/dist/section-2d-overlay.js.map +1 -1
  75. package/dist/shaders/section-2d-overlay.wgsl.d.ts +2 -2
  76. package/dist/shaders/section-2d-overlay.wgsl.d.ts.map +1 -1
  77. package/dist/shaders/section-2d-overlay.wgsl.js +2 -2
  78. package/dist/shaders/section-2d-overlay.wgsl.js.map +1 -1
  79. package/dist/symbolic-overlay-pipelines.d.ts +11 -12
  80. package/dist/symbolic-overlay-pipelines.d.ts.map +1 -1
  81. package/dist/symbolic-overlay-pipelines.js +7 -12
  82. package/dist/symbolic-overlay-pipelines.js.map +1 -1
  83. package/dist/types.d.ts +5 -19
  84. package/dist/types.d.ts.map +1 -1
  85. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ export { WebGPUDevice } from './device.js';
8
8
  export { RenderPipeline } from './pipeline.js';
9
9
  export { Camera } from './camera.js';
10
10
  export { pickFitPolicy } from './camera-fit-policy.js';
11
- export { Scene } from './scene.js';
11
+ // `Scene` is NOT exported: an exported class republishes every method `SceneContents` above just froze.
12
12
  export { Picker } from './picker.js';
13
13
  export { MathUtils } from './math.js';
14
14
  // The orthonormal camera basis `MathUtils.lookAt` renders through, exposed so
@@ -19,7 +19,7 @@ export { MathUtils } from './math.js';
19
19
  // is the same situation from outside it).
20
20
  export { viewBasis } from './math.js';
21
21
  export { SectionPlaneRenderer } from './section-plane.js';
22
- export { Section2DOverlayRenderer } from './section-2d-overlay.js';
22
+ // `Section2DOverlayRenderer` is NOT exported: `Renderer.setLineOverlay` and the section cap drive it from inside. Its types below stay published.
23
23
  // IfcAnnotation overlay pipelines (3D world-space). Self-contained — caller
24
24
  // passes a GPUDevice + presentation format and invokes `.render(pass, viewProj)`
25
25
  // from inside an RGBA-blended pass. See packages/renderer/src/symbolic-overlay-pipelines.ts.
@@ -30,14 +30,13 @@ export { SymbolicTextAtlas } from './symbolic-text-atlas.js';
30
30
  // holds the styling primitives shared with the store and UI.
31
31
  export { DEFAULT_CAP_STYLE, HATCH_PATTERN_IDS } from './section-cap-style.js';
32
32
  export { planeBasis, nearestCardinalAxis } from './section-plane-basis.js';
33
+ export { LINE_OVERLAY_CHANNELS } from './section-2d-overlay.js';
33
34
  export { Raycaster } from './raycaster.js';
34
35
  export { SnapDetector, SnapType } from './snap-detector.js';
35
36
  export { BVH } from './bvh.js';
36
37
  export { FederationRegistry, federationRegistry } from './federation-registry.js';
37
38
  export * from './types.js';
38
39
  export { resolveEnvironment, deriveSkyGradient, packEnvironmentUniforms, ENVIRONMENT_UNIFORM_SIZE, } from './environment.js';
39
- // Extracted manager classes
40
- export { PickingManager } from './picking-manager.js';
41
40
  export { resolveContributionThresholdPx, projectedAabbRadiusPx } from './contribution-cull.js';
42
41
  export { chunkCellKey, bucketBaseKeyFor, DEFAULT_CHUNK_CELL_SIZE } from './chunk-grid.js';
43
42
  export { selectEvictions, MIN_EVICTION_AGE_FRAMES } from './residency.js';
@@ -71,6 +70,7 @@ import { RenderPipeline } from './pipeline.js';
71
70
  import { Camera } from './camera.js';
72
71
  import { Scene } from './scene.js';
73
72
  import { Picker } from './picker.js';
73
+ import { reportableItemId } from './pick-resolve.js';
74
74
  import { MathUtils, viewBasis } from './math.js';
75
75
  import { FrustumUtils } from '@ifc-lite/spatial';
76
76
  import { VisualEnhancementResolver } from './visual-enhancement.js';
@@ -1283,6 +1283,11 @@ export class Renderer {
1283
1283
  this.scene.addMesh({
1284
1284
  expressId: meshData.expressId,
1285
1285
  modelIndex: meshData.modelIndex, // Preserve modelIndex for multi-model selection
1286
+ // Source item, so a pick can report it (#2985) — via the shared rule,
1287
+ // so this and the CPU raycaster cannot answer one click two ways.
1288
+ // In-tree callers pre-split merged pieces (Scene.getMeshDataPieces
1289
+ // drops the field incidentally); this is public, so it owns the rule.
1290
+ geometryItemId: reportableItemId(meshData, meshData.expressId),
1286
1291
  vertexBuffer,
1287
1292
  indexBuffer,
1288
1293
  indexCount: meshData.indices.length,
@@ -3042,18 +3047,6 @@ export class Renderer {
3042
3047
  invalidateBVHCache() {
3043
3048
  this.raycastEngine.invalidateBVHCache();
3044
3049
  }
3045
- /**
3046
- * Get the raycaster instance (for advanced usage)
3047
- */
3048
- getRaycaster() {
3049
- return this.raycastEngine.getRaycaster();
3050
- }
3051
- /**
3052
- * Get the snap detector instance (for advanced usage)
3053
- */
3054
- getSnapDetector() {
3055
- return this.raycastEngine.getSnapDetector();
3056
- }
3057
3050
  /**
3058
3051
  * Clear all caches (call when geometry changes)
3059
3052
  */
@@ -3113,6 +3106,7 @@ export class Renderer {
3113
3106
  getCamera() {
3114
3107
  return this.camera;
3115
3108
  }
3109
+ /** MEASURED external surface, not the 4400-line `Scene`: widening `SceneContents` is a published-API decision, not a detail — see `scene-contents.ts`. */
3116
3110
  getScene() {
3117
3111
  return this.scene;
3118
3112
  }
@@ -3156,63 +3150,32 @@ export class Renderer {
3156
3150
  this.overlays.setOverlayLineColor(color);
3157
3151
  }
3158
3152
  /**
3159
- * Upload pre-lifted 3D line-list vertices for the standalone annotation
3160
- * overlay. Each segment is `[x1, y1, z1, x2, y2, z2]` in world space.
3161
- * The overlay is drawn regardless of whether a section plane is active.
3162
- * Pass an empty Float32Array to clear.
3163
- */
3164
- uploadAnnotationLines3D(vertices) {
3165
- this.overlays.uploadAnnotationLines3D(vertices);
3166
- }
3167
- /**
3168
- * Clear the standalone annotation line overlay.
3169
- */
3170
- clearAnnotationLines3D() {
3171
- this.overlays.clearAnnotationLines3D();
3172
- }
3173
- /**
3174
- * Upload IfcAlignment centerline segments as a flat [x,y,z,x,y,z,...]
3175
- * line-list in world space. Rendered as thin lines (not a ribbon mesh)
3176
- * to match IfcGrid / IfcAnnotation. Pass an empty Float32Array to clear.
3177
- */
3178
- uploadAlignmentLines3D(vertices) {
3179
- this.overlays.uploadAlignmentLines3D(vertices);
3180
- }
3181
- /** Clear the alignment centerline overlay. */
3182
- clearAlignmentLines3D() {
3183
- this.overlays.clearAlignmentLines3D();
3184
- }
3185
- /**
3186
- * Upload structural-grid (IfcGridAxis) segments as a flat [x,y,z,x,y,z,...]
3187
- * line-list in world space (issue #967). Rendered as thin lines, mirroring
3188
- * the alignment overlay. Pass an empty Float32Array to clear.
3153
+ * Set one standalone 3D line overlay, or clear it by passing `null`.
3189
3154
  *
3190
- * Unlike alignment, grids do NOT expand model bounds: they're behind a
3191
- * visibility toggle, so toggling them on must not reframe the camera (and
3192
- * grid axes routinely extend past the model envelope).
3193
- */
3194
- uploadGridLines3D(vertices) {
3195
- this.overlays.uploadGridLines3D(vertices);
3196
- }
3197
- /** Clear the structural-grid overlay. */
3198
- clearGridLines3D() {
3199
- this.overlays.clearGridLines3D();
3200
- }
3201
- /**
3202
- * Upload the DXF reference-layer's line paths as a flat
3203
- * [x,y,z,x,y,z,...] line-list in world space (issue #2043, follow-up to
3204
- * the 2D-only DXF underlay from #1782/#1929). Mirrors
3205
- * `uploadGridLines3D`: a dedicated buffer so 3D DXF visibility is
3206
- * independent of the 2D underlay's own toggle, and does NOT expand
3207
- * model bounds/reframe the camera on upload it's behind its own
3208
- * visibility toggle, like grid axes. Pass an empty Float32Array to clear.
3155
+ * `vertices` is a flat world-space line-list `[x1,y1,z1, x2,y2,z2, …]`,
3156
+ * one segment per six floats. The vertices are already lifted to world
3157
+ * space, so these overlays draw whether or not a section plane is active.
3158
+ * A trailing partial segment is dropped rather than rejecting the array.
3159
+ * An empty array clears too, but `null` skips building the pipelines.
3160
+ *
3161
+ * Every channel is an independent buffer with its own visibility, so
3162
+ * setting one leaves the other three untouched. All four share the colour
3163
+ * set by {@link setOverlayLineColor}; label colour is per-text via
3164
+ * `SymbolicTextInput.color` on `uploadAnnotationTexts3D`.
3165
+ *
3166
+ * The channels differ in exactly one way — whether they grow the scene
3167
+ * bounds. `annotation` (#653) and `alignment` DO: a file holding only them
3168
+ * has no IfcProduct meshes to frame, so Home / fit-to-view would have
3169
+ * nothing to aim at and the near/far range would clip the lines away.
3170
+ * `grid` (IfcGridAxis, #967) and `dxf` (the DXF reference layer, #2043) do
3171
+ * NOT: they are reference layers that routinely extend past the model
3172
+ * envelope, so growing the bounds would reframe the camera whenever one
3173
+ * was ticked on. The rule is "does this content DEFINE the model's
3174
+ * extent", NOT "is it behind a visibility toggle" — annotations sit behind
3175
+ * `ifcAnnotationsVisible` too.
3209
3176
  */
3210
- uploadDxfLines3D(vertices) {
3211
- this.overlays.uploadDxfLines3D(vertices);
3212
- }
3213
- /** Clear the 3D DXF reference-layer overlay. */
3214
- clearDxfLines3D() {
3215
- this.overlays.clearDxfLines3D();
3177
+ setLineOverlay(channel, vertices) {
3178
+ this.overlays.setLineOverlay(channel, vertices);
3216
3179
  }
3217
3180
  /**
3218
3181
  * Show (or clear) the clash-overlap box: the wireframe AABB of a focused
@@ -3266,7 +3229,10 @@ export class Renderer {
3266
3229
  return this.overlays.hasSection2DOverlay();
3267
3230
  }
3268
3231
  /**
3269
- * Get render pipeline (for batching)
3232
+ * Get render pipeline (for batching). DELIBERATELY NOT NARROWED, unlike
3233
+ * `getScene()`: the measurement found ZERO external
3234
+ * `RenderPipeline` members — all 12 call sites pass the handle straight
3235
+ * back into a `SceneContents` upload method typed for the real class.
3270
3236
  */
3271
3237
  getPipeline() {
3272
3238
  return this.pipeline;
@@ -3308,7 +3274,11 @@ export class Renderer {
3308
3274
  *
3309
3275
  * Returning null instead routes into the `if (!device) return` check that
3310
3276
  * every call site already has, so a lost device degrades to "stop
3311
- * uploading" rather than an uncaught throw. See `isDeviceLost()` /
3277
+ * uploading" rather than an uncaught throw.
3278
+ *
3279
+ * DELIBERATELY NOT NARROWED, unlike `getScene()`: the one external
3280
+ * `GPUDevice` member measured is `queue`; every other call site
3281
+ * hands the device back to a `SceneContents` method. See `isDeviceLost()` /
3312
3282
  * `onDeviceLost()` for the recovery contract.
3313
3283
  */
3314
3284
  getGPUDevice() {