minidraco 0.7.0 → 0.8.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.
package/dist/three.js CHANGED
@@ -45,72 +45,72 @@ var Type = {
45
45
  };
46
46
  var GeometryAttribute = class {
47
47
  d = null;
48
- z = 1;
49
- P = 9 /* FLOAT32 */;
50
- _a = false;
51
- Q = 0;
52
- R = 0;
53
- Ja = Type.INVALID;
54
- Ka = 0;
48
+ y = 1;
49
+ S = 9 /* FLOAT32 */;
50
+ Za = false;
51
+ T = 0;
52
+ U = 0;
53
+ Ia = Type.INVALID;
54
+ Ja = 0;
55
55
  init(attributeType, buffer, numComponents, dataType, normalized, byteStride, byteOffset) {
56
56
  this.d = buffer;
57
- this.z = numComponents;
58
- this.P = dataType;
59
- this._a = normalized;
60
- this.Q = byteStride;
61
- this.R = byteOffset;
62
- this.Ja = attributeType;
57
+ this.y = numComponents;
58
+ this.S = dataType;
59
+ this.Za = normalized;
60
+ this.T = byteStride;
61
+ this.U = byteOffset;
62
+ this.Ia = attributeType;
63
63
  }
64
64
  resetBuffer(buffer, byteStride, byteOffset) {
65
65
  this.d = buffer;
66
- this.Q = byteStride;
67
- this.R = byteOffset;
66
+ this.T = byteStride;
67
+ this.U = byteOffset;
68
68
  }
69
69
  get attributeType() {
70
- return this.Ja;
70
+ return this.Ia;
71
71
  }
72
72
  get dataType() {
73
- return this.P;
73
+ return this.S;
74
74
  }
75
75
  get numComponents() {
76
- return this.z;
76
+ return this.y;
77
77
  }
78
78
  get buffer() {
79
79
  return this.d;
80
80
  }
81
81
  get byteStride() {
82
- return this.Q;
82
+ return this.T;
83
83
  }
84
84
  get byteOffset() {
85
- return this.R;
85
+ return this.U;
86
86
  }
87
87
  get uniqueId() {
88
- return this.Ka;
88
+ return this.Ja;
89
89
  }
90
90
  set uniqueId(id) {
91
- this.Ka = id;
91
+ this.Ja = id;
92
92
  }
93
93
  };
94
94
 
95
95
  // src/decoder/point_cloud/PointCloud.ts
96
96
  var NAMED_ATTRIBUTES_COUNT = 8;
97
97
  var PointCloud = class {
98
- wb = 0;
98
+ ub = 0;
99
99
  attributes_ = [];
100
100
  // named_attribute_index_[type] = [att_id, ...], one list per named type.
101
- $a = [[], [], [], [], [], [], [], []];
101
+ _a = [[], [], [], [], [], [], [], []];
102
102
  numNamedAttributes(type) {
103
103
  if (type < 0 || type >= NAMED_ATTRIBUTES_COUNT) {
104
104
  return 0;
105
105
  }
106
- return this.$a[type].length;
106
+ return this._a[type].length;
107
107
  }
108
108
  getNamedAttributeId(type, i) {
109
109
  if (i === void 0) i = 0;
110
110
  if (this.numNamedAttributes(type) <= i) {
111
111
  return -1;
112
112
  }
113
- return this.$a[type][i];
113
+ return this._a[type][i];
114
114
  }
115
115
  getNamedAttribute(type, i) {
116
116
  if (i === void 0) i = 0;
@@ -150,16 +150,16 @@ var PointCloud = class {
150
150
  this.attributes_.push(null);
151
151
  }
152
152
  if (pa.attributeType < NAMED_ATTRIBUTES_COUNT) {
153
- this.$a[pa.attributeType].push(attId);
153
+ this._a[pa.attributeType].push(attId);
154
154
  }
155
155
  pa.uniqueId = attId;
156
156
  this.attributes_[attId] = pa;
157
157
  }
158
158
  numPoints() {
159
- return this.wb;
159
+ return this.ub;
160
160
  }
161
161
  setNumPoints(num) {
162
- this.wb = num;
162
+ this.ub = num;
163
163
  }
164
164
  };
165
165
 
@@ -169,7 +169,7 @@ var Mesh = class extends PointCloud {
169
169
  // a per-face allocation. faces_[3*f + c] is corner c of face f; corner index
170
170
  // ci maps directly to faces_[ci].
171
171
  faces_ = new Int32Array(0);
172
- xb = 0;
172
+ vb = 0;
173
173
  // Sizes faces_ to hold numFaces faces. Called once per decode, before any
174
174
  // face index is written (edgebreaker: _assignPointsToCorners; sequential:
175
175
  // decodeConnectivity), so the buffer is allocated exactly here — the
@@ -181,42 +181,42 @@ var Mesh = class extends PointCloud {
181
181
  grown.set(this.faces_);
182
182
  this.faces_ = grown;
183
183
  }
184
- this.xb = numFaces;
184
+ this.vb = numFaces;
185
185
  }
186
186
  numFaces() {
187
- return this.xb;
187
+ return this.vb;
188
188
  }
189
189
  };
190
190
 
191
191
  // src/decoder/core/DataBuffer.ts
