@ifc-lite/renderer 1.1.6 → 1.2.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.
@@ -0,0 +1,67 @@
1
+ import type { MeshData } from '@ifc-lite/geometry';
2
+ export interface Ray {
3
+ origin: {
4
+ x: number;
5
+ y: number;
6
+ z: number;
7
+ };
8
+ direction: {
9
+ x: number;
10
+ y: number;
11
+ z: number;
12
+ };
13
+ }
14
+ export interface Vec3 {
15
+ x: number;
16
+ y: number;
17
+ z: number;
18
+ }
19
+ export interface Intersection {
20
+ point: Vec3;
21
+ normal: Vec3;
22
+ distance: number;
23
+ meshIndex: number;
24
+ triangleIndex: number;
25
+ expressId: number;
26
+ barycentricCoord: {
27
+ u: number;
28
+ v: number;
29
+ w: number;
30
+ };
31
+ }
32
+ export declare class Raycaster {
33
+ private epsilon;
34
+ /**
35
+ * Cast a ray through all meshes and return the closest intersection
36
+ */
37
+ raycast(ray: Ray, meshes: MeshData[]): Intersection | null;
38
+ /**
39
+ * Cast ray through a single mesh
40
+ */
41
+ private raycastMesh;
42
+ /**
43
+ * Ray-triangle intersection using Möller–Trumbore algorithm
44
+ */
45
+ private intersectTriangle;
46
+ /**
47
+ * Calculate triangle normal
48
+ */
49
+ private calculateTriangleNormal;
50
+ /**
51
+ * Vector math utilities
52
+ */
53
+ private subtract;
54
+ private cross;
55
+ private dot;
56
+ private normalize;
57
+ private length;
58
+ /**
59
+ * Get closest point on line segment to a point
60
+ */
61
+ closestPointOnSegment(p: Vec3, a: Vec3, b: Vec3): Vec3;
62
+ /**
63
+ * Distance from point to point
64
+ */
65
+ distance(a: Vec3, b: Vec3): number;
66
+ }
67
+ //# sourceMappingURL=raycaster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raycaster.d.ts","sourceRoot":"","sources":["../src/raycaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAa;IAE5B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,GAAG,IAAI;IAiB1D;;OAEG;IACH,OAAO,CAAC,WAAW;IAkFnB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA6DzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAO/B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,MAAM;IAId;;OAEG;IACH,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI;IAYtD;;OAEG;IACH,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM;CAGnC"}
@@ -0,0 +1,192 @@
1
+ export class Raycaster {
2
+ epsilon = 0.0000001;
3
+ /**
4
+ * Cast a ray through all meshes and return the closest intersection
5
+ */
6
+ raycast(ray, meshes) {
7
+ let closestIntersection = null;
8
+ let closestDistance = Infinity;
9
+ for (let meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
10
+ const mesh = meshes[meshIndex];
11
+ const intersection = this.raycastMesh(ray, mesh, meshIndex);
12
+ if (intersection && intersection.distance < closestDistance) {
13
+ closestDistance = intersection.distance;
14
+ closestIntersection = intersection;
15
+ }
16
+ }
17
+ return closestIntersection;
18
+ }
19
+ /**
20
+ * Cast ray through a single mesh
21
+ */
22
+ raycastMesh(ray, mesh, meshIndex) {
23
+ const positions = mesh.positions;
24
+ const indices = mesh.indices;
25
+ // Validate input
26
+ if (!indices || indices.length === 0 || !positions || positions.length === 0) {
27
+ return null;
28
+ }
29
+ // Ensure triangle count is valid
30
+ if (indices.length % 3 !== 0) {
31
+ console.warn(`Invalid index count for mesh ${mesh.expressId}: ${indices.length}`);
32
+ return null;
33
+ }
34
+ let closestIntersection = null;
35
+ let closestDistance = Infinity;
36
+ // Test each triangle
37
+ for (let i = 0; i < indices.length; i += 3) {
38
+ const idx0 = indices[i];
39
+ const idx1 = indices[i + 1];
40
+ const idx2 = indices[i + 2];
41
+ // Validate indices are within bounds
42
+ const maxIndex = positions.length / 3 - 1;
43
+ if (idx0 > maxIndex || idx1 > maxIndex || idx2 > maxIndex) {
44
+ continue; // Skip invalid triangles
45
+ }
46
+ const i0 = idx0 * 3;
47
+ const i1 = idx1 * 3;
48
+ const i2 = idx2 * 3;
49
+ const v0 = {
50
+ x: positions[i0],
51
+ y: positions[i0 + 1],
52
+ z: positions[i0 + 2],
53
+ };
54
+ const v1 = {
55
+ x: positions[i1],
56
+ y: positions[i1 + 1],
57
+ z: positions[i1 + 2],
58
+ };
59
+ const v2 = {
60
+ x: positions[i2],
61
+ y: positions[i2 + 1],
62
+ z: positions[i2 + 2],
63
+ };
64
+ // Skip degenerate triangles (NaN or identical vertices)
65
+ if (!isFinite(v0.x) || !isFinite(v0.y) || !isFinite(v0.z) ||
66
+ !isFinite(v1.x) || !isFinite(v1.y) || !isFinite(v1.z) ||
67
+ !isFinite(v2.x) || !isFinite(v2.y) || !isFinite(v2.z)) {
68
+ continue;
69
+ }
70
+ const intersection = this.intersectTriangle(ray, v0, v1, v2);
71
+ if (intersection && intersection.distance < closestDistance) {
72
+ closestDistance = intersection.distance;
73
+ // Calculate normal from triangle
74
+ const normal = this.calculateTriangleNormal(v0, v1, v2);
75
+ closestIntersection = {
76
+ point: intersection.point,
77
+ normal,
78
+ distance: intersection.distance,
79
+ meshIndex,
80
+ triangleIndex: i / 3,
81
+ expressId: mesh.expressId,
82
+ barycentricCoord: intersection.barycentricCoord,
83
+ };
84
+ }
85
+ }
86
+ return closestIntersection;
87
+ }
88
+ /**
89
+ * Ray-triangle intersection using Möller–Trumbore algorithm
90
+ */
91
+ intersectTriangle(ray, v0, v1, v2) {
92
+ // Edge vectors
93
+ const edge1 = this.subtract(v1, v0);
94
+ const edge2 = this.subtract(v2, v0);
95
+ // Calculate determinant
96
+ const h = this.cross(ray.direction, edge2);
97
+ const det = this.dot(edge1, h);
98
+ // Ray parallel to triangle
99
+ if (Math.abs(det) < this.epsilon) {
100
+ return null;
101
+ }
102
+ const invDet = 1.0 / det;
103
+ // Calculate u parameter
104
+ const s = this.subtract(ray.origin, v0);
105
+ const u = invDet * this.dot(s, h);
106
+ if (u < 0.0 || u > 1.0) {
107
+ return null;
108
+ }
109
+ // Calculate v parameter
110
+ const q = this.cross(s, edge1);
111
+ const v = invDet * this.dot(ray.direction, q);
112
+ if (v < 0.0 || u + v > 1.0) {
113
+ return null;
114
+ }
115
+ // Calculate t (distance along ray)
116
+ const t = invDet * this.dot(edge2, q);
117
+ if (t < this.epsilon) {
118
+ return null; // Intersection behind ray origin
119
+ }
120
+ // Calculate intersection point
121
+ const point = {
122
+ x: ray.origin.x + ray.direction.x * t,
123
+ y: ray.origin.y + ray.direction.y * t,
124
+ z: ray.origin.z + ray.direction.z * t,
125
+ };
126
+ // Barycentric coordinates
127
+ const w = 1.0 - u - v;
128
+ return {
129
+ point,
130
+ distance: t,
131
+ barycentricCoord: { u, v, w },
132
+ };
133
+ }
134
+ /**
135
+ * Calculate triangle normal
136
+ */
137
+ calculateTriangleNormal(v0, v1, v2) {
138
+ const edge1 = this.subtract(v1, v0);
139
+ const edge2 = this.subtract(v2, v0);
140
+ const normal = this.cross(edge1, edge2);
141
+ return this.normalize(normal);
142
+ }
143
+ /**
144
+ * Vector math utilities
145
+ */
146
+ subtract(a, b) {
147
+ return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
148
+ }
149
+ cross(a, b) {
150
+ return {
151
+ x: a.y * b.z - a.z * b.y,
152
+ y: a.z * b.x - a.x * b.z,
153
+ z: a.x * b.y - a.y * b.x,
154
+ };
155
+ }
156
+ dot(a, b) {
157
+ return a.x * b.x + a.y * b.y + a.z * b.z;
158
+ }
159
+ normalize(v) {
160
+ const length = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
161
+ if (length === 0)
162
+ return { x: 0, y: 0, z: 1 };
163
+ return {
164
+ x: v.x / length,
165
+ y: v.y / length,
166
+ z: v.z / length,
167
+ };
168
+ }
169
+ length(v) {
170
+ return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
171
+ }
172
+ /**
173
+ * Get closest point on line segment to a point
174
+ */
175
+ closestPointOnSegment(p, a, b) {
176
+ const ab = this.subtract(b, a);
177
+ const ap = this.subtract(p, a);
178
+ const t = Math.max(0, Math.min(1, this.dot(ap, ab) / this.dot(ab, ab)));
179
+ return {
180
+ x: a.x + ab.x * t,
181
+ y: a.y + ab.y * t,
182
+ z: a.z + ab.z * t,
183
+ };
184
+ }
185
+ /**
186
+ * Distance from point to point
187
+ */
188
+ distance(a, b) {
189
+ return this.length(this.subtract(a, b));
190
+ }
191
+ }
192
+ //# sourceMappingURL=raycaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raycaster.js","sourceRoot":"","sources":["../src/raycaster.ts"],"names":[],"mappings":"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"}
package/dist/scene.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Scene graph and mesh management
3
3
  */
