@ifc-lite/renderer 1.44.0 → 1.44.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.
@@ -0,0 +1,333 @@
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
+ * Even-odd triangulation of a flat ring set (issue #2516).
6
+ *
7
+ * Two consumers hand us the same shape of input — a bag of closed 2D rings in
8
+ * the (x, z) plane with no promised winding and no promised order:
9
+ *
10
+ * - section cut caps (`buildCapFillGeometry`), where the rings are a cut
11
+ * polygon's outer boundary plus the openings/voids the plane sliced
12
+ * through;
13
+ * - `IfcAnnotationFillArea` (`SymbolicFillPipeline`), where the rings are the
14
+ * annotation's outer bound plus its inner bounds.
15
+ *
16
+ * Both used to assume "ring 0 is the outer boundary, everything else is a hole"
17
+ * and then bridge the holes in and ear-clip. That produced a *near-empty* cap
18
+ * wherever a profile had a hole: the bridge duplicates two vertices, and the
19
+ * old ear test treated any vertex lying ON a candidate ear (including those
20
+ * duplicates) as obstructing it, so almost no ear was ever clipped. A 4x4
21
+ * square with a 2x2 hole came out at area 2 instead of 12.
22
+ *
23
+ * The fix here is deliberately NOT "reverse the hole's winding" — with the
24
+ * hole merely added rather than subtracted the same case comes out at 20. What
25
+ * is actually needed is the even-odd rule:
26
+ *
27
+ * 1. Nest the rings: a ring's depth is the number of other rings that
28
+ * contain it. Even depth = filled boundary, odd depth = hole. That is what
29
+ * makes a hole-inside-a-hole (an island) come back as solid rather than as
30
+ * another void.
31
+ * 2. Group each even-depth ring with its immediate children.
32
+ * 3. Bridge each group's holes into its boundary and ear-clip, with an ear
33
+ * test that (a) only lets REFLEX vertices obstruct an ear and (b) ignores
34
+ * vertices coincident with the ear's own corners, which is exactly the
35
+ * bridge duplicate that used to deadlock the clipper.
36
+ *
37
+ * Everything is O(n²) in the ring's vertex count, which is fine: fill regions
38
+ * and cut cross-sections are tens of vertices, not thousands.
39
+ */
40
+ import { chooseBridgeAnchor } from './fill-bridge-anchor.js';
41
+ import { orient, pointOnSegment, ringScale, samePoint, } from './fill-predicates.js';
42
+ /**
43
+ * Shoelace area of a ring in the (x, z) plane. Positive = counter-clockwise.
44
+ * Winding normalisation is built on this, and tests use it to state the
45
+ * analytic area a ring set must triangulate to.
46
+ */
47
+ export function signedRingArea(ring) {
48
+ let a = 0;
49
+ for (let i = 0; i < ring.length; i++) {
50
+ const p = ring[i];
51
+ const q = ring[(i + 1) % ring.length];
52
+ a += p.x * q.z - q.x * p.z;
53
+ }
54
+ return a / 2;
55
+ }
56
+ /** Crossing-number point-in-polygon. Points exactly on the ring are undefined
57
+ * here — callers screen those out with {@link pointOnRing} first. */
58
+ function pointInRing(p, ring) {
59
+ let inside = false;
60
+ for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
61
+ const a = ring[i];
62
+ const b = ring[j];
63
+ if (a.z > p.z !== b.z > p.z &&
64
+ p.x < ((b.x - a.x) * (p.z - a.z)) / (b.z - a.z) + a.x) {
65
+ inside = !inside;
66
+ }
67
+ }
68
+ return inside;
69
+ }
70
+ /** True when `p` lies on one of the ring's edges, endpoints included. */
71
+ function pointOnRing(p, ring) {
72
+ for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
73
+ if (pointOnSegment(p, ring[i], ring[j], true))
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+ /**
79
+ * True when `inner` sits inside `outer`. Well-formed IFC bounds never cross,
80
+ * so the first vertex of `inner` that is not ON `outer` settles it; shared
81
+ * vertices and shared edge stretches (a hole flush against the boundary) are
82
+ * skipped rather than decided.
83
+ */
84
+ function ringInsideRing(inner, outer) {
85
+ for (const p of inner) {
86
+ if (pointOnRing(p, outer))
87
+ continue;
88
+ return pointInRing(p, outer);
89
+ }
90
+ return false;
91
+ }
92
+ /**
93
+ * Sort a bag of rings into filled boundaries and their holes by the even-odd
94
+ * rule. Rings with fewer than 3 vertices are dropped.
95
+ *
96
+ * A ring nested at odd depth is a hole; at even depth it is filled — so an
97
+ * island inside a hole comes back as its own group rather than being counted
98
+ * as void. A ring at depth d+1 that is contained in a ring at depth d is
99
+ * necessarily its immediate child (every ring containing the child also
100
+ * contains the parent, so the counts can only differ by the parent itself),
101
+ * which is why no explicit tree is built.
102
+ */
103
+ export function groupRingsByNesting(rings) {
104
+ const usable = rings.filter((r) => r.length >= 3).map((r) => r.slice());
105
+ const depth = usable.map((r, i) => usable.reduce((d, other, j) => (j !== i && ringInsideRing(r, other) ? d + 1 : d), 0));
106
+ const groups = [];
107
+ for (let i = 0; i < usable.length; i++) {
108
+ if (depth[i] % 2 !== 0)
109
+ continue;
110
+ const holes = [];
111
+ for (let j = 0; j < usable.length; j++) {
112
+ if (j === i || depth[j] !== depth[i] + 1)
113
+ continue;
114
+ if (ringInsideRing(usable[j], usable[i]))
115
+ holes.push(usable[j]);
116
+ }
117
+ groups.push({ outer: usable[i], holes });
118
+ }
119
+ return groups;
120
+ }
121
+ function asCcw(ring) {
122
+ return signedRingArea(ring) >= 0 ? ring : ring.slice().reverse();
123
+ }
124
+ function asCw(ring) {
125
+ return signedRingArea(ring) <= 0 ? ring : ring.slice().reverse();
126
+ }
127
+ /**
128
+ * Stitch each hole into the outer ring with a single bridge edge so the result
129
+ * is one simple polygon ear-clipping can handle. Mirrors mapbox/earcut's
130
+ * `eliminateHoles` pass:
131
+ *
132
+ * 1. For each hole, pick its rightmost (max-x) vertex as the bridge start.
133
+ * 2. Sort holes by descending bridge-start x so outer holes go in first.
134
+ * 3. Pick the anchor on the boundary the bridge can actually reach without
135
+ * crossing anything — see `fill-bridge-anchor.ts`.
136
+ * 4. Splice the hole in at that anchor, closing both ends back to their
137
+ * starts to form a zero-area bridge edge.
138
+ *
139
+ * Windings are normalised here rather than assumed: the boundary is made CCW
140
+ * and every hole CW, so the merged ring's signed area stays consistent no
141
+ * matter how the caller's rings were wound.
142
+ */
143
+ export function joinHoles(outer, holes) {
144
+ if (holes.length === 0)
145
+ return outer;
146
+ const sorted = holes
147
+ // Same degenerate-ring rule the rest of the module uses. Without it a
148
+ // 1- or 2-point "hole" bridges in as a spur, which is silently wrong
149
+ // geometry rather than a dropped hole.
150
+ .filter((h) => h.length >= 3)
151
+ .map((h) => asCw(h))
152
+ .map((ring) => {
153
+ let bestI = 0;
154
+ for (let i = 1; i < ring.length; i++) {
155
+ if (ring[i].x > ring[bestI].x)
156
+ bestI = i;
157
+ }
158
+ return { ring, startIdx: bestI, startX: ring[bestI].x };
159
+ })
160
+ .sort((a, b) => b.startX - a.startX);
161
+ let result = asCcw(outer).slice();
162
+ for (const { ring, startIdx } of sorted) {
163
+ const bestIdx = chooseBridgeAnchor(result, ring, startIdx);
164
+ if (bestIdx < 0)
165
+ continue;
166
+ const rotated = [...ring.slice(startIdx), ...ring.slice(0, startIdx)];
167
+ result = [
168
+ ...result.slice(0, bestIdx + 1),
169
+ ...rotated,
170
+ rotated[0],
171
+ result[bestIdx],
172
+ ...result.slice(bestIdx + 1),
173
+ ];
174
+ }
175
+ return result;
176
+ }
177
+ function pointInTriangle(p, a, b, c) {
178
+ const s1 = (p.x - c.x) * (a.z - c.z) - (a.x - c.x) * (p.z - c.z);
179
+ const s2 = (p.x - a.x) * (b.z - a.z) - (b.x - a.x) * (p.z - a.z);
180
+ const s3 = (p.x - b.x) * (c.z - b.z) - (c.x - b.x) * (p.z - b.z);
181
+ const hasNeg = s1 < 0 || s2 < 0 || s3 < 0;
182
+ const hasPos = s1 > 0 || s2 > 0 || s3 > 0;
183
+ return !(hasNeg && hasPos);
184
+ }
185
+ /**
186
+ * Ear-clipping triangulation of a simple polygon (which may be a bridged
187
+ * polygon-with-holes). Returns triangles as index triples into `ring`.
188
+ *
189
+ * Two properties keep the bridged case from deadlocking, and both are the
190
+ * #2516 fix:
191
+ *
192
+ * - only a REFLEX vertex can obstruct an ear of a simple polygon, so convex
193
+ * vertices are not tested at all. Testing them made every vertex lying on
194
+ * an axis-aligned ear edge veto that ear;
195
+ * - a vertex coincident with one of the ear's own corners is skipped. That
196
+ * is precisely the duplicate the bridge introduces; the slit it belongs to
197
+ * has zero width, so it cannot cover any of the ear.
198
+ *
199
+ * When no ear can be found the clipper drops one zero-area (collinear or
200
+ * duplicated) vertex — which cannot change the covered region — and retries,
201
+ * rather than bailing out with most of the polygon untriangulated.
202
+ *
203
+ * If even that leaves no ear the loop stops and returns what it has, which is
204
+ * a PARTIAL fill. That is deliberate, and it is the least-bad option rather
205
+ * than an oversight:
206
+ *
207
+ * - it is not reachable for well-formed rings. Measured over 20 000 rotated
208
+ * multi-notch boundaries with a hole in a random solid column, 4 000
209
+ * axis-aligned ones and 2 000 concave stars with up to three concave
210
+ * holes: zero occurrences, zero area error. It fires on schema-illegal
211
+ * input, e.g. an inner bound that pokes outside its outer bound;
212
+ * - throwing would lose the whole cap upload over one bad profile;
213
+ * - falling back to a fan over the outer ring would reintroduce BOTH defects
214
+ * this module exists to remove — holes not subtracted, and inversion on
215
+ * concave cross-sections.
216
+ *
217
+ * What the partial output does NOT promise is that it only ever omits area:
218
+ * a self-intersecting ring triangulates to more than even-odd would fill,
219
+ * because ear clipping reads "inside" from the ring's normalised orientation
220
+ * rather than from crossing parity. What it does promise — and what a render
221
+ * thread needs — is that it returns in bounded time, emits only vertices it
222
+ * was given, and stays inside the input's own extent.
223
+ * `fill-triangulate.test.ts` pins those.
224
+ */
225
+ export function earClip(ring) {
226
+ const n = ring.length;
227
+ if (n < 3)
228
+ return [];
229
+ // No 3-vertex fast path: it returned the caller's index order unnormalised,
230
+ // so a clockwise TRIANGLE came back clockwise while a clockwise quad came
231
+ // back counter-clockwise. The winding-normalisation below costs nothing at
232
+ // n = 3 and makes every emitted triangle agree.
233
+ // Coordinate comparisons are measured against the ring's own extent, so the
234
+ // same ring triangulates identically whether it is stated in metres or in
235
+ // millimetres.
236
+ const scale = ringScale(ring);
237
+ // Walk the ring counter-clockwise so the ear test below has a fixed sign.
238
+ let area2 = 0;
239
+ for (let i = 0; i < n; i++) {
240
+ const a = ring[i];
241
+ const b = ring[(i + 1) % n];
242
+ area2 += a.x * b.z - b.x * a.z;
243
+ }
244
+ const indices = [];
245
+ for (let i = 0; i < n; i++)
246
+ indices.push(area2 > 0 ? i : n - 1 - i);
247
+ const triangles = [];
248
+ let safety = indices.length * indices.length;
249
+ while (indices.length > 3 && safety-- > 0) {
250
+ let found = false;
251
+ for (let i = 0; i < indices.length; i++) {
252
+ if (!isEar(ring, indices, i, scale))
253
+ continue;
254
+ const m = indices.length;
255
+ triangles.push([indices[(i + m - 1) % m], indices[i], indices[(i + 1) % m]]);
256
+ indices.splice(i, 1);
257
+ found = true;
258
+ break;
259
+ }
260
+ if (found)
261
+ continue;
262
+ const degenerate = findZeroAreaVertex(ring, indices);
263
+ if (degenerate < 0)
264
+ break; // see the note above on partial output
265
+ indices.splice(degenerate, 1);
266
+ }
267
+ if (indices.length === 3) {
268
+ triangles.push([indices[0], indices[1], indices[2]]);
269
+ }
270
+ return triangles;
271
+ }
272
+ function isEar(ring, indices, i, scale) {
273
+ const m = indices.length;
274
+ const ia = indices[(i + m - 1) % m];
275
+ const ib = indices[i];
276
+ const ic = indices[(i + 1) % m];
277
+ const a = ring[ia];
278
+ const b = ring[ib];
279
+ const c = ring[ic];
280
+ if (orient(a, b, c) <= 0)
281
+ return false; // reflex or degenerate corner
282
+ for (let j = 0; j < m; j++) {
283
+ const ij = indices[j];
284
+ if (ij === ia || ij === ib || ij === ic)
285
+ continue;
286
+ const p = ring[ij];
287
+ if (samePoint(p, a, scale) || samePoint(p, b, scale) || samePoint(p, c, scale))
288
+ continue;
289
+ const prev = ring[indices[(j + m - 1) % m]];
290
+ const next = ring[indices[(j + 1) % m]];
291
+ if (orient(prev, p, next) > 0)
292
+ continue; // strictly convex — cannot obstruct
293
+ if (pointInTriangle(p, a, b, c))
294
+ return false;
295
+ }
296
+ return true;
297
+ }
298
+ function findZeroAreaVertex(ring, indices) {
299
+ const m = indices.length;
300
+ for (let i = 0; i < m; i++) {
301
+ const a = ring[indices[(i + m - 1) % m]];
302
+ const b = ring[indices[i]];
303
+ const c = ring[indices[(i + 1) % m]];
304
+ if (orient(a, b, c) === 0)
305
+ return i;
306
+ }
307
+ return -1;
308
+ }
309
+ /**
310
+ * Triangulate a bag of rings under the even-odd rule. This is the single entry
311
+ * point both fill consumers call; see the module comment for why.
312
+ *
313
+ * A hole-free ring set takes the same path it always did — the ring is handed
314
+ * straight to {@link earClip} in its original vertex order — so profiles
315
+ * without holes are byte-identical to before #2516.
316
+ */
317
+ export function triangulateRings(rings) {
318
+ const points = [];
319
+ const triangles = [];
320
+ for (const group of groupRingsByNesting(rings)) {
321
+ const stitched = group.holes.length === 0 ? group.outer : joinHoles(group.outer, group.holes);
322
+ const tris = earClip(stitched);
323
+ if (tris.length === 0)
324
+ continue;
325
+ const base = points.length;
326
+ for (const p of stitched)
327
+ points.push(p);
328
+ for (const [a, b, c] of tris)
329
+ triangles.push([base + a, base + b, base + c]);
330
+ }
331
+ return { points, triangles };
332
+ }
333
+ //# sourceMappingURL=fill-triangulate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fill-triangulate.js","sourceRoot":"","sources":["../src/fill-triangulate.ts"],"names":[],"mappings":"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"}
package/dist/scene.d.ts CHANGED
@@ -89,6 +89,31 @@ export interface InstancedTemplateGPU {
89
89
  * can't vanish while the entity is the user's focus. */
90
90
  selectedCount: number;
91
91
  }
92
+ /**
93
+ * Pure helper: compute the exclusive end index of the next flushPending()
94
+ * append chunk, starting at `readIndex` and bounded by BOTH mesh count
95
+ * (`hardEnd`, computed by the caller) and index volume (`maxIndicesPerAppend`).
96
+ * Always takes at least one mesh past `readIndex` -- a single oversize mesh is
97
+ * split upstream by splitMeshForStreaming, so the volume cap never blocks the
98
+ * first mesh of a chunk.
99
+ *
100
+ * Non-finite-safe by construction: every non-finite `next` (a malformed mesh
101
+ * reporting NaN, +Infinity, or -Infinity for `indices.length`) closes the
102
+ * chunk explicitly instead of being folded into the running `chunkIndices`
103
+ * total. Only NaN would have made a naive cap check `chunkIndices + next >
104
+ * maxIndicesPerAppend` silently `false` forever (`NaN > cap` is always
105
+ * `false`); +Infinity actually made that same check fire immediately
106
+ * (`chunkIndices + Infinity > cap` is `true`), closing the chunk after a
107
+ * single oversize mesh instead of growing it unbounded. The current
108
+ * `!(chunkIndices + next <= maxIndicesPerAppend)` form below rejects both
109
+ * NaN and +Infinity explicitly rather than relying on that asymmetry.
110
+ * -Infinity needed a separate, explicit check: `-Infinity <= cap` is always
111
+ * `true`, so `!(... <= cap)` lets it straight through, and folding it into
112
+ * `chunkIndices` would poison the running total to -Infinity permanently,
113
+ * keeping the cap vacuous for every mesh after it, not just the malformed
114
+ * one.
115
+ */
116
+ export declare function computeFlushChunkEnd(getIndicesLength: (meshIndex: number) => number, readIndex: number, hardEnd: number, maxIndicesPerAppend: number): number;
92
117
  export declare class Scene {
93
118
  private meshes;
94
119
  private batchedMeshes;
@@ -1 +1 @@
1
- {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
package/dist/scene.js CHANGED
@@ -23,6 +23,55 @@ function destroyGpuResources(m) {
23
23
  }
24
24
  /** Shared empty result for getInstancedTemplates() when the instanced pass is hidden. */
25
25
  const EMPTY_INSTANCED_TEMPLATES = [];
26
+ /**
27
+ * Pure helper: compute the exclusive end index of the next flushPending()
28
+ * append chunk, starting at `readIndex` and bounded by BOTH mesh count
29
+ * (`hardEnd`, computed by the caller) and index volume (`maxIndicesPerAppend`).
30
+ * Always takes at least one mesh past `readIndex` -- a single oversize mesh is
31
+ * split upstream by splitMeshForStreaming, so the volume cap never blocks the
32
+ * first mesh of a chunk.
33
+ *
34
+ * Non-finite-safe by construction: every non-finite `next` (a malformed mesh
35
+ * reporting NaN, +Infinity, or -Infinity for `indices.length`) closes the
36
+ * chunk explicitly instead of being folded into the running `chunkIndices`
37
+ * total. Only NaN would have made a naive cap check `chunkIndices + next >
38
+ * maxIndicesPerAppend` silently `false` forever (`NaN > cap` is always
39
+ * `false`); +Infinity actually made that same check fire immediately
40
+ * (`chunkIndices + Infinity > cap` is `true`), closing the chunk after a
41
+ * single oversize mesh instead of growing it unbounded. The current
42
+ * `!(chunkIndices + next <= maxIndicesPerAppend)` form below rejects both
43
+ * NaN and +Infinity explicitly rather than relying on that asymmetry.
44
+ * -Infinity needed a separate, explicit check: `-Infinity <= cap` is always
45
+ * `true`, so `!(... <= cap)` lets it straight through, and folding it into
46
+ * `chunkIndices` would poison the running total to -Infinity permanently,
47
+ * keeping the cap vacuous for every mesh after it, not just the malformed
48
+ * one.
49
+ */
50
+ export function computeFlushChunkEnd(getIndicesLength, readIndex, hardEnd, maxIndicesPerAppend) {
51
+ let chunkEnd = readIndex;
52
+ let chunkIndices = 0;
53
+ while (chunkEnd < hardEnd) {
54
+ const next = getIndicesLength(chunkEnd);
55
+ if (!Number.isFinite(next)) {
56
+ // A malformed mesh reporting a non-finite indices.length (NaN, +/-Infinity)
57
+ // must close the chunk here rather than being folded into chunkIndices:
58
+ // `chunkIndices += -Infinity` would poison the running total to -Infinity
59
+ // permanently, making `!(chunkIndices + next <= maxIndicesPerAppend)`
60
+ // false forever and letting the volume cap never fire again for the
61
+ // rest of this chunk. Always take at least the first mesh past
62
+ // readIndex (same progress guarantee as the NaN case below).
63
+ if (chunkEnd === readIndex)
64
+ chunkEnd++;
65
+ break;
66
+ }
67
+ if (chunkEnd > readIndex && !(chunkIndices + next <= maxIndicesPerAppend)) {
68
+ break;
69
+ }
70
+ chunkIndices += next;
71
+ chunkEnd++;
72
+ }
73
+ return chunkEnd;
74
+ }
26
75
  export class Scene {
27
76
  meshes = [];
28
77
  batchedMeshes = []; // flat render array (rebuilt from buckets)
@@ -1637,18 +1686,26 @@ export class Scene {
1637
1686
  break;
1638
1687
  }
1639
1688
  const hardEnd = Math.min(this.meshQueue.length, this.meshQueueReadIndex + MESHES_PER_APPEND, this.meshQueueReadIndex + (MAX_MESHES_PER_FLUSH - processed));
1640
- let chunkEnd = this.meshQueueReadIndex;
1641
- let chunkIndices = 0;
1642
- while (chunkEnd < hardEnd) {
1643
- const next = this.meshQueue[chunkEnd].indices.length;
1644
- // Always take at least one mesh (a single oversize mesh is split upstream
1645
- // by splitMeshForStreaming); otherwise stop before exceeding the cap.
1646
- if (chunkEnd > this.meshQueueReadIndex && chunkIndices + next > MAX_INDICES_PER_APPEND) {
1647
- break;
1648
- }
1649
- chunkIndices += next;
1650
- chunkEnd++;
1651
- }
1689
+ const chunkEnd = computeFlushChunkEnd((i) => this.meshQueue[i].indices.length, this.meshQueueReadIndex, hardEnd, MAX_INDICES_PER_APPEND);
1690
+ // Defensive, not reachable today: chunkEnd is provably > meshQueueReadIndex
1691
+ // here because hardEnd is provably > meshQueueReadIndex whenever this outer
1692
+ // loop iterates, via three invariants that hold simultaneously above:
1693
+ // (1) this.meshQueue.length > this.meshQueueReadIndex -- the outer while
1694
+ // condition that got us into this iteration;
1695
+ // (2) this.meshQueueReadIndex + MESHES_PER_APPEND, and MESHES_PER_APPEND
1696
+ // (512) is a positive constant;
1697
+ // (3) this.meshQueueReadIndex + (MAX_MESHES_PER_FLUSH - processed), and
1698
+ // processed < MAX_MESHES_PER_FLUSH -- the other half of the outer
1699
+ // while condition -- so that term is >= readIndex + 1 too.
1700
+ // hardEnd is the min of all three, so hardEnd >= readIndex + 1, and
1701
+ // computeFlushChunkEnd always advances by at least one past readIndex.
1702
+ // If a future change breaks any one of those three invariants, hardEnd
1703
+ // could collapse to readIndex and the loop would spin the main thread at
1704
+ // 100% CPU doing zero allocation -- the exact signature that made #2379
1705
+ // expensive to diagnose. This break turns that failure mode into "flush
1706
+ // stops early" instead.
1707
+ if (chunkEnd === this.meshQueueReadIndex)
1708
+ break;
1652
1709
  const chunk = this.meshQueue.slice(this.meshQueueReadIndex, chunkEnd);
1653
1710
  this.meshQueueReadIndex = chunkEnd;
1654
1711
  this.appendToBatches(chunk, device, pipeline, true);