192
192
  var DataBuffer = class {
193
- p = new Uint8Array(0);
193
+ o = new Uint8Array(0);
194
194
  // Resizes to `size` bytes (contents preserved); when `data` is given, grows
195
195
  // as needed and copies its first `size` bytes in.
196
196
  update(data, size) {
197
197
  if (data === null) {
198
- this.yb(size);
198
+ this.wb(size);
199
199
  return;
200
200
  }
201
- if (size > this.p.length) {
202
- this.yb(size);
201
+ if (size > this.o.length) {
202
+ this.wb(size);
203
203
  }
204
- this.p.set(data.length === size ? data : data.subarray(0, size));
204
+ this.o.set(data.length === size ? data : data.subarray(0, size));
205
205
  }
206
206
  // The caller passes a Uint8Array of exactly dataSize bytes in the common
207
207
  // case; avoid allocating a wrapper view per value (dominates storage time /
208
208
  // GC pressure).
209
209
  write(bytePos, inArray, dataSize) {
210
- this.p.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
210
+ this.o.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
211
211
  }
212
212
  get data() {
213
- return this.p;
213
+ return this.o;
214
214
  }
215
- yb(newSize) {
216
- if (newSize === this.p.length) return;
215
+ wb(newSize) {
216
+ if (newSize === this.o.length) return;
217
217
  const newData = new Uint8Array(newSize);
218
- newData.set(this.p.subarray(0, Math.min(this.p.length, newSize)));
219
- this.p = newData;
218
+ newData.set(this.o.subarray(0, Math.min(this.o.length, newSize)));
219
+ this.o = newData;
220
220
  }
221
221
  };
222
222
 
@@ -329,112 +329,117 @@ var LAZY_INTEGER = 1;
329
329
  var LAZY_QUANTIZED = 2;
330
330
  var LAZY_OCTAHEDRON = 3;
331
331
  var PointAttribute = class extends GeometryAttribute {
332
- E = false;
333
- ab = 0;
334
- F = [];
335
- $ = null;
332
+ D = false;
333
+ $a = 0;
334
+ E = [];
335
+ ca = null;
336
336
  // Lazily-created cached typed-array view over the attribute buffer, keyed
337
337
  // on (constructor, underlying ArrayBuffer). An attribute only ever reads
338
338
  // through the one view type its data type dictates.
339
+ xb = null;
340
+ yb = null;
339
341
  zb = null;
340
- Ab = null;
341
- Bb = null;
342
342
  // Deferred inverse transform. The integer attribute decoders leave their
343
343
  // decoded values here as int32 -- quantized floats, octahedral normals or
344
344
  // plain integers -- with the transform's parameters, and extractTo applies
345
345
  // the transform while gathering the values into point order: one pass over
346
346
  // the points instead of an inverse-transform pass into a per-value buffer
347
347
  // followed by a gather from it, and no such buffer at all.
348
- La = LAZY_NONE;
349
- aa = null;
350
- Cb = [];
351
- Ma = 0;
348
+ Ka = LAZY_NONE;
349
+ da = null;
350
+ Ab = [];
351
+ La = 0;
352
+ // Set when the decoder knows every lazy value is below 2^24 in magnitude
353
+ // (see _lazyFloatValues); the extraction then skips its scan.
354
+ ab = false;
352
355
  constructor(geometryAttribute) {
353
356
  super();
354
357
  if (geometryAttribute instanceof GeometryAttribute) {
355
358
  this.d = geometryAttribute.d;
356
- this.z = geometryAttribute.z;
357
- this.P = geometryAttribute.P;
358
- this._a = geometryAttribute._a;
359
- this.Q = geometryAttribute.Q;
360
- this.R = geometryAttribute.R;
359
+ this.y = geometryAttribute.y;
360
+ this.S = geometryAttribute.S;
361
+ this.Za = geometryAttribute.Za;
362
+ this.T = geometryAttribute.T;
363
+ this.U = geometryAttribute.U;
364
+ this.Ia = geometryAttribute.Ia;
361
365
  this.Ja = geometryAttribute.Ja;
362
- this.Ka = geometryAttribute.Ka;
363
366
  }
364
367
  }
365
368
  // Intentionally shadows GeometryAttribute.init with a different signature (matches draco.js / C++ source).
366
369
  // @ts-expect-error -- signature intentionally differs from the base class, as in the source.
367
370
  init(attributeType, numComponents, dataType, normalized, numAttributeValues) {
368
- this.$ = new DataBuffer();
371
+ this.ca = new DataBuffer();
369
372
  const byteStride = dataTypeLength(dataType) * numComponents;
370
- super.init(attributeType, this.$, numComponents, dataType, normalized, byteStride, 0);
373
+ super.init(attributeType, this.ca, numComponents, dataType, normalized, byteStride, 0);
371
374
  this.reset(numAttributeValues);
372
375
  this.setIdentityMapping();
373
376
  }
374
377
  reset(numAttributeValues) {
375
- if (this.$ === null) {
376
- this.$ = new DataBuffer();
378
+ if (this.ca === null) {
379
+ this.ca = new DataBuffer();
377
380
  }
378
381
  const entrySize = dataTypeLength(this.dataType) * this.numComponents;
379
- this.$.update(null, numAttributeValues * entrySize);
380
- this.resetBuffer(this.$, entrySize, 0);
381
- this.ab = numAttributeValues;
382
+ this.ca.update(null, numAttributeValues * entrySize);
383
+ this.resetBuffer(this.ca, entrySize, 0);
384
+ this.$a = numAttributeValues;
382
385
  return true;
383
386
  }
384
387
  // Sizes the attribute without allocating storage, for the deferred
385
388
  // transforms below (the values live in the decoder's portable attribute).
386
389
  resetLazy(numAttributeValues) {
387
- this.ab = numAttributeValues;
390
+ this.$a = numAttributeValues;
388
391
  }
389
392
  // numValues decoded integers of the attribute's own integer type, stored as
390
393
  // int32; extractTo converts them to the requested output type.
391
394
  setLazyInteger(values) {
392
- this.La = LAZY_INTEGER;
393
- this.aa = values;
395
+ this.Ka = LAZY_INTEGER;
396
+ this.da = values;
394
397
  }
395
398
  // Quantized float values: value * delta + min per component (float32
396
399
  // arithmetic, see _extractQuantized), as the C++ Dequantizer computes them.
397
- setLazyQuantized(values, minValues, delta) {
398
- this.La = LAZY_QUANTIZED;
399
- this.aa = values;
400
- this.Cb = minValues;
401
- this.Ma = delta;
400
+ setLazyQuantized(values, minValues, delta, bounded) {
401
+ this.Ka = LAZY_QUANTIZED;
402
+ this.da = values;
403
+ this.Ab = minValues;
404
+ this.La = delta;
405
+ this.ab = bounded;
402
406
  }
403
407
  // Octahedral normals: two quantized coordinates per value, dequantized by
404
408
  // `scale` and turned into unit vectors (see _extractOctahedron).
405
- setLazyOctahedron(values, scale) {
406
- this.La = LAZY_OCTAHEDRON;
407
- this.aa = values;
408
- this.Ma = scale;
409
+ setLazyOctahedron(values, scale, bounded) {
410
+ this.Ka = LAZY_OCTAHEDRON;
411
+ this.da = values;
412
+ this.La = scale;
413
+ this.ab = bounded;
409
414
  }
410
415
  get size() {
411
- return this.ab;
416
+ return this.$a;
412
417
  }
413
418
  mappedIndex(pointIndex) {
414
- if (this.E) {
419
+ if (this.D) {
415
420
  return pointIndex;
416
421
  }
417
- return this.F[pointIndex];
422
+ return this.E[pointIndex];
418
423
  }
419
424
  get isMappingIdentity() {
420
- return this.E;
425
+ return this.D;
421
426
  }
422
427
  get indicesMapSize() {
423
- if (this.E) {
428
+ if (this.D) {
424
429
  return 0;
425
430
  }
426
- return this.F.length;
431
+ return this.E.length;
427
432
  }
428
433
  // Direct access to the explicit point->value index map (a Uint32Array after
429
434
  // any of the setExplicitMapping* calls). Lets hot mapping loops write
430
435
  // entries without a per-entry dispatch.
431
436
  get indicesMap() {
432
- return this.F;
437
+ return this.E;
433
438
  }
434
439
  // Implicit mapping: point index equals attribute entry index.
435
440
  setIdentityMapping() {
436
- this.E = true;
437
- this.F = [];
441
+ this.D = true;
442
+ this.E = [];
438
443
  }
439
444
  // Explicit mapping without an invalid-index fill. Only for callers that
440
445
  // provably write every entry right away (the fill was ~4% of decode time on
@@ -444,31 +449,31 @@ var PointAttribute = class extends GeometryAttribute {
444
449
  // and avoids boxed-number storage; it is read once per point per attribute.
445
450
  // Must be UNSIGNED so the 0xFFFFFFFF invalid sentinel round-trips intact.
446
451
  setExplicitMappingUnfilled(numPoints) {
447
- this.E = false;
448
- this.F = new Uint32Array(numPoints);
452
+ this.D = false;
453
+ this.E = new Uint32Array(numPoints);
449
454
  }
450
455
  // Adopts an already-computed map, shared with other attributes of the same
451
456
  // mesh. The map must be treated as read-only from here on (reads go through
452
457
  // mappedIndex/extractTo).
453
458
  setExplicitMappingShared(map) {
454
- this.E = false;
455
- this.F = map;
459
+ this.D = false;
460
+ this.E = map;
456
461
  }
457
462
  // Like setExplicitMappingUnfilled, but from decode-scoped scratch. Only for
458
463
  // attributes that never escape the decode (see ScratchArena) -- the portable
459
464
  // attributes the sequential decoders build and discard.
460
465
  setExplicitMappingScratch(numPoints) {
461
- this.E = false;
462
- this.F = scratchUint32(numPoints);
466
+ this.D = false;
467
+ this.E = scratchUint32(numPoints);
463
468
  }
464
469
  // Cached typed-array view of the given type over the attribute buffer.
465
- Db(Ctor, bufData) {
466
- if (this.zb !== Ctor || this.Ab !== bufData.buffer) {
467
- this.zb = Ctor;
468
- this.Ab = bufData.buffer;
469
- this.Bb = new Ctor(bufData.buffer);
470
+ Bb(Ctor, bufData) {
471
+ if (this.xb !== Ctor || this.yb !== bufData.buffer) {
472
+ this.xb = Ctor;
473
+ this.yb = bufData.buffer;
474
+ this.zb = new Ctor(bufData.buffer);
470
475
  }
471
- return this.Bb;
476
+ return this.zb;
472
477
  }
473
478
  // Mirrors C++ PointAttribute::ConvertValue<T>() for buffer-backed
474
479
  // attributes. Attribute buffers start at byteOffset 0 and entries are
@@ -476,44 +481,44 @@ var PointAttribute = class extends GeometryAttribute {
476
481
  // of a per-component DataView dispatch.
477
482
  convertValue(attIndex, outVal) {
478
483
  const bufData = this.d.data;
479
- const nc = this.z;
480
- const Ctor = viewCtorFor(this.P);
484
+ const nc = this.y;
485
+ const Ctor = viewCtorFor(this.S);
481
486
  if (Ctor === null) {
482
487
  for (let i = 0; i < nc; ++i) outVal[i] = 0;
483
488
  return;
484
489
  }
485
- const view = this.Db(Ctor, bufData);
486
- const baseIndex = (bufData.byteOffset + this.R + this.Q * attIndex) / Ctor.BYTES_PER_ELEMENT;
490
+ const view = this.Bb(Ctor, bufData);
491
+ const baseIndex = (bufData.byteOffset + this.U + this.T * attIndex) / Ctor.BYTES_PER_ELEMENT;
487
492
  for (let i = 0; i < nc; ++i) outVal[i] = view[baseIndex + i];
488
493
  }
489
494
  // Flat-array extraction of all values into one output typed array, in point
490
495
  // order (applying the deferred transform, if any, on the way).
491
496
  extractTo(OutputTypedArray, numPoints) {
492
- const numComponents = this.z;
497
+ const numComponents = this.y;
493
498
  const array = new OutputTypedArray(numPoints * numComponents);
494
499
  if (numPoints === 0) {
495
500
  return array;
496
501
  }
497
- const kind = this.La;
502
+ const kind = this.Ka;
498
503
  if (kind !== LAZY_NONE) {
499
- if (this.aa !== null) {
500
- if (kind === LAZY_QUANTIZED) this.gc(array, numPoints);
501
- else if (kind === LAZY_OCTAHEDRON) this.hc(array, numPoints);
502
- else this.ic(array, numPoints);
504
+ if (this.da !== null) {
505
+ if (kind === LAZY_QUANTIZED) this.ec(array, numPoints);
506
+ else if (kind === LAZY_OCTAHEDRON) this.fc(array, numPoints);
507
+ else this.gc(array, numPoints);
503
508
  }
504
509
  return array;
505
510
  }
506
- const Ctor = viewCtorFor(this.P);
511
+ const Ctor = viewCtorFor(this.S);
507
512
  if (this.d === null || Ctor === null) {
508
513
  return array;
509
514
  }
510
515
  const bufData = this.d.data;
511
- const isIdentity = this.E;
512
- const indicesMap = this.F;
513
- const srcView = this.Db(Ctor, bufData);
516
+ const isIdentity = this.D;
517
+ const indicesMap = this.E;
518
+ const srcView = this.Bb(Ctor, bufData);
514
519
  const shift = 31 - Math.clz32(Ctor.BYTES_PER_ELEMENT);
515
- const srcStart = bufData.byteOffset + this.R >> shift;
516
- const strideElements = this.Q >> shift;
520
+ const srcStart = bufData.byteOffset + this.U >> shift;
521
+ const strideElements = this.T >> shift;
517
522
  if (isIdentity && strideElements === numComponents) {
518
523
  const srcEnd = srcStart + numPoints * numComponents;
519
524
  if (srcView.constructor === OutputTypedArray) {
@@ -541,7 +546,7 @@ var PointAttribute = class extends GeometryAttribute {
541
546
  // Point -> value index; the identity mapping (sequential meshes) gets a
542
547
  // plain iota so the loops carry no per-point branch.
543
548
  bb(numPoints) {
544
- if (!this.E) return this.F;
549
+ if (!this.D) return this.E;
545
550
  const map = new Uint32Array(numPoints);
546
551
  for (let p = 0; p < numPoints; ++p) map[p] = p;
547
552
  return map;
@@ -552,8 +557,11 @@ var PointAttribute = class extends GeometryAttribute {
552
557
  // without the (measurably costly) int-to-float32-to-double round trip per
553
558
  // component. Larger values (quantization above 24 bits, never seen in
554
559
  // practice) are rounded in place once here, after which the same holds.
555
- Eb() {
556
- const values = this.aa;
560
+ // The decoder marks the attribute bounded when its prediction transform
561
+ // already confines the values to that range, and the scan is skipped.
562
+ Cb() {
563
+ const values = this.da;
564
+ if (this.ab) return values;
557
565
  for (let i = 0; i < values.length; ++i) {
558
566
  if (values[i] >= 16777216 || values[i] <= -16777216) {
559
567
  for (let j = 0; j < values.length; ++j) values[j] = Math.fround(values[j]);
@@ -563,13 +571,13 @@ var PointAttribute = class extends GeometryAttribute {
563
571
  return values;
564
572
  }
565
573
  // C++ Dequantizer: float(value) * delta + min, all in float32.
566
- gc(out, numPoints) {
567
- const values = this.Eb();
574
+ ec(out, numPoints) {
575
+ const values = this.Cb();
568
576
  const map = this.bb(numPoints);
569
- const numComponents = this.z;
577
+ const numComponents = this.y;
570
578
  const fround = Math.fround;
571
- const delta = this.Ma;
572
- const min = this.Cb;
579
+ const delta = this.La;
580
+ const min = this.Ab;
573
581
  if (numComponents === 3) {
574
582
  const m0 = min[0];
575
583
  const m1 = min[1];
@@ -601,11 +609,11 @@ var PointAttribute = class extends GeometryAttribute {
601
609
  }
602
610
  // OctahedronToolBox.QuantizedOctahedralCoordsToUnitVector, two quantized
603
611
  // coordinates per value to one unit vector per point.
604
- hc(out, numPoints) {
605
- const values = this.Eb();
612
+ fc(out, numPoints) {
613
+ const values = this.Cb();
606
614
  const map = this.bb(numPoints);
607
615
  const fround = Math.fround;
608
- const scale = this.Ma;
616
+ const scale = this.La;
609
617
  for (let p = 0, d = 0; p < numPoints; ++p, d += 3) {
610
618
  const s = map[p] * 2;
611
619
  let y = fround(fround(values[s] * scale) - 1);
@@ -630,11 +638,11 @@ var PointAttribute = class extends GeometryAttribute {
630
638
  }
631
639
  // The int32 values wrap to the attribute's own integer type (as storing
632
640
  // them into it would) before the output store converts them.
633
- ic(out, numPoints) {
634
- const values = this.aa;
641
+ gc(out, numPoints) {
642
+ const values = this.da;
635
643
  const map = this.bb(numPoints);
636
- const numComponents = this.z;
637
- const dt = this.P;
644
+ const numComponents = this.y;
645
+ const dt = this.S;
638
646
  const shift = 32 - 8 * dataTypeLength(dt);
639
647
  const signed = dt === 1 /* INT8 */ || dt === 3 /* INT16 */ || dt === 5 /* INT32 */;
640
648
  for (let p = 0, d = 0; p < numPoints; ++p) {
@@ -666,21 +674,21 @@ function decodeVarint(buffer) {
666
674
 
667
675
  // src/decoder/core/DecoderBuffer.ts
668
676
  var BitDecoder = class {
669
- Na = null;
670
- q = 0;
671
- ra = 0;
677
+ Ma = null;
678
+ s = 0;
679
+ qa = 0;
672
680
  reset(uint8Array, byteLength) {
673
- this.Na = uint8Array;
674
- this.ra = byteLength;
675
- this.q = 0;
681
+ this.Ma = uint8Array;
682
+ this.qa = byteLength;
683
+ this.s = 0;
676
684
  }
677
685
  getBits(nbits) {
678
686
  if (nbits > 32) return void 0;
679
- const buf = this.Na;
680
- let off = this.q;
687
+ const buf = this.Ma;
688
+ let off = this.s;
681
689
  const byteOffset = off >> 3;
682
690
  const bitShift = off & 7;
683
- if (byteOffset + 4 < this.ra) {
691
+ if (byteOffset + 4 < this.qa) {
684
692
  const val = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> 0;
685
693
  let result;
686
694
  if (nbits > 32 - bitShift) {
@@ -691,7 +699,7 @@ var BitDecoder = class {
691
699
  } else {
692
700
  result = val >>> bitShift;
693
701
  }
694
- this.q = off + nbits;
702
+ this.s = off + nbits;
695
703
  return nbits === 32 ? result : result & (1 << nbits) - 1;
696
704
  }
697
705
  let value = 0;
@@ -699,7 +707,7 @@ var BitDecoder = class {
699
707
  let currOff = off;
700
708
  while (bitsRead < nbits) {
701
709
  const bOff = currOff >> 3;
702
- if (bOff >= this.ra) return void 0;
710
+ if (bOff >= this.qa) return void 0;
703
711
  const bShift = currOff & 7;
704
712
  const bitsAvail = 8 - bShift;
705
713
  const bitsNeeded = nbits - bitsRead;
@@ -709,53 +717,53 @@ var BitDecoder = class {
709
717
  bitsRead += bitsToRead;
710
718
  currOff += bitsToRead;
711
719
  }
712
- this.q = currOff;
720
+ this.s = currOff;
713
721
  return value;
714
722
  }
715
723
  };
716
724
  var DecoderBuffer = class {
717
- p = null;
718
- Oa = null;
719
- M = 0;
725
+ o = null;
726
+ Na = null;
727
+ O = 0;
720
728
  e = 0;
721
- sa = new BitDecoder();
722
- Pa = false;
729
+ ra = new BitDecoder();
730
+ Oa = false;
723
731
  init(data, dataSize = data.length) {
724
- this.p = data;
725
- this.Oa = new DataView(data.buffer, data.byteOffset, data.byteLength);
726
- this.M = dataSize;
732
+ this.o = data;
733
+ this.Na = new DataView(data.buffer, data.byteOffset, data.byteLength);
734
+ this.O = dataSize;
727
735
  this.e = 0;
728
736
  }
729
737
  // Typed little-endian reads.
730
738
  decodeUint8() {
731
- if (this.e + 1 > this.M) return void 0;
732
- const val = this.p[this.e];
739
+ if (this.e + 1 > this.O) return void 0;
740
+ const val = this.o[this.e];
733
741
  this.e += 1;
734
742
  return val;
735
743
  }
736
744
  decodeUint16() {
737
- if (this.e + 2 > this.M) return void 0;
738
- const val = this.Oa.getUint16(this.e, true);
745
+ if (this.e + 2 > this.O) return void 0;
746
+ const val = this.Na.getUint16(this.e, true);
739
747
  this.e += 2;
740
748
  return val;
741
749
  }
742
750
  decodeInt32() {
743
- if (this.e + 4 > this.M) return void 0;
744
- const val = this.Oa.getInt32(this.e, true);
751
+ if (this.e + 4 > this.O) return void 0;
752
+ const val = this.Na.getInt32(this.e, true);
745
753
  this.e += 4;
746
754
  return val;
747
755
  }
748
756
  decodeFloat32() {
749
- if (this.e + 4 > this.M) return void 0;
750
- const val = this.Oa.getFloat32(this.e, true);
757
+ if (this.e + 4 > this.O) return void 0;
758
+ const val = this.Na.getFloat32(this.e, true);
751
759
  this.e += 4;
752
760
  return val;
753
761
  }
754
762
  // A view into the stream (no copy), only valid until the caller's next
755
763
  // chance to mutate the buffer — copy out before keeping it.
756
764
  decodeBytesView(size) {
757
- if (this.e + size > this.M) return void 0;
758
- const result = this.p.subarray(this.e, this.e + size);
765
+ if (this.e + size > this.O) return void 0;
766
+ const result = this.o.subarray(this.e, this.e + size);
759
767
  this.e += size;
760
768
  return result;
761
769
  }
@@ -768,35 +776,35 @@ var DecoderBuffer = class {
768
776
  if (size === void 0) return void 0;
769
777
  outSize = size;
770
778
  }
771
- this.Pa = true;
772
- this.sa.reset(this.p.subarray(this.e), this.M - this.e);
779
+ this.Oa = true;
780
+ this.ra.reset(this.o.subarray(this.e), this.O - this.e);
773
781
  return outSize;
774
782
  }
775
783
  endBitDecoding() {
776
- this.Pa = false;
777
- this.e += Math.ceil(this.sa.q / 8);
784
+ this.Oa = false;
785
+ this.e += Math.ceil(this.ra.s / 8);
778
786
  }
779
787
  decodeLeastSignificantBits32(nbits) {
780
- if (!this.Pa) return void 0;
781
- return this.sa.getBits(nbits);
788
+ if (!this.Oa) return void 0;
789
+ return this.ra.getBits(nbits);
782
790
  }
783
791
  advance(bytes) {
784
792
  this.e += bytes;
785
793
  }
786
794
  get data() {
787
- return this.p;
795
+ return this.o;
788
796
  }
789
797
  get dataHead() {
790
- return this.p.subarray(this.e);
798
+ return this.o.subarray(this.e);
791
799
  }
792
800
  get remainingSize() {
793
- return this.M - this.e;
801
+ return this.O - this.e;
794
802
  }
795
803
  get decodedSize() {
796
804
  return this.e;
797
805
  }
798
806
  get bitDecoderActive() {
799
- return this.Pa;
807
+ return this.Oa;
800
808
  }
801
809
  };
802
810
 
@@ -814,17 +822,17 @@ var METADATA_FLAG_MASK = 32768;
814
822
  var kMaxSubmetadataLevel = 1e3;
815
823
  var MetadataDecoder = class {
816
824
  constructor(buffer_) {
817
- this.G = buffer_;
825
+ this.F = buffer_;
818
826
  }
819
827
  buffer_;
820
828
  // Skips per-attribute metadata followed by the geometry-level metadata.
821
829
  skipGeometryMetadata() {
822
- const numAttMetadata = decodeVarint(this.G);
830
+ const numAttMetadata = decodeVarint(this.F);
823
831
  if (numAttMetadata === void 0) {
824
832
  return false;
825
833
  }
826
834
  for (let i = 0; i < numAttMetadata; ++i) {
827
- if (decodeVarint(this.G) === void 0) {
835
+ if (decodeVarint(this.F) === void 0) {
828
836
  return false;
829
837
  }
830
838
  if (!this.cb(0)) {
@@ -839,41 +847,41 @@ var MetadataDecoder = class {
839
847
  if (level > kMaxSubmetadataLevel) {
840
848
  return false;
841
849
  }
842
- const numEntries = decodeVarint(this.G);
850
+ const numEntries = decodeVarint(this.F);
843
851
  if (numEntries === void 0) {
844
852
  return false;
845
853
  }
846
854
  for (let i = 0; i < numEntries; ++i) {
847
- const nameSkipped = this.Fb();
848
- const dataSize = nameSkipped ? decodeVarint(this.G) : void 0;
849
- if (dataSize === void 0 || dataSize === 0 || !this.Gb(dataSize)) {
855
+ const nameSkipped = this.Db();
856
+ const dataSize = nameSkipped ? decodeVarint(this.F) : void 0;
857
+ if (dataSize === void 0 || dataSize === 0 || !this.Eb(dataSize)) {
850
858
  return false;
851
859
  }
852
860
  }
853
- const numSubMetadata = decodeVarint(this.G);
854
- if (numSubMetadata === void 0 || numSubMetadata > this.G.remainingSize) {
861
+ const numSubMetadata = decodeVarint(this.F);
862
+ if (numSubMetadata === void 0 || numSubMetadata > this.F.remainingSize) {
855
863
  return false;
856
864
  }
857
865
  for (let i = 0; i < numSubMetadata; ++i) {
858
- if (!this.Fb() || !this.cb(level + 1)) {
866
+ if (!this.Db() || !this.cb(level + 1)) {
859
867
  return false;
860
868
  }
861
869
  }
862
870
  return true;
863
871
  }
864
872
  // Skips a name (uint8 length prefix followed by that many bytes).
865
- Fb() {
866
- const nameLen = this.G.decodeUint8();
873
+ Db() {
874
+ const nameLen = this.F.decodeUint8();
867
875
  if (nameLen === void 0) {
868
876
  return false;
869
877
  }
870
- return this.Gb(nameLen);
878
+ return this.Eb(nameLen);
871
879
  }
872
- Gb(size) {
873
- if (size > this.G.remainingSize) {
880
+ Eb(size) {
881
+ if (size > this.F.remainingSize) {
874
882
  return false;
875
883
  }
876
- this.G.advance(size);
884
+ this.F.advance(size);
877
885
  return true;
878
886
  }
879
887
  };
@@ -1011,12 +1019,12 @@ var RAnsDecoder = class {
1011
1019
  // written back once. Removes per-symbol property reads and call indirection.
1012
1020
  decodeSymbols(out, count) {
1013
1021
  if (this.coarse) {
1014
- this.jc(out, count);
1022
+ this.hc(out, count);
1015
1023
  return;
1016
1024
  }
1017
- this.kc(out, count, this.lutTable);
1025
+ this.ic(out, count, this.lutTable);
1018
1026
  }
1019
- kc(out, count, lutTable) {
1027
+ ic(out, count, lutTable) {
1020
1028
  const buf = this.buf;
1021
1029
  const lRansBase = this.lRansBase;
1022
1030
  const ransPrecisionBits = this.ransPrecisionBits;
@@ -1040,7 +1048,7 @@ var RAnsDecoder = class {
1040
1048
  }
1041
1049
  // Short-stream loop: bucket table + cumProb scan instead of the full lut.
1042
1050
  // Same state arithmetic as the lut loops, so the output is identical.
1043
- jc(out, count) {
1051
+ hc(out, count) {
1044
1052
  const buf = this.buf;
1045
1053
  const lRansBase = this.lRansBase;
1046
1054
  const ransPrecisionBits = this.ransPrecisionBits;
@@ -1102,12 +1110,15 @@ var RAnsDecoder = class {
1102
1110
  return false;
1103
1111
  }
1104
1112
  cumProbTable[numSymbols] = ransPrecision;
1105
- const bucketShift = this.ransPrecisionBits - COARSE_BUCKET_BITS;
1106
- const bucketTable = numSymbols > 65536 ? acquirePooled(Uint32Array, 1 << COARSE_BUCKET_BITS) : acquirePooled(Uint16Array, 1 << COARSE_BUCKET_BITS);
1113
+ let bucketBits = 33 - Math.clz32(numSymbols);
1114
+ if (bucketBits > COARSE_BUCKET_BITS) bucketBits = COARSE_BUCKET_BITS;
1115
+ const numBuckets = 1 << bucketBits;
1116
+ const bucketShift = this.ransPrecisionBits - bucketBits;
1117
+ const bucketTable = numSymbols > 65536 ? acquirePooled(Uint32Array, numBuckets) : acquirePooled(Uint16Array, numBuckets);
1107
1118
  this.bucketShift = bucketShift;
1108
1119
  this.bucketTable = bucketTable;
1109
1120
  let symbol = 0;
1110
- for (let b = 0; b < 1 << COARSE_BUCKET_BITS; ++b) {
1121
+ for (let b = 0; b < numBuckets; ++b) {
1111
1122
  const rem = b << bucketShift;
1112
1123
  while (cumProbTable[symbol + 1] <= rem) symbol++;
1113
1124
  bucketTable[b] = symbol;
@@ -1141,12 +1152,36 @@ var RAnsDecoder = class {
1141
1152
  return true;
1142
1153
  }
1143
1154
  };
1144
- function ransDecodeSymbolsPair(a, outA, countA, b, outB, countB) {
1145
- if (!a.coarse && !b.coarse) {
1146
- ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB);
1147
- } else {
1148
- a.decodeSymbols(outA, countA);
1149
- b.decodeSymbols(outB, countB);
1155
+ function ransDecodeStreams(streams) {
1156
+ const live = [];
1157
+ for (const stream of streams) {
1158
+ if (stream.count === 0) continue;
1159
+ if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
1160
+ else live.push({ ans: stream.ans, out: stream.out, count: stream.count });
1161
+ }
1162
+ const byLength = (x, y) => y.count - x.count;
1163
+ live.sort(byLength);
1164
+ while (live.length >= 3) {
1165
+ const a = live[0];
1166
+ const b = live[1];
1167
+ const c = live[2];
1168
+ const shared = c.count;
1169
+ ransDecodeSymbolsTrioU16(a.ans, a.out, shared, b.ans, b.out, shared, c.ans, c.out, shared);
1170
+ live.splice(2, 1);
1171
+ a.out = a.out.subarray(shared);
1172
+ a.count -= shared;
1173
+ b.out = b.out.subarray(shared);
1174
+ b.count -= shared;
1175
+ if (a.count === 0) live.shift();
1176
+ if (b.count === 0) live.splice(live.indexOf(b), 1);
1177
+ live.sort(byLength);
1178
+ }
1179
+ if (live.length === 2) {
1180
+ const a = live[0];
1181
+ const b = live[1];
1182
+ ransDecodeSymbolsPairU16(a.ans, a.out, a.count, b.ans, b.out, b.count);
1183
+ } else if (live.length === 1) {
1184
+ live[0].ans.decodeSymbols(live[0].out, live[0].count);
1150
1185
  }
1151
1186
  }
1152
1187
  function ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB) {
@@ -1278,10 +1313,10 @@ function ransDecodeSymbolsTrioU16(a, outA, countA, b, outB, countB, c, outC, cou
1278
1313
 
1279
1314
  // src/decoder/compression/point_cloud/PointCloudDecoder.ts
1280
1315
  var PointCloudDecoder = class {
1281
- S = null;
1316
+ V = null;
1282
1317
  d = null;
1283
- v = [];
1284
- Qa = [];
1318
+ w = [];
1319
+ Pa = [];
1285
1320
  // Returns an error message, or '' on success (outHeader is then populated).
1286
1321
  static decodeHeader(buffer, outHeader) {
1287
1322
  const kIoErrorMsg = "Failed to parse Draco header.";
@@ -1311,7 +1346,7 @@ var PointCloudDecoder = class {
1311
1346
  // Main entry point, given the already-parsed header (see Decode.ts).
1312
1347
  decode(header, inBuffer, outPointCloud) {
1313
1348
  this.d = inBuffer;
1314
- this.S = outPointCloud;
1349
+ this.V = outPointCloud;
1315
1350
  if (header.versionMajor !== 2 || header.versionMinor !== 2) {
1316
1351
  return "Unsupported bitstream version (Draco 2.2 meshes only).";
1317
1352
  }
@@ -1333,27 +1368,27 @@ var PointCloudDecoder = class {
1333
1368
  if (attDecoderId < 0) {
1334
1369
  return false;
1335
1370
  }
1336
- while (this.v.length <= attDecoderId) {
1337
- this.v.push(null);
1371
+ while (this.w.length <= attDecoderId) {
1372
+ this.w.push(null);
1338
1373
  }
1339
- this.v[attDecoderId] = decoder;
1374
+ this.w[attDecoderId] = decoder;
1340
1375
  return true;
1341
1376
  }
1342
1377
  getPortableAttribute(parentAttId) {
1343
- if (parentAttId < 0 || parentAttId >= this.S.numAttributes()) {
1378
+ if (parentAttId < 0 || parentAttId >= this.V.numAttributes()) {
1344
1379
  return null;
1345
1380
  }
1346
- const parentAttDecoderId = this.Qa[parentAttId];
1347
- return this.v[parentAttDecoderId].getPortableAttribute(parentAttId);
1381
+ const parentAttDecoderId = this.Pa[parentAttId];
1382
+ return this.w[parentAttDecoderId].getPortableAttribute(parentAttId);
1348
1383
  }
1349
1384
  attributesDecoder(decId) {
1350
- return this.v[decId];
1385
+ return this.w[decId];
1351
1386
  }
1352
1387
  numAttributesDecoders() {
1353
- return this.v.length;
1388
+ return this.w.length;
1354
1389
  }
1355
1390
  pointCloud() {
1356
- return this.S;
1391
+ return this.V;
1357
1392
  }
1358
1393
  buffer() {
1359
1394
  return this.d;
@@ -1379,52 +1414,40 @@ var PointCloudDecoder = class {
1379
1414
  return false;
1380
1415
  }
1381
1416
  }
1382
- for (let i = 0; i < this.v.length; ++i) {
1383
- if (!this.v[i].init(this, this.S)) {
1417
+ for (let i = 0; i < this.w.length; ++i) {
1418
+ if (!this.w[i].init(this, this.V)) {
1384
1419
  return false;
1385
1420
  }
1386
1421
  }
1387
1422
  for (let i = 0; i < numAttributesDecoders; ++i) {
1388
- if (!this.v[i].decodeAttributesDecoderData(this.d)) {
1423
+ if (!this.w[i].decodeAttributesDecoderData(this.d)) {
1389
1424
  return false;
1390
1425
  }
1391
1426
  }
1392
1427
  for (let i = 0; i < numAttributesDecoders; ++i) {
1393
- const numAttributes = this.v[i].getNumAttributes();
1428
+ const numAttributes = this.w[i].getNumAttributes();
1394
1429
  for (let j = 0; j < numAttributes; ++j) {
1395
- const attId = this.v[i].getAttributeId(j);
1396
- while (this.Qa.length <= attId) {
1397
- this.Qa.push(0);
1430
+ const attId = this.w[i].getAttributeId(j);
1431
+ while (this.Pa.length <= attId) {
1432
+ this.Pa.push(0);
1398
1433
  }
1399
- this.Qa[attId] = i;
1434
+ this.Pa[attId] = i;
1400
1435
  }
1401
1436
  }
1402
1437
  return this.decodeAllAttributes();
1403
1438
  }
1404
1439
  decodeAllAttributes() {
1405
- const decoders = this.v;
1406
- for (let i2 = 0; i2 < decoders.length; i2++) {
1407
- if (!decoders[i2].decodeAttributesParse(this.d)) {
1440
+ const decoders = this.w;
1441
+ for (let i = 0; i < decoders.length; i++) {
1442
+ if (!decoders[i].decodeAttributesParse(this.d)) {
1408
1443
  return false;
1409
1444
  }
1410
1445
  }
1411
1446
  const pending = [];
1412
- for (let i2 = 0; i2 < decoders.length; i2++) {
1413
- decoders[i2].collectPendingSymbolStreams(pending);
1414
- }
1415
- const paired = pending.filter((stream) => !stream.ans.coarse);
1416
- let i = 0;
1417
- for (; i + 1 < paired.length; i += 2) {
1418
- const a = paired[i];
1419
- const b = paired[i + 1];
1420
- ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
1421
- }
1422
- if (i < paired.length) {
1423
- paired[i].ans.decodeSymbols(paired[i].out, paired[i].count);
1424
- }
1425
- for (const stream of pending) {
1426
- if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
1447
+ for (let i = 0; i < decoders.length; i++) {
1448
+ decoders[i].collectPendingSymbolStreams(pending);
1427
1449
  }
1450
+ ransDecodeStreams(pending);
1428
1451
  for (let k = 0; k < decoders.length; k++) {
1429
1452
  if (!decoders[k].decodeAttributesFinish()) {
1430
1453
  return false;
@@ -1436,10 +1459,10 @@ var PointCloudDecoder = class {
1436
1459
 
1437
1460
  // src/decoder/compression/mesh/MeshDecoder.ts
1438
1461
  var MeshDecoder = class extends PointCloudDecoder {
1439
- H = null;
1462
+ G = null;
1440
1463
  // Returns an error message, or '' on success.
1441
1464
  decodeMesh(header, inBuffer, outMesh) {
1442
- this.H = outMesh;
1465
+ this.G = outMesh;
1443
1466
  return this.decode(header, inBuffer, outMesh);
1444
1467
  }
1445
1468
  // Connectivity accessors used by the mesh prediction schemes; the sequential
@@ -1454,7 +1477,7 @@ var MeshDecoder = class extends PointCloudDecoder {
1454
1477
  return null;
1455
1478
  }
1456
1479
  mesh() {
1457
- return this.H;
1480
+ return this.G;
1458
1481
  }
1459
1482
  decodeGeometryData() {
1460
1483
  return this.decodeConnectivity() && super.decodeGeometryData();
@@ -1463,89 +1486,84 @@ var MeshDecoder = class extends PointCloudDecoder {
1463
1486
 
1464
1487
  // src/decoder/mesh/MeshAttributeCornerTable.ts
1465
1488
  var kInvalidCornerIndex = -1;
1466
- var kInvalidVertexIndex = -1;
1467
1489
  var MeshAttributeCornerTable = class {
1468
- ba = [];
1469
- ta = [];
1470
- ca = [];
1471
- ua = [];
1490
+ // Base vertices touched by a seam edge of this table.
1491
+ sa = new Uint8Array(0);
1492
+ W = new Int32Array(0);
1493
+ // Attribute vertex -> 1 when its fan is open in this table (see
1494
+ // CornerTable._vertexOnBoundary). The C++ also keeps each attribute
1495
+ // vertex's left-most corner, but the decoder only ever asked it whether
1496
+ // that corner sits on a boundary, which this answers directly.
1497
+ B = new Uint8Array(0);
1472
1498
  // Attribute-vertex count. C++ keeps a vertex -> attribute-entry map here, but
1473
1499
  // the decoder only ever reads its size, so track the count directly instead
1474
1500
  // of allocating an Int32Array per attribute corner table.
1475
- va = 0;
1476
- w = null;
1477
- // Lazily built; see oppositeCornerArray.
1478
- T = null;
1479
- // Every corner passed to addSeamEdge (may contain duplicates); lets
1480
- // oppositeCornerArray patch seams without scanning every corner's flag.
1481
- // Preallocated to its exact upper bound (2 per seam edge) by the caller via
1482
- // reserveSeamEdges -- a plain array grown by push() was measurable on
1483
- // seam-heavy files.
1484
- da = [];
1485
- U = 0;
1501
+ ta = 0;
1502
+ H = null;
1503
+ // The base table's opposite corners with both corners of every seam edge
1504
+ // set to -1: what opposite() answers, and what the traversals read.
1505
+ I = new Int32Array(0);
1506
+ // Starts the table as a copy of the base connectivity; addSeamEdge then
1507
+ // cuts the seams and the ring pass numbers the vertices. Decode-scoped
1508
+ // scratch throughout: the table lives only until the decode finishes (the
1509
+ // result mesh keeps no reference to it), so pooling keeps a primitive-heavy
1510
+ // file from allocating a fresh set per attribute per prim.
1486
1511
  initEmpty(table) {
1487
- if (table === null) {
1488
- return false;
1489
- }
1490
- this.ba = scratchUint8Zeroed(table.numCorners());
1491
- this.ta = scratchUint8Zeroed(table.numVertices());
1492
- this.ca = scratchInt32Filled(table.numCorners(), kInvalidVertexIndex);
1493
- this.va = 0;
1494
- this.ua = [];
1495
- this.T = null;
1496
- this.da = [];
1497
- this.U = 0;
1498
- this.w = table;
1499
- return true;
1500
- }
1501
- // Sizes the seam-corner list for numSeamEdges upcoming addSeamEdge calls
1502
- // (each adds at most two corners). Decode-scoped scratch.
1503
- reserveSeamEdges(numSeamEdges) {
1504
- this.da = scratchInt32(numSeamEdges * 2);
1505
- this.U = 0;
1506
- }
1512
+ const numCorners = table.numCorners();
1513
+ this.H = table;
1514
+ this.sa = scratchUint8Zeroed(table.numVertices());
1515
+ this.I = scratchInt32(numCorners);
1516
+ this.I.set(table.oppositeCornerArray());
1517
+ this.W = scratchInt32(numCorners);
1518
+ this.W.set(table.cornerToVertexArray());
1519
+ this.ta = 0;
1520
+ }
1521
+ // Cuts the edge opposite corner c (and its twin) and flags its two vertices.
1507
1522
  addSeamEdge(c) {
1508
- const cornerToVertex = this.w.cornerToVertexArray();
1509
- const oppositeCorners = this.w.oppositeCornerArray();
1510
- const isEdge = this.ba;
1511
- const isVert = this.ta;
1512
- const seamCorners = this.da;
1513
- isEdge[c] = 1;
1514
- seamCorners[this.U++] = c;
1523
+ const cornerToVertex = this.H.cornerToVertexArray();
1524
+ const opposite = this.I;
1525
+ const isVert = this.sa;
1526
+ const oppCorner = opposite[c];
1527
+ opposite[c] = kInvalidCornerIndex;
1515
1528
  let rem = c - (c / 3 | 0) * 3;
1516
1529
  isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
1517
1530
  isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
1518
- const oppCorner = oppositeCorners[c];
1519
1531
  if (oppCorner !== kInvalidCornerIndex) {
1520
- isEdge[oppCorner] = 1;
1521
- seamCorners[this.U++] = oppCorner;
1532
+ opposite[oppCorner] = kInvalidCornerIndex;
1522
1533
  rem = oppCorner - (oppCorner / 3 | 0) * 3;
1523
1534
  isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
1524
1535
  isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
1525
1536
  }
1526
1537
  }
1527
- // Installs attribute-vertex numbering computed externally (the edgebreaker
1528
- // decoder's fused ring pass fills corner_to_vertex_map_ directly and hands
1529
- // over the per-vertex left-most corners here). leftMostMap is decode-scoped
1530
- // scratch sized for at least numNewVertices entries.
1531
- setRecomputedVertices(leftMostMap, numNewVertices) {
1532
- this.va = numNewVertices;
1533
- this.ua = leftMostMap.length === numNewVertices ? leftMostMap : leftMostMap.subarray(0, numNewVertices);
1534
- }
1535
- isCornerOppositeToSeamEdge(corner) {
1536
- return this.ba[corner];
1538
+ // Installs the vertex numbering computed by the edgebreaker decoder's ring
1539
+ // pass, which fills corner_to_vertex_map_ directly and hands over the
1540
+ // per-vertex boundary flags here (decode-scoped scratch sized for at
1541
+ // least numVertices entries).
1542
+ setRecomputedVertices(onBoundary, numVertices) {
1543
+ this.ta = numVertices;
1544
+ this.B = onBoundary;
1545
+ }
1546
+ // A table without interior seams is the base connectivity itself: every
1547
+ // vertex ring is one attribute vertex, and the boundary edges are already
1548
+ // open in the base opposite table. Shares the base arrays (read-only from
1549
+ // here on), so its traversal also resolves to the base table's cached one.
1550
+ initAsBase(table) {
1551
+ this.H = table;
1552
+ this.I = table.oppositeCornerArray();
1553
+ this.W = table.cornerToVertexArray();
1554
+ this.setRecomputedVertices(table.vertexOnBoundaryArray(), table.numVertices());
1537
1555
  }
1538
1556
  opposite(corner) {
1539
- if (corner === kInvalidCornerIndex || this.isCornerOppositeToSeamEdge(corner)) {
1557
+ if (corner === kInvalidCornerIndex) {
1540
1558
  return kInvalidCornerIndex;
1541
1559
  }
1542
- return this.w.opposite(corner);
1560
+ return this.I[corner];
1543
1561
  }
1544
1562
  next(corner) {
1545
- return this.w.next(corner);
1563
+ return this.H.next(corner);
1546
1564
  }
1547
1565
  previous(corner) {
1548
- return this.w.previous(corner);
1566
+ return this.H.previous(corner);
1549
1567
  }
1550
1568
  swingRight(corner) {
1551
1569
  return this.previous(this.opposite(this.previous(corner)));
@@ -1554,68 +1572,48 @@ var MeshAttributeCornerTable = class {
1554
1572
  return this.next(this.opposite(this.next(corner)));
1555
1573
  }
1556
1574
  numVertices() {
1557
- return this.va;
1575
+ return this.ta;
1558
1576
  }
1559
1577
  numFaces() {
1560
- return this.w.numFaces();
1578
+ return this.H.numFaces();
1561
1579
  }
1562
1580
  numCorners() {
1563
- return this.w.numCorners();
1581
+ return this.H.numCorners();
1564
1582
  }
1565
1583
  // --- Flat-array accessors: let DepthFirstTraverser avoid per-corner dispatch. ---
1566
1584
  cornerToVertexArray() {
1567
- return this.ca;
1585
+ return this.W;
1568
1586
  }
1569
- // Seam-aware opposite corners (seam edges -> -1), matching opposite(). Cached on
1570
- // first use; seams and connectivity are finalized before traversal, so it's stable.
1587
+ // Seam-aware opposite corners (seam edges -> -1), matching opposite().
1571
1588
  oppositeCornerArray() {
1572
- if (this.T === null) {
1573
- const nc = this.w.numCorners();
1574
- const base = this.w.oppositeCornerArray();
1575
- const seamCorners = this.da;
1576
- const numSeamCorners = this.U;
1577
- if (numSeamCorners === 0) {
1578
- this.T = base;
1579
- } else {
1580
- const eff = scratchInt32(nc);
1581
- eff.set(base.length === nc ? base : base.subarray(0, nc));
1582
- for (let i = 0; i < numSeamCorners; ++i) {
1583
- eff[seamCorners[i]] = kInvalidCornerIndex;
1584
- }
1585
- this.T = eff;
1586
- }
1587
- }
1588
- return this.T;
1589
+ return this.I;
1589
1590
  }
1590
- vertexLeftmostCornerArray() {
1591
- return this.ua;
1591
+ vertexOnBoundaryArray() {
1592
+ return this.B;
1592
1593
  }
1593
1594
  // Takes over another table's state wholesale. Only valid when both tables
1594
1595
  // were built from the same corner table and the same seam edges, in which
1595
1596
  // case every one of these is identical and read-only from here on.
1596
1597
  adoptFrom(other) {
1597
- this.w = other.w;
1598
- this.ba = other.ba;
1598
+ this.H = other.H;
1599
+ this.sa = other.sa;
1600
+ this.W = other.W;
1599
1601
  this.ta = other.ta;
1600
- this.ca = other.ca;
1601
- this.va = other.va;
1602
- this.ua = other.ua;
1603
- this.T = other.T;
1604
- this.da = other.da;
1605
- this.U = other.U;
1602
+ this.B = other.B;
1603
+ this.I = other.I;
1606
1604
  }
1607
1605
  };
1608
1606
 
1609
1607
  // src/decoder/compression/attributes/AttributesDecoder.ts
1610
1608
  var AttributesDecoder = class {
1611
- Ra = [];
1609
+ Qa = [];
1612
1610
  // Inverse of _pointAttributeIds: point attribute id -> local id.
1613
- wa = [];
1614
- Hb = null;
1615
- S = null;
1611
+ ua = [];
1612
+ Fb = null;
1613
+ V = null;
1616
1614
  init(decoder, pointCloud) {
1617
- this.Hb = decoder;
1618
- this.S = pointCloud;
1615
+ this.Fb = decoder;
1616
+ this.V = pointCloud;
1619
1617
  return true;
1620
1618
  }
1621
1619
  decodeAttributesDecoderData(buffer) {
@@ -1623,8 +1621,8 @@ var AttributesDecoder = class {
1623
1621
  if (numAttributes === void 0 || numAttributes === 0 || numAttributes > 5 * buffer.remainingSize) {
1624
1622
  return false;
1625
1623
  }
1626
- this.Ra.length = numAttributes;
1627
- const pc = this.S;
1624
+ this.Qa.length = numAttributes;
1625
+ const pc = this.V;
1628
1626
  for (let i = 0; i < numAttributes; i++) {
1629
1627
  const attType = buffer.decodeUint8();
1630
1628
  if (attType === void 0) return false;
@@ -1650,56 +1648,56 @@ var AttributesDecoder = class {
1650
1648
  ga.uniqueId = uniqueId;
1651
1649
  const attId = pc.addAttribute(new PointAttribute(ga));
1652
1650
  pc.attribute(attId).uniqueId = uniqueId;
1653
- this.Ra[i] = attId;
1654
- while (this.wa.length <= attId) {
1655
- this.wa.push(-1);
1651
+ this.Qa[i] = attId;
1652
+ while (this.ua.length <= attId) {
1653
+ this.ua.push(-1);
1656
1654
  }
1657
- this.wa[attId] = i;
1655
+ this.ua[attId] = i;
1658
1656
  }
1659
1657
  return true;
1660
1658
  }
1661
1659
  getAttributeId(i) {
1662
- return this.Ra[i];
1660
+ return this.Qa[i];
1663
1661
  }
1664
1662
  getNumAttributes() {
1665
- return this.Ra.length;
1663
+ return this.Qa.length;
1666
1664
  }
1667
1665
  getDecoder() {
1668
- return this.Hb;
1666
+ return this.Fb;
1669
1667
  }
1670
1668
  getLocalIdForPointAttribute(pointAttributeId) {
1671
- if (pointAttributeId >= this.wa.length) {
1669
+ if (pointAttributeId >= this.ua.length) {
1672
1670
  return -1;
1673
1671
  }
1674
- return this.wa[pointAttributeId];
1672
+ return this.ua[pointAttributeId];
1675
1673
  }
1676
1674
  };
1677
1675
 
1678
1676
  // src/decoder/compression/attributes/SequentialAttributeDecoder.ts
1679
1677
  var SequentialAttributeDecoder = class {
1680
1678
  n = null;
1681
- I = null;
1682
- Ib = -1;
1679
+ J = null;
1680
+ Gb = -1;
1683
1681
  // Decoded portable attribute (after lossless decoding).
1684
1682
  ea = null;
1685
1683
  init(decoder, attributeId) {
1686
1684
  this.n = decoder;
1687
- this.I = decoder.pointCloud().attribute(attributeId);
1688
- this.Ib = attributeId;
1685
+ this.J = decoder.pointCloud().attribute(attributeId);
1686
+ this.Gb = attributeId;
1689
1687
  return true;
1690
1688
  }
1691
1689
  // --- Two-phase decode ---
1692
1690
  // The controller calls Parse for every attribute first (headers, schemes,
1693
1691
  // prediction data -- all size-driven cursor movement), collects the pending
1694
- // rANS symbol streams, decodes them in pairs (see ransDecodeSymbolsPair),
1692
+ // rANS symbol streams, decodes them in lockstep (see ransDecodeStreams),
1695
1693
  // then calls Finish per attribute in order. Decoders without a deferrable
1696
1694
  // stream simply do the whole decode in Parse (decodeValues); the defaults
1697
1695
  // below are theirs.
1698
1696
  decodePortableAttributeParse(pointIds, buffer) {
1699
- if (this.I.numComponents <= 0) {
1697
+ if (this.J.numComponents <= 0) {
1700
1698
  return false;
1701
1699
  }
1702
- if (!this.Jb(pointIds.length)) {
1700
+ if (!this.Hb(pointIds.length)) {
1703
1701
  return false;
1704
1702
  }
1705
1703
  return this.decodeValues(pointIds, buffer);
@@ -1707,8 +1705,8 @@ var SequentialAttributeDecoder = class {
1707
1705
  // Sizes (and here allocates) the attribute's storage for numValues values;
1708
1706
  // the integer decoders override it to skip the allocation, their values
1709
1707
  // staying in the portable attribute (see PointAttribute.setLazyInteger).
1710
- Jb(numValues) {
1711
- return this.I.reset(numValues);
1708
+ Hb(numValues) {
1709
+ return this.J.reset(numValues);
1712
1710
  }
1713
1711
  pendingSymbolStream() {
1714
1712
  return null;
@@ -1725,10 +1723,10 @@ var SequentialAttributeDecoder = class {
1725
1723
  return true;
1726
1724
  }
1727
1725
  getPortableAttribute() {
1728
- if (!this.I.isMappingIdentity && this.ea && this.ea.isMappingIdentity) {
1729
- const size = this.I.indicesMapSize;
1726
+ if (!this.J.isMappingIdentity && this.ea && this.ea.isMappingIdentity) {
1727
+ const size = this.J.indicesMapSize;
1730
1728
  this.ea.setExplicitMappingScratch(size);
1731
- const src = this.I.indicesMap;
1729
+ const src = this.J.indicesMap;
1732
1730
  const dst = this.ea.indicesMap;
1733
1731
  if (src.length === size) {
1734
1732
  dst.set(src);
@@ -1739,10 +1737,10 @@ var SequentialAttributeDecoder = class {
1739
1737
  return this.ea;
1740
1738
  }
1741
1739
  get attribute() {
1742
- return this.I;
1740
+ return this.J;
1743
1741
  }
1744
1742
  get attributeId() {
1745
- return this.Ib;
1743
+ return this.Gb;
1746
1744
  }
1747
1745
  get decoder() {
1748
1746
  return this.n;
@@ -1763,13 +1761,13 @@ var SequentialAttributeDecoder = class {
1763
1761
  // Decodes raw attribute values in their original format.
1764
1762
  decodeValues(pointIds, buffer) {
1765
1763
  const numValues = pointIds.length;
1766
- const entrySize = this.I.byteStride;
1764
+ const entrySize = this.J.byteStride;
1767
1765
  const totalSize = numValues * entrySize;
1768
1766
  const valueData = buffer.decodeBytesView(totalSize);
1769
1767
  if (valueData === void 0) {
1770
1768
  return false;
1771
1769
  }
1772
- this.I.buffer.write(0, valueData, totalSize);
1770
+ this.J.buffer.write(0, valueData, totalSize);
1773
1771
  return true;
1774
1772
  }
1775
1773
  };
@@ -1784,14 +1782,14 @@ function convertSymbolsToSignedInts(input, count, output) {
1784
1782
 
1785
1783
  // src/decoder/compression/entropy/RAnsSymbolDecoder.ts
1786
1784
  var RAnsSymbolDecoder = class {
1787
- Kb = 0;
1788
- o;
1785
+ Ib = 0;
1786
+ K;
1789
1787
  constructor(uniqueSymbolsBitLength) {
1790
1788
  const unclamped = Math.trunc(3 * uniqueSymbolsBitLength / 2);
1791
- this.o = new RAnsDecoder(unclamped < 12 ? 12 : unclamped > 20 ? 20 : unclamped);
1789
+ this.K = new RAnsDecoder(unclamped < 12 ? 12 : unclamped > 20 ? 20 : unclamped);
1792
1790
  }
1793
1791
  get numSymbols() {
1794
- return this.Kb;
1792
+ return this.Ib;
1795
1793
  }
1796
1794
  // Initialize the decoder and decode the probability table. expectedCount is
1797
1795
  // the number of symbols the caller will decode (lets short streams skip the
@@ -1799,7 +1797,7 @@ var RAnsSymbolDecoder = class {
1799
1797
  create(buffer, expectedCount = 2147483647) {
1800
1798
  const numSymbols = decodeVarint(buffer);
1801
1799
  if (numSymbols === void 0) return false;
1802
- this.Kb = numSymbols;
1800
+ this.Ib = numSymbols;
1803
1801
  if (Math.trunc(numSymbols / 64) > buffer.remainingSize) {
1804
1802
  return false;
1805
1803
  }
@@ -1832,7 +1830,7 @@ var RAnsSymbolDecoder = class {
1832
1830
  }
1833
1831
  }
1834
1832
  buffer.advance(pos - startPos);
1835
- return this.o.ransBuildLookUpTable(probabilityTable, numSymbols, expectedCount);
1833
+ return this.K.ransBuildLookUpTable(probabilityTable, numSymbols, expectedCount);
1836
1834
  }
1837
1835
  // Starts decoding, advancing buffer past the encoded data.
1838
1836
  startDecoding(buffer) {
@@ -1843,10 +1841,10 @@ var RAnsSymbolDecoder = class {
1843
1841
  }
1844
1842
  const base = buffer.decodedSize;
1845
1843
  buffer.advance(Number(bytesEncoded));
1846
- return ansReadInit(this.o, buffer.data, base + Number(bytesEncoded), base, this.o.lRansBase, 4);
1844
+ return ansReadInit(this.K, buffer.data, base + Number(bytesEncoded), base, this.K.lRansBase, 4);
1847
1845
  }
1848
1846
  endDecoding() {
1849
- this.o.readEnd();
1847
+ this.K.readEnd();
1850
1848
  }
1851
1849
  };
1852
1850
 
@@ -1874,12 +1872,12 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1874
1872
  if (numValues > 0 && tagDecoder.numSymbols === 0) {
1875
1873
  return false;
1876
1874
  }
1877
- const tagAns = tagDecoder.o;
1875
+ const tagAns = tagDecoder.K;
1878
1876
  srcBuffer.startBitDecoding(false);
1879
- const bd = srcBuffer.sa;
1880
- const buf = bd.Na;
1881
- const byteLength = bd.ra;
1882
- let bitOffset = bd.q;
1877
+ const bd = srcBuffer.ra;
1878
+ const buf = bd.Ma;
1879
+ const byteLength = bd.qa;
1880
+ let bitOffset = bd.s;
1883
1881
  let valueId = 0;
1884
1882
  for (let i = 0; i < numValues; i += numComponents) {
1885
1883
  const bitLength = tagAns.ransRead();
@@ -1898,7 +1896,7 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1898
1896
  outValues[valueId++] = value & mask;
1899
1897
  }
1900
1898
  if (j === numComponents) continue;
1901
- bd.q = bitOffset;
1899
+ bd.s = bitOffset;
1902
1900
  for (; j < numComponents; ++j) {
1903
1901
  const val = bd.getBits(bitLength);
1904
1902
  if (val === void 0) {
@@ -1906,9 +1904,9 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1906
1904
  }
1907
1905
  outValues[valueId++] = val;
1908
1906
  }
1909
- bitOffset = bd.q;
1907
+ bitOffset = bd.s;
1910
1908
  } else {
1911
- bd.q = bitOffset;
1909
+ bd.s = bitOffset;
1912
1910
  for (let j = 0; j < numComponents; ++j) {
1913
1911
  const val = bd.getBits(bitLength);
1914
1912
  if (val === void 0) {
@@ -1916,10 +1914,10 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1916
1914
  }
1917
1915
  outValues[valueId++] = val;
1918
1916
  }
1919
- bitOffset = bd.q;
1917
+ bitOffset = bd.s;
1920
1918
  }
1921
1919
  }
1922
- bd.q = bitOffset;
1920
+ bd.s = bitOffset;
1923
1921
  tagDecoder.endDecoding();
1924
1922
  srcBuffer.endBitDecoding();
1925
1923
  return true;
@@ -1946,15 +1944,15 @@ function decodeRawSymbols(numValues, srcBuffer, outValues) {
1946
1944
  if (decoder === null) {
1947
1945
  return false;
1948
1946
  }
1949
- decoder.o.decodeSymbols(outValues, numValues);
1947
+ decoder.K.decodeSymbols(outValues, numValues);
1950
1948
  decoder.endDecoding();
1951
1949
  return true;
1952
1950
  }
1953
1951
 
1954
1952
  // src/decoder/compression/bit_coders/RAnsBitDecoder.ts
1955
1953
  var RAnsBitDecoder = class {
1956
- db = new AnsDecoder();
1957
- eb = 0;
1954
+ va = new AnsDecoder();
1955
+ wa = 0;
1958
1956
  // ANS_P8_PRECISION - probZero, precomputed
1959
1957
  // Returns false when the data is invalid.
1960
1958
  startDecoding(sourceBuffer) {
@@ -1962,21 +1960,21 @@ var RAnsBitDecoder = class {
1962
1960
  if (probZero === void 0) {
1963
1961
  return false;
1964
1962
  }
1965
- this.eb = ANS_P8_PRECISION - probZero;
1963
+ this.wa = ANS_P8_PRECISION - probZero;
1966
1964
  const sizeInBytes = decodeVarint(sourceBuffer);
1967
1965
  if (sizeInBytes === void 0 || sizeInBytes > sourceBuffer.remainingSize) {
1968
1966
  return false;
1969
1967
  }
1970
1968
  const base = sourceBuffer.decodedSize;
1971
- if (!ansReadInit(this.db, sourceBuffer.data, base + sizeInBytes, base, ANS_L_BASE, 3)) {
1969
+ if (!ansReadInit(this.va, sourceBuffer.data, base + sizeInBytes, base, ANS_L_BASE, 3)) {
1972
1970
  return false;
1973
1971
  }
1974
1972
  sourceBuffer.advance(sizeInBytes);
1975
1973
  return true;
1976
1974
  }
1977
1975
  decodeNextBit() {
1978
- const ans = this.db;
1979
- const p = this.eb;
1976
+ const ans = this.va;
1977
+ const p = this.wa;
1980
1978
  if (ans.state < ANS_L_BASE && ans.bufOffset > ans.bufStart) {
1981
1979
  ans.state = ans.state << 8 | ans.buf[--ans.bufOffset];
1982
1980
  }
@@ -1997,13 +1995,16 @@ var RAnsBitDecoder = class {
1997
1995
 
1998
1996
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeDecoder.ts
1999
1997
  var PredictionSchemeDecoder = class {
2000
- h;
1998
+ f;
2001
1999
  constructor(transform) {
2002
- this.h = transform;
2000
+ this.f = transform;
2003
2001
  }
2004
2002
  /** True if all correction values are guaranteed to be positive. */
2005
2003
  areCorrectionsPositive() {
2006
- return this.h.areCorrectionsPositive();
2004
+ return this.f.areCorrectionsPositive();
2005
+ }
2006
+ boundsValues(limit) {
2007
+ return this.f.boundsValues(limit);
2007
2008
  }
2008
2009
  getNumParentAttributes() {
2009
2010
  return 0;
@@ -2015,7 +2016,7 @@ var PredictionSchemeDecoder = class {
2015
2016
  return false;
2016
2017
  }
2017
2018
  decodePredictionData(buffer) {
2018
- return this.h.decodeTransformData(buffer);
2019
+ return this.f.decodeTransformData(buffer);
2019
2020
  }
2020
2021
  /**
2021
2022
  * Like computeOriginalValues, but inCorr still holds unsigned zigzag-coded
@@ -2072,18 +2073,18 @@ var MAX_NUM_PARALLELOGRAMS = 4;
2072
2073
  var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends MeshPredictionSchemeDecoder {
2073
2074
  // Crease edges stored per context (number of available parallelograms),
2074
2075
  // one list per context up to MAX_NUM_PARALLELOGRAMS.
2075
- Sa = [[], [], [], []];
2076
+ Ra = [[], [], [], []];
2076
2077
  decodePredictionData(buffer) {
2077
2078
  for (let i = 0; i < MAX_NUM_PARALLELOGRAMS; ++i) {
2078
2079
  const numFlags = decodeVarint(buffer);
2079
2080
  if (numFlags === void 0) return false;
2080
2081
  if (numFlags > this.c.cornerTable.numCorners()) return false;
2081
2082
  if (numFlags > 0) {
2082
- this.Sa[i] = new Array(numFlags);
2083
+ this.Ra[i] = new Array(numFlags);
2083
2084
  const decoder = new RAnsBitDecoder();
2084
2085
  if (!decoder.startDecoding(buffer)) return false;
2085
2086
  for (let j = 0; j < numFlags; ++j) {
2086
- this.Sa[i][j] = decoder.decodeNextBit();
2087
+ this.Ra[i][j] = decoder.decodeNextBit();
2087
2088
  }
2088
2089
  decoder.endDecoding();
2089
2090
  }
@@ -2091,12 +2092,12 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2091
2092
  return super.decodePredictionData(buffer);
2092
2093
  }
2093
2094
  computeOriginalValues(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2094
- this.h.init(numComponents);
2095
+ this.f.init(numComponents);
2095
2096
  const predVals = [];
2096
2097
  for (let i = 0; i < MAX_NUM_PARALLELOGRAMS; ++i) {
2097
2098
  predVals.push(new Int32Array(numComponents));
2098
2099
  }
2099
- this.h.computeOriginalValue(predVals[0], 0, inCorr, 0, outData, 0);
2100
+ this.f.computeOriginalValue(predVals[0], 0, inCorr, 0, outData, 0);
2100
2101
  const table = this.c.cornerTable;
2101
2102
  const vertexToDataMap = this.c.vertexToDataMap;
2102
2103
  const oppositeCorners = table.oppositeCornerArray();
@@ -2142,8 +2143,8 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2142
2143
  for (let i = 0; i < numParallelograms; ++i) {
2143
2144
  const context = numParallelograms - 1;
2144
2145
  const pos = isCreaseEdgePos[context]++;
2145
- if (this.Sa[context].length <= pos) return false;
2146
- const isCrease = this.Sa[context][pos];
2146
+ if (this.Ra[context].length <= pos) return false;
2147
+ const isCrease = this.Ra[context][pos];
2147
2148
  if (!isCrease) {
2148
2149
  ++numUsedParallelograms;
2149
2150
  for (let j = 0; j < numComponents; ++j) {
@@ -2155,12 +2156,12 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2155
2156
  const dstOffset = p * numComponents;
2156
2157
  if (numUsedParallelograms === 0) {
2157
2158
  const srcOffset = (p - 1) * numComponents;
2158
- this.h.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2159
+ this.f.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2159
2160
  } else {
2160
2161
  for (let c = 0; c < numComponents; ++c) {
2161
2162
  multiPredVals[c] = multiPredVals[c] / numUsedParallelograms | 0;
2162
2163
  }
2163
- this.h.computeOriginalValue(multiPredVals, 0, inCorr, dstOffset, outData, dstOffset);
2164
+ this.f.computeOriginalValue(multiPredVals, 0, inCorr, dstOffset, outData, dstOffset);
2164
2165
  }
2165
2166
  }
2166
2167
  return true;
@@ -2170,34 +2171,82 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2170
2171
  // src/decoder/compression/attributes/prediction_schemes/MeshPredictionSchemeData.ts
2171
2172
  var MeshPredictionSchemeData = class {
2172
2173
  cornerTable;
2173
- vertexToDataMap;
2174
- dataToCornerMap;
2175
- constructor(cornerTable, dataToCornerMap, vertexToDataMap) {
2174
+ p;
2175
+ constructor(cornerTable, encodingData) {
2176
2176
  this.cornerTable = cornerTable;
2177
- this.vertexToDataMap = vertexToDataMap;
2178
- this.dataToCornerMap = dataToCornerMap;
2177
+ this.p = encodingData;
2178
+ }
2179
+ get vertexToDataMap() {
2180
+ return this.p.vertexToEncodedAttributeValueIndexMap;
2181
+ }
2182
+ get dataToCornerMap() {
2183
+ return this.p.encodedAttributeValueIndexToCornerMap;
2184
+ }
2185
+ // The parallelogram parents of every value: for value p, the data ids of
2186
+ // the opposite corner's vertex and of that face's next and prev vertices
2187
+ // (parents[3p .. 3p+2]), or -1 in parents[3p] when the value is not
2188
+ // parallelogram-predictable (no opposite face, or a parent decoded after
2189
+ // it). The scheme's per-value walk -- corner, opposite corner, three
2190
+ // vertices, three data ids: four dependent random reads -- is thus done
2191
+ // once per traversal and shared by every attribute predicted over it (a
2192
+ // position, a texture coordinate and a colour on one connectivity all use
2193
+ // it), and the prediction loops read it sequentially. Decode-scoped
2194
+ // scratch, cached on the traversal entry.
2195
+ parallelogramParents() {
2196
+ const entry = this.p.cacheEntry;
2197
+ if (entry !== null && entry.parents !== null) {
2198
+ return entry.parents;
2199
+ }
2200
+ const table = this.cornerTable;
2201
+ const oppositeCorners = table.oppositeCornerArray();
2202
+ const cornerToVertex = table.cornerToVertexArray();
2203
+ const vertexToDataMap = this.vertexToDataMap;
2204
+ const dataToCornerMap = this.dataToCornerMap;
2205
+ const numValues = dataToCornerMap.length;
2206
+ const parents = scratchInt32(numValues * 3);
2207
+ if (numValues > 0) parents[0] = -1;
2208
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2209
+ const oci = oppositeCorners[dataToCornerMap[p]];
2210
+ if (oci < 0) {
2211
+ parents[o] = -1;
2212
+ continue;
2213
+ }
2214
+ const rem = oci - (oci / 3 | 0) * 3;
2215
+ const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2216
+ const vertNext = vertexToDataMap[cornerToVertex[rem === 2 ? oci - 2 : oci + 1]];
2217
+ const vertPrev = vertexToDataMap[cornerToVertex[rem === 0 ? oci + 2 : oci - 1]];
2218
+ if (vertOpp < p && vertNext < p && vertPrev < p) {
2219
+ parents[o] = vertOpp;
2220
+ parents[o + 1] = vertNext;
2221
+ parents[o + 2] = vertPrev;
2222
+ } else {
2223
+ parents[o] = -1;
2224
+ }
2225
+ }
2226
+ if (entry !== null) entry.parents = parents;
2227
+ return parents;
2179
2228
  }
2180
2229
  };
2181
2230
 
2182
2231
  // src/decoder/compression/attributes/NormalCompressionUtils.ts
2183
2232
  var OctahedronToolBox = class {
2184
- N = -1;
2185
- xa = -1;
2233
+ P = -1;
2234
+ fa = -1;
2186
2235
  m = -1;
2187
- lc = 1;
2188
- f = -1;
2236
+ jc = 1;
2237
+ h = -1;
2189
2238
  // q: quantization bits, valid range 2..30.
2190
2239
  setQuantizationBits(q) {
2191
2240
  if (q < 2 || q > 30) return false;
2192
- this.N = q;
2193
- this.xa = (1 << q) - 1;
2194
- this.m = this.xa - 1;
2195
- this.lc = Math.fround(2 / Math.fround(this.m));
2196
- this.f = this.m / 2 | 0;
2241
+ this.P = q;
2242
+ this.fa = (1 << q) - 1;
2243
+ this.m = this.fa - 1;
2244
+ this.jc = Math.fround(2 / Math.fround(this.m));
2245
+ this.h = this.m / 2 | 0;
2197
2246
  return true;
2198
2247
  }
2199
2248
  quantizationBits() {
2200
- return this.N;
2249
+ return this.P;
2201
2250
  }
2202
2251
  // Canonicalizes edge points into consistent quadrants. Writes result into
2203
2252
  // out[0], out[1] (caller-owned reusable 2-element array).
@@ -2205,14 +2254,14 @@ var OctahedronToolBox = class {
2205
2254
  if (s === 0 && t === 0 || s === 0 && t === this.m || s === this.m && t === 0) {
2206
2255
  s = this.m;
2207
2256
  t = this.m;
2208
- } else if (s === 0 && t > this.f) {
2209
- t = this.f - (t - this.f);
2210
- } else if (s === this.m && t < this.f) {
2211
- t = this.f + (this.f - t);
2212
- } else if (t === this.m && s < this.f) {
2213
- s = this.f + (this.f - s);
2214
- } else if (t === 0 && s > this.f) {
2215
- s = this.f - (s - this.f);
2257
+ } else if (s === 0 && t > this.h) {
2258
+ t = this.h - (t - this.h);
2259
+ } else if (s === this.m && t < this.h) {
2260
+ t = this.h + (this.h - t);
2261
+ } else if (t === this.m && s < this.h) {
2262
+ s = this.h + (this.h - s);
2263
+ } else if (t === 0 && s > this.h) {
2264
+ s = this.h - (s - this.h);
2216
2265
  }
2217
2266
  out[0] = s;
2218
2267
  out[1] = t;
@@ -2222,8 +2271,8 @@ var OctahedronToolBox = class {
2222
2271
  integerVectorToQuantizedOctahedralCoords(intVec, out) {
2223
2272
  let s, t;
2224
2273
  if (intVec[0] >= 0) {
2225
- s = intVec[1] + this.f;
2226
- t = intVec[2] + this.f;
2274
+ s = intVec[1] + this.h;
2275
+ t = intVec[2] + this.h;
2227
2276
  } else {
2228
2277
  if (intVec[1] < 0) {
2229
2278
  s = Math.abs(intVec[2]);
@@ -2242,14 +2291,14 @@ var OctahedronToolBox = class {
2242
2291
  canonicalizeIntegerVector(vec) {
2243
2292
  const absSum = Math.abs(vec[0]) + Math.abs(vec[1]) + Math.abs(vec[2]);
2244
2293
  if (absSum === 0) {
2245
- vec[0] = this.f;
2294
+ vec[0] = this.h;
2246
2295
  } else {
2247
- vec[0] = Math.trunc(vec[0] * this.f / absSum);
2248
- vec[1] = Math.trunc(vec[1] * this.f / absSum);
2296
+ vec[0] = Math.trunc(vec[0] * this.h / absSum);
2297
+ vec[1] = Math.trunc(vec[1] * this.h / absSum);
2249
2298
  if (vec[2] >= 0) {
2250
- vec[2] = this.f - Math.abs(vec[0]) - Math.abs(vec[1]);
2299
+ vec[2] = this.h - Math.abs(vec[0]) - Math.abs(vec[1]);
2251
2300
  } else {
2252
- vec[2] = -(this.f - Math.abs(vec[0]) - Math.abs(vec[1]));
2301
+ vec[2] = -(this.h - Math.abs(vec[0]) - Math.abs(vec[1]));
2253
2302
  }
2254
2303
  }
2255
2304
  }
@@ -2295,31 +2344,31 @@ function fillInt32PositionCache(cache, att, map, numEntries, tempPos) {
2295
2344
  }
2296
2345
  }
2297
2346
  var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2347
+ xa = null;
2298
2348
  ya = null;
2299
- za = null;
2300
2349
  c;
2301
- fb = new Array(3);
2302
- Aa = null;
2350
+ db = new Array(3);
2351
+ za = null;
2303
2352
  // flat Int32 positions, indexed by data id
2304
- s = null;
2305
- Lb = null;
2353
+ q = null;
2354
+ Jb = null;
2306
2355
  // corner -> posCache offset, precomputed
2307
2356
  constructor(meshData) {
2308
2357
  this.c = meshData;
2309
2358
  }
2310
2359
  setPositionAttribute(positionAttribute) {
2311
- this.ya = positionAttribute;
2360
+ this.xa = positionAttribute;
2312
2361
  }
2313
2362
  setEntryToPointIdMap(map) {
2314
- this.za = map;
2363
+ this.ya = map;
2315
2364
  }
2316
2365
  buildPositionCache(numEntries) {
2317
2366
  const posCache = scratchInt32(numEntries * 3);
2318
- fillInt32PositionCache(posCache, this.ya, this.za, numEntries, this.fb);
2319
- this.Aa = posCache;
2367
+ fillInt32PositionCache(posCache, this.xa, this.ya, numEntries, this.db);
2368
+ this.za = posCache;
2320
2369
  const table = this.c.cornerTable;
2321
2370
  const cornerToVertex = table.cornerToVertexArray();
2322
- this.s = table.oppositeCornerArray();
2371
+ this.q = table.oppositeCornerArray();
2323
2372
  const vertexToDataMap = this.c.vertexToDataMap;
2324
2373
  const nc = cornerToVertex.length;
2325
2374
  const c2o = scratchInt32(nc);
@@ -2327,12 +2376,12 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2327
2376
  const v = cornerToVertex[c];
2328
2377
  c2o[c] = v < 0 ? -1 : vertexToDataMap[v] * 3;
2329
2378
  }
2330
- this.Lb = c2o;
2379
+ this.Jb = c2o;
2331
2380
  }
2332
2381
  computePredictedValue(cornerId, prediction) {
2333
- const oppositeCorners = this.s;
2334
- const cornerToOffset = this.Lb;
2335
- const posCache = this.Aa;
2382
+ const oppositeCorners = this.q;
2383
+ const cornerToOffset = this.Jb;
2384
+ const posCache = this.za;
2336
2385
  const centerOffset = cornerToOffset[cornerId];
2337
2386
  const centX = posCache[centerOffset];
2338
2387
  const centY = posCache[centerOffset + 1];
@@ -2410,8 +2459,8 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2410
2459
  var GEOMETRY_ATTRIBUTE_POSITION = 0;
2411
2460
  var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSchemeDecoder {
2412
2461
  t;
2413
- B = new OctahedronToolBox();
2414
- gb = new RAnsBitDecoder();
2462
+ z = new OctahedronToolBox();
2463
+ eb = new RAnsBitDecoder();
2415
2464
  constructor(transform, meshData) {
2416
2465
  super(transform, meshData);
2417
2466
  this.t = new MeshPredictionSchemeGeometricNormalPredictorArea(meshData);
@@ -2429,11 +2478,11 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2429
2478
  return true;
2430
2479
  }
2431
2480
  decodePredictionData(buffer) {
2432
- if (!this.h.decodeTransformData(buffer)) return false;
2433
- return this.gb.startDecoding(buffer);
2481
+ if (!this.f.decodeTransformData(buffer)) return false;
2482
+ return this.eb.startDecoding(buffer);
2434
2483
  }
2435
2484
  computeOriginalValues(inCorr, outData, _size, _numComponents, entryToPointIdMap) {
2436
- this.B.setQuantizationBits(this.h.quantizationBits());
2485
+ this.z.setQuantizationBits(this.f.quantizationBits());
2437
2486
  this.t.setEntryToPointIdMap(entryToPointIdMap);
2438
2487
  const cornerMapSize = this.c.dataToCornerMap.length;
2439
2488
  this.t.buildPositionCache(cornerMapSize);
@@ -2442,17 +2491,17 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2442
2491
  for (let dataId = 0; dataId < cornerMapSize; ++dataId) {
2443
2492
  const cornerId = this.c.dataToCornerMap[dataId];
2444
2493
  this.t.computePredictedValue(cornerId, predNormal3D);
2445
- this.B.canonicalizeIntegerVector(predNormal3D);
2446
- if (this.gb.decodeNextBit()) {
2494
+ this.z.canonicalizeIntegerVector(predNormal3D);
2495
+ if (this.eb.decodeNextBit()) {
2447
2496
  predNormal3D[0] = -predNormal3D[0];
2448
2497
  predNormal3D[1] = -predNormal3D[1];
2449
2498
  predNormal3D[2] = -predNormal3D[2];
2450
2499
  }
2451
- this.B.integerVectorToQuantizedOctahedralCoords(predNormal3D, predNormalOct);
2500
+ this.z.integerVectorToQuantizedOctahedralCoords(predNormal3D, predNormalOct);
2452
2501
  const dataOffset = dataId * 2;
2453
- this.h.computeOriginalValue(predNormalOct, 0, inCorr, dataOffset, outData, dataOffset);
2502
+ this.f.computeOriginalValue(predNormalOct, 0, inCorr, dataOffset, outData, dataOffset);
2454
2503
  }
2455
- this.gb.endDecoding();
2504
+ this.eb.endDecoding();
2456
2505
  return true;
2457
2506
  }
2458
2507
  };
@@ -2461,10 +2510,10 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2461
2510
  var kInvalidCornerIndex3 = -1;
2462
2511
  var MeshPredictionSchemeMultiParallelogramDecoder = class extends MeshPredictionSchemeDecoder {
2463
2512
  computeOriginalValues(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2464
- this.h.init(numComponents);
2513
+ this.f.init(numComponents);
2465
2514
  const predVals = new Int32Array(numComponents);
2466
2515
  const parallelogramPredVals = new Int32Array(numComponents);
2467
- this.h.computeOriginalValue(predVals, 0, inCorr, 0, outData, 0);
2516
+ this.f.computeOriginalValue(predVals, 0, inCorr, 0, outData, 0);
2468
2517
  const table = this.c.cornerTable;
2469
2518
  const vertexToDataMap = this.c.vertexToDataMap;
2470
2519
  const oppositeCorners = table.oppositeCornerArray();
@@ -2501,12 +2550,12 @@ var MeshPredictionSchemeMultiParallelogramDecoder = class extends MeshPrediction
2501
2550
  const dstOffset = p * numComponents;
2502
2551
  if (numParallelograms === 0) {
2503
2552
  const srcOffset = (p - 1) * numComponents;
2504
- this.h.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2553
+ this.f.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2505
2554
  } else {
2506
2555
  for (let c = 0; c < numComponents; ++c) {
2507
2556
  predVals[c] = predVals[c] / numParallelograms | 0;
2508
2557
  }
2509
- this.h.computeOriginalValue(predVals, 0, inCorr, dstOffset, outData, dstOffset);
2558
+ this.f.computeOriginalValue(predVals, 0, inCorr, dstOffset, outData, dstOffset);
2510
2559
  }
2511
2560
  }
2512
2561
  return true;
@@ -2518,8 +2567,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2518
2567
  // Zigzag-fused variant: decodes corrections that are still in their unsigned
2519
2568
  // zigzag form, unpacking each one inline.
2520
2569
  computeOriginalValuesZigzag(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2521
- this.h.init(numComponents);
2522
- return this.mc(inCorr, outData, numComponents, true);
2570
+ this.f.init(numComponents);
2571
+ return this.kc(inCorr, outData, numComponents, true);
2523
2572
  }
2524
2573
  // The wrap transform's corrections are zigzag-coded; with `zigzag` set the
2525
2574
  // decode folds the (val >>> 1) ^ -(val & 1) unpacking into each correction
@@ -2527,23 +2576,19 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2527
2576
  // whole array (see computeOriginalValuesZigzag). Every correction is read
2528
2577
  // exactly once before its slot is overwritten, so the in-place aliasing of
2529
2578
  // inCorr and outData is preserved.
2530
- mc(inCorr, outData, numComponents, zigzag) {
2579
+ kc(inCorr, outData, numComponents, zigzag) {
2531
2580
  if (numComponents === 2) {
2532
- return this.nc(inCorr, outData, zigzag);
2581
+ return this.lc(inCorr, outData, zigzag);
2533
2582
  }
2534
2583
  if (numComponents === 3) {
2535
- return this.oc(inCorr, outData, zigzag);
2584
+ return this.mc(inCorr, outData, zigzag);
2536
2585
  }
2537
2586
  if (numComponents === 4) {
2538
- return this.pc(inCorr, outData, zigzag);
2587
+ return this.nc(inCorr, outData, zigzag);
2539
2588
  }
2540
- const table = this.c.cornerTable;
2541
- const vertexToDataMap = this.c.vertexToDataMap;
2542
- const oppositeCorners = table.oppositeCornerArray();
2543
- const cornerToVertex = table.cornerToVertexArray();
2544
- const dataToCornerMap = this.c.dataToCornerMap;
2545
- const transform = this.h;
2546
- const minValue = transform.fa;
2589
+ const parents = this.c.parallelogramParents();
2590
+ const transform = this.f;
2591
+ const minValue = transform.X;
2547
2592
  const maxValue = transform.m;
2548
2593
  const maxDif = transform.ga;
2549
2594
  for (let c = 0; c < numComponents; ++c) {
@@ -2562,30 +2607,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2562
2607
  }
2563
2608
  outData[c] = orig;
2564
2609
  }
2565
- const cornerMapSize = dataToCornerMap.length;
2566
- for (let p = 1; p < cornerMapSize; ++p) {
2567
- const cornerId = dataToCornerMap[p];
2610
+ const numValues = this.c.dataToCornerMap.length;
2611
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2568
2612
  const dstOffset = p * numComponents;
2569
- const oci = oppositeCorners[cornerId];
2570
- let hasPrediction = false;
2571
- let vOppOff = 0;
2572
- let vNextOff = 0;
2573
- let vPrevOff = 0;
2574
- if (oci >= 0) {
2575
- const rem = oci - (oci / 3 | 0) * 3;
2576
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2577
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2578
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2579
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2580
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2581
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2582
- vOppOff = vertOpp * numComponents;
2583
- vNextOff = vertNext * numComponents;
2584
- vPrevOff = vertPrev * numComponents;
2585
- hasPrediction = true;
2586
- }
2587
- }
2588
- if (hasPrediction) {
2613
+ const vertOpp = parents[o];
2614
+ if (vertOpp >= 0) {
2615
+ const vOppOff = vertOpp * numComponents;
2616
+ const vNextOff = parents[o + 1] * numComponents;
2617
+ const vPrevOff = parents[o + 2] * numComponents;
2589
2618
  for (let c = 0; c < numComponents; ++c) {
2590
2619
  let pred = outData[vNextOff + c] + outData[vPrevOff + c] - outData[vOppOff + c] | 0;
2591
2620
  if (pred > maxValue) {
@@ -2603,7 +2632,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2603
2632
  outData[dstOffset + c] = orig;
2604
2633
  }
2605
2634
  } else {
2606
- const srcOffset = (p - 1) * numComponents;
2635
+ const srcOffset = dstOffset - numComponents;
2607
2636
  for (let c = 0; c < numComponents; ++c) {
2608
2637
  let pred = outData[srcOffset + c];
2609
2638
  if (pred > maxValue) {
@@ -2624,14 +2653,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2624
2653
  }
2625
2654
  return true;
2626
2655
  }
2627
- nc(inCorr, outData, zigzag) {
2628
- const table = this.c.cornerTable;
2629
- const vertexToDataMap = this.c.vertexToDataMap;
2630
- const oppositeCorners = table.oppositeCornerArray();
2631
- const cornerToVertex = table.cornerToVertexArray();
2632
- const dataToCornerMap = this.c.dataToCornerMap;
2633
- const transform = this.h;
2634
- const minValue = transform.fa;
2656
+ lc(inCorr, outData, zigzag) {
2657
+ const parents = this.c.parallelogramParents();
2658
+ const transform = this.f;
2659
+ const minValue = transform.X;
2635
2660
  const maxValue = transform.m;
2636
2661
  const maxDif = transform.ga;
2637
2662
  let pred0 = 0;
@@ -2662,30 +2687,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2662
2687
  }
2663
2688
  outData[0] = orig0;
2664
2689
  outData[1] = orig1;
2665
- const cornerMapSize = dataToCornerMap.length;
2666
- for (let p = 1; p < cornerMapSize; ++p) {
2667
- const cornerId = dataToCornerMap[p];
2690
+ const numValues = this.c.dataToCornerMap.length;
2691
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2668
2692
  const dstOffset = p * 2;
2669
- const oci = oppositeCorners[cornerId];
2670
- let hasPrediction = false;
2671
- let vOppOff = 0;
2672
- let vNextOff = 0;
2673
- let vPrevOff = 0;
2674
- if (oci >= 0) {
2675
- const rem = oci - (oci / 3 | 0) * 3;
2676
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2677
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2678
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2679
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2680
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2681
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2682
- vOppOff = vertOpp * 2;
2683
- vNextOff = vertNext * 2;
2684
- vPrevOff = vertPrev * 2;
2685
- hasPrediction = true;
2686
- }
2687
- }
2688
- if (hasPrediction) {
2693
+ const vertOpp = parents[o];
2694
+ if (vertOpp >= 0) {
2695
+ const vOppOff = vertOpp * 2;
2696
+ const vNextOff = parents[o + 1] * 2;
2697
+ const vPrevOff = parents[o + 2] * 2;
2689
2698
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2690
2699
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2691
2700
  } else {
@@ -2722,14 +2731,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2722
2731
  }
2723
2732
  return true;
2724
2733
  }
2725
- oc(inCorr, outData, zigzag) {
2726
- const table = this.c.cornerTable;
2727
- const vertexToDataMap = this.c.vertexToDataMap;
2728
- const oppositeCorners = table.oppositeCornerArray();
2729
- const cornerToVertex = table.cornerToVertexArray();
2730
- const dataToCornerMap = this.c.dataToCornerMap;
2731
- const transform = this.h;
2732
- const minValue = transform.fa;
2734
+ mc(inCorr, outData, zigzag) {
2735
+ const parents = this.c.parallelogramParents();
2736
+ const transform = this.f;
2737
+ const minValue = transform.X;
2733
2738
  const maxValue = transform.m;
2734
2739
  const maxDif = transform.ga;
2735
2740
  let pred0 = 0;
@@ -2774,30 +2779,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2774
2779
  outData[0] = orig0;
2775
2780
  outData[1] = orig1;
2776
2781
  outData[2] = orig2;
2777
- const cornerMapSize = dataToCornerMap.length;
2778
- for (let p = 1; p < cornerMapSize; ++p) {
2779
- const cornerId = dataToCornerMap[p];
2782
+ const numValues = this.c.dataToCornerMap.length;
2783
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2780
2784
  const dstOffset = p * 3;
2781
- const oci = oppositeCorners[cornerId];
2782
- let hasPrediction = false;
2783
- let vOppOff = 0;
2784
- let vNextOff = 0;
2785
- let vPrevOff = 0;
2786
- if (oci >= 0) {
2787
- const rem = oci - (oci / 3 | 0) * 3;
2788
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2789
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2790
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2791
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2792
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2793
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2794
- vOppOff = vertOpp * 3;
2795
- vNextOff = vertNext * 3;
2796
- vPrevOff = vertPrev * 3;
2797
- hasPrediction = true;
2798
- }
2799
- }
2800
- if (hasPrediction) {
2785
+ const vertOpp = parents[o];
2786
+ if (vertOpp >= 0) {
2787
+ const vOppOff = vertOpp * 3;
2788
+ const vNextOff = parents[o + 1] * 3;
2789
+ const vPrevOff = parents[o + 2] * 3;
2801
2790
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2802
2791
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2803
2792
  pred2 = outData[vNextOff + 2] + outData[vPrevOff + 2] - outData[vOppOff + 2] | 0;
@@ -2851,14 +2840,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2851
2840
  }
2852
2841
  // Four components: tangents, RGBA colors, skin joints/weights. Same
2853
2842
  // structure as the 2/3-component loops.
2854
- pc(inCorr, outData, zigzag) {
2855
- const table = this.c.cornerTable;
2856
- const vertexToDataMap = this.c.vertexToDataMap;
2857
- const oppositeCorners = table.oppositeCornerArray();
2858
- const cornerToVertex = table.cornerToVertexArray();
2859
- const dataToCornerMap = this.c.dataToCornerMap;
2860
- const transform = this.h;
2861
- const minValue = transform.fa;
2843
+ nc(inCorr, outData, zigzag) {
2844
+ const parents = this.c.parallelogramParents();
2845
+ const transform = this.f;
2846
+ const minValue = transform.X;
2862
2847
  const maxValue = transform.m;
2863
2848
  const maxDif = transform.ga;
2864
2849
  let pred0 = 0;
@@ -2870,31 +2855,15 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2870
2855
  let pred1 = pred0;
2871
2856
  let pred2 = pred0;
2872
2857
  let pred3 = pred0;
2873
- const cornerMapSize = dataToCornerMap.length;
2874
- for (let p = 0; p < cornerMapSize; ++p) {
2858
+ const numValues = this.c.dataToCornerMap.length;
2859
+ for (let p = 0, o = 0; p < numValues; ++p, o += 3) {
2875
2860
  const dstOffset = p * 4;
2876
2861
  if (p > 0) {
2877
- const cornerId = dataToCornerMap[p];
2878
- const oci = oppositeCorners[cornerId];
2879
- let hasPrediction = false;
2880
- let vOppOff = 0;
2881
- let vNextOff = 0;
2882
- let vPrevOff = 0;
2883
- if (oci >= 0) {
2884
- const rem = oci - (oci / 3 | 0) * 3;
2885
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2886
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2887
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2888
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2889
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2890
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2891
- vOppOff = vertOpp * 4;
2892
- vNextOff = vertNext * 4;
2893
- vPrevOff = vertPrev * 4;
2894
- hasPrediction = true;
2895
- }
2896
- }
2897
- if (hasPrediction) {
2862
+ const vertOpp = parents[o];
2863
+ if (vertOpp >= 0) {
2864
+ const vOppOff = vertOpp * 4;
2865
+ const vNextOff = parents[o + 1] * 4;
2866
+ const vPrevOff = parents[o + 2] * 4;
2898
2867
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2899
2868
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2900
2869
  pred2 = outData[vNextOff + 2] + outData[vPrevOff + 2] - outData[vOppOff + 2] | 0;
@@ -2979,39 +2948,39 @@ function bigIntSqrt(value) {
2979
2948
  return x;
2980
2949
  }
2981
2950
  var MeshPredictionSchemeTexCoordsPortablePredictor = class {
2951
+ xa = null;
2982
2952
  ya = null;
2983
- za = null;
2984
2953
  u = new Int32Array(2);
2985
- Ta = new Uint8Array(0);
2986
- Ba = 0;
2954
+ Sa = new Uint8Array(0);
2955
+ Aa = 0;
2987
2956
  c;
2988
- fb = new Array(3);
2957
+ db = new Array(3);
2989
2958
  // Flat Int32 position cache so fetches are array reads, not convertValue calls.
2990
- Aa = null;
2959
+ za = null;
2991
2960
  j = null;
2992
2961
  constructor(meshData) {
2993
2962
  this.c = meshData;
2994
2963
  }
2995
2964
  setPositionAttribute(positionAttribute) {
2996
- this.ya = positionAttribute;
2965
+ this.xa = positionAttribute;
2997
2966
  }
2998
2967
  setEntryToPointIdMap(map) {
2999
- this.za = map;
2968
+ this.ya = map;
3000
2969
  }
3001
2970
  get predictedValue() {
3002
2971
  return this.u;
3003
2972
  }
3004
2973
  resizeOrientations(numOrientations) {
3005
- this.Ta = new Uint8Array(numOrientations);
3006
- this.Ba = numOrientations;
2974
+ this.Sa = new Uint8Array(numOrientations);
2975
+ this.Aa = numOrientations;
3007
2976
  }
3008
2977
  setOrientation(i, v) {
3009
- this.Ta[i] = v ? 1 : 0;
2978
+ this.Sa[i] = v ? 1 : 0;
3010
2979
  }
3011
2980
  buildPositionCache(numEntries) {
3012
2981
  const posCache = new Int32Array(numEntries * 3);
3013
- fillInt32PositionCache(posCache, this.ya, this.za, numEntries, this.fb);
3014
- this.Aa = posCache;
2982
+ fillInt32PositionCache(posCache, this.xa, this.ya, numEntries, this.db);
2983
+ this.za = posCache;
3015
2984
  this.j = this.c.cornerTable.cornerToVertexArray();
3016
2985
  }
3017
2986
  computePredictedValue(cornerId, data, dataId) {
@@ -3034,7 +3003,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3034
3003
  this.u[1] = pUV1;
3035
3004
  return true;
3036
3005
  }
3037
- const posCache = this.Aa;
3006
+ const posCache = this.za;
3038
3007
  let posOffset = dataId * 3;
3039
3008
  const tip0 = posCache[posOffset];
3040
3009
  const tip1 = posCache[posOffset + 1];
@@ -3071,7 +3040,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3071
3040
  const pnAbsMaxG = Math.max(Math.abs(pn0), Math.abs(pn1), Math.abs(pn2));
3072
3041
  const cnDotPnAbs = Math.abs(cnDotPn);
3073
3042
  if (cnNorm2 > SAFE_PRODUCT / pnNorm2Squared || nUVAbsMax > SAFE_PRODUCT / pnNorm2Squared || pnUVAbsMax > 0 && cnDotPnAbs > SAFE_PRODUCT / pnUVAbsMax || pnAbsMaxG > 0 && cnDotPnAbs > SAFE_PRODUCT / pnAbsMaxG) {
3074
- return this.qc(
3043
+ return this.oc(
3075
3044
  tip0,
3076
3045
  tip1,
3077
3046
  tip2,
@@ -3103,10 +3072,10 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3103
3072
  const normSquared = Math.floor(Math.sqrt(cxNorm2Squared * pnNorm2Squared));
3104
3073
  const cxUV0 = pnUV1 * normSquared;
3105
3074
  const cxUV1 = -pnUV0 * normSquared;
3106
- if (this.Ba === 0) {
3075
+ if (this.Aa === 0) {
3107
3076
  return false;
3108
3077
  }
3109
- const orientation = this.Ta[--this.Ba];
3078
+ const orientation = this.Sa[--this.Aa];
3110
3079
  if (orientation) {
3111
3080
  this.u[0] = Math.trunc((xUV0 + cxUV0) / pnNorm2Squared);
3112
3081
  this.u[1] = Math.trunc((xUV1 + cxUV1) / pnNorm2Squared);
@@ -3141,7 +3110,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3141
3110
  // <uint64_t>, including the uint64 wraparound in IntSqrt(cxNorm2*pnNorm2) and
3142
3111
  // the unsigned add/sub forming the final UV. Returns false in the same
3143
3112
  // overflow cases as the double path so encoder and decoder agree on fallback.
3144
- qc(tip0, tip1, tip2, next0, next1, next2, pn0, pn1, pn2, nUV0, nUV1, pUV0, pUV1, pnNorm2SquaredNum) {
3113
+ oc(tip0, tip1, tip2, next0, next1, next2, pn0, pn1, pn2, nUV0, nUV1, pUV0, pUV1, pnNorm2SquaredNum) {
3145
3114
  const B = BigInt;
3146
3115
  const tip = [B(tip0), B(tip1), B(tip2)];
3147
3116
  const nxt = [B(next0), B(next1), B(next2)];
@@ -3175,8 +3144,8 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3175
3144
  const normSquared = bigIntSqrt(cxNorm2 * pnN2 & MASK64);
3176
3145
  const cxUV0 = B.asIntN(64, pnUV1 * normSquared);
3177
3146
  const cxUV1 = B.asIntN(64, -pnUV0 * normSquared);
3178
- if (this.Ba === 0) return false;
3179
- const orientation = this.Ta[--this.Ba];
3147
+ if (this.Aa === 0) return false;
3148
+ const orientation = this.Sa[--this.Aa];
3180
3149
  let s0, s1;
3181
3150
  if (orientation) {
3182
3151
  s0 = B.asUintN(64, B.asUintN(64, xUV0) + B.asUintN(64, cxUV0));
@@ -3232,7 +3201,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3232
3201
  return false;
3233
3202
  }
3234
3203
  this.t.setEntryToPointIdMap(entryToPointIdMap);
3235
- this.h.init(numComponents);
3204
+ this.f.init(numComponents);
3236
3205
  const cornerMapSize = this.c.dataToCornerMap.length;
3237
3206
  this.t.buildPositionCache(cornerMapSize);
3238
3207
  for (let p = 0; p < cornerMapSize; ++p) {
@@ -3241,7 +3210,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3241
3210
  return false;
3242
3211
  }
3243
3212
  const dstOffset = p * numComponents;
3244
- this.h.computeOriginalValue(this.t.predictedValue, 0, inCorr, dstOffset, outData, dstOffset);
3213
+ this.f.computeOriginalValue(this.t.predictedValue, 0, inCorr, dstOffset, outData, dstOffset);
3245
3214
  }
3246
3215
  return true;
3247
3216
  }
@@ -3250,7 +3219,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3250
3219
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeDeltaDecoder.ts
3251
3220
  var PredictionSchemeDeltaDecoder = class extends PredictionSchemeDecoder {
3252
3221
  computeOriginalValues(inCorr, outData, size, numComponents, _entryToPointIdMap) {
3253
- const transform = this.h;
3222
+ const transform = this.f;
3254
3223
  transform.init(numComponents);
3255
3224
  if (transform.computeOriginalValuesDelta) {
3256
3225
  transform.computeOriginalValuesDelta(inCorr, outData, size, numComponents);
@@ -3296,11 +3265,7 @@ function createPredictionSchemeForDecoder(method, attId, decoder, transform) {
3296
3265
  const encodingData = meshDecoder.getAttributeEncodingData(attId);
3297
3266
  if (cornerTable !== null && encodingData !== null) {
3298
3267
  const attCornerTable = meshDecoder.getAttributeCornerTable(attId);
3299
- const meshData = new MeshPredictionSchemeData(
3300
- attCornerTable !== null ? attCornerTable : cornerTable,
3301
- encodingData.encodedAttributeValueIndexToCornerMap,
3302
- encodingData.vertexToEncodedAttributeValueIndexMap
3303
- );
3268
+ const meshData = new MeshPredictionSchemeData(attCornerTable !== null ? attCornerTable : cornerTable, encodingData);
3304
3269
  const ret = createMeshPredictionSchemeDecoder(method, transform, meshData);
3305
3270
  if (ret !== null) return ret;
3306
3271
  }
@@ -3309,22 +3274,25 @@ function createPredictionSchemeForDecoder(method, attId, decoder, transform) {
3309
3274
 
3310
3275
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeWrapDecodingTransform.ts
3311
3276
  var PredictionSchemeWrapDecodingTransform = class {
3312
- z = 0;
3313
- fa = 0;
3277
+ y = 0;
3278
+ X = 0;
3314
3279
  m = 0;
3315
3280
  ga = 0;
3316
3281
  getType() {
3317
3282
  return 1 /* PREDICTION_TRANSFORM_WRAP */;
3318
3283
  }
3319
3284
  init(numComponents) {
3320
- this.z = numComponents;
3285
+ this.y = numComponents;
3321
3286
  }
3322
3287
  areCorrectionsPositive() {
3323
3288
  return false;
3324
3289
  }
3290
+ boundsValues(limit) {
3291
+ return this.m < limit && this.X > -limit;
3292
+ }
3325
3293
  computeOriginalValue(predictedVals, predictedOffset, corrVals, corrOffset, outOriginalVals, outOffset) {
3326
- const nc = this.z;
3327
- const minValue = this.fa;
3294
+ const nc = this.y;
3295
+ const minValue = this.X;
3328
3296
  const maxValue = this.m;
3329
3297
  const maxDif = this.ga;
3330
3298
  for (let i = 0; i < nc; ++i) {
@@ -3350,7 +3318,7 @@ var PredictionSchemeWrapDecodingTransform = class {
3350
3318
  if (maxValue === void 0) return false;
3351
3319
  const dif = maxValue - minValue;
3352
3320
  if (dif < 0 || dif >= 2147483647) return false;
3353
- this.fa = minValue;
3321
+ this.X = minValue;
3354
3322
  this.m = maxValue;
3355
3323
  this.ga = 1 + dif;
3356
3324
  return true;
@@ -3359,39 +3327,39 @@ var PredictionSchemeWrapDecodingTransform = class {
3359
3327
 
3360
3328
  // src/decoder/compression/attributes/SequentialIntegerAttributeDecoder.ts
3361
3329
  var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder {
3362
- ha = null;
3330
+ Q = null;
3363
3331
  // Two-phase decode state (see SequentialAttributeDecoder): the parse phase
3364
3332
  // stashes the primed raw-symbol stream here so the controller can batch and
3365
3333
  // pair several attributes' decodes; the finish phase consumes it.
3366
- ia = null;
3367
- hb = 0;
3368
- Mb = null;
3334
+ ha = null;
3335
+ fb = 0;
3336
+ Kb = null;
3369
3337
  // Int32 view over the portable attribute's storage (see preparePortableAttribute).
3370
- V = null;
3338
+ Y = null;
3371
3339
  // --- Two-phase decode (parse headers / batch symbol decode / finish) ---
3372
3340
  pendingSymbolStream() {
3373
- if (this.ia === null) {
3341
+ if (this.ha === null) {
3374
3342
  return null;
3375
3343
  }
3376
- const portableData = this.V;
3344
+ const portableData = this.Y;
3377
3345
  return {
3378
- ans: this.ia.o,
3379
- out: new Uint32Array(portableData.buffer, portableData.byteOffset, this.hb),
3380
- count: this.hb
3346
+ ans: this.ha.K,
3347
+ out: new Uint32Array(portableData.buffer, portableData.byteOffset, this.fb),
3348
+ count: this.fb
3381
3349
  };
3382
3350
  }
3383
3351
  decodePortableAttributeFinish() {
3384
- if (this.ia !== null) {
3385
- this.ia.endDecoding();
3386
- this.ia = null;
3352
+ if (this.ha !== null) {
3353
+ this.ha.endDecoding();
3354
+ this.ha = null;
3387
3355
  }
3388
- return this.rc(this.Mb);
3356
+ return this.pc(this.Kb);
3389
3357
  }
3390
3358
  // The parse phase of the integer decode: prediction scheme, portable
3391
3359
  // attribute, the symbol stream (raw streams are deferred to the finish
3392
3360
  // phase) and the prediction data.
3393
3361
  decodeValues(pointIds, buffer) {
3394
- this.Mb = pointIds;
3362
+ this.Kb = pointIds;
3395
3363
  let predictionSchemeMethod = buffer.decodeUint8();
3396
3364
  if (predictionSchemeMethod !== void 0) predictionSchemeMethod = predictionSchemeMethod << 24 >> 24;
3397
3365
  if (predictionSchemeMethod === void 0) return false;
@@ -3405,10 +3373,10 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3405
3373
  if (predictionTransformType < -1 /* PREDICTION_TRANSFORM_NONE */ || predictionTransformType >= 4 /* NUM_PREDICTION_SCHEME_TRANSFORM_TYPES */) {
3406
3374
  return false;
3407
3375
  }
3408
- this.ha = this.createIntPredictionScheme(predictionSchemeMethod, predictionTransformType);
3376
+ this.Q = this.createIntPredictionScheme(predictionSchemeMethod, predictionTransformType);
3409
3377
  }
3410
- if (this.ha) {
3411
- if (!this.initPredictionScheme(this.ha)) {
3378
+ if (this.Q) {
3379
+ if (!this.initPredictionScheme(this.Q)) {
3412
3380
  return false;
3413
3381
  }
3414
3382
  }
@@ -3419,7 +3387,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3419
3387
  const numEntries = pointIds.length;
3420
3388
  const numValues = numEntries * numComponents;
3421
3389
  this.preparePortableAttribute(numEntries, numComponents);
3422
- const portableAttributeData = this.V;
3390
+ const portableAttributeData = this.Y;
3423
3391
  if (portableAttributeData === null) {
3424
3392
  return false;
3425
3393
  }
@@ -3433,8 +3401,8 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3433
3401
  if (decoder === null) {
3434
3402
  return false;
3435
3403
  }
3436
- this.ia = decoder;
3437
- this.hb = numValues;
3404
+ this.ha = decoder;
3405
+ this.fb = numValues;
3438
3406
  } else if (scheme === 0 /* SYMBOL_CODING_TAGGED */) {
3439
3407
  const outUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
3440
3408
  if (!decodeTaggedSymbols(numValues, numComponents, buffer, outUint32)) {
@@ -3458,25 +3426,25 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3458
3426
  portableAttributeData[i] = val;
3459
3427
  }
3460
3428
  }
3461
- if (this.ha) {
3462
- if (!this.ha.decodePredictionData(buffer)) {
3429
+ if (this.Q) {
3430
+ if (!this.Q.decodePredictionData(buffer)) {
3463
3431
  return false;
3464
3432
  }
3465
3433
  }
3466
3434
  return true;
3467
3435
  }
3468
3436
  // The post-symbol tail of the decode: zigzag unpacking and prediction.
3469
- rc(pointIds) {
3437
+ pc(pointIds) {
3470
3438
  const numComponents = this.getNumValueComponents();
3471
3439
  const numValues = pointIds.length * numComponents;
3472
- const data = this.V;
3440
+ const data = this.Y;
3473
3441
  if (data === null) {
3474
3442
  return false;
3475
3443
  }
3476
3444
  if (numValues === 0) {
3477
3445
  return true;
3478
3446
  }
3479
- const ps = this.ha;
3447
+ const ps = this.Q;
3480
3448
  if (ps === null) {
3481
3449
  convertSymbolsToSignedInts(new Uint32Array(data.buffer, data.byteOffset, numValues), numValues, data);
3482
3450
  return true;
@@ -3491,7 +3459,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3491
3459
  return ps.computeOriginalValues(data, data, numValues, numComponents, pointIds);
3492
3460
  }
3493
3461
  transformAttributeToOriginalFormat(pointIds) {
3494
- return this.ib(pointIds.length);
3462
+ return this.gb(pointIds.length);
3495
3463
  }
3496
3464
  // Prediction scheme for decoding integer values; subclasses override for others.
3497
3465
  createIntPredictionScheme(method, transformType) {
@@ -3504,21 +3472,28 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3504
3472
  getNumValueComponents() {
3505
3473
  return this.attribute.numComponents;
3506
3474
  }
3475
+ // Whether the decoded values are known to lie below 2^24 in magnitude (the
3476
+ // range in which the float extraction needs no per-value float32 rounding,
3477
+ // see PointAttribute._lazyFloatValues): true when a prediction transform
3478
+ // clamps them into such a range. Unpredicted values are unbounded.
3479
+ Lb() {
3480
+ return this.Q !== null && this.Q.boundsValues(16777216);
3481
+ }
3507
3482
  // The decoded values stay in the portable attribute; the final attribute
3508
3483
  // only takes its size (see PointAttribute.setLazyInteger and the overrides
3509
3484
  // in the quantization / normal decoders).
3510
- Jb(numValues) {
3485
+ Hb(numValues) {
3511
3486
  this.attribute.resetLazy(numValues);
3512
3487
  return true;
3513
3488
  }
3514
3489
  // Hands the decoded integer values to the attribute, converted to its
3515
3490
  // integer type on extraction.
3516
- ib(_numValues) {
3491
+ gb(_numValues) {
3517
3492
  const dt = this.attribute.dataType;
3518
3493
  if (dt < 1 /* INT8 */ || dt > 6 /* UINT32 */) {
3519
3494
  return false;
3520
3495
  }
3521
- this.attribute.setLazyInteger(this.V);
3496
+ this.attribute.setLazyInteger(this.Y);
3522
3497
  return true;
3523
3498
  }
3524
3499
  preparePortableAttribute(numEntries, numComponents) {
@@ -3538,23 +3513,27 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3538
3513
  portAtt.uniqueId = this.attribute.uniqueId;
3539
3514
  this.ea = portAtt;
3540
3515
  const data = portAtt.buffer.data;
3541
- this.V = numEntries === 0 ? null : new Int32Array(data.buffer, data.byteOffset + portAtt.byteOffset, numEntries * numComponents);
3516
+ this.Y = numEntries === 0 ? null : new Int32Array(data.buffer, data.byteOffset + portAtt.byteOffset, numEntries * numComponents);
3542
3517
  }
3543
3518
  };
3544
3519
 
3545
3520
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeNormalOctahedronTransformBase.ts
3546
3521
  var PredictionSchemeNormalOctahedronTransformBase = class {
3547
- B = new OctahedronToolBox();
3522
+ z = new OctahedronToolBox();
3548
3523
  areCorrectionsPositive() {
3549
3524
  return true;
3550
3525
  }
3526
+ // Outputs are origS/origT + center with origS/origT in [-center, center].
3527
+ boundsValues(limit) {
3528
+ return this.z.fa < limit;
3529
+ }
3551
3530
  /** No-op to fulfill the transform interface. */
3552
3531
  init(_numComponents) {
3553
3532
  }
3554
3533
  quantizationBits() {
3555
- return this.B.quantizationBits();
3534
+ return this.z.quantizationBits();
3556
3535
  }
3557
- Nb(maxQuantizedValue) {
3536
+ Mb(maxQuantizedValue) {
3558
3537
  if (maxQuantizedValue % 2 === 0) return false;
3559
3538
  let q = 0;
3560
3539
  let v = maxQuantizedValue;
@@ -3562,7 +3541,7 @@ var PredictionSchemeNormalOctahedronTransformBase = class {
3562
3541
  v >>>= 1;
3563
3542
  q++;
3564
3543
  }
3565
- return this.B.setQuantizationBits(q);
3544
+ return this.z.setQuantizationBits(q);
3566
3545
  }
3567
3546
  };
3568
3547
 
@@ -3576,14 +3555,14 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
3576
3555
  if (maxQuantizedValue === void 0) return false;
3577
3556
  const centerValue = buffer.decodeInt32();
3578
3557
  if (centerValue === void 0) return false;
3579
- if (!this.Nb(maxQuantizedValue)) return false;
3580
- const q = this.B.quantizationBits();
3558
+ if (!this.Mb(maxQuantizedValue)) return false;
3559
+ const q = this.z.quantizationBits();
3581
3560
  return q >= 2 && q <= 30;
3582
3561
  }
3583
3562
  computeOriginalValue(predVals, predOffset, corrVals, corrOffset, outOrigVals, outOffset) {
3584
- const toolBox = this.B;
3585
- const center = toolBox.f;
3586
- const maxQuantizedValue = toolBox.xa;
3563
+ const toolBox = this.z;
3564
+ const center = toolBox.h;
3565
+ const maxQuantizedValue = toolBox.fa;
3587
3566
  const corrS = corrVals[corrOffset];
3588
3567
  const corrT = corrVals[corrOffset + 1];
3589
3568
  let predS = predVals[predOffset] - center;
@@ -3709,9 +3688,9 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
3709
3688
  // The arithmetic is computeOriginalValue above verbatim -- keep them in
3710
3689
  // sync; only the plumbing differs.
3711
3690
  computeOriginalValuesDelta(inCorr, outData, size, numComponents) {
3712
- const toolBox = this.B;
3713
- const center = toolBox.f;
3714
- const maxQuantizedValue = toolBox.xa;
3691
+ const toolBox = this.z;
3692
+ const center = toolBox.h;
3693
+ const maxQuantizedValue = toolBox.fa;
3715
3694
  let prevS = 0;
3716
3695
  let prevT = 0;
3717
3696
  for (let i = 0; i < size; i += numComponents) {
@@ -3845,12 +3824,12 @@ var PredictionSchemeNormalOctahedronDecodingTransform = class extends Prediction
3845
3824
  decodeTransformData(buffer) {
3846
3825
  const maxQuantizedValue = buffer.decodeInt32();
3847
3826
  if (maxQuantizedValue === void 0) return false;
3848
- return this.Nb(maxQuantizedValue);
3827
+ return this.Mb(maxQuantizedValue);
3849
3828
  }
3850
3829
  computeOriginalValue(predVals, predOffset, corrVals, corrOffset, outOrigVals, outOffset) {
3851
- const toolBox = this.B;
3852
- const center = toolBox.f;
3853
- const maxQuantizedValue = toolBox.xa;
3830
+ const toolBox = this.z;
3831
+ const center = toolBox.h;
3832
+ const maxQuantizedValue = toolBox.fa;
3854
3833
  const predS = predVals[predOffset] - center;
3855
3834
  const predT = predVals[predOffset + 1] - center;
3856
3835
  const corrS = corrVals[corrOffset];
@@ -3929,7 +3908,7 @@ var PredictionSchemeNormalOctahedronDecodingTransform = class extends Prediction
3929
3908
 
3930
3909
  // src/decoder/compression/attributes/SequentialNormalAttributeDecoder.ts
3931
3910
  var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeDecoder {
3932
- N = -1;
3911
+ P = -1;
3933
3912
  init(decoder, attributeId) {
3934
3913
  if (!super.init(decoder, attributeId)) {
3935
3914
  return false;
@@ -3944,15 +3923,19 @@ var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeD
3944
3923
  decodeDataNeededByPortableTransform(_pointIds, buffer) {
3945
3924
  const qBits = buffer.decodeUint8();
3946
3925
  if (qBits === void 0) return false;
3947
- this.N = qBits;
3926
+ this.P = qBits;
3948
3927
  return true;
3949
3928
  }
3950
3929
  // The octahedral-to-unit-vector transform is deferred to extractTo (see
3951
3930
  // PointAttribute.setLazyOctahedron).
3952
- ib(_numPoints) {
3953
- const q = this.N;
3931
+ gb(_numPoints) {
3932
+ const q = this.P;
3954
3933
  if (q < 2 || q > 30) return false;
3955
- this.attribute.setLazyOctahedron(this.V, Math.fround(2 / Math.fround((1 << q) - 2)));
3934
+ this.attribute.setLazyOctahedron(
3935
+ this.Y,
3936
+ Math.fround(2 / Math.fround((1 << q) - 2)),
3937
+ this.Lb()
3938
+ );
3956
3939
  return true;
3957
3940
  }
3958
3941
  createIntPredictionScheme(method, transformType) {
@@ -3966,9 +3949,9 @@ var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeD
3966
3949
 
3967
3950
  // src/decoder/compression/attributes/SequentialQuantizationAttributeDecoder.ts
3968
3951
  var SequentialQuantizationAttributeDecoder = class extends SequentialIntegerAttributeDecoder {
3969
- N = -1;
3970
- jb = [];
3971
- Ob = 0;
3952
+ P = -1;
3953
+ hb = [];
3954
+ Nb = 0;
3972
3955
  init(decoder, attributeId) {
3973
3956
  if (!super.init(decoder, attributeId)) {
3974
3957
  return false;
@@ -3978,39 +3961,39 @@ var SequentialQuantizationAttributeDecoder = class extends SequentialIntegerAttr
3978
3961
  // The quantization parameters (AttributeQuantizationTransform::DecodeParameters).
3979
3962
  decodeDataNeededByPortableTransform(_pointIds, buffer) {
3980
3963
  const numComponents = this.attribute.numComponents;
3981
- this.jb = new Array(numComponents);
3964
+ this.hb = new Array(numComponents);
3982
3965
  for (let i = 0; i < numComponents; i++) {
3983
3966
  const val = buffer.decodeFloat32();
3984
3967
  if (val === void 0) return false;
3985
- this.jb[i] = val;
3968
+ this.hb[i] = val;
3986
3969
  }
3987
3970
  const range = buffer.decodeFloat32();
3988
3971
  if (range === void 0) return false;
3989
- this.Ob = range;
3972
+ this.Nb = range;
3990
3973
  const qBits = buffer.decodeUint8();
3991
3974
  if (qBits === void 0 || qBits < 1 || qBits > 30) return false;
3992
- this.N = qBits;
3975
+ this.P = qBits;
3993
3976
  return true;
3994
3977
  }
3995
3978
  // Dequantization is deferred to extractTo (see PointAttribute.setLazyQuantized).
3996
- ib(_numValues) {
3997
- const maxQuantizedValue = (1 << this.N >>> 0) - 1;
3979
+ gb(_numValues) {
3980
+ const maxQuantizedValue = (1 << this.P >>> 0) - 1;
3998
3981
  if (maxQuantizedValue <= 0) return false;
3999
- const delta = Math.fround(this.Ob / Math.fround(maxQuantizedValue));
4000
- this.attribute.setLazyQuantized(this.V, this.jb, delta);
3982
+ const delta = Math.fround(this.Nb / Math.fround(maxQuantizedValue));
3983
+ this.attribute.setLazyQuantized(this.Y, this.hb, delta, this.Lb());
4001
3984
  return true;
4002
3985
  }
4003
3986
  };
4004
3987
 
4005
3988
  // src/decoder/compression/attributes/SequentialAttributeDecodersController.ts
4006
3989
  var SequentialAttributeDecodersController = class extends AttributesDecoder {
4007
- Ca = [];
3990
+ Ba = [];
4008
3991
  // Replaced by the sequencer's output in _prepareSequence.
4009
- Ua = new Int32Array(0);
4010
- W;
3992
+ Ta = new Int32Array(0);
3993
+ Z;
4011
3994
  constructor(sequencer) {
4012
3995
  super();
4013
- this.W = sequencer;
3996
+ this.Z = sequencer;
4014
3997
  }
4015
3998
  decodeAttributesDecoderData(buffer) {
4016
3999
  if (!super.decodeAttributesDecoderData(buffer)) {
@@ -4024,19 +4007,19 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4024
4007
  if (decoder === null || !decoder.init(this.getDecoder(), this.getAttributeId(i))) {
4025
4008
  return false;
4026
4009
  }
4027
- this.Ca[i] = decoder;
4010
+ this.Ba[i] = decoder;
4028
4011
  }
4029
4012
  return true;
4030
4013
  }
4031
- sc() {
4032
- if (!this.W.generateSequence()) {
4014
+ qc() {
4015
+ if (!this.Z.generateSequence()) {
4033
4016
  return false;
4034
4017
  }
4035
- this.Ua = this.W.getOutputPointIds();
4018
+ this.Ta = this.Z.getOutputPointIds();
4036
4019
  const numAttributes = this.getNumAttributes();
4037
4020
  for (let i = 0; i < numAttributes; i++) {
4038
4021
  const pa = this.getDecoder().pointCloud().attribute(this.getAttributeId(i));
4039
- if (!this.W.updatePointToAttributeIndexMapping(pa)) {
4022
+ if (!this.Z.updatePointToAttributeIndexMapping(pa)) {
4040
4023
  return false;
4041
4024
  }
4042
4025
  }
@@ -4050,24 +4033,24 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4050
4033
  // of the finish work reads the buffer, and dependents only read parent
4051
4034
  // portable VALUES in finish, so ordering and output stay identical.
4052
4035
  decodeAttributesParse(buffer) {
4053
- if (!this.sc()) {
4036
+ if (!this.qc()) {
4054
4037
  return false;
4055
4038
  }
4056
- const decoders = this.Ca;
4039
+ const decoders = this.Ba;
4057
4040
  for (let i = 0; i < decoders.length; i++) {
4058
- if (!decoders[i].decodePortableAttributeParse(this.Ua, buffer)) {
4041
+ if (!decoders[i].decodePortableAttributeParse(this.Ta, buffer)) {
4059
4042
  return false;
4060
4043
  }
4061
4044
  }
4062
4045
  for (let i = 0; i < decoders.length; i++) {
4063
- if (!decoders[i].decodeDataNeededByPortableTransform(this.Ua, buffer)) {
4046
+ if (!decoders[i].decodeDataNeededByPortableTransform(this.Ta, buffer)) {
4064
4047
  return false;
4065
4048
  }
4066
4049
  }
4067
4050
  return true;
4068
4051
  }
4069
4052
  collectPendingSymbolStreams(out) {
4070
- const decoders = this.Ca;
4053
+ const decoders = this.Ba;
4071
4054
  for (let i = 0; i < decoders.length; i++) {
4072
4055
  const pending = decoders[i].pendingSymbolStream();
4073
4056
  if (pending !== null) {
@@ -4076,14 +4059,14 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4076
4059
  }
4077
4060
  }
4078
4061
  decodeAttributesFinish() {
4079
- const decoders = this.Ca;
4062
+ const decoders = this.Ba;
4080
4063
  for (let i = 0; i < decoders.length; i++) {
4081
4064
  if (!decoders[i].decodePortableAttributeFinish()) {
4082
4065
  return false;
4083
4066
  }
4084
4067
  }
4085
4068
  for (let i = 0; i < decoders.length; i++) {
4086
- if (!decoders[i].transformAttributeToOriginalFormat(this.Ua)) {
4069
+ if (!decoders[i].transformAttributeToOriginalFormat(this.Ta)) {
4087
4070
  return false;
4088
4071
  }
4089
4072
  }
@@ -4094,7 +4077,7 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4094
4077
  if (locId < 0) {
4095
4078
  return null;
4096
4079
  }
4097
- return this.Ca[locId].getPortableAttribute();
4080
+ return this.Ba[locId].getPortableAttribute();
4098
4081
  }
4099
4082
  createSequentialDecoder(decoderType) {
4100
4083
  switch (decoderType) {
@@ -4130,30 +4113,30 @@ var TopologySplitEventData = class {
4130
4113
  // src/decoder/compression/mesh/traverser/DepthFirstTraverser.ts
4131
4114
  var kInvalidCornerIndex4 = -1;
4132
4115
  var kInvalidFaceIndex = -1;
4133
- var kInvalidVertexIndex2 = -1;
4116
+ var kInvalidVertexIndex = -1;
4134
4117
  var DepthFirstTraverser = class {
4135
4118
  a = null;
4136
- Da = null;
4137
- X = null;
4138
- Pb = [];
4139
- ja = 0;
4119
+ Ca = null;
4120
+ _ = null;
4121
+ Ob = [];
4122
+ ia = 0;
4140
4123
  // Identifies the traversal order for the shared traversal cache
4141
4124
  // (MESH_TRAVERSAL_DEPTH_FIRST). See MeshTraversalSequencer.
4142
- Qb = 0;
4125
+ Pb = 0;
4143
4126
  // The sequencer derives the point id sequence from the corner map after
4144
4127
  // the traversal (see traverseFromCorner).
4145
4128
  emitsPointIds = false;
4146
4129
  j = null;
4147
- s = null;
4148
- Rb = null;
4149
- J = 0;
4130
+ q = null;
4131
+ B = null;
4132
+ L = 0;
4150
4133
  init(cornerTable, observer) {
4151
4134
  this.a = cornerTable;
4152
- this.Da = observer;
4135
+ this.Ca = observer;
4153
4136
  this.j = cornerTable.cornerToVertexArray();
4154
- this.s = cornerTable.oppositeCornerArray();
4155
- this.Rb = cornerTable.vertexLeftmostCornerArray();
4156
- this.J = cornerTable.numCorners();
4137
+ this.q = cornerTable.oppositeCornerArray();
4138
+ this.B = cornerTable.vertexOnBoundaryArray();
4139
+ this.L = cornerTable.numCorners();
4157
4140
  }
4158
4141
  cornerTable() {
4159
4142
  return this.a;
@@ -4167,8 +4150,8 @@ var DepthFirstTraverser = class {
4167
4150
  // Decode-scoped scratch: released in bulk at the end of the decode.
4168
4151
  onTraversalStart() {
4169
4152
  const cornerTable = this.a;
4170
- this.X = scratchUint8Zeroed(cornerTable.numFaces());
4171
- this.Pb = scratchInt32(this.J);
4153
+ this._ = scratchUint8Zeroed(cornerTable.numFaces());
4154
+ this.Ob = scratchInt32(this.L);
4172
4155
  }
4173
4156
  // Traverses every face, seeding a new traversal at the first corner of each
4174
4157
  // face not yet reached. The visited check lives here rather than behind a
@@ -4177,8 +4160,8 @@ var DepthFirstTraverser = class {
4177
4160
  // was measurable next to the traversal itself.
4178
4161
  traverseAll() {
4179
4162
  const numFaces = this.a.numFaces();
4180
- const isFaceVisited = this.X;
4181
- for (let f = 0; f < numFaces && this.ja < numFaces; ++f) {
4163
+ const isFaceVisited = this._;
4164
+ for (let f = 0; f < numFaces && this.ia < numFaces; ++f) {
4182
4165
  if (isFaceVisited[f] === 0 && !this.traverseFromCorner(3 * f)) {
4183
4166
  return false;
4184
4167
  }
@@ -4186,19 +4169,19 @@ var DepthFirstTraverser = class {
4186
4169
  return true;
4187
4170
  }
4188
4171
  traverseFromCorner(cornerId) {
4189
- if (this.X[cornerId / 3 | 0]) {
4172
+ if (this._[cornerId / 3 | 0]) {
4190
4173
  return true;
4191
4174
  }
4192
- const isFaceVisited = this.X;
4193
- const observer = this.Da;
4175
+ const isFaceVisited = this._;
4176
+ const observer = this.Ca;
4194
4177
  const cornerToVertex = this.j;
4195
- const oppositeCorners = this.s;
4196
- const vertexLeftmost = this.Rb;
4197
- const stack = this.Pb;
4198
- let numVisitedFaces = this.ja;
4199
- const encodingData = observer.C;
4200
- const encodedToCornerMap = observer.kb;
4201
- const vertexToEncodedMap = observer.lb;
4178
+ const oppositeCorners = this.q;
4179
+ const vertexOnBoundary = this.B;
4180
+ const stack = this.Ob;
4181
+ let numVisitedFaces = this.ia;
4182
+ const encodingData = observer.p;
4183
+ const encodedToCornerMap = observer.ib;
4184
+ const vertexToEncodedMap = observer.jb;
4202
4185
  let numValues = encodingData.numValues;
4203
4186
  let stackSize = 0;
4204
4187
  stack[stackSize++] = cornerId;
@@ -4206,7 +4189,7 @@ var DepthFirstTraverser = class {
4206
4189
  const prevCorner = cornerId % 3 === 0 ? cornerId + 2 : cornerId - 1;
4207
4190
  const nextVert = cornerToVertex[nextCorner];
4208
4191
  const prevVert = cornerToVertex[prevCorner];
4209
- if (nextVert === kInvalidVertexIndex2 || prevVert === kInvalidVertexIndex2) {
4192
+ if (nextVert === kInvalidVertexIndex || prevVert === kInvalidVertexIndex) {
4210
4193
  return false;
4211
4194
  }
4212
4195
  if (vertexToEncodedMap[nextVert] < 0) {
@@ -4228,22 +4211,16 @@ var DepthFirstTraverser = class {
4228
4211
  isFaceVisited[faceId] = 1;
4229
4212
  numVisitedFaces++;
4230
4213
  const vertId = cornerToVertex[cornerId];
4231
- if (vertId === kInvalidVertexIndex2) {
4214
+ if (vertId === kInvalidVertexIndex) {
4232
4215
  encodingData.numValues = numValues;
4233
4216
  return false;
4234
4217
  }
4235
4218
  const faceBase = faceId * 3;
4236
4219
  const nextCornerId = cornerId === faceBase + 2 ? faceBase : cornerId + 1;
4237
4220
  if (vertexToEncodedMap[vertId] < 0) {
4238
- const lc = vertexLeftmost[vertId];
4239
- let onBoundary = true;
4240
- if (lc >= 0) {
4241
- const nextLc = lc % 3 === 2 ? lc - 2 : lc + 1;
4242
- onBoundary = oppositeCorners[nextLc] < 0;
4243
- }
4244
4221
  encodedToCornerMap[numValues] = cornerId;
4245
4222
  vertexToEncodedMap[vertId] = numValues++;
4246
- if (!onBoundary) {
4223
+ if (vertexOnBoundary[vertId] === 0) {
4247
4224
  cornerId = oppositeCorners[nextCornerId];
4248
4225
  faceId = cornerId / 3 | 0;
4249
4226
  continue;
@@ -4276,7 +4253,7 @@ var DepthFirstTraverser = class {
4276
4253
  }
4277
4254
  }
4278
4255
  }
4279
- this.ja = numVisitedFaces;
4256
+ this.ia = numVisitedFaces;
4280
4257
  encodingData.numValues = numValues;
4281
4258
  return true;
4282
4259
  }
@@ -4288,51 +4265,51 @@ var kInvalidFaceIndex2 = -1;
4288
4265
  var kMaxPriority = 3;
4289
4266
  var MaxPredictionDegreeTraverser = class {
4290
4267
  a = null;
4291
- Da = null;
4292
- X = null;
4293
- mb = null;
4294
- ja = 0;
4268
+ Ca = null;
4269
+ _ = null;
4270
+ kb = null;
4271
+ ia = 0;
4295
4272
  // One stack (bucket) per priority level [0, kMaxPriority).
4296
- Va = null;
4297
- Y = 0;
4273
+ Ua = null;
4274
+ $ = 0;
4298
4275
  // Prediction degree accumulated per vertex during traversal.
4299
- nb = null;
4276
+ lb = null;
4300
4277
  // Flat connectivity arrays (see DepthFirstTraverser for why).
4301
4278
  j = null;
4302
- s = null;
4279
+ q = null;
4303
4280
  // Identifies the traversal order for the shared traversal cache
4304
4281
  // (MESH_TRAVERSAL_PREDICTION_DEGREE). See MeshTraversalSequencer.
4305
- Qb = 1;
4282
+ Pb = 1;
4306
4283
  // Point ids are appended through the observer as vertices are visited.
4307
4284
  emitsPointIds = true;
4308
4285
  init(cornerTable, observer) {
4309
4286
  this.a = cornerTable;
4310
- this.Da = observer;
4311
- this.X = new Uint8Array(cornerTable.numFaces());
4312
- this.mb = new Uint8Array(cornerTable.numVertices());
4287
+ this.Ca = observer;
4288
+ this._ = new Uint8Array(cornerTable.numFaces());
4289
+ this.kb = new Uint8Array(cornerTable.numVertices());
4313
4290
  this.j = cornerTable.cornerToVertexArray();
4314
- this.s = cornerTable.oppositeCornerArray();
4315
- this.Va = [[], [], []];
4291
+ this.q = cornerTable.oppositeCornerArray();
4292
+ this.Ua = [[], [], []];
4316
4293
  }
4317
4294
  cornerTable() {
4318
4295
  return this.a;
4319
4296
  }
4320
4297
  // corner is always valid (>= 0) where these are used.
4321
- Sb(c) {
4298
+ Qb(c) {
4322
4299
  return c % 3 === 2 ? c - 2 : c + 1;
4323
4300
  }
4324
- Tb(c) {
4301
+ Rb(c) {
4325
4302
  return c % 3 === 0 ? c + 2 : c - 1;
4326
4303
  }
4327
4304
  onTraversalStart() {
4328
- this.nb = new Int32Array(this.a.numVertices());
4305
+ this.lb = new Int32Array(this.a.numVertices());
4329
4306
  }
4330
4307
  // Same contract as DepthFirstTraverser.traverseAll. Seeds every face
4331
4308
  // through traverseFromCorner (which re-checks the first face's vertices),
4332
4309
  // exactly as the sequencer's loop always has.
4333
4310
  traverseAll() {
4334
4311
  const numFaces = this.a.numFaces();
4335
- for (let f = 0; f < numFaces && this.ja < numFaces; ++f) {
4312
+ for (let f = 0; f < numFaces && this.ia < numFaces; ++f) {
4336
4313
  if (!this.traverseFromCorner(3 * f)) {
4337
4314
  return false;
4338
4315
  }
@@ -4341,11 +4318,11 @@ var MaxPredictionDegreeTraverser = class {
4341
4318
  }
4342
4319
  // Returns the priority of traversing the edge leading to cornerId. Mutates
4343
4320
  // the prediction degree of the destination vertex.
4344
- Ub(cornerId) {
4321
+ Sb(cornerId) {
4345
4322
  const vTip = this.j[cornerId];
4346
4323
  let priority = 0;
4347
- if (!this.mb[vTip]) {
4348
- const degree = ++this.nb[vTip];
4324
+ if (!this.kb[vTip]) {
4325
+ const degree = ++this.lb[vTip];
4349
4326
  priority = degree > 1 ? 1 : 2;
4350
4327
  }
4351
4328
  if (priority >= kMaxPriority) {
@@ -4353,38 +4330,38 @@ var MaxPredictionDegreeTraverser = class {
4353
4330
  }
4354
4331
  return priority;
4355
4332
  }
4356
- Vb(ci, priority) {
4357
- this.Va[priority].push(ci);
4358
- if (priority < this.Y) {
4359
- this.Y = priority;
4333
+ Tb(ci, priority) {
4334
+ this.Ua[priority].push(ci);
4335
+ if (priority < this.$) {
4336
+ this.$ = priority;
4360
4337
  }
4361
4338
  }
4362
4339
  // Retrieves the next available corner to traverse, processed by priority.
4363
4340
  // Returns kInvalidCornerIndex when no corner is available.
4364
- tc() {
4365
- for (let i = this.Y; i < kMaxPriority; ++i) {
4366
- const stack = this.Va[i];
4341
+ rc() {
4342
+ for (let i = this.$; i < kMaxPriority; ++i) {
4343
+ const stack = this.Ua[i];
4367
4344
  if (stack.length > 0) {
4368
4345
  const ret = stack.pop();
4369
- this.Y = i;
4346
+ this.$ = i;
4370
4347
  return ret;
4371
4348
  }
4372
4349
  }
4373
4350
  return kInvalidCornerIndex5;
4374
4351
  }
4375
4352
  traverseFromCorner(cornerId) {
4376
- if (this.nb.length === 0) {
4353
+ if (this.lb.length === 0) {
4377
4354
  return true;
4378
4355
  }
4379
4356
  const cornerToVertex = this.j;
4380
- const oppositeCorners = this.s;
4381
- const isFaceVisited = this.X;
4382
- const isVertexVisited = this.mb;
4383
- const observer = this.Da;
4384
- this.Va[0].push(cornerId);
4385
- this.Y = 0;
4386
- const firstNext = this.Sb(cornerId);
4387
- const firstPrev = this.Tb(cornerId);
4357
+ const oppositeCorners = this.q;
4358
+ const isFaceVisited = this._;
4359
+ const isVertexVisited = this.kb;
4360
+ const observer = this.Ca;
4361
+ this.Ua[0].push(cornerId);
4362
+ this.$ = 0;
4363
+ const firstNext = this.Qb(cornerId);
4364
+ const firstPrev = this.Rb(cornerId);
4388
4365
  const nextVert = cornerToVertex[firstNext];
4389
4366
  const prevVert = cornerToVertex[firstPrev];
4390
4367
  if (!isVertexVisited[nextVert]) {
@@ -4400,7 +4377,7 @@ var MaxPredictionDegreeTraverser = class {
4400
4377
  isVertexVisited[tipVertex] = 1;
4401
4378
  observer.onNewVertexVisited(tipVertex, cornerId);
4402
4379
  }
4403
- while ((cornerId = this.tc()) !== kInvalidCornerIndex5) {
4380
+ while ((cornerId = this.rc()) !== kInvalidCornerIndex5) {
4404
4381
  let faceId = cornerId / 3 | 0;
4405
4382
  if (isFaceVisited[faceId]) {
4406
4383
  continue;
@@ -4408,34 +4385,34 @@ var MaxPredictionDegreeTraverser = class {
4408
4385
  while (true) {
4409
4386
  faceId = cornerId / 3 | 0;
4410
4387
  isFaceVisited[faceId] = 1;
4411
- this.ja++;
4388
+ this.ia++;
4412
4389
  const vertId = cornerToVertex[cornerId];
4413
4390
  if (!isVertexVisited[vertId]) {
4414
4391
  isVertexVisited[vertId] = 1;
4415
4392
  observer.onNewVertexVisited(vertId, cornerId);
4416
4393
  }
4417
- const rightCornerId = oppositeCorners[this.Sb(cornerId)];
4418
- const leftCornerId = oppositeCorners[this.Tb(cornerId)];
4394
+ const rightCornerId = oppositeCorners[this.Qb(cornerId)];
4395
+ const leftCornerId = oppositeCorners[this.Rb(cornerId)];
4419
4396
  const rightFaceId = rightCornerId === kInvalidCornerIndex5 ? kInvalidFaceIndex2 : rightCornerId / 3 | 0;
4420
4397
  const leftFaceId = leftCornerId === kInvalidCornerIndex5 ? kInvalidFaceIndex2 : leftCornerId / 3 | 0;
4421
4398
  const isRightFaceVisited = rightFaceId === kInvalidFaceIndex2 || isFaceVisited[rightFaceId] !== 0;
4422
4399
  const isLeftFaceVisited = leftFaceId === kInvalidFaceIndex2 || isFaceVisited[leftFaceId] !== 0;
4423
4400
  if (!isLeftFaceVisited) {
4424
- const priority = this.Ub(leftCornerId);
4425
- if (isRightFaceVisited && priority <= this.Y) {
4401
+ const priority = this.Sb(leftCornerId);
4402
+ if (isRightFaceVisited && priority <= this.$) {
4426
4403
  cornerId = leftCornerId;
4427
4404
  continue;
4428
4405
  } else {
4429
- this.Vb(leftCornerId, priority);
4406
+ this.Tb(leftCornerId, priority);
4430
4407
  }
4431
4408
  }
4432
4409
  if (!isRightFaceVisited) {
4433
- const priority = this.Ub(rightCornerId);
4434
- if (priority <= this.Y) {
4410
+ const priority = this.Sb(rightCornerId);
4411
+ if (priority <= this.$) {
4435
4412
  cornerId = rightCornerId;
4436
4413
  continue;
4437
4414
  } else {
4438
- this.Vb(rightCornerId, priority);
4415
+ this.Tb(rightCornerId, priority);
4439
4416
  }
4440
4417
  }
4441
4418
  break;
@@ -4447,67 +4424,67 @@ var MaxPredictionDegreeTraverser = class {
4447
4424
 
4448
4425
  // src/decoder/compression/mesh/traverser/MeshAttributeIndicesEncodingObserver.ts
4449
4426
  var MeshAttributeIndicesEncodingObserver = class {
4450
- C;
4451
- W;
4452
- lb;
4453
- kb;
4454
- Wb;
4427
+ p;
4428
+ Z;
4429
+ jb;
4430
+ ib;
4431
+ Ub;
4455
4432
  constructor(mesh, sequencer, encodingData) {
4456
- this.C = encodingData;
4457
- this.W = sequencer;
4458
- this.lb = encodingData.vertexToEncodedAttributeValueIndexMap;
4459
- this.kb = encodingData.encodedAttributeValueIndexToCornerMap;
4460
- this.Wb = mesh.faces_;
4433
+ this.p = encodingData;
4434
+ this.Z = sequencer;
4435
+ this.jb = encodingData.vertexToEncodedAttributeValueIndexMap;
4436
+ this.ib = encodingData.encodedAttributeValueIndexToCornerMap;
4437
+ this.Ub = mesh.faces_;
4461
4438
  }
4462
4439
  onNewVertexVisited(vertex, corner) {
4463
- const pointId = this.Wb[corner];
4464
- this.W.addPointId(pointId);
4465
- const numValues = this.C.numValues;
4466
- this.kb[numValues] = corner;
4467
- this.lb[vertex] = numValues;
4468
- this.C.numValues++;
4440
+ const pointId = this.Ub[corner];
4441
+ this.Z.addPointId(pointId);
4442
+ const numValues = this.p.numValues;
4443
+ this.ib[numValues] = corner;
4444
+ this.jb[vertex] = numValues;
4445
+ this.p.numValues++;
4469
4446
  }
4470
4447
  };
4471
4448
 
4472
4449
  // src/decoder/compression/mesh/traverser/MeshTraversalSequencer.ts
4473
4450
  var MeshTraversalSequencer = class {
4474
- H;
4475
- C;
4476
- Ea = null;
4451
+ G;
4452
+ p;
4453
+ Da = null;
4477
4454
  x = new Int32Array(0);
4478
- Fa = 0;
4455
+ Ea = 0;
4479
4456
  // Per-decode cache, keyed by corner table, shared across the attribute
4480
4457
  // decoders of one mesh (see MeshEdgebreakerDecoderImpl).
4481
- ob;
4458
+ mb;
4482
4459
  // The cache entry the last generateSequence resolved to (hit or store);
4483
4460
  // carries the shared indicesMap.
4484
- pb = null;
4461
+ nb = null;
4485
4462
  // One representative corner per point id, when the connectivity decoder
4486
4463
  // recorded them (see MeshEdgebreakerDecoderImpl._assignAttributeVerticesAndPoints).
4487
- ka;
4464
+ ja;
4488
4465
  constructor(mesh, encodingData, traversalCache, pointCorner) {
4489
- this.H = mesh;
4490
- this.C = encodingData;
4491
- this.ob = traversalCache;
4492
- this.ka = pointCorner;
4466
+ this.G = mesh;
4467
+ this.p = encodingData;
4468
+ this.mb = traversalCache;
4469
+ this.ja = pointCorner;
4493
4470
  }
4494
4471
  setTraverser(traverser) {
4495
- this.Ea = traverser;
4472
+ this.Da = traverser;
4496
4473
  }
4497
4474
  generateSequence() {
4498
- const cornerTable = this.Ea.cornerTable();
4499
- const methodId = this.Ea.Qb;
4475
+ const cornerTable = this.Da.cornerTable();
4476
+ const methodId = this.Da.Pb;
4500
4477
  const cacheKey = cornerTable.cornerToVertexArray();
4501
- const encodingData = this.C;
4502
- let byMethod = this.ob.get(cacheKey);
4478
+ const encodingData = this.p;
4479
+ let byMethod = this.mb.get(cacheKey);
4503
4480
  const cached = byMethod && byMethod.get(methodId);
4504
4481
  if (cached !== void 0) {
4505
4482
  this.x = cached.pointIds;
4506
- encodingData.adoptTraversalResult(cached.vertexMap, cached.cornerMap, cached.numValues);
4507
- this.pb = cached;
4483
+ encodingData.adoptTraversalResult(cached);
4484
+ this.nb = cached;
4508
4485
  return true;
4509
4486
  }
4510
- if (!this.uc()) {
4487
+ if (!this.sc()) {
4511
4488
  return false;
4512
4489
  }
4513
4490
  const numValues = encodingData.numValues;
@@ -4519,39 +4496,41 @@ var MeshTraversalSequencer = class {
4519
4496
  }
4520
4497
  if (byMethod === void 0) {
4521
4498
  byMethod = /* @__PURE__ */ new Map();
4522
- this.ob.set(cacheKey, byMethod);
4499
+ this.mb.set(cacheKey, byMethod);
4523
4500
  }
4524
4501
  const entry = {
4525
4502
  pointIds: this.x,
4526
4503
  vertexMap: encodingData.vertexToEncodedAttributeValueIndexMap,
4527
4504
  cornerMap: encodingData.encodedAttributeValueIndexToCornerMap,
4528
4505
  numValues,
4529
- indicesMap: null
4506
+ indicesMap: null,
4507
+ parents: null
4530
4508
  };
4531
4509
  byMethod.set(methodId, entry);
4532
- this.pb = entry;
4510
+ encodingData.cacheEntry = entry;
4511
+ this.nb = entry;
4533
4512
  return true;
4534
4513
  }
4535
4514
  getOutputPointIds() {
4536
4515
  return this.x;
4537
4516
  }
4538
4517
  addPointId(pointId) {
4539
- this.x[this.Fa++] = pointId;
4518
+ this.x[this.Ea++] = pointId;
4540
4519
  }
4541
4520
  updatePointToAttributeIndexMapping(attribute) {
4542
- const entry = this.pb;
4521
+ const entry = this.nb;
4543
4522
  if (entry !== null && entry.indicesMap !== null) {
4544
4523
  attribute.setExplicitMappingShared(entry.indicesMap);
4545
4524
  return true;
4546
4525
  }
4547
- const cornerTable = this.Ea.cornerTable();
4548
- const numFaces = this.H.numFaces();
4549
- const numPoints = this.H.numPoints();
4526
+ const cornerTable = this.Da.cornerTable();
4527
+ const numFaces = this.G.numFaces();
4528
+ const numPoints = this.G.numPoints();
4550
4529
  attribute.setExplicitMappingUnfilled(numPoints);
4551
4530
  const cornerToVertex = cornerTable.cornerToVertexArray();
4552
- const vertexToAttEntry = this.C.vertexToEncodedAttributeValueIndexMap;
4531
+ const vertexToAttEntry = this.p.vertexToEncodedAttributeValueIndexMap;
4553
4532
  const indicesMap = attribute.indicesMap;
4554
- const pointCorner = this.ka;
4533
+ const pointCorner = this.ja;
4555
4534
  if (pointCorner !== null) {
4556
4535
  for (let p = 0; p < numPoints; ++p) {
4557
4536
  const vertId = cornerToVertex[pointCorner[p]];
@@ -4566,7 +4545,7 @@ var MeshTraversalSequencer = class {
4566
4545
  }
4567
4546
  } else {
4568
4547
  const numCorners = numFaces * 3;
4569
- const faces = this.H.faces_;
4548
+ const faces = this.G.faces_;
4570
4549
  for (let ci = 0; ci < numCorners; ++ci) {
4571
4550
  const vertId = cornerToVertex[ci];
4572
4551
  if (vertId < 0) {
@@ -4585,26 +4564,26 @@ var MeshTraversalSequencer = class {
4585
4564
  }
4586
4565
  return true;
4587
4566
  }
4588
- uc() {
4589
- this.Fa = 0;
4590
- this.x = scratchInt32(this.H.numPoints());
4591
- const traverser = this.Ea;
4567
+ sc() {
4568
+ this.Ea = 0;
4569
+ this.x = scratchInt32(this.G.numPoints());
4570
+ const traverser = this.Da;
4592
4571
  traverser.onTraversalStart();
4593
4572
  if (!traverser.traverseAll()) {
4594
4573
  return false;
4595
4574
  }
4596
4575
  if (!traverser.emitsPointIds) {
4597
- const numValues = this.C.numValues;
4598
- const cornerMap = this.C.encodedAttributeValueIndexToCornerMap;
4599
- const faces = this.H.faces_;
4576
+ const numValues = this.p.numValues;
4577
+ const cornerMap = this.p.encodedAttributeValueIndexToCornerMap;
4578
+ const faces = this.G.faces_;
4600
4579
  const outPointIds = this.x;
4601
4580
  for (let i = 0; i < numValues; ++i) {
4602
4581
  outPointIds[i] = faces[cornerMap[i]];
4603
4582
  }
4604
- this.Fa = numValues;
4583
+ this.Ea = numValues;
4605
4584
  }
4606
- if (this.Fa < this.x.length) {
4607
- this.x = this.x.subarray(0, this.Fa);
4585
+ if (this.Ea < this.x.length) {
4586
+ this.x = this.x.subarray(0, this.Ea);
4608
4587
  }
4609
4588
  return true;
4610
4589
  }
@@ -4615,30 +4594,30 @@ var kInvalidCornerIndex6 = -1;
4615
4594
  var MeshEdgebreakerDecoderImpl = class {
4616
4595
  n;
4617
4596
  a = null;
4618
- O = [];
4619
- la = new Uint8Array(0);
4620
- Z = 0;
4621
- qb = new MeshAttributeIndicesEncodingData();
4622
- Xb = -1;
4597
+ R = [];
4598
+ ka = new Uint8Array(0);
4599
+ aa = 0;
4600
+ ob = new MeshAttributeIndicesEncodingData();
4601
+ Vb = -1;
4623
4602
  // Cache of vertex-traversal results keyed by corner table, so attributes
4624
4603
  // sharing connectivity traverse once.
4625
- vc = /* @__PURE__ */ new Map();
4604
+ tc = /* @__PURE__ */ new Map();
4626
4605
  i = [];
4627
- K;
4606
+ M;
4628
4607
  // One corner per point id (decode-scoped scratch), filled by
4629
4608
  // _assignAttributeVerticesAndPoints; null when points are the base vertices.
4630
- ka = null;
4609
+ ja = null;
4631
4610
  // Corners on a boundary edge, counted by _decodeAttributeConnectivities.
4632
- Yb = 0;
4611
+ Wb = 0;
4633
4612
  constructor(decoder, TraversalDecoderClass) {
4634
4613
  this.n = decoder;
4635
- this.K = new TraversalDecoderClass();
4614
+ this.M = new TraversalDecoderClass();
4636
4615
  }
4637
4616
  getCornerTable() {
4638
4617
  return this.a;
4639
4618
  }
4640
4619
  // The attribute data set whose attributes decoder owns attId, if any.
4641
- Zb(attId) {
4620
+ Xb(attId) {
4642
4621
  for (let i = 0; i < this.i.length; ++i) {
4643
4622
  const ad = this.i[i];
4644
4623
  if (ad.decoderId < 0 || ad.decoderId >= this.n.numAttributesDecoders()) {
@@ -4654,12 +4633,12 @@ var MeshEdgebreakerDecoderImpl = class {
4654
4633
  return null;
4655
4634
  }
4656
4635
  getAttributeCornerTable(attId) {
4657
- const ad = this.Zb(attId);
4636
+ const ad = this.Xb(attId);
4658
4637
  return ad !== null && ad.isConnectivityUsed ? ad.connectivityData : null;
4659
4638
  }
4660
4639
  getAttributeEncodingData(attId) {
4661
- const ad = this.Zb(attId);
4662
- return ad !== null ? ad.encodingData : this.qb;
4640
+ const ad = this.Xb(attId);
4641
+ return ad !== null ? ad.encodingData : this.ob;
4663
4642
  }
4664
4643
  createAttributesDecoder(attDecoderId) {
4665
4644
  const buffer = this.n.buffer();
@@ -4677,10 +4656,10 @@ var MeshEdgebreakerDecoderImpl = class {
4677
4656
  }
4678
4657
  this.i[attDataId].decoderId = attDecoderId;
4679
4658
  } else {
4680
- if (this.Xb >= 0) {
4659
+ if (this.Vb >= 0) {
4681
4660
  return false;
4682
4661
  }
4683
- this.Xb = attDecoderId;
4662
+ this.Vb = attDecoderId;
4684
4663
  }
4685
4664
  const traversalMethod = buffer.decodeUint8();
4686
4665
  if (traversalMethod === void 0 || traversalMethod >= 2 /* NUM_TRAVERSAL_METHODS */) {
@@ -4690,7 +4669,7 @@ var MeshEdgebreakerDecoderImpl = class {
4690
4669
  let cornerTable;
4691
4670
  if (decoderType === 0 /* MESH_VERTEX_ATTRIBUTE */) {
4692
4671
  if (attDataId < 0) {
4693
- encodingData = this.qb;
4672
+ encodingData = this.ob;
4694
4673
  } else {
4695
4674
  encodingData = this.i[attDataId].encodingData;
4696
4675
  this.i[attDataId].isConnectivityUsed = false;
@@ -4701,12 +4680,12 @@ var MeshEdgebreakerDecoderImpl = class {
4701
4680
  return false;
4702
4681
  }
4703
4682
  const ad = this.i[attDataId];
4704
- if (ad.noInteriorSeams) this.wc(ad);
4683
+ if (ad.noInteriorSeams) this.uc(ad);
4705
4684
  encodingData = ad.encodingData;
4706
4685
  cornerTable = ad.connectivityData;
4707
4686
  }
4708
4687
  const mesh = this.n.mesh();
4709
- const sequencer = new MeshTraversalSequencer(mesh, encodingData, this.vc, this.ka);
4688
+ const sequencer = new MeshTraversalSequencer(mesh, encodingData, this.tc, this.ja);
4710
4689
  const observer = new MeshAttributeIndicesEncodingObserver(mesh, sequencer, encodingData);
4711
4690
  const traverser = traversalMethod === 1 /* MESH_TRAVERSAL_PREDICTION_DEGREE */ ? new MaxPredictionDegreeTraverser() : new DepthFirstTraverser();
4712
4691
  traverser.init(cornerTable, observer);
@@ -4717,17 +4696,17 @@ var MeshEdgebreakerDecoderImpl = class {
4717
4696
  const buffer = this.n.buffer();
4718
4697
  const numEncodedVertices = decodeVarint(buffer);
4719
4698
  if (numEncodedVertices === void 0) return false;
4720
- this.Z = numEncodedVertices;
4699
+ this.aa = numEncodedVertices;
4721
4700
  const numFaces = decodeVarint(buffer);
4722
4701
  if (numFaces === void 0) return false;
4723
4702
  if (numFaces > 2147483647 / 3) {
4724
4703
  return false;
4725
4704
  }
4726
- if (this.Z > numFaces * 3) {
4705
+ if (this.aa > numFaces * 3) {
4727
4706
  return false;
4728
4707
  }
4729
4708
  const minNumFaceEdges = Math.floor(3 * numFaces / 2);
4730
- const maxNumVertexEdges = this.Z * (this.Z - 1) / 2;
4709
+ const maxNumVertexEdges = this.aa * (this.aa - 1) / 2;
4731
4710
  if (maxNumVertexEdges < minNumFaceEdges) {
4732
4711
  return false;
4733
4712
  }
@@ -4754,29 +4733,31 @@ var MeshEdgebreakerDecoderImpl = class {
4754
4733
  ad.numSeamCorners = 0;
4755
4734
  this.i.push(ad);
4756
4735
  }
4757
- this.a.reset(numFaces, this.Z + numEncodedSplitSymbols);
4758
- this.la = scratchUint8Filled(this.Z + numEncodedSplitSymbols, 1);
4759
- if (!this.xc(buffer)) {
4736
+ this.a.reset(numFaces, this.aa + numEncodedSplitSymbols);
4737
+ this.ka = scratchUint8Filled(this.aa + numEncodedSplitSymbols, 1);
4738
+ if (!this.vc(buffer)) {
4760
4739
  return false;
4761
4740
  }
4762
- this.K.init(this);
4763
- this.K.setNumEncodedVertices(this.Z + numEncodedSplitSymbols);
4764
- this.K.setNumAttributeData(numAttributeData);
4741
+ this.M.init(this);
4742
+ this.M.setNumEncodedVertices(this.aa + numEncodedSplitSymbols);
4743
+ this.M.setNumAttributeData(numAttributeData);
4765
4744
  const traversalEndBuffer = new DecoderBuffer();
4766
- if (!this.K.start(traversalEndBuffer)) {
4745
+ if (!this.M.start(traversalEndBuffer)) {
4767
4746
  return false;
4768
4747
  }
4769
- const numConnectivityVerts = this.yc(numEncodedSymbols);
4748
+ const numConnectivityVerts = this.wc(numEncodedSymbols);
4770
4749
  if (numConnectivityVerts === -1) {
4771
4750
  return false;
4772
4751
  }
4773
4752
  buffer.init(traversalEndBuffer.dataHead, traversalEndBuffer.remainingSize);
4753
+ this.a.finishBoundaries();
4774
4754
  if (this.i.length > 0) {
4775
- this.zc();
4755
+ this.xc();
4776
4756
  }
4777
- this.K.done();
4778
- const numBoundaryCorners = this.Yb;
4757
+ this.M.done();
4758
+ const numBoundaryCorners = this.Wb;
4779
4759
  const distinctTables = [];
4760
+ const seamEdgeCounts = [];
4780
4761
  const adoptions = [];
4781
4762
  let previousConnectivityData = null;
4782
4763
  let previousSeamCorners = null;
@@ -4803,25 +4784,25 @@ var MeshEdgebreakerDecoderImpl = class {
4803
4784
  adoptions.push(connectivityData, previousConnectivityData);
4804
4785
  } else {
4805
4786
  connectivityData.initEmpty(this.a);
4806
- connectivityData.reserveSeamEdges(seamCount);
4807
4787
  for (let s = 0; s < seamCount; ++s) {
4808
4788
  connectivityData.addSeamEdge(seamCorners[s]);
4809
4789
  }
4810
4790
  distinctTables.push(connectivityData);
4791
+ seamEdgeCounts.push(seamCount);
4811
4792
  }
4812
4793
  previousConnectivityData = connectivityData;
4813
4794
  previousSeamCorners = seamCorners;
4814
4795
  previousSeamCount = seamCount;
4815
4796
  }
4816
4797
  if (this.i.length === 0) {
4817
- this.Ac(numConnectivityVerts);
4818
- } else if (!this.Bc(distinctTables)) {
4798
+ this.yc(numConnectivityVerts);
4799
+ } else if (!this.zc(distinctTables, seamEdgeCounts)) {
4819
4800
  return false;
4820
4801
  }
4821
4802
  for (let i = 0; i < adoptions.length; i += 2) {
4822
4803
  adoptions[i].adoptFrom(adoptions[i + 1]);
4823
4804
  }
4824
- this.qb.init(this.a.numVertices());
4805
+ this.ob.init(this.a.numVertices());
4825
4806
  for (let i = 0; i < this.i.length; ++i) {
4826
4807
  let attConnectivityVerts = this.i[i].connectivityData.numVertices();
4827
4808
  if (attConnectivityVerts < this.a.numVertices()) {
@@ -4831,11 +4812,11 @@ var MeshEdgebreakerDecoderImpl = class {
4831
4812
  }
4832
4813
  return true;
4833
4814
  }
4834
- Cc(encoderSymbolId, outResult) {
4835
- if (this.O.length === 0) {
4815
+ Ac(encoderSymbolId, outResult) {
4816
+ if (this.R.length === 0) {
4836
4817
  return false;
4837
4818
  }
4838
- const back = this.O[this.O.length - 1];
4819
+ const back = this.R[this.R.length - 1];
4839
4820
  if (back.sourceSymbolId > encoderSymbolId) {
4840
4821
  outResult.encoderSplitSymbolId = -1;
4841
4822
  return true;
@@ -4845,24 +4826,24 @@ var MeshEdgebreakerDecoderImpl = class {
4845
4826
  }
4846
4827
  outResult.faceEdge = back.sourceEdge;
4847
4828
  outResult.encoderSplitSymbolId = back.splitSymbolId;
4848
- this.O.pop();
4829
+ this.R.pop();
4849
4830
  return true;
4850
4831
  }
4851
- yc(numSymbols) {
4852
- const activeCornerStack = scratchInt32(numSymbols + this.O.length + 16);
4832
+ wc(numSymbols) {
4833
+ const activeCornerStack = scratchInt32(numSymbols + this.R.length + 16);
4853
4834
  let activeCornerStackSize = 0;
4854
4835
  const topologySplitActiveCorners = /* @__PURE__ */ new Map();
4855
4836
  const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
4856
4837
  const invalidVertices = [];
4857
4838
  const removeInvalidVertices = this.i.length === 0;
4858
- let maxNumVertices = this.la.length;
4839
+ let maxNumVertices = this.ka.length;
4859
4840
  let numFacesDecoded = 0;
4860
4841
  const cornerToVertex = this.a.j;
4861
- const oppositeCorners = this.a.s;
4842
+ const oppositeCorners = this.a.q;
4862
4843
  const vc = this.a;
4863
- let vertexCorners = vc.y;
4864
- const isVertHole = this.la;
4865
- const traversalDecoder = this.K;
4844
+ let vertexCorners = vc.v;
4845
+ const isVertHole = this.ka;
4846
+ const traversalDecoder = this.M;
4866
4847
  for (let symbolId = 0; symbolId < numSymbols; ++symbolId) {
4867
4848
  const faceIndex = numFacesDecoded++;
4868
4849
  let checkTopologySplit = false;
@@ -4914,13 +4895,13 @@ var MeshEdgebreakerDecoderImpl = class {
4914
4895
  oppositeCorners[oppCorner] = cornerA;
4915
4896
  oppositeCorners[cornerA] = oppCorner;
4916
4897
  let newVertIndex;
4917
- if (vc.l < vertexCorners.length) {
4918
- newVertIndex = vc.l++;
4898
+ if (vc.k < vertexCorners.length) {
4899
+ newVertIndex = vc.k++;
4919
4900
  } else {
4920
4901
  newVertIndex = vc.addNewVertex();
4921
- vertexCorners = vc.y;
4902
+ vertexCorners = vc.v;
4922
4903
  }
4923
- if (vc.l > maxNumVertices) return -1;
4904
+ if (vc.k > maxNumVertices) return -1;
4924
4905
  cornerToVertex[oppCorner] = newVertIndex;
4925
4906
  vertexCorners[newVertIndex] = oppCorner;
4926
4907
  const pA = cornerA % 3 === 0 ? cornerA + 2 : cornerA - 1;
@@ -4981,16 +4962,16 @@ var MeshEdgebreakerDecoderImpl = class {
4981
4962
  } else if (symbol === TOPOLOGY_E) {
4982
4963
  const corner = 3 * faceIndex;
4983
4964
  let firstVertIndex;
4984
- if (vc.l + 3 <= vertexCorners.length) {
4985
- firstVertIndex = vc.l;
4986
- vc.l += 3;
4965
+ if (vc.k + 3 <= vertexCorners.length) {
4966
+ firstVertIndex = vc.k;
4967
+ vc.k += 3;
4987
4968
  } else {
4988
4969
  firstVertIndex = vc.addNewVertex();
4989
4970
  vc.addNewVertex();
4990
4971
  vc.addNewVertex();
4991
- vertexCorners = vc.y;
4972
+ vertexCorners = vc.v;
4992
4973
  }
4993
- if (vc.l > maxNumVertices) return -1;
4974
+ if (vc.k > maxNumVertices) return -1;
4994
4975
  cornerToVertex[corner] = firstVertIndex;
4995
4976
  cornerToVertex[corner + 1] = firstVertIndex + 1;
4996
4977
  cornerToVertex[corner + 2] = firstVertIndex + 2;
@@ -5003,9 +4984,9 @@ var MeshEdgebreakerDecoderImpl = class {
5003
4984
  return -1;
5004
4985
  }
5005
4986
  traversalDecoder.newActiveCornerReached(activeCornerStack[activeCornerStackSize - 1]);
5006
- if (checkTopologySplit && this.O.length > 0) {
4987
+ if (checkTopologySplit && this.R.length > 0) {
5007
4988
  const encoderSymbolId = numSymbols - symbolId - 1;
5008
- while (this.Cc(encoderSymbolId, splitResult)) {
4989
+ while (this.Ac(encoderSymbolId, splitResult)) {
5009
4990
  if (splitResult.encoderSplitSymbolId < 0) return -1;
5010
4991
  const actTopCorner = activeCornerStack[activeCornerStackSize - 1];
5011
4992
  let newActiveCorner;
@@ -5019,27 +5000,27 @@ var MeshEdgebreakerDecoderImpl = class {
5019
5000
  }
5020
5001
  }
5021
5002
  }
5022
- if (vc.l > maxNumVertices) {
5003
+ if (vc.k > maxNumVertices) {
5023
5004
  return -1;
5024
5005
  }
5025
- numFacesDecoded = this.Dc(activeCornerStack, activeCornerStackSize, numFacesDecoded);
5006
+ numFacesDecoded = this.Bc(activeCornerStack, activeCornerStackSize, numFacesDecoded);
5026
5007
  if (numFacesDecoded === -1) {
5027
5008
  return -1;
5028
5009
  }
5029
5010
  if (numFacesDecoded !== this.a.numFaces()) {
5030
5011
  return -1;
5031
5012
  }
5032
- return this.Ec(invalidVertices);
5013
+ return this.Cc(invalidVertices);
5033
5014
  }
5034
5015
  // Connects the remaining active-stack corners to newly decoded start faces.
5035
5016
  // Returns the updated decoded-face count, or -1 on malformed input.
5036
- Dc(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
5017
+ Bc(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
5037
5018
  const ct = this.a;
5038
- const oppositeCorners = ct.s;
5019
+ const oppositeCorners = ct.q;
5039
5020
  const cornerToVertex = ct.j;
5040
- const vertexCorners = ct.y;
5041
- const isVertHole = this.la;
5042
- const traversalDecoder = this.K;
5021
+ const vertexCorners = ct.v;
5022
+ const isVertHole = this.ka;
5023
+ const traversalDecoder = this.M;
5043
5024
  const numCorners = ct.numCorners();
5044
5025
  const numFaces = ct.numFaces();
5045
5026
  const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
@@ -5087,11 +5068,11 @@ var MeshEdgebreakerDecoderImpl = class {
5087
5068
  // Removes invalid (isolated) vertices by swapping them with the last valid
5088
5069
  // vertex in the table, matching C++ mesh_edgebreaker_decoder_impl.cc (the
5089
5070
  // forward iteration order matters). Returns the final vertex count, or -1.
5090
- Ec(invalidVertices) {
5071
+ Cc(invalidVertices) {
5091
5072
  const ct = this.a;
5092
5073
  const cornerToVertex = ct.j;
5093
- const vertexCorners = ct.y;
5094
- const isVertHole = this.la;
5074
+ const vertexCorners = ct.v;
5075
+ const isVertHole = this.ka;
5095
5076
  const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
5096
5077
  let numVertices = ct.numVertices();
5097
5078
  for (let ivIdx = 0; ivIdx < invalidVertices.length; ++ivIdx) {
@@ -5133,7 +5114,7 @@ var MeshEdgebreakerDecoderImpl = class {
5133
5114
  }
5134
5115
  // Hole events were removed from the bitstream in 2.1; for 2.2 this only
5135
5116
  // decodes the inline topology-split events.
5136
- xc(decoderBuffer) {
5117
+ vc(decoderBuffer) {
5137
5118
  const numTopologySplits = decodeVarint(decoderBuffer);
5138
5119
  if (numTopologySplits === void 0) return false;
5139
5120
  if (numTopologySplits > 0) {
@@ -5151,12 +5132,12 @@ var MeshEdgebreakerDecoderImpl = class {
5151
5132
  if (delta2 > eventData.sourceSymbolId) return false;
5152
5133
  eventData.splitSymbolId = eventData.sourceSymbolId - delta2;
5153
5134
  lastSourceSymbolId = eventData.sourceSymbolId;
5154
- this.O.push(eventData);
5135
+ this.R.push(eventData);
5155
5136
  }
5156
5137
  decoderBuffer.startBitDecoding(false);
5157
5138
  for (let i = 0; i < numTopologySplits; ++i) {
5158
5139
  const edgeData = decoderBuffer.decodeLeastSignificantBits32(1);
5159
- this.O[i].sourceEdge = edgeData & 1;
5140
+ this.R[i].sourceEdge = edgeData & 1;
5160
5141
  }
5161
5142
  decoderBuffer.endBitDecoding();
5162
5143
  }
@@ -5174,11 +5155,11 @@ var MeshEdgebreakerDecoderImpl = class {
5174
5155
  // the face's base corner -- is just `oppCorner >= faceBaseCorner`, since the
5175
5156
  // base corner is a multiple of 3. That removes the per-corner division; the
5176
5157
  // invalid-corner case (-1) is still handled by the branch above it.
5177
- zc() {
5158
+ xc() {
5178
5159
  const oppositeCorners = this.a.oppositeCornerArray();
5179
5160
  const attributeData = this.i;
5180
5161
  const numAttrData = attributeData.length;
5181
- const connectivityDecoders = this.K._b;
5162
+ const connectivityDecoders = this.M.Yb;
5182
5163
  const numCorners = this.a.numCorners();
5183
5164
  const candidates = scratchInt32(numCorners);
5184
5165
  let numCandidates = 0;
@@ -5197,42 +5178,24 @@ var MeshEdgebreakerDecoderImpl = class {
5197
5178
  numCandidates -= (opp | corner - opp - 1) >> 31;
5198
5179
  numBoundaryCorners -= opp >> 31;
5199
5180
  }
5200
- this.Yb = numBoundaryCorners;
5201
- for (let i = 0; i < numAttrData; ++i) {
5202
- const ad = attributeData[i];
5203
- const seamCorners = ad.attributeSeamCorners;
5204
- let numSeamCorners = ad.numSeamCorners;
5205
- const decoder = connectivityDecoders[i];
5206
- const ans = decoder.db;
5207
- const p = decoder.eb;
5208
- const buf = ans.buf;
5209
- const bufStart = ans.bufStart;
5210
- let state = ans.state;
5211
- let bufOffset = ans.bufOffset;
5212
- for (let n = 0; n < numCandidates; ++n) {
5213
- const cc = candidates[n];
5214
- if (cc < 0) {
5215
- seamCorners[numSeamCorners++] = ~cc;
5216
- continue;
5217
- }
5218
- if (state < ANS_L_BASE && bufOffset > bufStart) {
5219
- state = state << 8 | buf[--bufOffset];
5220
- }
5221
- const rem = state & 255;
5222
- const xn = (state >>> 8) * p;
5223
- const mask = rem - p >> 31;
5224
- const stateIfZero = state - xn - p;
5225
- state = stateIfZero + (mask & xn + rem - stateIfZero);
5226
- seamCorners[numSeamCorners] = cc;
5227
- numSeamCorners -= mask;
5228
- }
5229
- ans.state = state;
5230
- ans.bufOffset = bufOffset;
5231
- ad.numSeamCorners = numSeamCorners;
5181
+ this.Wb = numBoundaryCorners;
5182
+ let i = 0;
5183
+ for (; i + 2 <= numAttrData; i += 2) {
5184
+ decodeSeamBits2(
5185
+ candidates,
5186
+ numCandidates,
5187
+ attributeData[i],
5188
+ connectivityDecoders[i],
5189
+ attributeData[i + 1],
5190
+ connectivityDecoders[i + 1]
5191
+ );
5192
+ }
5193
+ if (i < numAttrData) {
5194
+ decodeSeamBits1(candidates, numCandidates, attributeData[i], connectivityDecoders[i]);
5232
5195
  }
5233
5196
  }
5234
5197
  // Position-only connectivity: vertex indices equal point indices.
5235
- Ac(numConnectivityVerts) {
5198
+ yc(numConnectivityVerts) {
5236
5199
  const mesh = this.n.mesh();
5237
5200
  const ct = this.a;
5238
5201
  mesh.setNumFaces(ct.numFaces());
@@ -5242,58 +5205,48 @@ var MeshEdgebreakerDecoderImpl = class {
5242
5205
  for (let c = 0; c < numCorners; ++c) {
5243
5206
  faces[c] = baseCornerToVertex[c];
5244
5207
  }
5245
- this.ka = null;
5208
+ this.ja = null;
5246
5209
  this.n.pointCloud().setNumPoints(numConnectivityVerts);
5247
5210
  }
5248
- // Builds an attribute corner table whose only seams are boundary edges (see
5249
- // decodeConnectivity), for a per-corner decoder that asked for it. With no
5250
- // interior seam every vertex ring is one attribute vertex, numbered in
5251
- // vertex order with isolated vertices skipped -- what the ring walk in
5252
- // _assignAttributeVerticesAndPoints assigns such a table, without the walk.
5253
- wc(ad) {
5254
- const ct = this.a;
5255
- const table = ad.connectivityData;
5256
- table.initEmpty(ct);
5257
- table.reserveSeamEdges(ad.numSeamCorners);
5258
- for (let s = 0; s < ad.numSeamCorners; ++s) table.addSeamEdge(ad.attributeSeamCorners[s]);
5259
- const numVertices = ct.numVertices();
5260
- const numCorners = ct.numCorners();
5261
- const vertexLeftmost = ct.vertexLeftmostCornerArray();
5262
- const cornerToVertex = ct.cornerToVertexArray();
5263
- const vertexIds = scratchInt32(numVertices);
5264
- const leftMost = scratchInt32(numVertices);
5265
- let numAttVertices = 0;
5266
- for (let v = 0; v < numVertices; ++v) {
5267
- const c = vertexLeftmost[v];
5268
- vertexIds[v] = c === kInvalidCornerIndex6 ? -1 : numAttVertices;
5269
- if (c !== kInvalidCornerIndex6) leftMost[numAttVertices++] = c;
5270
- }
5271
- const c2v = table.ca;
5272
- for (let c = 0; c < numCorners; ++c) c2v[c] = vertexIds[cornerToVertex[c]];
5273
- table.setRecomputedVertices(leftMost, numAttVertices);
5211
+ // Sets up an attribute corner table whose only seams are boundary edges
5212
+ // (see decodeConnectivity), for a per-corner decoder that asked for it:
5213
+ // the base connectivity itself.
5214
+ uc(ad) {
5215
+ ad.connectivityData.initAsBase(this.a);
5274
5216
  ad.noInteriorSeams = false;
5275
5217
  }
5276
- // One walk around every vertex ring that (a) numbers the attribute vertices
5277
- // of every distinct attribute corner table (C++ MeshAttributeCornerTable::
5278
- // RecomputeVertices, one per table) and (b) assigns the mesh's point ids
5279
- // (C++ AssignPointsToCorners). Each of those is a per-vertex procedure that
5280
- // only reads the ring's own corners and its table's running counter, so
5281
- // running them side by side on one buffered ring produces exactly the ids
5282
- // the separate passes would -- while the ring's corner chain (a serial,
5283
- // cache-missing pointer chase through swingRight) is followed once instead
5284
- // of once per table plus once for the points. Also records one corner per
5285
- // point (_pointCorner) so point-to-value maps can be built per point rather
5286
- // than per corner (see MeshTraversalSequencer).
5218
+ // One walk around the ring of every seam vertex that (a) numbers the
5219
+ // attribute vertices of every distinct attribute corner table (C++
5220
+ // MeshAttributeCornerTable::RecomputeVertices, one per table) and (b)
5221
+ // assigns the mesh's point ids (C++ AssignPointsToCorners). Each of those
5222
+ // is a per-vertex procedure that only reads the ring's own corners and its
5223
+ // table's running counter, so running them side by side on one buffered
5224
+ // ring produces exactly the ids the separate passes would -- while the
5225
+ // ring's corner chain (a serial, cache-missing pointer chase through
5226
+ // swingRight) is followed once instead of once per table plus once for the
5227
+ // points. Also records one corner per point (_pointCorner) so
5228
+ // point-to-value maps can be built per point rather than per corner (see
5229
+ // MeshTraversalSequencer).
5230
+ //
5231
+ // A vertex on no table's seam -- interior or on a boundary -- is one
5232
+ // attribute vertex per table and one point whatever its ring holds (the
5233
+ // C++ passes swing right from its leftmost corner and never meet a split),
5234
+ // so it needs no walk at all: every table starts as a copy of the base
5235
+ // numbering (see MeshAttributeCornerTable.initEmpty), its point id is taken
5236
+ // in vertex order here, and its corners get that id in a sequential pass
5237
+ // after the loop (or none at all, when the points turn out to be the base
5238
+ // vertices). Attribute vertex ids need not be compact (only their identity
5239
+ // is ever used), so a seam vertex keeps its base id for its first
5240
+ // sub-vertex and the further sub-vertices take fresh ids past the base
5241
+ // vertex count; the ring walk only rewrites those corners.
5287
5242
  //
5288
5243
  // The buffered ring makes the swing-left prefix of the seam-vertex recompute
5289
5244
  // an index walk: swingLeft(ring[j]) is ring[j - 1] (the opposite table is
5290
- // symmetric), and for a closed ring ring[k - 1] when j is 0. An open ring
5291
- // whose leftmost corner still has a left neighbor (never the case for the
5292
- // corner table the edgebreaker decoder builds, which keeps the left-most
5293
- // corner of every boundary vertex, but allowed for by the C++ code) is
5294
- // extended leftwards first, so the walk covers exactly the corners the
5295
- // separate passes would have reached.
5296
- Bc(tables) {
5245
+ // symmetric), and for a closed ring ring[k - 1] when j is 0. The C++ walks
5246
+ // start at the vertex's leftmost corner and only ever swing right from it
5247
+ // (or left through the seam-aware table, which stops at the boundary), so
5248
+ // an open ring is walked from that corner too.
5249
+ zc(tables, seamEdgeCounts) {
5297
5250
  const mesh = this.n.mesh();
5298
5251
  const ct = this.a;
5299
5252
  mesh.setNumFaces(ct.numFaces());
@@ -5302,18 +5255,23 @@ var MeshEdgebreakerDecoderImpl = class {
5302
5255
  const faces = mesh.faces_;
5303
5256
  const vertexLeftmost = ct.vertexLeftmostCornerArray();
5304
5257
  const baseOpposite = ct.oppositeCornerArray();
5305
- const isVertHole = this.la;
5258
+ const baseCornerToVertex = ct.cornerToVertexArray();
5259
+ const isVertHole = this.ka;
5260
+ const baseOnBoundary = ct.vertexOnBoundaryArray();
5306
5261
  const numTables = tables.length;
5307
5262
  const attCornerToVertex = new Array(numTables);
5308
- const edgeOnSeam = new Array(numTables);
5263
+ const attOpposite = new Array(numTables);
5309
5264
  const vertexOnSeam = new Array(numTables);
5310
- const leftMostMaps = new Array(numTables);
5311
- const numAttVertices = new Int32Array(numTables);
5265
+ const onBoundaryMaps = new Array(numTables);
5266
+ const numExtraVertices = new Int32Array(numTables);
5312
5267
  for (let t = 0; t < numTables; ++t) {
5313
- attCornerToVertex[t] = tables[t].ca;
5314
- edgeOnSeam[t] = tables[t].ba;
5315
- vertexOnSeam[t] = tables[t].ta;
5316
- leftMostMaps[t] = scratchInt32(numCorners);
5268
+ attCornerToVertex[t] = tables[t].W;
5269
+ attOpposite[t] = tables[t].I;
5270
+ vertexOnSeam[t] = tables[t].sa;
5271
+ const onBoundary = scratchUint8(numVertices + 2 * seamEdgeCounts[t]);
5272
+ onBoundary.set(baseOnBoundary);
5273
+ onBoundary.fill(1, numVertices);
5274
+ onBoundaryMaps[t] = onBoundary;
5317
5275
  }
5318
5276
  const ring = scratchInt32(numCorners);
5319
5277
  const ringNext = scratchInt32(numCorners);
@@ -5321,12 +5279,10 @@ var MeshEdgebreakerDecoderImpl = class {
5321
5279
  const idChange = scratchUint8Zeroed(numCorners);
5322
5280
  let numPoints = 0;
5323
5281
  const plainPointId = scratchInt32(numVertices);
5324
- const plainVertIds = new Array(numTables);
5325
- for (let t = 0; t < numTables; ++t) plainVertIds[t] = scratchInt32(numVertices);
5282
+ let numWalked = 0;
5326
5283
  for (let v = 0; v < numVertices; ++v) {
5327
5284
  const c = vertexLeftmost[v];
5328
5285
  if (c === kInvalidCornerIndex6) continue;
5329
- const hole = isVertHole[v] !== 0;
5330
5286
  let anySeam = false;
5331
5287
  for (let t = 0; t < numTables; ++t) {
5332
5288
  if (vertexOnSeam[t][v] !== 0) {
@@ -5334,20 +5290,14 @@ var MeshEdgebreakerDecoderImpl = class {
5334
5290
  break;
5335
5291
  }
5336
5292
  }
5337
- if (!hole && !anySeam) {
5338
- for (let t = 0; t < numTables; ++t) {
5339
- const vertId = numAttVertices[t];
5340
- leftMostMaps[t][vertId] = c;
5341
- plainVertIds[t][v] = vertId;
5342
- numAttVertices[t] = vertId + 1;
5343
- }
5293
+ if (!anySeam) {
5344
5294
  const pointId2 = numPoints++;
5345
5295
  pointCorner[pointId2] = c;
5346
5296
  plainPointId[v] = pointId2;
5347
5297
  continue;
5348
5298
  }
5349
5299
  plainPointId[v] = -1;
5350
- let start = 0;
5300
+ numWalked++;
5351
5301
  let k = 0;
5352
5302
  let actC = c;
5353
5303
  for (; ; ) {
@@ -5364,50 +5314,14 @@ var MeshEdgebreakerDecoderImpl = class {
5364
5314
  if (k === numCorners) return false;
5365
5315
  }
5366
5316
  const closed = actC === c;
5367
- if (!closed) {
5368
- const o = baseOpposite[ringNext[0]];
5369
- let left = o < 0 ? kInvalidCornerIndex6 : o % 3 === 2 ? o - 2 : o + 1;
5370
- if (left !== kInvalidCornerIndex6) {
5371
- let m = 0;
5372
- let cur = left;
5373
- while (cur !== kInvalidCornerIndex6 && cur !== c) {
5374
- if (k + ++m > numCorners) return false;
5375
- const ln = cur % 3 === 2 ? cur - 2 : cur + 1;
5376
- const lo = baseOpposite[ln];
5377
- cur = lo < 0 ? kInvalidCornerIndex6 : lo % 3 === 2 ? lo - 2 : lo + 1;
5378
- }
5379
- for (let j2 = k - 1; j2 >= 0; --j2) {
5380
- ring[j2 + m] = ring[j2];
5381
- ringNext[j2 + m] = ringNext[j2];
5382
- }
5383
- cur = left;
5384
- for (let i = 1; i <= m; ++i) {
5385
- const ln = cur % 3 === 2 ? cur - 2 : cur + 1;
5386
- ring[m - i] = cur;
5387
- ringNext[m - i] = ln;
5388
- const lo = baseOpposite[ln];
5389
- cur = lo < 0 ? kInvalidCornerIndex6 : lo % 3 === 2 ? lo - 2 : lo + 1;
5390
- }
5391
- start = m;
5392
- k += m;
5393
- }
5394
- }
5395
5317
  const end = k;
5396
5318
  for (let t = 0; t < numTables; ++t) {
5319
+ if (vertexOnSeam[t][v] === 0) continue;
5397
5320
  const c2v = attCornerToVertex[t];
5398
- const leftMostMap = leftMostMaps[t];
5399
- let vertId = numAttVertices[t];
5400
- if (vertexOnSeam[t][v] === 0) {
5401
- leftMostMap[vertId] = c;
5402
- for (let j3 = start; j3 < end; ++j3) c2v[ring[j3]] = vertId;
5403
- numAttVertices[t] = vertId + 1;
5404
- continue;
5405
- }
5406
- const isEdgeOnSeam = edgeOnSeam[t];
5407
- let j2 = start;
5321
+ const opposite = attOpposite[t];
5322
+ let j2 = 0;
5408
5323
  for (; ; ) {
5409
- const rn = ringNext[j2];
5410
- if (isEdgeOnSeam[rn] !== 0 || baseOpposite[rn] < 0) break;
5324
+ if (opposite[ringNext[j2]] < 0) break;
5411
5325
  if (j2 > 0) {
5412
5326
  --j2;
5413
5327
  } else if (closed) {
@@ -5415,39 +5329,39 @@ var MeshEdgebreakerDecoderImpl = class {
5415
5329
  } else {
5416
5330
  break;
5417
5331
  }
5418
- if (j2 === start) return false;
5332
+ if (j2 === 0) return false;
5419
5333
  }
5420
5334
  const first = ring[j2];
5421
- const firstVertId = vertId;
5422
- c2v[first] = vertId;
5423
- leftMostMap[vertId] = first;
5335
+ let vertId = v;
5336
+ onBoundaryMaps[t][v] = 1;
5337
+ let numExtra = numExtraVertices[t];
5424
5338
  const steps2 = closed ? end - 1 : end - 1 - j2;
5425
5339
  for (let s = 0; s < steps2; ++s) {
5426
5340
  if (++j2 === end) j2 = 0;
5427
5341
  const rc = ring[j2];
5428
- if (isEdgeOnSeam[ringNext[j2]] !== 0) {
5429
- leftMostMap[++vertId] = rc;
5342
+ if (opposite[ringNext[j2]] < 0) {
5343
+ vertId = numVertices + numExtra++;
5430
5344
  idChange[rc] = 1;
5431
5345
  }
5432
5346
  c2v[rc] = vertId;
5433
5347
  }
5434
- if (vertId !== firstVertId) idChange[first] = 1;
5435
- numAttVertices[t] = vertId + 1;
5348
+ if (vertId !== v) idChange[first] = 1;
5349
+ numExtraVertices[t] = numExtra;
5436
5350
  }
5437
- let j = start;
5438
- if (!hole) {
5351
+ let j = 0;
5352
+ if (isVertHole[v] === 0) {
5439
5353
  for (let t = 0; t < numTables; ++t) {
5440
5354
  if (vertexOnSeam[t][v] === 0) continue;
5441
5355
  const c2v = attCornerToVertex[t];
5442
5356
  const vertId = c2v[c];
5443
- let jj = start;
5357
+ let jj = 0;
5444
5358
  let found = false;
5445
5359
  for (; ; ) {
5446
5360
  if (++jj === end) {
5447
5361
  if (!closed) return false;
5448
5362
  jj = 0;
5449
5363
  }
5450
- if (jj === start) break;
5364
+ if (jj === 0) break;
5451
5365
  if (c2v[ring[jj]] !== vertId) {
5452
5366
  found = true;
5453
5367
  break;
@@ -5473,38 +5387,125 @@ var MeshEdgebreakerDecoderImpl = class {
5473
5387
  faces[rc] = pointId;
5474
5388
  }
5475
5389
  }
5476
- const baseCornerToVertex = ct.cornerToVertexArray();
5477
- for (let c = 0; c < numCorners; ++c) {
5478
- const v = baseCornerToVertex[c];
5479
- const pointId = plainPointId[v];
5480
- if (pointId < 0) continue;
5481
- faces[c] = pointId;
5482
- for (let t = 0; t < numTables; ++t) attCornerToVertex[t][c] = plainVertIds[t][v];
5390
+ if (numWalked === 0 && numPoints === numVertices) {
5391
+ faces.set(baseCornerToVertex);
5392
+ } else {
5393
+ for (let c = 0; c < numCorners; ++c) {
5394
+ const pointId = plainPointId[baseCornerToVertex[c]];
5395
+ if (pointId >= 0) faces[c] = pointId;
5396
+ }
5483
5397
  }
5484
5398
  for (let t = 0; t < numTables; ++t) {
5485
- tables[t].setRecomputedVertices(leftMostMaps[t], numAttVertices[t]);
5399
+ tables[t].setRecomputedVertices(onBoundaryMaps[t], numVertices + numExtraVertices[t]);
5486
5400
  }
5487
- this.ka = pointCorner;
5401
+ this.ja = pointCorner;
5488
5402
  this.n.pointCloud().setNumPoints(numPoints);
5489
5403
  return true;
5490
5404
  }
5491
5405
  };
5406
+ function decodeSeamBits1(candidates, numCandidates, ad, decoder) {
5407
+ const seamCorners = ad.attributeSeamCorners;
5408
+ let numSeamCorners = ad.numSeamCorners;
5409
+ const ans = decoder.va;
5410
+ const p = decoder.wa;
5411
+ const buf = ans.buf;
5412
+ const bufStart = ans.bufStart;
5413
+ let state = ans.state;
5414
+ let bufOffset = ans.bufOffset;
5415
+ for (let n = 0; n < numCandidates; ++n) {
5416
+ const cc = candidates[n];
5417
+ if (cc < 0) {
5418
+ seamCorners[numSeamCorners++] = ~cc;
5419
+ continue;
5420
+ }
5421
+ if (state < ANS_L_BASE && bufOffset > bufStart) {
5422
+ state = state << 8 | buf[--bufOffset];
5423
+ }
5424
+ const rem = state & 255;
5425
+ const xn = (state >>> 8) * p;
5426
+ const mask = rem - p >> 31;
5427
+ const stateIfZero = state - xn - p;
5428
+ state = stateIfZero + (mask & xn + rem - stateIfZero);
5429
+ seamCorners[numSeamCorners] = cc;
5430
+ numSeamCorners -= mask;
5431
+ }
5432
+ ans.state = state;
5433
+ ans.bufOffset = bufOffset;
5434
+ ad.numSeamCorners = numSeamCorners;
5435
+ }
5436
+ function decodeSeamBits2(candidates, numCandidates, ad0, decoder0, ad1, decoder1) {
5437
+ const seam0 = ad0.attributeSeamCorners;
5438
+ const seam1 = ad1.attributeSeamCorners;
5439
+ let num0 = ad0.numSeamCorners;
5440
+ let num1 = ad1.numSeamCorners;
5441
+ const ans0 = decoder0.va;
5442
+ const ans1 = decoder1.va;
5443
+ const p0 = decoder0.wa;
5444
+ const p1 = decoder1.wa;
5445
+ const buf0 = ans0.buf;
5446
+ const buf1 = ans1.buf;
5447
+ const start0 = ans0.bufStart;
5448
+ const start1 = ans1.bufStart;
5449
+ let state0 = ans0.state;
5450
+ let state1 = ans1.state;
5451
+ let off0 = ans0.bufOffset;
5452
+ let off1 = ans1.bufOffset;
5453
+ for (let n = 0; n < numCandidates; ++n) {
5454
+ const cc = candidates[n];
5455
+ if (cc < 0) {
5456
+ seam0[num0++] = ~cc;
5457
+ seam1[num1++] = ~cc;
5458
+ continue;
5459
+ }
5460
+ if (state0 < ANS_L_BASE && off0 > start0) {
5461
+ state0 = state0 << 8 | buf0[--off0];
5462
+ }
5463
+ if (state1 < ANS_L_BASE && off1 > start1) {
5464
+ state1 = state1 << 8 | buf1[--off1];
5465
+ }
5466
+ const rem0 = state0 & 255;
5467
+ const rem1 = state1 & 255;
5468
+ const xn0 = (state0 >>> 8) * p0;
5469
+ const xn1 = (state1 >>> 8) * p1;
5470
+ const mask0 = rem0 - p0 >> 31;
5471
+ const mask1 = rem1 - p1 >> 31;
5472
+ const zero0 = state0 - xn0 - p0;
5473
+ const zero1 = state1 - xn1 - p1;
5474
+ state0 = zero0 + (mask0 & xn0 + rem0 - zero0);
5475
+ state1 = zero1 + (mask1 & xn1 + rem1 - zero1);
5476
+ seam0[num0] = cc;
5477
+ seam1[num1] = cc;
5478
+ num0 -= mask0;
5479
+ num1 -= mask1;
5480
+ }
5481
+ ans0.state = state0;
5482
+ ans0.bufOffset = off0;
5483
+ ad0.numSeamCorners = num0;
5484
+ ans1.state = state1;
5485
+ ans1.bufOffset = off1;
5486
+ ad1.numSeamCorners = num1;
5487
+ }
5492
5488
  var MeshAttributeIndicesEncodingData = class {
5493
5489
  vertexToEncodedAttributeValueIndexMap = new Int32Array(0);
5494
5490
  encodedAttributeValueIndexToCornerMap = new Int32Array(0);
5495
5491
  numValues = 0;
5492
+ // The traversal cache entry the maps came from (see MeshTraversalSequencer);
5493
+ // carries what later passes derive from the traversal and share.
5494
+ cacheEntry = null;
5496
5495
  init(numVertices) {
5497
5496
  this.vertexToEncodedAttributeValueIndexMap = scratchInt32Filled(numVertices, -1);
5498
5497
  this.encodedAttributeValueIndexToCornerMap = scratchInt32(numVertices);
5499
5498
  this.numValues = 0;
5499
+ this.cacheEntry = null;
5500
5500
  }
5501
5501
  // Adopts a traversal result from an identical corner table, avoiding a
5502
5502
  // redundant traversal. The maps depend only on connectivity and are read-only
5503
5503
  // downstream, so sharing is safe.
5504
- adoptTraversalResult(vertexToEncodedMap, encodedToCornerMap, numValues) {
5505
- this.vertexToEncodedAttributeValueIndexMap = vertexToEncodedMap;
5506
- this.encodedAttributeValueIndexToCornerMap = encodedToCornerMap;
5507
- this.numValues = numValues;
5504
+ adoptTraversalResult(entry) {
5505
+ this.vertexToEncodedAttributeValueIndexMap = entry.vertexMap;
5506
+ this.encodedAttributeValueIndexToCornerMap = entry.cornerMap;
5507
+ this.numValues = entry.numValues;
5508
+ this.cacheEntry = entry;
5508
5509
  }
5509
5510
  };
5510
5511
  var AttributeData = class {
@@ -5519,31 +5520,36 @@ var AttributeData = class {
5519
5520
  noInteriorSeams = false;
5520
5521
  };
5521
5522
  var CornerTable = class {
5522
- $b = 0;
5523
- J = 0;
5524
- l = 0;
5523
+ Zb = 0;
5524
+ L = 0;
5525
+ k = 0;
5525
5526
  j = null;
5526
5527
  // corner -> vertex
5527
- s = null;
5528
+ q = null;
5528
5529
  // corner -> opposite corner
5529
- y = null;
5530
+ v = null;
5530
5531
  // vertex -> left-most corner
5532
+ // vertex -> 1 when its fan is open (C++ IsOnBoundary: the edge left of
5533
+ // the left-most corner has no opposite face), computed once after the
5534
+ // connectivity decode (see finishBoundaries) for the traversals, whose
5535
+ // critical path would otherwise chase two dependent loads per new vertex.
5536
+ B = null;
5531
5537
  reset(numFaces, numVertices) {
5532
- this.$b = numFaces;
5533
- this.J = numFaces * 3;
5534
- this.l = 0;
5535
- this.j = scratchInt32Filled(this.J, -1);
5536
- this.s = scratchInt32Filled(this.J, -1);
5537
- this.y = scratchInt32Filled(numVertices, -1);
5538
+ this.Zb = numFaces;
5539
+ this.L = numFaces * 3;
5540
+ this.k = 0;
5541
+ this.j = scratchInt32Filled(this.L, -1);
5542
+ this.q = scratchInt32Filled(this.L, -1);
5543
+ this.v = scratchInt32Filled(numVertices, -1);
5538
5544
  }
5539
5545
  numFaces() {
5540
- return this.$b;
5546
+ return this.Zb;
5541
5547
  }
5542
5548
  numCorners() {
5543
- return this.J;
5549
+ return this.L;
5544
5550
  }
5545
5551
  numVertices() {
5546
- return this.l;
5552
+ return this.k;
5547
5553
  }
5548
5554
  next(corner) {
5549
5555
  if (corner < 0) return -1;
@@ -5556,34 +5562,50 @@ var CornerTable = class {
5556
5562
  return rem === 0 ? corner + 2 : corner - 1;
5557
5563
  }
5558
5564
  vertex(corner) {
5559
- if (corner < 0 || corner >= this.J) return -1;
5565
+ if (corner < 0 || corner >= this.L) return -1;
5560
5566
  return this.j[corner];
5561
5567
  }
5562
5568
  opposite(corner) {
5563
- if (corner < 0 || corner >= this.J) return -1;
5564
- return this.s[corner];
5569
+ if (corner < 0 || corner >= this.L) return -1;
5570
+ return this.q[corner];
5565
5571
  }
5566
5572
  // Flat-array accessors; let callers avoid polymorphic per-corner dispatch.
5567
5573
  cornerToVertexArray() {
5568
5574
  return this.j;
5569
5575
  }
5570
5576
  oppositeCornerArray() {
5571
- return this.s;
5577
+ return this.q;
5572
5578
  }
5573
5579
  vertexLeftmostCornerArray() {
5574
- return this.y;
5580
+ return this.v;
5581
+ }
5582
+ vertexOnBoundaryArray() {
5583
+ return this.B;
5584
+ }
5585
+ // Derives _vertexOnBoundary from the finished connectivity (decode-scoped
5586
+ // scratch). Isolated vertices count as boundary; they are never traversed.
5587
+ finishBoundaries() {
5588
+ const numVertices = this.k;
5589
+ const vertexCorners = this.v;
5590
+ const oppositeCorners = this.q;
5591
+ const onBoundary = scratchUint8(numVertices);
5592
+ for (let v = 0; v < numVertices; ++v) {
5593
+ const lc = vertexCorners[v];
5594
+ onBoundary[v] = lc < 0 || oppositeCorners[lc % 3 === 2 ? lc - 2 : lc + 1] < 0 ? 1 : 0;
5595
+ }
5596
+ this.B = onBoundary;
5575
5597
  }
5576
5598
  // Mirrors C++ CornerTable::AddNewVertex() (push_back(kInvalidCornerIndex)).
5577
5599
  addNewVertex() {
5578
- const newVertex = this.l;
5579
- this.l++;
5580
- if (newVertex >= this.y.length) {
5581
- const newCapacity = Math.max(newVertex + 1, this.y.length * 2, 64);
5600
+ const newVertex = this.k;
5601
+ this.k++;
5602
+ if (newVertex >= this.v.length) {
5603
+ const newCapacity = Math.max(newVertex + 1, this.v.length * 2, 64);
5582
5604
  const newArr = scratchInt32Filled(newCapacity, -1);
5583
- newArr.set(this.y);
5584
- this.y = newArr;
5605
+ newArr.set(this.v);
5606
+ this.v = newArr;
5585
5607
  }
5586
- this.y[newVertex] = -1;
5608
+ this.v[newVertex] = -1;
5587
5609
  return newVertex;
5588
5610
  }
5589
5611
  // Next corner around a vertex, CCW. SwingLeft(c) = Next(Opposite(Next(c))).
@@ -5605,14 +5627,14 @@ var CornerTable = class {
5605
5627
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalDecoder.ts
5606
5628
  var MeshEdgebreakerTraversalDecoder = class {
5607
5629
  d = new DecoderBuffer();
5608
- L = new DecoderBuffer();
5609
- rb = null;
5610
- _b = [];
5611
- ac = 0;
5630
+ N = new DecoderBuffer();
5631
+ pb = null;
5632
+ Yb = [];
5633
+ _b = 0;
5612
5634
  // _symbolBuffer's bit cursor, captured once bit decoding starts: decodeSymbol
5613
5635
  // runs per decoded face and would otherwise reach it through two property
5614
5636
  // loads and a method call per read.
5615
- bc = null;
5637
+ $b = null;
5616
5638
  init(decoder) {
5617
5639
  const srcBuffer = decoder.n.buffer();
5618
5640
  this.d.init(srcBuffer.dataHead, srcBuffer.remainingSize);
@@ -5621,7 +5643,7 @@ var MeshEdgebreakerTraversalDecoder = class {
5621
5643
  setNumEncodedVertices(_numVertices) {
5622
5644
  }
5623
5645
  setNumAttributeData(numData) {
5624
- this.ac = numData;
5646
+ this._b = numData;
5625
5647
  }
5626
5648
  // Sets outBuffer to the data encoded after the traversal section.
5627
5649
  start(outBuffer) {
@@ -5638,29 +5660,29 @@ var MeshEdgebreakerTraversalDecoder = class {
5638
5660
  return true;
5639
5661
  }
5640
5662
  decodeStartFaceConfiguration() {
5641
- return this.rb.decodeNextBit();
5663
+ return this.pb.decodeNextBit();
5642
5664
  }
5643
5665
  decodeSymbol() {
5644
- const bd = this.bc;
5666
+ const bd = this.$b;
5645
5667
  if (bd !== null) {
5646
- const buf = bd.Na;
5647
- const off = bd.q;
5668
+ const buf = bd.Ma;
5669
+ const off = bd.s;
5648
5670
  const byteOffset = off >> 3;
5649
- if (byteOffset + 4 < bd.ra) {
5671
+ if (byteOffset + 4 < bd.qa) {
5650
5672
  const bits = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> (off & 7) & 7;
5651
5673
  if ((bits & 1) === TOPOLOGY_C) {
5652
- bd.q = off + 1;
5674
+ bd.s = off + 1;
5653
5675
  return TOPOLOGY_C;
5654
5676
  }
5655
- bd.q = off + 3;
5677
+ bd.s = off + 3;
5656
5678
  return bits;
5657
5679
  }
5658
5680
  }
5659
- let symbol = this.L.decodeLeastSignificantBits32(1);
5681
+ let symbol = this.N.decodeLeastSignificantBits32(1);
5660
5682
  if (symbol === TOPOLOGY_C) {
5661
5683
  return symbol;
5662
5684
  }
5663
- const symbolSuffix = this.L.decodeLeastSignificantBits32(2);
5685
+ const symbolSuffix = this.N.decodeLeastSignificantBits32(2);
5664
5686
  symbol |= symbolSuffix << 1;
5665
5687
  return symbol;
5666
5688
  }
@@ -5669,18 +5691,18 @@ var MeshEdgebreakerTraversalDecoder = class {
5669
5691
  mergeVertices(_dest, _source) {
5670
5692
  }
5671
5693
  done() {
5672
- if (this.L.bitDecoderActive) {
5673
- this.L.endBitDecoding();
5694
+ if (this.N.bitDecoderActive) {
5695
+ this.N.endBitDecoding();
5674
5696
  }
5675
5697
  }
5676
5698
  decodeTraversalSymbols() {
5677
- this.L.init(this.d.dataHead, this.d.remainingSize);
5678
- const traversalSize = this.L.startBitDecoding(true);
5699
+ this.N.init(this.d.dataHead, this.d.remainingSize);
5700
+ const traversalSize = this.N.startBitDecoding(true);
5679
5701
  if (traversalSize === void 0) {
5680
5702
  return false;
5681
5703
  }
5682
- this.bc = this.L.sa;
5683
- this.d.init(this.L.dataHead, this.L.remainingSize);
5704
+ this.$b = this.N.ra;
5705
+ this.d.init(this.N.dataHead, this.N.remainingSize);
5684
5706
  if (traversalSize > this.d.remainingSize) {
5685
5707
  return false;
5686
5708
  }
@@ -5689,19 +5711,19 @@ var MeshEdgebreakerTraversalDecoder = class {
5689
5711
  }
5690
5712
  decodeStartFaces() {
5691
5713
  try {
5692
- this.rb = new RAnsBitDecoder();
5693
- return this.rb.startDecoding(this.d);
5714
+ this.pb = new RAnsBitDecoder();
5715
+ return this.pb.startDecoding(this.d);
5694
5716
  } catch {
5695
5717
  return false;
5696
5718
  }
5697
5719
  }
5698
5720
  decodeAttributeSeams() {
5699
- for (let i = 0; i < this.ac; ++i) {
5721
+ for (let i = 0; i < this._b; ++i) {
5700
5722
  const decoder = new RAnsBitDecoder();
5701
5723
  if (!decoder.startDecoding(this.d)) {
5702
5724
  return false;
5703
5725
  }
5704
- this._b.push(decoder);
5726
+ this.Yb.push(decoder);
5705
5727
  }
5706
5728
  return true;
5707
5729
  }
@@ -5710,17 +5732,17 @@ var MeshEdgebreakerTraversalDecoder = class {
5710
5732
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalPredictiveDecoder.ts
5711
5733
  var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTraversalDecoder {
5712
5734
  a = null;
5713
- l = 0;
5735
+ k = 0;
5714
5736
  A = -1;
5715
- ma = -1;
5716
- k = [];
5717
- sb = null;
5737
+ la = -1;
5738
+ l = [];
5739
+ qb = null;
5718
5740
  init(decoder) {
5719
5741
  super.init(decoder);
5720
5742
  this.a = decoder.getCornerTable();
5721
5743
  }
5722
5744
  setNumEncodedVertices(numVertices) {
5723
- this.l = numVertices;
5745
+ this.k = numVertices;
5724
5746
  }
5725
5747
  start(outBuffer) {
5726
5748
  if (!super.start(outBuffer)) {
@@ -5730,18 +5752,18 @@ var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTra
5730
5752
  if (numSplitSymbols === void 0 || numSplitSymbols < 0) {
5731
5753
  return false;
5732
5754
  }
5733
- if (numSplitSymbols >= this.l) {
5755
+ if (numSplitSymbols >= this.k) {
5734
5756
  return false;
5735
5757
  }
5736
- this.k = new Array(this.l).fill(0);
5737
- this.sb = new RAnsBitDecoder();
5738
- return this.sb.startDecoding(outBuffer);
5758
+ this.l = new Array(this.k).fill(0);
5759
+ this.qb = new RAnsBitDecoder();
5760
+ return this.qb.startDecoding(outBuffer);
5739
5761
  }
5740
5762
  decodeSymbol() {
5741
- if (this.ma !== -1) {
5742
- if (this.sb.decodeNextBit()) {
5743
- this.A = this.ma;
5744
- return this.ma;
5763
+ if (this.la !== -1) {
5764
+ if (this.qb.decodeNextBit()) {
5765
+ this.A = this.la;
5766
+ return this.la;
5745
5767
  }
5746
5768
  }
5747
5769
  this.A = super.decodeSymbol();
@@ -5754,55 +5776,55 @@ var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTra
5754
5776
  switch (this.A) {
5755
5777
  case TOPOLOGY_C:
5756
5778
  case TOPOLOGY_S:
5757
- this.k[ct.vertex(next)] += 1;
5758
- this.k[ct.vertex(prev)] += 1;
5779
+ this.l[ct.vertex(next)] += 1;
5780
+ this.l[ct.vertex(prev)] += 1;
5759
5781
  break;
5760
5782
  case TOPOLOGY_R:
5761
- this.k[ct.vertex(corner)] += 1;
5762
- this.k[ct.vertex(next)] += 1;
5763
- this.k[ct.vertex(prev)] += 2;
5783
+ this.l[ct.vertex(corner)] += 1;
5784
+ this.l[ct.vertex(next)] += 1;
5785
+ this.l[ct.vertex(prev)] += 2;
5764
5786
  break;
5765
5787
  case TOPOLOGY_L:
5766
- this.k[ct.vertex(corner)] += 1;
5767
- this.k[ct.vertex(next)] += 2;
5768
- this.k[ct.vertex(prev)] += 1;
5788
+ this.l[ct.vertex(corner)] += 1;
5789
+ this.l[ct.vertex(next)] += 2;
5790
+ this.l[ct.vertex(prev)] += 1;
5769
5791
  break;
5770
5792
  case TOPOLOGY_E:
5771
- this.k[ct.vertex(corner)] += 2;
5772
- this.k[ct.vertex(next)] += 2;
5773
- this.k[ct.vertex(prev)] += 2;
5793
+ this.l[ct.vertex(corner)] += 2;
5794
+ this.l[ct.vertex(next)] += 2;
5795
+ this.l[ct.vertex(prev)] += 2;
5774
5796
  break;
5775
5797
  default:
5776
5798
  break;
5777
5799
  }
5778
5800
  if (this.A === TOPOLOGY_C || this.A === TOPOLOGY_R) {
5779
5801
  const pivot = ct.vertex(ct.next(corner));
5780
- if (this.k[pivot] < 6) {
5781
- this.ma = TOPOLOGY_R;
5802
+ if (this.l[pivot] < 6) {
5803
+ this.la = TOPOLOGY_R;
5782
5804
  } else {
5783
- this.ma = TOPOLOGY_C;
5805
+ this.la = TOPOLOGY_C;
5784
5806
  }
5785
5807
  } else {
5786
- this.ma = -1;
5808
+ this.la = -1;
5787
5809
  }
5788
5810
  }
5789
5811
  mergeVertices(dest, source) {
5790
- this.k[dest] += this.k[source];
5812
+ this.l[dest] += this.l[source];
5791
5813
  }
5792
5814
  };
5793
5815
 
5794
5816
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalValenceDecoder.ts
5795
5817
  var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraversalDecoder {
5796
5818
  a = null;
5797
- l = 0;
5819
+ k = 0;
5798
5820
  A = -1;
5799
- Wa = -1;
5800
- Xa = 2;
5801
- tb = 7;
5802
- k = new Int32Array(0);
5803
- na = [];
5821
+ Va = -1;
5822
+ Wa = 2;
5823
+ rb = 7;
5824
+ l = new Int32Array(0);
5825
+ ma = [];
5804
5826
  // Int32Array, not number[]: read and written once per decoded symbol.
5805
- Ga = new Int32Array(0);
5827
+ Fa = new Int32Array(0);
5806
5828
  // corner -> vertex of _cornerTable, cached at init(); the array is created
5807
5829
  // once by CornerTable.reset() before the traversal decoder is initialized and
5808
5830
  // never replaced, so the per-symbol hot path can read it without two property
@@ -5814,7 +5836,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5814
5836
  this.j = this.a.j;
5815
5837
  }
5816
5838
  setNumEncodedVertices(numVertices) {
5817
- this.l = numVertices;
5839
+ this.k = numVertices;
5818
5840
  }
5819
5841
  start(outBuffer) {
5820
5842
  if (!this.decodeStartFaces()) {
@@ -5824,11 +5846,12 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5824
5846
  return false;
5825
5847
  }
5826
5848
  outBuffer.init(this.d.dataHead, this.d.remainingSize);
5827
- this.k = scratchInt32Filled(this.l, 0);
5828
- const numUniqueValences = this.tb - this.Xa + 1;
5829
- this.na = new Array(numUniqueValences);
5830
- this.Ga = new Int32Array(numUniqueValences);
5849
+ this.l = scratchInt32Filled(this.k, 0);
5850
+ const numUniqueValences = this.rb - this.Wa + 1;
5851
+ this.ma = new Array(numUniqueValences);
5852
+ this.Fa = new Int32Array(numUniqueValences);
5831
5853
  const pending = [];
5854
+ const streams = [];
5832
5855
  for (let i = 0; i < numUniqueValences; ++i) {
5833
5856
  const numSymbols = decodeVarint(outBuffer);
5834
5857
  if (numSymbols === void 0) {
@@ -5838,13 +5861,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5838
5861
  return false;
5839
5862
  }
5840
5863
  if (numSymbols > 0) {
5841
- this.na[i] = scratchUint32(numSymbols);
5864
+ this.ma[i] = scratchUint32(numSymbols);
5842
5865
  const scheme = outBuffer.decodeUint8();
5843
5866
  if (scheme === 0 /* SYMBOL_CODING_TAGGED */) {
5844
- if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this.na[i])) {
5867
+ if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this.ma[i])) {
5845
5868
  return false;
5846
5869
  }
5847
- this.Ga[i] = numSymbols;
5870
+ this.Fa[i] = numSymbols;
5848
5871
  continue;
5849
5872
  }
5850
5873
  if (scheme !== 1 /* SYMBOL_CODING_RAW */) {
@@ -5864,56 +5887,25 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5864
5887
  if (!decoder.startDecoding(outBuffer)) {
5865
5888
  return false;
5866
5889
  }
5867
- pending.push({ decoder, out: this.na[i], count: numSymbols });
5868
- this.Ga[i] = numSymbols;
5890
+ pending.push(decoder);
5891
+ streams.push({ ans: decoder.K, out: this.ma[i], count: numSymbols });
5892
+ this.Fa[i] = numSymbols;
5869
5893
  } else {
5870
- this.na[i] = new Uint32Array(0);
5871
- this.Ga[i] = 0;
5872
- }
5873
- }
5874
- const lockstep = pending.filter((entry) => !entry.decoder.o.coarse);
5875
- let p = 0;
5876
- while (lockstep.length - p >= 3) {
5877
- const a = lockstep[p];
5878
- const b = lockstep[p + 1];
5879
- const c = lockstep[p + 2];
5880
- ransDecodeSymbolsTrioU16(
5881
- a.decoder.o,
5882
- a.out,
5883
- a.count,
5884
- b.decoder.o,
5885
- b.out,
5886
- b.count,
5887
- c.decoder.o,
5888
- c.out,
5889
- c.count
5890
- );
5891
- p += 3;
5892
- }
5893
- if (lockstep.length - p === 2) {
5894
- const a = lockstep[p];
5895
- const b = lockstep[p + 1];
5896
- ransDecodeSymbolsPairU16(a.decoder.o, a.out, a.count, b.decoder.o, b.out, b.count);
5897
- p += 2;
5898
- }
5899
- for (; p < lockstep.length; ++p) {
5900
- lockstep[p].decoder.o.decodeSymbols(lockstep[p].out, lockstep[p].count);
5901
- }
5902
- for (const entry of pending) {
5903
- if (entry.decoder.o.coarse) {
5904
- entry.decoder.o.decodeSymbols(entry.out, entry.count);
5894
+ this.ma[i] = new Uint32Array(0);
5895
+ this.Fa[i] = 0;
5905
5896
  }
5906
- entry.decoder.endDecoding();
5907
5897
  }
5898
+ ransDecodeStreams(streams);
5899
+ for (const decoder of pending) decoder.endDecoding();
5908
5900
  return true;
5909
5901
  }
5910
5902
  decodeSymbol() {
5911
- if (this.Wa !== -1) {
5912
- const contextCounter = --this.Ga[this.Wa];
5903
+ if (this.Va !== -1) {
5904
+ const contextCounter = --this.Fa[this.Va];
5913
5905
  if (contextCounter < 0) {
5914
5906
  return TOPOLOGY_INVALID;
5915
5907
  }
5916
- const symbolId = this.na[this.Wa][contextCounter];
5908
+ const symbolId = this.ma[this.Va][contextCounter];
5917
5909
  if (symbolId > 4) {
5918
5910
  return TOPOLOGY_INVALID;
5919
5911
  }
@@ -5925,7 +5917,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5925
5917
  }
5926
5918
  newActiveCornerReached(corner) {
5927
5919
  const cornerToVertex = this.j;
5928
- const valences = this.k;
5920
+ const valences = this.l;
5929
5921
  const next = corner % 3 === 2 ? corner - 2 : corner + 1;
5930
5922
  const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
5931
5923
  const vertNext = cornerToVertex[next];
@@ -5956,32 +5948,32 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5956
5948
  }
5957
5949
  const activeValence = valences[vertNext];
5958
5950
  let clampedValence;
5959
- if (activeValence < this.Xa) {
5960
- clampedValence = this.Xa;
5961
- } else if (activeValence > this.tb) {
5962
- clampedValence = this.tb;
5951
+ if (activeValence < this.Wa) {
5952
+ clampedValence = this.Wa;
5953
+ } else if (activeValence > this.rb) {
5954
+ clampedValence = this.rb;
5963
5955
  } else {
5964
5956
  clampedValence = activeValence;
5965
5957
  }
5966
- this.Wa = clampedValence - this.Xa;
5958
+ this.Va = clampedValence - this.Wa;
5967
5959
  }
5968
5960
  mergeVertices(dest, source) {
5969
- this.k[dest] += this.k[source];
5961
+ this.l[dest] += this.l[source];
5970
5962
  }
5971
5963
  };
5972
5964
 
5973
5965
  // src/decoder/compression/mesh/MeshEdgebreakerDecoder.ts
5974
5966
  var MeshEdgebreakerDecoder = class extends MeshDecoder {
5975
5967
  // Set by initializeDecoder(), which runs before anything below is reached.
5976
- oa = null;
5968
+ na = null;
5977
5969
  getCornerTable() {
5978
- return this.oa.getCornerTable();
5970
+ return this.na.getCornerTable();
5979
5971
  }
5980
5972
  getAttributeCornerTable(attId) {
5981
- return this.oa.getAttributeCornerTable(attId);
5973
+ return this.na.getAttributeCornerTable(attId);
5982
5974
  }
5983
5975
  getAttributeEncodingData(attId) {
5984
- return this.oa.getAttributeEncodingData(attId);
5976
+ return this.na.getAttributeEncodingData(attId);
5985
5977
  }
5986
5978
  initializeDecoder() {
5987
5979
  const traversalDecoderType = this.buffer().decodeUint8();
@@ -5989,30 +5981,30 @@ var MeshEdgebreakerDecoder = class extends MeshDecoder {
5989
5981
  if (TraversalDecoderClass === null) {
5990
5982
  return false;
5991
5983
  }
5992
- this.oa = new MeshEdgebreakerDecoderImpl(this, TraversalDecoderClass);
5984
+ this.na = new MeshEdgebreakerDecoderImpl(this, TraversalDecoderClass);
5993
5985
  return true;
5994
5986
  }
5995
5987
  createAttributesDecoder(attDecoderId) {
5996
- return this.oa.createAttributesDecoder(attDecoderId);
5988
+ return this.na.createAttributesDecoder(attDecoderId);
5997
5989
  }
5998
5990
  decodeConnectivity() {
5999
- return this.oa.decodeConnectivity();
5991
+ return this.na.decodeConnectivity();
6000
5992
  }
6001
5993
  };
6002
5994
 
6003
5995
  // src/decoder/compression/attributes/LinearSequencer.ts
6004
5996
  var LinearSequencer = class {
6005
- Ya;
5997
+ Xa;
6006
5998
  x = new Int32Array(0);
6007
5999
  constructor(numPoints) {
6008
- this.Ya = numPoints;
6000
+ this.Xa = numPoints;
6009
6001
  }
6010
6002
  generateSequence() {
6011
- if (this.Ya < 0) {
6003
+ if (this.Xa < 0) {
6012
6004
  return false;
6013
6005
  }
6014
- const ids = new Int32Array(this.Ya);
6015
- for (let i = 0; i < this.Ya; ++i) {
6006
+ const ids = new Int32Array(this.Xa);
6007
+ for (let i = 0; i < this.Xa; ++i) {
6016
6008
  ids[i] = i;
6017
6009
  }
6018
6010
  this.x = ids;
@@ -6046,7 +6038,7 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6046
6038
  return false;
6047
6039
  }
6048
6040
  if (connectivityMethod === 0) {
6049
- if (!this.Fc(numFaces)) {
6041
+ if (!this.Dc(numFaces)) {
6050
6042
  return false;
6051
6043
  }
6052
6044
  } else {
@@ -6085,7 +6077,7 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6085
6077
  new SequentialAttributeDecodersController(new LinearSequencer(this.pointCloud().numPoints()))
6086
6078
  );
6087
6079
  }
6088
- Fc(numFaces) {
6080
+ Dc(numFaces) {
6089
6081
  const numIndices = numFaces * 3;
6090
6082
  const indicesBuffer = new Uint32Array(numIndices);
6091
6083
  if (!decodeSymbols(numIndices, 1, this.buffer(), indicesBuffer)) {
@@ -6196,12 +6188,12 @@ var MinidracoLoader = class extends Loader {
6196
6188
  mainThreadByteThreshold;
6197
6189
  // The pool, once its module has loaded; null again after dispose() so a
6198
6190
  // later decode spawns a fresh one.
6199
- qa = null;
6200
- ub = null;
6191
+ pa = null;
6192
+ sb = null;
6201
6193
  // Set when the pool module fails to load or the pool breaks: decoding
6202
6194
  // transparently falls back to the main thread.
6203
- vb = false;
6204
- Ha = null;
6195
+ tb = false;
6196
+ Ga = null;
6205
6197
  // Accepts either a LoadingManager (three-compatible form) or an options bag.
6206
6198
  constructor(managerOrOptions) {
6207
6199
  const options = isLoadingManager(managerOrOptions) ? { manager: managerOrOptions } : managerOrOptions ?? {};
@@ -6215,7 +6207,7 @@ var MinidracoLoader = class extends Loader {
6215
6207
  // (bundlers emit it as a hashed asset), and CDN origins are handled by the
6216
6208
  // blob bootstrap in the pool. Takes effect for the next pool spawned.
6217
6209
  setWorkerUrl(url) {
6218
- this.Ha = url;
6210
+ this.Ga = url;
6219
6211
  return this;
6220
6212
  }
6221
6213
  // No-ops kept for API compatibility with THREE.DRACOLoader — minidraco has
@@ -6232,7 +6224,7 @@ var MinidracoLoader = class extends Loader {
6232
6224
  }
6233
6225
  setWorkerLimit(limit) {
6234
6226
  this.workerLimit = limit;
6235
- if (this.qa !== null) this.qa.limit = limit;
6227
+ if (this.pa !== null) this.pa.limit = limit;
6236
6228
  return this;
6237
6229
  }
6238
6230
  // Toggle the worker pool on/off. true enables the pool, keeping the current
@@ -6244,15 +6236,15 @@ var MinidracoLoader = class extends Loader {
6244
6236
  // Loads the pool module and spawns the whole pool now, so the workers' JIT
6245
6237
  // warmup overlaps the model download instead of the first decode burst.
6246
6238
  preload() {
6247
- if (this.dc()) {
6248
- this.ec().then((pool) => pool?.spawnAll());
6239
+ if (this.bc()) {
6240
+ this.cc().then((pool) => pool?.spawnAll());
6249
6241
  }
6250
6242
  return this;
6251
6243
  }
6252
6244
  dispose() {
6253
- if (this.qa !== null) this.qa.dispose();
6254
- this.qa = null;
6255
- this.ub = null;
6245
+ if (this.pa !== null) this.pa.dispose();
6246
+ this.pa = null;
6247
+ this.sb = null;
6256
6248
  return this;
6257
6249
  }
6258
6250
  load(url, onLoad, onProgress, onError) {
@@ -6292,21 +6284,21 @@ var MinidracoLoader = class extends Loader {
6292
6284
  return cachedTask.promise;
6293
6285
  }
6294
6286
  }
6295
- const geometryPending = this.Ic(buffer, taskConfig);
6287
+ const geometryPending = this.Gc(buffer, taskConfig);
6296
6288
  _taskCache.set(buffer, { key: taskKey, promise: geometryPending });
6297
6289
  return geometryPending;
6298
6290
  }
6299
- async Ic(buffer, taskConfig) {
6300
- if (this.dc()) {
6291
+ async Gc(buffer, taskConfig) {
6292
+ if (this.bc()) {
6301
6293
  if (buffer.byteLength > this.mainThreadByteThreshold) {
6302
- const pool = await this.ec();
6294
+ const pool = await this.cc();
6303
6295
  if (pool !== null) {
6304
6296
  try {
6305
6297
  const raw = await pool.decode(buffer, taskConfig);
6306
- return this.fc(raw, taskConfig);
6298
+ return this.dc(raw, taskConfig);
6307
6299
  } catch (error) {
6308
6300
  if (error?.isDecodeError) throw error;
6309
- this.vb = true;
6301
+ this.tb = true;
6310
6302
  }
6311
6303
  }
6312
6304
  } else {
@@ -6315,28 +6307,28 @@ var MinidracoLoader = class extends Loader {
6315
6307
  }
6316
6308
  return this._decodeBuffer(buffer, taskConfig);
6317
6309
  }
6318
- dc() {
6319
- return this.workerLimit > 0 && typeof Worker !== "undefined" && !this.vb;
6310
+ bc() {
6311
+ return this.workerLimit > 0 && typeof Worker !== "undefined" && !this.tb;
6320
6312
  }
6321
6313
  // The pool, loading its module on first use. Resolves null (and marks the
6322
6314
  // workers broken) when the module cannot be loaded, e.g. a bundler that does
6323
6315
  // not split dynamic imports out of dependencies.
6324
- ec() {
6325
- this.ub ??= import("./pool.js").then(
6326
- (module) => this.qa = new module.WorkerPool(this.workerLimit, this.Ha),
6316
+ cc() {
6317
+ this.sb ??= import("./pool.js").then(
6318
+ (module) => this.pa = new module.WorkerPool(this.workerLimit, this.Ga),
6327
6319
  () => {
6328
- this.vb = true;
6320
+ this.tb = true;
6329
6321
  return null;
6330
6322
  }
6331
6323
  );
6332
- return this.ub;
6324
+ return this.sb;
6333
6325
  }
6334
- fc(raw, taskConfig) {
6326
+ dc(raw, taskConfig) {
6335
6327
  const geometry = new BufferGeometry();
6336
6328
  for (const attribute of raw.attributes) {
6337
6329
  const bufferAttribute = new BufferAttribute(attribute.array, attribute.itemSize);
6338
6330
  if (attribute.name === "color") {
6339
- this.Jc(bufferAttribute, taskConfig.vertexColorSpace);
6331
+ this.Hc(bufferAttribute, taskConfig.vertexColorSpace);
6340
6332
  bufferAttribute.normalized = !(attribute.array instanceof Float32Array);
6341
6333
  }
6342
6334
  geometry.setAttribute(attribute.name, bufferAttribute);
@@ -6377,9 +6369,9 @@ var MinidracoLoader = class extends Loader {
6377
6369
  }
6378
6370
  const faces = dracoGeometry.faces_;
6379
6371
  const indices = new Uint32Array(faces.buffer, faces.byteOffset, dracoGeometry.numFaces() * 3);
6380
- return this.fc({ indices, attributes }, taskConfig);
6372
+ return this.dc({ indices, attributes }, taskConfig);
6381
6373
  }
6382
- Jc(attribute, inputColorSpace) {
6374
+ Hc(attribute, inputColorSpace) {
6383
6375
  if (inputColorSpace !== SRGBColorSpace) return;
6384
6376
  const _color = new Color();
6385
6377
  for (let i = 0, il = attribute.count; i < il; i++) {