4
- import type { Mesh, InstancedMesh, BatchedMesh } from './types.js';
4
+ import type { Mesh, InstancedMesh, BatchedMesh, Vec3 } from './types.js';
5
5
  import type { MeshData } from '@ifc-lite/geometry';
6
6
  export declare class Scene {
7
7
  private meshes;
@@ -10,6 +10,10 @@ export declare class Scene {
10
10
  private batchedMeshMap;
11
11
  private batchedMeshData;
12
12
  private meshDataMap;
13
+ private boundingBoxes;
14
+ private pendingBatchKeys;
15
+ private lastBatchRebuildTime;
16
+ private batchRebuildThrottleMs;
13
17
  /**
14
18
  * Add mesh to scene
15
19
  */
@@ -33,16 +37,22 @@ export declare class Scene {
33
37
  /**
34
38
  * Store MeshData for lazy GPU buffer creation (used for selection highlighting)
35
39
  * This avoids creating 2x GPU buffers during streaming
40
+ * Accumulates multiple mesh pieces per expressId (elements can have multiple geometry pieces)
36
41
  */
37
42
  addMeshData(meshData: MeshData): void;
38
43
  /**
39
44
  * Get MeshData by expressId (for lazy buffer creation)
45
+ * Returns merged MeshData if element has multiple pieces
40
46
  */
41
47
  getMeshData(expressId: number): MeshData | undefined;
42
48
  /**
43
49
  * Check if MeshData exists for an expressId
44
50
  */
45
51
  hasMeshData(expressId: number): boolean;
52
+ /**
53
+ * Get all MeshData pieces for an expressId (without merging)
54
+ */
55
+ getMeshDataPieces(expressId: number): MeshData[] | undefined;
46
56
  /**
47
57
  * Generate color key for grouping meshes
48
58
  */
@@ -50,14 +60,33 @@ export declare class Scene {
50
60
  /**
51
61
  * Append meshes to color batches incrementally
52
62
  * Merges new meshes into existing color groups or creates new ones
63
+ *
64
+ * OPTIMIZATION: Throttles batch rebuilding during streaming to avoid O(N²) cost
65
+ * - Mesh data is accumulated immediately (fast)
66
+ * - GPU buffers are rebuilt at most every batchRebuildThrottleMs (expensive)
67
+ */
68
+ appendToBatches(meshDataArray: MeshData[], device: GPUDevice, pipeline: any, isStreaming?: boolean): void;
69
+ /**
70
+ * Rebuild all pending batches (call this after streaming completes)
71
+ */
72
+ rebuildPendingBatches(device: GPUDevice, pipeline: any): void;
73
+ /**
74
+ * Check if there are pending batch rebuilds
75
+ */
76
+ hasPendingBatches(): boolean;
77
+ /**
78
+ * Update colors for existing meshes and rebuild affected batches
79
+ * Call this when deferred color parsing completes
53
80
  */
54
- appendToBatches(meshDataArray: MeshData[], device: GPUDevice, pipeline: any): void;
81
+ updateMeshColors(updates: Map<number, [number, number, number, number]>, device: GPUDevice, pipeline: any): void;
55
82
  /**
56
83
  * Create a new batched mesh from mesh data array
57
84
  */
58
85
  private createBatchedMesh;
59
86
  /**
60
87
  * Merge multiple mesh geometries into single vertex/index buffers
88
+ *
89
+ * OPTIMIZATION: Uses efficient loops and bulk index adjustment
61
90
  */
62
91
  private mergeGeometry;
63
92
  /**
@@ -83,5 +112,30 @@ export declare class Scene {
83
112
  z: number;
84
113
  };
85
114
  } | null;
115
+ /**
116
+ * Get all expressIds that have mesh data (for CPU raycasting)
117
+ */
118
+ getAllMeshDataExpressIds(): number[];
119
+ /**
120
+ * Get or compute bounding box for a mesh
121
+ */
122
+ private getBoundingBox;
123
+ /**
124
+ * Ray-box intersection test (slab method)
125
+ */
126
+ private rayIntersectsBox;
127
+ /**
128
+ * Möller–Trumbore ray-triangle intersection
129
+ * Returns distance to intersection or null if no hit
130
+ */
131
+ private rayTriangleIntersect;
132
+ /**
133
+ * CPU raycast against all mesh data
134
+ * Returns expressId of closest hit or null
135
+ */
136
+ raycast(rayOrigin: Vec3, rayDir: Vec3, hiddenIds?: Set<number>, isolatedIds?: Set<number> | null): {
137
+ expressId: number;
138
+ distance: number;
139
+ } | null;
86
140
  }
87
141
  //# sourceMappingURL=scene.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,eAAe,CAAsC;IAC7D,OAAO,CAAC,WAAW,CAAoC;IAEvD;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIzB;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAI3C;;OAEG;IACH,SAAS,IAAI,IAAI,EAAE;IAInB;;OAEG;IACH,kBAAkB,IAAI,aAAa,EAAE;IAIrC;;OAEG;IACH,gBAAgB,IAAI,WAAW,EAAE;IAIjC;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIrC;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIpD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIvC;;OAEG;IACH,OAAO,CAAC,QAAQ;IAShB;;;OAGG;IACH,eAAe,CAAC,aAAa,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,GAAG,IAAI;IAwClF;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqDzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkDrB;;OAEG;IACH,kBAAkB,IAAI,IAAI;IAY1B;;OAEG;IACH,KAAK,IAAI,IAAI;IA6Bb;;OAEG;IACH,SAAS,IAAI;QAAE,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,GAAG,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,IAAI;CAU3G"}
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}