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/index.js CHANGED
@@ -33,72 +33,72 @@ var Type = {
33
33
  };
34
34
  var GeometryAttribute = class {
35
35
  c = null;
36
- w = 1;
37
- L = 9 /* FLOAT32 */;
38
- Qa = false;
39
- M = 0;
40
- N = 0;
41
- Aa = Type.INVALID;
42
- Ba = 0;
36
+ v = 1;
37
+ O = 9 /* FLOAT32 */;
38
+ Pa = false;
39
+ P = 0;
40
+ Q = 0;
41
+ za = Type.INVALID;
42
+ Aa = 0;
43
43
  init(attributeType, buffer, numComponents, dataType, normalized, byteStride, byteOffset) {
44
44
  this.c = buffer;
45
- this.w = numComponents;
46
- this.L = dataType;
47
- this.Qa = normalized;
48
- this.M = byteStride;
49
- this.N = byteOffset;
50
- this.Aa = attributeType;
45
+ this.v = numComponents;
46
+ this.O = dataType;
47
+ this.Pa = normalized;
48
+ this.P = byteStride;
49
+ this.Q = byteOffset;
50
+ this.za = attributeType;
51
51
  }
52
52
  resetBuffer(buffer, byteStride, byteOffset) {
53
53
  this.c = buffer;
54
- this.M = byteStride;
55
- this.N = byteOffset;
54
+ this.P = byteStride;
55
+ this.Q = byteOffset;
56
56
  }
57
57
  get attributeType() {
58
- return this.Aa;
58
+ return this.za;
59
59
  }
60
60
  get dataType() {
61
- return this.L;
61
+ return this.O;
62
62
  }
63
63
  get numComponents() {
64
- return this.w;
64
+ return this.v;
65
65
  }
66
66
  get buffer() {
67
67
  return this.c;
68
68
  }
69
69
  get byteStride() {
70
- return this.M;
70
+ return this.P;
71
71
  }
72
72
  get byteOffset() {
73
- return this.N;
73
+ return this.Q;
74
74
  }
75
75
  get uniqueId() {
76
- return this.Ba;
76
+ return this.Aa;
77
77
  }
78
78
  set uniqueId(id) {
79
- this.Ba = id;
79
+ this.Aa = id;
80
80
  }
81
81
  };
82
82
 
83
83
  // src/decoder/point_cloud/PointCloud.ts
84
84
  var NAMED_ATTRIBUTES_COUNT = 8;
85
85
  var PointCloud = class {
86
- kb = 0;
86
+ ib = 0;
87
87
  attributes_ = [];
88
88
  // named_attribute_index_[type] = [att_id, ...], one list per named type.
89
- Ra = [[], [], [], [], [], [], [], []];
89
+ Qa = [[], [], [], [], [], [], [], []];
90
90
  numNamedAttributes(type) {
91
91
  if (type < 0 || type >= NAMED_ATTRIBUTES_COUNT) {
92
92
  return 0;
93
93
  }
94
- return this.Ra[type].length;
94
+ return this.Qa[type].length;
95
95
  }
96
96
  getNamedAttributeId(type, i) {
97
97
  if (i === void 0) i = 0;
98
98
  if (this.numNamedAttributes(type) <= i) {
99
99
  return -1;
100
100
  }
101
- return this.Ra[type][i];
101
+ return this.Qa[type][i];
102
102
  }
103
103
  getNamedAttribute(type, i) {
104
104
  if (i === void 0) i = 0;
@@ -138,16 +138,16 @@ var PointCloud = class {
138
138
  this.attributes_.push(null);
139
139
  }
140
140
  if (pa.attributeType < NAMED_ATTRIBUTES_COUNT) {
141
- this.Ra[pa.attributeType].push(attId);
141
+ this.Qa[pa.attributeType].push(attId);
142
142
  }
143
143
  pa.uniqueId = attId;
144
144
  this.attributes_[attId] = pa;
145
145
  }
146
146
  numPoints() {
147
- return this.kb;
147
+ return this.ib;
148
148
  }
149
149
  setNumPoints(num) {
150
- this.kb = num;
150
+ this.ib = num;
151
151
  }
152
152
  };
153
153
 
@@ -157,7 +157,7 @@ var Mesh = class extends PointCloud {
157
157
  // a per-face allocation. faces_[3*f + c] is corner c of face f; corner index
158
158
  // ci maps directly to faces_[ci].
159
159
  faces_ = new Int32Array(0);
160
- lb = 0;
160
+ jb = 0;
161
161
  // Sizes faces_ to hold numFaces faces. Called once per decode, before any
162
162
  // face index is written (edgebreaker: _assignPointsToCorners; sequential:
163
163
  // decodeConnectivity), so the buffer is allocated exactly here — the
@@ -169,42 +169,42 @@ var Mesh = class extends PointCloud {
169
169
  grown.set(this.faces_);
170
170
  this.faces_ = grown;
171
171
  }
172
- this.lb = numFaces;
172
+ this.jb = numFaces;
173
173
  }
174
174
  numFaces() {
175
- return this.lb;
175
+ return this.jb;
176
176
  }
177
177
  };
178
178
 
179
179
  // src/decoder/core/DataBuffer.ts
180
180
  var DataBuffer = class {
181
- n = new Uint8Array(0);
181
+ m = new Uint8Array(0);
182
182
  // Resizes to `size` bytes (contents preserved); when `data` is given, grows
183
183
  // as needed and copies its first `size` bytes in.
184
184
  update(data, size) {
185
185
  if (data === null) {
186
- this.mb(size);
186
+ this.kb(size);
187
187
  return;
188
188
  }
189
- if (size > this.n.length) {
190
- this.mb(size);
189
+ if (size > this.m.length) {
190
+ this.kb(size);
191
191
  }
192
- this.n.set(data.length === size ? data : data.subarray(0, size));
192
+ this.m.set(data.length === size ? data : data.subarray(0, size));
193
193
  }
194
194
  // The caller passes a Uint8Array of exactly dataSize bytes in the common
195
195
  // case; avoid allocating a wrapper view per value (dominates storage time /
196
196
  // GC pressure).
197
197
  write(bytePos, inArray, dataSize) {
198
- this.n.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
198
+ this.m.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
199
199
  }
200
200
  get data() {
201
- return this.n;
201
+ return this.m;
202
202
  }
203
- mb(newSize) {
204
- if (newSize === this.n.length) return;
203
+ kb(newSize) {
204
+ if (newSize === this.m.length) return;
205
205
  const newData = new Uint8Array(newSize);
206
- newData.set(this.n.subarray(0, Math.min(this.n.length, newSize)));
207
- this.n = newData;
206
+ newData.set(this.m.subarray(0, Math.min(this.m.length, newSize)));
207
+ this.m = newData;
208
208
  }
209
209
  };
210
210
 
@@ -317,112 +317,117 @@ var LAZY_INTEGER = 1;
317
317
  var LAZY_QUANTIZED = 2;
318
318
  var LAZY_OCTAHEDRON = 3;
319
319
  var PointAttribute = class extends GeometryAttribute {
320
- A = false;
321
- Sa = 0;
322
- B = [];
323
- W = null;
320
+ z = false;
321
+ Ra = 0;
322
+ A = [];
323
+ Z = null;
324
324
  // Lazily-created cached typed-array view over the attribute buffer, keyed
325
325
  // on (constructor, underlying ArrayBuffer). An attribute only ever reads
326
326
  // through the one view type its data type dictates.
327
+ lb = null;
328
+ mb = null;
327
329
  nb = null;
328
- ob = null;
329
- pb = null;
330
330
  // Deferred inverse transform. The integer attribute decoders leave their
331
331
  // decoded values here as int32 -- quantized floats, octahedral normals or
332
332
  // plain integers -- with the transform's parameters, and extractTo applies
333
333
  // the transform while gathering the values into point order: one pass over
334
334
  // the points instead of an inverse-transform pass into a per-value buffer
335
335
  // followed by a gather from it, and no such buffer at all.
336
- Ca = LAZY_NONE;
337
- X = null;
338
- qb = [];
339
- Da = 0;
336
+ Ba = LAZY_NONE;
337
+ _ = null;
338
+ ob = [];
339
+ Ca = 0;
340
+ // Set when the decoder knows every lazy value is below 2^24 in magnitude
341
+ // (see _lazyFloatValues); the extraction then skips its scan.
342
+ Sa = false;
340
343
  constructor(geometryAttribute) {
341
344
  super();
342
345
  if (geometryAttribute instanceof GeometryAttribute) {
343
346
  this.c = geometryAttribute.c;
344
- this.w = geometryAttribute.w;
345
- this.L = geometryAttribute.L;
346
- this.Qa = geometryAttribute.Qa;
347
- this.M = geometryAttribute.M;
348
- this.N = geometryAttribute.N;
347
+ this.v = geometryAttribute.v;
348
+ this.O = geometryAttribute.O;
349
+ this.Pa = geometryAttribute.Pa;
350
+ this.P = geometryAttribute.P;
351
+ this.Q = geometryAttribute.Q;
352
+ this.za = geometryAttribute.za;
349
353
  this.Aa = geometryAttribute.Aa;
350
- this.Ba = geometryAttribute.Ba;
351
354
  }
352
355
  }
353
356
  // Intentionally shadows GeometryAttribute.init with a different signature (matches draco.js / C++ source).
354
357
  // @ts-expect-error -- signature intentionally differs from the base class, as in the source.
355
358
  init(attributeType, numComponents, dataType, normalized, numAttributeValues) {
356
- this.W = new DataBuffer();
359
+ this.Z = new DataBuffer();
357
360
  const byteStride = dataTypeLength(dataType) * numComponents;
358
- super.init(attributeType, this.W, numComponents, dataType, normalized, byteStride, 0);
361
+ super.init(attributeType, this.Z, numComponents, dataType, normalized, byteStride, 0);
359
362
  this.reset(numAttributeValues);
360
363
  this.setIdentityMapping();
361
364
  }
362
365
  reset(numAttributeValues) {
363
- if (this.W === null) {
364
- this.W = new DataBuffer();
366
+ if (this.Z === null) {
367
+ this.Z = new DataBuffer();
365
368
  }
366
369
  const entrySize = dataTypeLength(this.dataType) * this.numComponents;
367
- this.W.update(null, numAttributeValues * entrySize);
368
- this.resetBuffer(this.W, entrySize, 0);
369
- this.Sa = numAttributeValues;
370
+ this.Z.update(null, numAttributeValues * entrySize);
371
+ this.resetBuffer(this.Z, entrySize, 0);
372
+ this.Ra = numAttributeValues;
370
373
  return true;
371
374
  }
372
375
  // Sizes the attribute without allocating storage, for the deferred
373
376
  // transforms below (the values live in the decoder's portable attribute).
374
377
  resetLazy(numAttributeValues) {
375
- this.Sa = numAttributeValues;
378
+ this.Ra = numAttributeValues;
376
379
  }
377
380
  // numValues decoded integers of the attribute's own integer type, stored as
378
381
  // int32; extractTo converts them to the requested output type.
379
382
  setLazyInteger(values) {
380
- this.Ca = LAZY_INTEGER;
381
- this.X = values;
383
+ this.Ba = LAZY_INTEGER;
384
+ this._ = values;
382
385
  }
383
386
  // Quantized float values: value * delta + min per component (float32
384
387
  // arithmetic, see _extractQuantized), as the C++ Dequantizer computes them.
385
- setLazyQuantized(values, minValues, delta) {
386
- this.Ca = LAZY_QUANTIZED;
387
- this.X = values;
388
- this.qb = minValues;
389
- this.Da = delta;
388
+ setLazyQuantized(values, minValues, delta, bounded) {
389
+ this.Ba = LAZY_QUANTIZED;
390
+ this._ = values;
391
+ this.ob = minValues;
392
+ this.Ca = delta;
393
+ this.Sa = bounded;
390
394
  }
391
395
  // Octahedral normals: two quantized coordinates per value, dequantized by
392
396
  // `scale` and turned into unit vectors (see _extractOctahedron).
393
- setLazyOctahedron(values, scale) {
394
- this.Ca = LAZY_OCTAHEDRON;
395
- this.X = values;
396
- this.Da = scale;
397
+ setLazyOctahedron(values, scale, bounded) {
398
+ this.Ba = LAZY_OCTAHEDRON;
399
+ this._ = values;
400
+ this.Ca = scale;
401
+ this.Sa = bounded;
397
402
  }
398
403
  get size() {
399
- return this.Sa;
404
+ return this.Ra;
400
405
  }
401
406
  mappedIndex(pointIndex) {
402
- if (this.A) {
407
+ if (this.z) {
403
408
  return pointIndex;
404
409
  }
405
- return this.B[pointIndex];
410
+ return this.A[pointIndex];
406
411
  }
407
412
  get isMappingIdentity() {
408
- return this.A;
413
+ return this.z;
409
414
  }
410
415
  get indicesMapSize() {
411
- if (this.A) {
416
+ if (this.z) {
412
417
  return 0;
413
418
  }
414
- return this.B.length;
419
+ return this.A.length;
415
420
  }
416
421
  // Direct access to the explicit point->value index map (a Uint32Array after
417
422
  // any of the setExplicitMapping* calls). Lets hot mapping loops write
418
423
  // entries without a per-entry dispatch.
419
424
  get indicesMap() {
420
- return this.B;
425
+ return this.A;
421
426
  }
422
427
  // Implicit mapping: point index equals attribute entry index.
423
428
  setIdentityMapping() {
424
- this.A = true;
425
- this.B = [];
429
+ this.z = true;
430
+ this.A = [];
426
431
  }
427
432
  // Explicit mapping without an invalid-index fill. Only for callers that
428
433
  // provably write every entry right away (the fill was ~4% of decode time on
@@ -432,31 +437,31 @@ var PointAttribute = class extends GeometryAttribute {
432
437
  // and avoids boxed-number storage; it is read once per point per attribute.
433
438
  // Must be UNSIGNED so the 0xFFFFFFFF invalid sentinel round-trips intact.
434
439
  setExplicitMappingUnfilled(numPoints) {
435
- this.A = false;
436
- this.B = new Uint32Array(numPoints);
440
+ this.z = false;
441
+ this.A = new Uint32Array(numPoints);
437
442
  }
438
443
  // Adopts an already-computed map, shared with other attributes of the same
439
444
  // mesh. The map must be treated as read-only from here on (reads go through
440
445
  // mappedIndex/extractTo).
441
446
  setExplicitMappingShared(map) {
442
- this.A = false;
443
- this.B = map;
447
+ this.z = false;
448
+ this.A = map;
444
449
  }
445
450
  // Like setExplicitMappingUnfilled, but from decode-scoped scratch. Only for
446
451
  // attributes that never escape the decode (see ScratchArena) -- the portable
447
452
  // attributes the sequential decoders build and discard.
448
453
  setExplicitMappingScratch(numPoints) {
449
- this.A = false;
450
- this.B = scratchUint32(numPoints);
454
+ this.z = false;
455
+ this.A = scratchUint32(numPoints);
451
456
  }
452
457
  // Cached typed-array view of the given type over the attribute buffer.
453
- rb(Ctor, bufData) {
454
- if (this.nb !== Ctor || this.ob !== bufData.buffer) {
455
- this.nb = Ctor;
456
- this.ob = bufData.buffer;
457
- this.pb = new Ctor(bufData.buffer);
458
+ pb(Ctor, bufData) {
459
+ if (this.lb !== Ctor || this.mb !== bufData.buffer) {
460
+ this.lb = Ctor;
461
+ this.mb = bufData.buffer;
462
+ this.nb = new Ctor(bufData.buffer);
458
463
  }
459
- return this.pb;
464
+ return this.nb;
460
465
  }
461
466
  // Mirrors C++ PointAttribute::ConvertValue<T>() for buffer-backed
462
467
  // attributes. Attribute buffers start at byteOffset 0 and entries are
@@ -464,44 +469,44 @@ var PointAttribute = class extends GeometryAttribute {
464
469
  // of a per-component DataView dispatch.
465
470
  convertValue(attIndex, outVal) {
466
471
  const bufData = this.c.data;
467
- const nc = this.w;
468
- const Ctor = viewCtorFor(this.L);
472
+ const nc = this.v;
473
+ const Ctor = viewCtorFor(this.O);
469
474
  if (Ctor === null) {
470
475
  for (let i = 0; i < nc; ++i) outVal[i] = 0;
471
476
  return;
472
477
  }
473
- const view = this.rb(Ctor, bufData);
474
- const baseIndex = (bufData.byteOffset + this.N + this.M * attIndex) / Ctor.BYTES_PER_ELEMENT;
478
+ const view = this.pb(Ctor, bufData);
479
+ const baseIndex = (bufData.byteOffset + this.Q + this.P * attIndex) / Ctor.BYTES_PER_ELEMENT;
475
480
  for (let i = 0; i < nc; ++i) outVal[i] = view[baseIndex + i];
476
481
  }
477
482
  // Flat-array extraction of all values into one output typed array, in point
478
483
  // order (applying the deferred transform, if any, on the way).
479
484
  extractTo(OutputTypedArray, numPoints) {
480
- const numComponents = this.w;
485
+ const numComponents = this.v;
481
486
  const array = new OutputTypedArray(numPoints * numComponents);
482
487
  if (numPoints === 0) {
483
488
  return array;
484
489
  }
485
- const kind = this.Ca;
490
+ const kind = this.Ba;
486
491
  if (kind !== LAZY_NONE) {
487
- if (this.X !== null) {
488
- if (kind === LAZY_QUANTIZED) this.Sb(array, numPoints);
489
- else if (kind === LAZY_OCTAHEDRON) this.Tb(array, numPoints);
490
- else this.Ub(array, numPoints);
492
+ if (this._ !== null) {
493
+ if (kind === LAZY_QUANTIZED) this.Qb(array, numPoints);
494
+ else if (kind === LAZY_OCTAHEDRON) this.Rb(array, numPoints);
495
+ else this.Sb(array, numPoints);
491
496
  }
492
497
  return array;
493
498
  }
494
- const Ctor = viewCtorFor(this.L);
499
+ const Ctor = viewCtorFor(this.O);
495
500
  if (this.c === null || Ctor === null) {
496
501
  return array;
497
502
  }
498
503
  const bufData = this.c.data;
499
- const isIdentity = this.A;
500
- const indicesMap = this.B;
501
- const srcView = this.rb(Ctor, bufData);
504
+ const isIdentity = this.z;
505
+ const indicesMap = this.A;
506
+ const srcView = this.pb(Ctor, bufData);
502
507
  const shift = 31 - Math.clz32(Ctor.BYTES_PER_ELEMENT);
503
- const srcStart = bufData.byteOffset + this.N >> shift;
504
- const strideElements = this.M >> shift;
508
+ const srcStart = bufData.byteOffset + this.Q >> shift;
509
+ const strideElements = this.P >> shift;
505
510
  if (isIdentity && strideElements === numComponents) {
506
511
  const srcEnd = srcStart + numPoints * numComponents;
507
512
  if (srcView.constructor === OutputTypedArray) {
@@ -529,7 +534,7 @@ var PointAttribute = class extends GeometryAttribute {
529
534
  // Point -> value index; the identity mapping (sequential meshes) gets a
530
535
  // plain iota so the loops carry no per-point branch.
531
536
  Ta(numPoints) {
532
- if (!this.A) return this.B;
537
+ if (!this.z) return this.A;
533
538
  const map = new Uint32Array(numPoints);
534
539
  for (let p = 0; p < numPoints; ++p) map[p] = p;
535
540
  return map;
@@ -540,8 +545,11 @@ var PointAttribute = class extends GeometryAttribute {
540
545
  // without the (measurably costly) int-to-float32-to-double round trip per
541
546
  // component. Larger values (quantization above 24 bits, never seen in
542
547
  // practice) are rounded in place once here, after which the same holds.
543
- sb() {
544
- const values = this.X;
548
+ // The decoder marks the attribute bounded when its prediction transform
549
+ // already confines the values to that range, and the scan is skipped.
550
+ qb() {
551
+ const values = this._;
552
+ if (this.Sa) return values;
545
553
  for (let i = 0; i < values.length; ++i) {
546
554
  if (values[i] >= 16777216 || values[i] <= -16777216) {
547
555
  for (let j = 0; j < values.length; ++j) values[j] = Math.fround(values[j]);
@@ -551,13 +559,13 @@ var PointAttribute = class extends GeometryAttribute {
551
559
  return values;
552
560
  }
553
561
  // C++ Dequantizer: float(value) * delta + min, all in float32.
554
- Sb(out, numPoints) {
555
- const values = this.sb();
562
+ Qb(out, numPoints) {
563
+ const values = this.qb();
556
564
  const map = this.Ta(numPoints);
557
- const numComponents = this.w;
565
+ const numComponents = this.v;
558
566
  const fround = Math.fround;
559
- const delta = this.Da;
560
- const min = this.qb;
567
+ const delta = this.Ca;
568
+ const min = this.ob;
561
569
  if (numComponents === 3) {
562
570
  const m0 = min[0];
563
571
  const m1 = min[1];
@@ -589,11 +597,11 @@ var PointAttribute = class extends GeometryAttribute {
589
597
  }
590
598
  // OctahedronToolBox.QuantizedOctahedralCoordsToUnitVector, two quantized
591
599
  // coordinates per value to one unit vector per point.
592
- Tb(out, numPoints) {
593
- const values = this.sb();
600
+ Rb(out, numPoints) {
601
+ const values = this.qb();
594
602
  const map = this.Ta(numPoints);
595
603
  const fround = Math.fround;
596
- const scale = this.Da;
604
+ const scale = this.Ca;
597
605
  for (let p = 0, d = 0; p < numPoints; ++p, d += 3) {
598
606
  const s = map[p] * 2;
599
607
  let y = fround(fround(values[s] * scale) - 1);
@@ -618,11 +626,11 @@ var PointAttribute = class extends GeometryAttribute {
618
626
  }
619
627
  // The int32 values wrap to the attribute's own integer type (as storing
620
628
  // them into it would) before the output store converts them.
621
- Ub(out, numPoints) {
622
- const values = this.X;
629
+ Sb(out, numPoints) {
630
+ const values = this._;
623
631
  const map = this.Ta(numPoints);
624
- const numComponents = this.w;
625
- const dt = this.L;
632
+ const numComponents = this.v;
633
+ const dt = this.O;
626
634
  const shift = 32 - 8 * dataTypeLength(dt);
627
635
  const signed = dt === 1 /* INT8 */ || dt === 3 /* INT16 */ || dt === 5 /* INT32 */;
628
636
  for (let p = 0, d = 0; p < numPoints; ++p) {
@@ -654,21 +662,21 @@ function decodeVarint(buffer) {
654
662
 
655
663
  // src/decoder/core/DecoderBuffer.ts
656
664
  var BitDecoder = class {
657
- Ea = null;
658
- o = 0;
659
- ka = 0;
665
+ Da = null;
666
+ p = 0;
667
+ ja = 0;
660
668
  reset(uint8Array, byteLength) {
661
- this.Ea = uint8Array;
662
- this.ka = byteLength;
663
- this.o = 0;
669
+ this.Da = uint8Array;
670
+ this.ja = byteLength;
671
+ this.p = 0;
664
672
  }
665
673
  getBits(nbits) {
666
674
  if (nbits > 32) return void 0;
667
- const buf = this.Ea;
668
- let off = this.o;
675
+ const buf = this.Da;
676
+ let off = this.p;
669
677
  const byteOffset = off >> 3;
670
678
  const bitShift = off & 7;
671
- if (byteOffset + 4 < this.ka) {
679
+ if (byteOffset + 4 < this.ja) {
672
680
  const val = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> 0;
673
681
  let result;
674
682
  if (nbits > 32 - bitShift) {
@@ -679,7 +687,7 @@ var BitDecoder = class {
679
687
  } else {
680
688
  result = val >>> bitShift;
681
689
  }
682
- this.o = off + nbits;
690
+ this.p = off + nbits;
683
691
  return nbits === 32 ? result : result & (1 << nbits) - 1;
684
692
  }
685
693
  let value = 0;
@@ -687,7 +695,7 @@ var BitDecoder = class {
687
695
  let currOff = off;
688
696
  while (bitsRead < nbits) {
689
697
  const bOff = currOff >> 3;
690
- if (bOff >= this.ka) return void 0;
698
+ if (bOff >= this.ja) return void 0;
691
699
  const bShift = currOff & 7;
692
700
  const bitsAvail = 8 - bShift;
693
701
  const bitsNeeded = nbits - bitsRead;
@@ -697,53 +705,53 @@ var BitDecoder = class {
697
705
  bitsRead += bitsToRead;
698
706
  currOff += bitsToRead;
699
707
  }
700
- this.o = currOff;
708
+ this.p = currOff;
701
709
  return value;
702
710
  }
703
711
  };
704
712
  var DecoderBuffer = class {
705
- n = null;
706
- Fa = null;
707
- I = 0;
713
+ m = null;
714
+ Ea = null;
715
+ K = 0;
708
716
  d = 0;
709
- la = new BitDecoder();
710
- Ga = false;
717
+ ka = new BitDecoder();
718
+ Fa = false;
711
719
  init(data, dataSize = data.length) {
712
- this.n = data;
713
- this.Fa = new DataView(data.buffer, data.byteOffset, data.byteLength);
714
- this.I = dataSize;
720
+ this.m = data;
721
+ this.Ea = new DataView(data.buffer, data.byteOffset, data.byteLength);
722
+ this.K = dataSize;
715
723
  this.d = 0;
716
724
  }
717
725
  // Typed little-endian reads.
718
726
  decodeUint8() {
719
- if (this.d + 1 > this.I) return void 0;
720
- const val = this.n[this.d];
727
+ if (this.d + 1 > this.K) return void 0;
728
+ const val = this.m[this.d];
721
729
  this.d += 1;
722
730
  return val;
723
731
  }
724
732
  decodeUint16() {
725
- if (this.d + 2 > this.I) return void 0;
726
- const val = this.Fa.getUint16(this.d, true);
733
+ if (this.d + 2 > this.K) return void 0;
734
+ const val = this.Ea.getUint16(this.d, true);
727
735
  this.d += 2;
728
736
  return val;
729
737
  }
730
738
  decodeInt32() {
731
- if (this.d + 4 > this.I) return void 0;
732
- const val = this.Fa.getInt32(this.d, true);
739
+ if (this.d + 4 > this.K) return void 0;
740
+ const val = this.Ea.getInt32(this.d, true);
733
741
  this.d += 4;
734
742
  return val;
735
743
  }
736
744
  decodeFloat32() {
737
- if (this.d + 4 > this.I) return void 0;
738
- const val = this.Fa.getFloat32(this.d, true);
745
+ if (this.d + 4 > this.K) return void 0;
746
+ const val = this.Ea.getFloat32(this.d, true);
739
747
  this.d += 4;
740
748
  return val;
741
749
  }
742
750
  // A view into the stream (no copy), only valid until the caller's next
743
751
  // chance to mutate the buffer — copy out before keeping it.
744
752
  decodeBytesView(size) {
745
- if (this.d + size > this.I) return void 0;
746
- const result = this.n.subarray(this.d, this.d + size);
753
+ if (this.d + size > this.K) return void 0;
754
+ const result = this.m.subarray(this.d, this.d + size);
747
755
  this.d += size;
748
756
  return result;
749
757
  }
@@ -756,35 +764,35 @@ var DecoderBuffer = class {
756
764
  if (size === void 0) return void 0;
757
765
  outSize = size;
758
766
  }
759
- this.Ga = true;
760
- this.la.reset(this.n.subarray(this.d), this.I - this.d);
767
+ this.Fa = true;
768
+ this.ka.reset(this.m.subarray(this.d), this.K - this.d);
761
769
  return outSize;
762
770
  }
763
771
  endBitDecoding() {
764
- this.Ga = false;
765
- this.d += Math.ceil(this.la.o / 8);
772
+ this.Fa = false;
773
+ this.d += Math.ceil(this.ka.p / 8);
766
774
  }
767
775
  decodeLeastSignificantBits32(nbits) {
768
- if (!this.Ga) return void 0;
769
- return this.la.getBits(nbits);
776
+ if (!this.Fa) return void 0;
777
+ return this.ka.getBits(nbits);
770
778
  }
771
779
  advance(bytes) {
772
780
  this.d += bytes;
773
781
  }
774
782
  get data() {
775
- return this.n;
783
+ return this.m;
776
784
  }
777
785
  get dataHead() {
778
- return this.n.subarray(this.d);
786
+ return this.m.subarray(this.d);
779
787
  }
780
788
  get remainingSize() {
781
- return this.I - this.d;
789
+ return this.K - this.d;
782
790
  }
783
791
  get decodedSize() {
784
792
  return this.d;
785
793
  }
786
794
  get bitDecoderActive() {
787
- return this.Ga;
795
+ return this.Fa;
788
796
  }
789
797
  };
790
798
 
@@ -802,17 +810,17 @@ var METADATA_FLAG_MASK = 32768;
802
810
  var kMaxSubmetadataLevel = 1e3;
803
811
  var MetadataDecoder = class {
804
812
  constructor(buffer_) {
805
- this.C = buffer_;
813
+ this.B = buffer_;
806
814
  }
807
815
  buffer_;
808
816
  // Skips per-attribute metadata followed by the geometry-level metadata.
809
817
  skipGeometryMetadata() {
810
- const numAttMetadata = decodeVarint(this.C);
818
+ const numAttMetadata = decodeVarint(this.B);
811
819
  if (numAttMetadata === void 0) {
812
820
  return false;
813
821
  }
814
822
  for (let i = 0; i < numAttMetadata; ++i) {
815
- if (decodeVarint(this.C) === void 0) {
823
+ if (decodeVarint(this.B) === void 0) {
816
824
  return false;
817
825
  }
818
826
  if (!this.Ua(0)) {
@@ -827,41 +835,41 @@ var MetadataDecoder = class {
827
835
  if (level > kMaxSubmetadataLevel) {
828
836
  return false;
829
837
  }
830
- const numEntries = decodeVarint(this.C);
838
+ const numEntries = decodeVarint(this.B);
831
839
  if (numEntries === void 0) {
832
840
  return false;
833
841
  }
834
842
  for (let i = 0; i < numEntries; ++i) {
835
- const nameSkipped = this.tb();
836
- const dataSize = nameSkipped ? decodeVarint(this.C) : void 0;
837
- if (dataSize === void 0 || dataSize === 0 || !this.ub(dataSize)) {
843
+ const nameSkipped = this.rb();
844
+ const dataSize = nameSkipped ? decodeVarint(this.B) : void 0;
845
+ if (dataSize === void 0 || dataSize === 0 || !this.sb(dataSize)) {
838
846
  return false;
839
847
  }
840
848
  }
841
- const numSubMetadata = decodeVarint(this.C);
842
- if (numSubMetadata === void 0 || numSubMetadata > this.C.remainingSize) {
849
+ const numSubMetadata = decodeVarint(this.B);
850
+ if (numSubMetadata === void 0 || numSubMetadata > this.B.remainingSize) {
843
851
  return false;
844
852
  }
845
853
  for (let i = 0; i < numSubMetadata; ++i) {
846
- if (!this.tb() || !this.Ua(level + 1)) {
854
+ if (!this.rb() || !this.Ua(level + 1)) {
847
855
  return false;
848
856
  }
849
857
  }
850
858
  return true;
851
859
  }
852
860
  // Skips a name (uint8 length prefix followed by that many bytes).
853
- tb() {
854
- const nameLen = this.C.decodeUint8();
861
+ rb() {
862
+ const nameLen = this.B.decodeUint8();
855
863
  if (nameLen === void 0) {
856
864
  return false;
857
865
  }
858
- return this.ub(nameLen);
866
+ return this.sb(nameLen);
859
867
  }
860
- ub(size) {
861
- if (size > this.C.remainingSize) {
868
+ sb(size) {
869
+ if (size > this.B.remainingSize) {
862
870
  return false;
863
871
  }
864
- this.C.advance(size);
872
+ this.B.advance(size);
865
873
  return true;
866
874
  }
867
875
  };
@@ -999,12 +1007,12 @@ var RAnsDecoder = class {
999
1007
  // written back once. Removes per-symbol property reads and call indirection.
1000
1008
  decodeSymbols(out, count) {
1001
1009
  if (this.coarse) {
1002
- this.Vb(out, count);
1010
+ this.Tb(out, count);
1003
1011
  return;
1004
1012
  }
1005
- this.Wb(out, count, this.lutTable);
1013
+ this.Ub(out, count, this.lutTable);
1006
1014
  }
1007
- Wb(out, count, lutTable) {
1015
+ Ub(out, count, lutTable) {
1008
1016
  const buf = this.buf;
1009
1017
  const lRansBase = this.lRansBase;
1010
1018
  const ransPrecisionBits = this.ransPrecisionBits;
@@ -1028,7 +1036,7 @@ var RAnsDecoder = class {
1028
1036
  }
1029
1037
  // Short-stream loop: bucket table + cumProb scan instead of the full lut.
1030
1038
  // Same state arithmetic as the lut loops, so the output is identical.
1031
- Vb(out, count) {
1039
+ Tb(out, count) {
1032
1040
  const buf = this.buf;
1033
1041
  const lRansBase = this.lRansBase;
1034
1042
  const ransPrecisionBits = this.ransPrecisionBits;
@@ -1090,12 +1098,15 @@ var RAnsDecoder = class {
1090
1098
  return false;
1091
1099
  }
1092
1100
  cumProbTable[numSymbols] = ransPrecision;
1093
- const bucketShift = this.ransPrecisionBits - COARSE_BUCKET_BITS;
1094
- const bucketTable = numSymbols > 65536 ? acquirePooled(Uint32Array, 1 << COARSE_BUCKET_BITS) : acquirePooled(Uint16Array, 1 << COARSE_BUCKET_BITS);
1101
+ let bucketBits = 33 - Math.clz32(numSymbols);
1102
+ if (bucketBits > COARSE_BUCKET_BITS) bucketBits = COARSE_BUCKET_BITS;
1103
+ const numBuckets = 1 << bucketBits;
1104
+ const bucketShift = this.ransPrecisionBits - bucketBits;
1105
+ const bucketTable = numSymbols > 65536 ? acquirePooled(Uint32Array, numBuckets) : acquirePooled(Uint16Array, numBuckets);
1095
1106
  this.bucketShift = bucketShift;
1096
1107
  this.bucketTable = bucketTable;
1097
1108
  let symbol = 0;
1098
- for (let b = 0; b < 1 << COARSE_BUCKET_BITS; ++b) {
1109
+ for (let b = 0; b < numBuckets; ++b) {
1099
1110
  const rem = b << bucketShift;
1100
1111
  while (cumProbTable[symbol + 1] <= rem) symbol++;
1101
1112
  bucketTable[b] = symbol;
@@ -1129,12 +1140,36 @@ var RAnsDecoder = class {
1129
1140
  return true;
1130
1141
  }
1131
1142
  };
1132
- function ransDecodeSymbolsPair(a, outA, countA, b, outB, countB) {
1133
- if (!a.coarse && !b.coarse) {
1134
- ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB);
1135
- } else {
1136
- a.decodeSymbols(outA, countA);
1137
- b.decodeSymbols(outB, countB);
1143
+ function ransDecodeStreams(streams) {
1144
+ const live = [];
1145
+ for (const stream of streams) {
1146
+ if (stream.count === 0) continue;
1147
+ if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
1148
+ else live.push({ ans: stream.ans, out: stream.out, count: stream.count });
1149
+ }
1150
+ const byLength = (x, y) => y.count - x.count;
1151
+ live.sort(byLength);
1152
+ while (live.length >= 3) {
1153
+ const a = live[0];
1154
+ const b = live[1];
1155
+ const c = live[2];
1156
+ const shared = c.count;
1157
+ ransDecodeSymbolsTrioU16(a.ans, a.out, shared, b.ans, b.out, shared, c.ans, c.out, shared);
1158
+ live.splice(2, 1);
1159
+ a.out = a.out.subarray(shared);
1160
+ a.count -= shared;
1161
+ b.out = b.out.subarray(shared);
1162
+ b.count -= shared;
1163
+ if (a.count === 0) live.shift();
1164
+ if (b.count === 0) live.splice(live.indexOf(b), 1);
1165
+ live.sort(byLength);
1166
+ }
1167
+ if (live.length === 2) {
1168
+ const a = live[0];
1169
+ const b = live[1];
1170
+ ransDecodeSymbolsPairU16(a.ans, a.out, a.count, b.ans, b.out, b.count);
1171
+ } else if (live.length === 1) {
1172
+ live[0].ans.decodeSymbols(live[0].out, live[0].count);
1138
1173
  }
1139
1174
  }
1140
1175
  function ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB) {
@@ -1266,10 +1301,10 @@ function ransDecodeSymbolsTrioU16(a, outA, countA, b, outB, countB, c, outC, cou
1266
1301
 
1267
1302
  // src/decoder/compression/point_cloud/PointCloudDecoder.ts
1268
1303
  var PointCloudDecoder = class {
1269
- O = null;
1304
+ R = null;
1270
1305
  c = null;
1271
- s = [];
1272
- Ha = [];
1306
+ t = [];
1307
+ Ga = [];
1273
1308
  // Returns an error message, or '' on success (outHeader is then populated).
1274
1309
  static decodeHeader(buffer, outHeader) {
1275
1310
  const kIoErrorMsg = "Failed to parse Draco header.";
@@ -1299,7 +1334,7 @@ var PointCloudDecoder = class {
1299
1334
  // Main entry point, given the already-parsed header (see Decode.ts).
1300
1335
  decode(header, inBuffer, outPointCloud) {
1301
1336
  this.c = inBuffer;
1302
- this.O = outPointCloud;
1337
+ this.R = outPointCloud;
1303
1338
  if (header.versionMajor !== 2 || header.versionMinor !== 2) {
1304
1339
  return "Unsupported bitstream version (Draco 2.2 meshes only).";
1305
1340
  }
@@ -1321,27 +1356,27 @@ var PointCloudDecoder = class {
1321
1356
  if (attDecoderId < 0) {
1322
1357
  return false;
1323
1358
  }
1324
- while (this.s.length <= attDecoderId) {
1325
- this.s.push(null);
1359
+ while (this.t.length <= attDecoderId) {
1360
+ this.t.push(null);
1326
1361
  }
1327
- this.s[attDecoderId] = decoder;
1362
+ this.t[attDecoderId] = decoder;
1328
1363
  return true;
1329
1364
  }
1330
1365
  getPortableAttribute(parentAttId) {
1331
- if (parentAttId < 0 || parentAttId >= this.O.numAttributes()) {
1366
+ if (parentAttId < 0 || parentAttId >= this.R.numAttributes()) {
1332
1367
  return null;
1333
1368
  }
1334
- const parentAttDecoderId = this.Ha[parentAttId];
1335
- return this.s[parentAttDecoderId].getPortableAttribute(parentAttId);
1369
+ const parentAttDecoderId = this.Ga[parentAttId];
1370
+ return this.t[parentAttDecoderId].getPortableAttribute(parentAttId);
1336
1371
  }
1337
1372
  attributesDecoder(decId) {
1338
- return this.s[decId];
1373
+ return this.t[decId];
1339
1374
  }
1340
1375
  numAttributesDecoders() {
1341
- return this.s.length;
1376
+ return this.t.length;
1342
1377
  }
1343
1378
  pointCloud() {
1344
- return this.O;
1379
+ return this.R;
1345
1380
  }
1346
1381
  buffer() {
1347
1382
  return this.c;
@@ -1367,52 +1402,40 @@ var PointCloudDecoder = class {
1367
1402
  return false;
1368
1403
  }
1369
1404
  }
1370
- for (let i = 0; i < this.s.length; ++i) {
1371
- if (!this.s[i].init(this, this.O)) {
1405
+ for (let i = 0; i < this.t.length; ++i) {
1406
+ if (!this.t[i].init(this, this.R)) {
1372
1407
  return false;
1373
1408
  }
1374
1409
  }
1375
1410
  for (let i = 0; i < numAttributesDecoders; ++i) {
1376
- if (!this.s[i].decodeAttributesDecoderData(this.c)) {
1411
+ if (!this.t[i].decodeAttributesDecoderData(this.c)) {
1377
1412
  return false;
1378
1413
  }
1379
1414
  }
1380
1415
  for (let i = 0; i < numAttributesDecoders; ++i) {
1381
- const numAttributes = this.s[i].getNumAttributes();
1416
+ const numAttributes = this.t[i].getNumAttributes();
1382
1417
  for (let j = 0; j < numAttributes; ++j) {
1383
- const attId = this.s[i].getAttributeId(j);
1384
- while (this.Ha.length <= attId) {
1385
- this.Ha.push(0);
1418
+ const attId = this.t[i].getAttributeId(j);
1419
+ while (this.Ga.length <= attId) {
1420
+ this.Ga.push(0);
1386
1421
  }
1387
- this.Ha[attId] = i;
1422
+ this.Ga[attId] = i;
1388
1423
  }
1389
1424
  }
1390
1425
  return this.decodeAllAttributes();
1391
1426
  }
1392
1427
  decodeAllAttributes() {
1393
- const decoders = this.s;
1394
- for (let i2 = 0; i2 < decoders.length; i2++) {
1395
- if (!decoders[i2].decodeAttributesParse(this.c)) {
1428
+ const decoders = this.t;
1429
+ for (let i = 0; i < decoders.length; i++) {
1430
+ if (!decoders[i].decodeAttributesParse(this.c)) {
1396
1431
  return false;
1397
1432
  }
1398
1433
  }
1399
1434
  const pending = [];
1400
- for (let i2 = 0; i2 < decoders.length; i2++) {
1401
- decoders[i2].collectPendingSymbolStreams(pending);
1402
- }
1403
- const paired = pending.filter((stream) => !stream.ans.coarse);
1404
- let i = 0;
1405
- for (; i + 1 < paired.length; i += 2) {
1406
- const a = paired[i];
1407
- const b = paired[i + 1];
1408
- ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
1409
- }
1410
- if (i < paired.length) {
1411
- paired[i].ans.decodeSymbols(paired[i].out, paired[i].count);
1412
- }
1413
- for (const stream of pending) {
1414
- if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
1435
+ for (let i = 0; i < decoders.length; i++) {
1436
+ decoders[i].collectPendingSymbolStreams(pending);
1415
1437
  }
1438
+ ransDecodeStreams(pending);
1416
1439
  for (let k = 0; k < decoders.length; k++) {
1417
1440
  if (!decoders[k].decodeAttributesFinish()) {
1418
1441
  return false;
@@ -1424,10 +1447,10 @@ var PointCloudDecoder = class {
1424
1447
 
1425
1448
  // src/decoder/compression/mesh/MeshDecoder.ts
1426
1449
  var MeshDecoder = class extends PointCloudDecoder {
1427
- D = null;
1450
+ C = null;
1428
1451
  // Returns an error message, or '' on success.
1429
1452
  decodeMesh(header, inBuffer, outMesh) {
1430
- this.D = outMesh;
1453
+ this.C = outMesh;
1431
1454
  return this.decode(header, inBuffer, outMesh);
1432
1455
  }
1433
1456
  // Connectivity accessors used by the mesh prediction schemes; the sequential
@@ -1442,7 +1465,7 @@ var MeshDecoder = class extends PointCloudDecoder {
1442
1465
  return null;
1443
1466
  }
1444
1467
  mesh() {
1445
- return this.D;
1468
+ return this.C;
1446
1469
  }
1447
1470
  decodeGeometryData() {
1448
1471
  return this.decodeConnectivity() && super.decodeGeometryData();
@@ -1451,89 +1474,84 @@ var MeshDecoder = class extends PointCloudDecoder {
1451
1474
 
1452
1475
  // src/decoder/mesh/MeshAttributeCornerTable.ts
1453
1476
  var kInvalidCornerIndex = -1;
1454
- var kInvalidVertexIndex = -1;
1455
1477
  var MeshAttributeCornerTable = class {
1456
- Y = [];
1457
- ma = [];
1458
- Z = [];
1459
- na = [];
1478
+ // Base vertices touched by a seam edge of this table.
1479
+ la = new Uint8Array(0);
1480
+ S = new Int32Array(0);
1481
+ // Attribute vertex -> 1 when its fan is open in this table (see
1482
+ // CornerTable._vertexOnBoundary). The C++ also keeps each attribute
1483
+ // vertex's left-most corner, but the decoder only ever asked it whether
1484
+ // that corner sits on a boundary, which this answers directly.
1485
+ y = new Uint8Array(0);
1460
1486
  // Attribute-vertex count. C++ keeps a vertex -> attribute-entry map here, but
1461
1487
  // the decoder only ever reads its size, so track the count directly instead
1462
1488
  // of allocating an Int32Array per attribute corner table.
1463
- oa = 0;
1464
- t = null;
1465
- // Lazily built; see oppositeCornerArray.
1466
- P = null;
1467
- // Every corner passed to addSeamEdge (may contain duplicates); lets
1468
- // oppositeCornerArray patch seams without scanning every corner's flag.
1469
- // Preallocated to its exact upper bound (2 per seam edge) by the caller via
1470
- // reserveSeamEdges -- a plain array grown by push() was measurable on
1471
- // seam-heavy files.
1472
- _ = [];
1473
- Q = 0;
1489
+ ma = 0;
1490
+ D = null;
1491
+ // The base table's opposite corners with both corners of every seam edge
1492
+ // set to -1: what opposite() answers, and what the traversals read.
1493
+ E = new Int32Array(0);
1494
+ // Starts the table as a copy of the base connectivity; addSeamEdge then
1495
+ // cuts the seams and the ring pass numbers the vertices. Decode-scoped
1496
+ // scratch throughout: the table lives only until the decode finishes (the
1497
+ // result mesh keeps no reference to it), so pooling keeps a primitive-heavy
1498
+ // file from allocating a fresh set per attribute per prim.
1474
1499
  initEmpty(table) {
1475
- if (table === null) {
1476
- return false;
1477
- }
1478
- this.Y = scratchUint8Zeroed(table.numCorners());
1479
- this.ma = scratchUint8Zeroed(table.numVertices());
1480
- this.Z = scratchInt32Filled(table.numCorners(), kInvalidVertexIndex);
1481
- this.oa = 0;
1482
- this.na = [];
1483
- this.P = null;
1484
- this._ = [];
1485
- this.Q = 0;
1486
- this.t = table;
1487
- return true;
1488
- }
1489
- // Sizes the seam-corner list for numSeamEdges upcoming addSeamEdge calls
1490
- // (each adds at most two corners). Decode-scoped scratch.
1491
- reserveSeamEdges(numSeamEdges) {
1492
- this._ = scratchInt32(numSeamEdges * 2);
1493
- this.Q = 0;
1494
- }
1500
+ const numCorners = table.numCorners();
1501
+ this.D = table;
1502
+ this.la = scratchUint8Zeroed(table.numVertices());
1503
+ this.E = scratchInt32(numCorners);
1504
+ this.E.set(table.oppositeCornerArray());
1505
+ this.S = scratchInt32(numCorners);
1506
+ this.S.set(table.cornerToVertexArray());
1507
+ this.ma = 0;
1508
+ }
1509
+ // Cuts the edge opposite corner c (and its twin) and flags its two vertices.
1495
1510
  addSeamEdge(c) {
1496
- const cornerToVertex = this.t.cornerToVertexArray();
1497
- const oppositeCorners = this.t.oppositeCornerArray();
1498
- const isEdge = this.Y;
1499
- const isVert = this.ma;
1500
- const seamCorners = this._;
1501
- isEdge[c] = 1;
1502
- seamCorners[this.Q++] = c;
1511
+ const cornerToVertex = this.D.cornerToVertexArray();
1512
+ const opposite = this.E;
1513
+ const isVert = this.la;
1514
+ const oppCorner = opposite[c];
1515
+ opposite[c] = kInvalidCornerIndex;
1503
1516
  let rem = c - (c / 3 | 0) * 3;
1504
1517
  isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
1505
1518
  isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
1506
- const oppCorner = oppositeCorners[c];
1507
1519
  if (oppCorner !== kInvalidCornerIndex) {
1508
- isEdge[oppCorner] = 1;
1509
- seamCorners[this.Q++] = oppCorner;
1520
+ opposite[oppCorner] = kInvalidCornerIndex;
1510
1521
  rem = oppCorner - (oppCorner / 3 | 0) * 3;
1511
1522
  isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
1512
1523
  isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
1513
1524
  }
1514
1525
  }
1515
- // Installs attribute-vertex numbering computed externally (the edgebreaker
1516
- // decoder's fused ring pass fills corner_to_vertex_map_ directly and hands
1517
- // over the per-vertex left-most corners here). leftMostMap is decode-scoped
1518
- // scratch sized for at least numNewVertices entries.
1519
- setRecomputedVertices(leftMostMap, numNewVertices) {
1520
- this.oa = numNewVertices;
1521
- this.na = leftMostMap.length === numNewVertices ? leftMostMap : leftMostMap.subarray(0, numNewVertices);
1522
- }
1523
- isCornerOppositeToSeamEdge(corner) {
1524
- return this.Y[corner];
1526
+ // Installs the vertex numbering computed by the edgebreaker decoder's ring
1527
+ // pass, which fills corner_to_vertex_map_ directly and hands over the
1528
+ // per-vertex boundary flags here (decode-scoped scratch sized for at
1529
+ // least numVertices entries).
1530
+ setRecomputedVertices(onBoundary, numVertices) {
1531
+ this.ma = numVertices;
1532
+ this.y = onBoundary;
1533
+ }
1534
+ // A table without interior seams is the base connectivity itself: every
1535
+ // vertex ring is one attribute vertex, and the boundary edges are already
1536
+ // open in the base opposite table. Shares the base arrays (read-only from
1537
+ // here on), so its traversal also resolves to the base table's cached one.
1538
+ initAsBase(table) {
1539
+ this.D = table;
1540
+ this.E = table.oppositeCornerArray();
1541
+ this.S = table.cornerToVertexArray();
1542
+ this.setRecomputedVertices(table.vertexOnBoundaryArray(), table.numVertices());
1525
1543
  }
1526
1544
  opposite(corner) {
1527
- if (corner === kInvalidCornerIndex || this.isCornerOppositeToSeamEdge(corner)) {
1545
+ if (corner === kInvalidCornerIndex) {
1528
1546
  return kInvalidCornerIndex;
1529
1547
  }
1530
- return this.t.opposite(corner);
1548
+ return this.E[corner];
1531
1549
  }
1532
1550
  next(corner) {
1533
- return this.t.next(corner);
1551
+ return this.D.next(corner);
1534
1552
  }
1535
1553
  previous(corner) {
1536
- return this.t.previous(corner);
1554
+ return this.D.previous(corner);
1537
1555
  }
1538
1556
  swingRight(corner) {
1539
1557
  return this.previous(this.opposite(this.previous(corner)));
@@ -1542,68 +1560,48 @@ var MeshAttributeCornerTable = class {
1542
1560
  return this.next(this.opposite(this.next(corner)));
1543
1561
  }
1544
1562
  numVertices() {
1545
- return this.oa;
1563
+ return this.ma;
1546
1564
  }
1547
1565
  numFaces() {
1548
- return this.t.numFaces();
1566
+ return this.D.numFaces();
1549
1567
  }
1550
1568
  numCorners() {
1551
- return this.t.numCorners();
1569
+ return this.D.numCorners();
1552
1570
  }
1553
1571
  // --- Flat-array accessors: let DepthFirstTraverser avoid per-corner dispatch. ---
1554
1572
  cornerToVertexArray() {
1555
- return this.Z;
1573
+ return this.S;
1556
1574
  }
1557
- // Seam-aware opposite corners (seam edges -> -1), matching opposite(). Cached on
1558
- // first use; seams and connectivity are finalized before traversal, so it's stable.
1575
+ // Seam-aware opposite corners (seam edges -> -1), matching opposite().
1559
1576
  oppositeCornerArray() {
1560
- if (this.P === null) {
1561
- const nc = this.t.numCorners();
1562
- const base = this.t.oppositeCornerArray();
1563
- const seamCorners = this._;
1564
- const numSeamCorners = this.Q;
1565
- if (numSeamCorners === 0) {
1566
- this.P = base;
1567
- } else {
1568
- const eff = scratchInt32(nc);
1569
- eff.set(base.length === nc ? base : base.subarray(0, nc));
1570
- for (let i = 0; i < numSeamCorners; ++i) {
1571
- eff[seamCorners[i]] = kInvalidCornerIndex;
1572
- }
1573
- this.P = eff;
1574
- }
1575
- }
1576
- return this.P;
1577
+ return this.E;
1577
1578
  }
1578
- vertexLeftmostCornerArray() {
1579
- return this.na;
1579
+ vertexOnBoundaryArray() {
1580
+ return this.y;
1580
1581
  }
1581
1582
  // Takes over another table's state wholesale. Only valid when both tables
1582
1583
  // were built from the same corner table and the same seam edges, in which
1583
1584
  // case every one of these is identical and read-only from here on.
1584
1585
  adoptFrom(other) {
1585
- this.t = other.t;
1586
- this.Y = other.Y;
1586
+ this.D = other.D;
1587
+ this.la = other.la;
1588
+ this.S = other.S;
1587
1589
  this.ma = other.ma;
1588
- this.Z = other.Z;
1589
- this.oa = other.oa;
1590
- this.na = other.na;
1591
- this.P = other.P;
1592
- this._ = other._;
1593
- this.Q = other.Q;
1590
+ this.y = other.y;
1591
+ this.E = other.E;
1594
1592
  }
1595
1593
  };
1596
1594
 
1597
1595
  // src/decoder/compression/attributes/AttributesDecoder.ts
1598
1596
  var AttributesDecoder = class {
1599
- Ia = [];
1597
+ Ha = [];
1600
1598
  // Inverse of _pointAttributeIds: point attribute id -> local id.
1601
- pa = [];
1602
- vb = null;
1603
- O = null;
1599
+ na = [];
1600
+ tb = null;
1601
+ R = null;
1604
1602
  init(decoder, pointCloud) {
1605
- this.vb = decoder;
1606
- this.O = pointCloud;
1603
+ this.tb = decoder;
1604
+ this.R = pointCloud;
1607
1605
  return true;
1608
1606
  }
1609
1607
  decodeAttributesDecoderData(buffer) {
@@ -1611,8 +1609,8 @@ var AttributesDecoder = class {
1611
1609
  if (numAttributes === void 0 || numAttributes === 0 || numAttributes > 5 * buffer.remainingSize) {
1612
1610
  return false;
1613
1611
  }
1614
- this.Ia.length = numAttributes;
1615
- const pc = this.O;
1612
+ this.Ha.length = numAttributes;
1613
+ const pc = this.R;
1616
1614
  for (let i = 0; i < numAttributes; i++) {
1617
1615
  const attType = buffer.decodeUint8();
1618
1616
  if (attType === void 0) return false;
@@ -1638,56 +1636,56 @@ var AttributesDecoder = class {
1638
1636
  ga.uniqueId = uniqueId;
1639
1637
  const attId = pc.addAttribute(new PointAttribute(ga));
1640
1638
  pc.attribute(attId).uniqueId = uniqueId;
1641
- this.Ia[i] = attId;
1642
- while (this.pa.length <= attId) {
1643
- this.pa.push(-1);
1639
+ this.Ha[i] = attId;
1640
+ while (this.na.length <= attId) {
1641
+ this.na.push(-1);
1644
1642
  }
1645
- this.pa[attId] = i;
1643
+ this.na[attId] = i;
1646
1644
  }
1647
1645
  return true;
1648
1646
  }
1649
1647
  getAttributeId(i) {
1650
- return this.Ia[i];
1648
+ return this.Ha[i];
1651
1649
  }
1652
1650
  getNumAttributes() {
1653
- return this.Ia.length;
1651
+ return this.Ha.length;
1654
1652
  }
1655
1653
  getDecoder() {
1656
- return this.vb;
1654
+ return this.tb;
1657
1655
  }
1658
1656
  getLocalIdForPointAttribute(pointAttributeId) {
1659
- if (pointAttributeId >= this.pa.length) {
1657
+ if (pointAttributeId >= this.na.length) {
1660
1658
  return -1;
1661
1659
  }
1662
- return this.pa[pointAttributeId];
1660
+ return this.na[pointAttributeId];
1663
1661
  }
1664
1662
  };
1665
1663
 
1666
1664
  // src/decoder/compression/attributes/SequentialAttributeDecoder.ts
1667
1665
  var SequentialAttributeDecoder = class {
1668
1666
  l = null;
1669
- E = null;
1670
- wb = -1;
1667
+ F = null;
1668
+ ub = -1;
1671
1669
  // Decoded portable attribute (after lossless decoding).
1672
1670
  $ = null;
1673
1671
  init(decoder, attributeId) {
1674
1672
  this.l = decoder;
1675
- this.E = decoder.pointCloud().attribute(attributeId);
1676
- this.wb = attributeId;
1673
+ this.F = decoder.pointCloud().attribute(attributeId);
1674
+ this.ub = attributeId;
1677
1675
  return true;
1678
1676
  }
1679
1677
  // --- Two-phase decode ---
1680
1678
  // The controller calls Parse for every attribute first (headers, schemes,
1681
1679
  // prediction data -- all size-driven cursor movement), collects the pending
1682
- // rANS symbol streams, decodes them in pairs (see ransDecodeSymbolsPair),
1680
+ // rANS symbol streams, decodes them in lockstep (see ransDecodeStreams),
1683
1681
  // then calls Finish per attribute in order. Decoders without a deferrable
1684
1682
  // stream simply do the whole decode in Parse (decodeValues); the defaults
1685
1683
  // below are theirs.
1686
1684
  decodePortableAttributeParse(pointIds, buffer) {
1687
- if (this.E.numComponents <= 0) {
1685
+ if (this.F.numComponents <= 0) {
1688
1686
  return false;
1689
1687
  }
1690
- if (!this.xb(pointIds.length)) {
1688
+ if (!this.vb(pointIds.length)) {
1691
1689
  return false;
1692
1690
  }
1693
1691
  return this.decodeValues(pointIds, buffer);
@@ -1695,8 +1693,8 @@ var SequentialAttributeDecoder = class {
1695
1693
  // Sizes (and here allocates) the attribute's storage for numValues values;
1696
1694
  // the integer decoders override it to skip the allocation, their values
1697
1695
  // staying in the portable attribute (see PointAttribute.setLazyInteger).
1698
- xb(numValues) {
1699
- return this.E.reset(numValues);
1696
+ vb(numValues) {
1697
+ return this.F.reset(numValues);
1700
1698
  }
1701
1699
  pendingSymbolStream() {
1702
1700
  return null;
@@ -1713,10 +1711,10 @@ var SequentialAttributeDecoder = class {
1713
1711
  return true;
1714
1712
  }
1715
1713
  getPortableAttribute() {
1716
- if (!this.E.isMappingIdentity && this.$ && this.$.isMappingIdentity) {
1717
- const size = this.E.indicesMapSize;
1714
+ if (!this.F.isMappingIdentity && this.$ && this.$.isMappingIdentity) {
1715
+ const size = this.F.indicesMapSize;
1718
1716
  this.$.setExplicitMappingScratch(size);
1719
- const src = this.E.indicesMap;
1717
+ const src = this.F.indicesMap;
1720
1718
  const dst = this.$.indicesMap;
1721
1719
  if (src.length === size) {
1722
1720
  dst.set(src);
@@ -1727,10 +1725,10 @@ var SequentialAttributeDecoder = class {
1727
1725
  return this.$;
1728
1726
  }
1729
1727
  get attribute() {
1730
- return this.E;
1728
+ return this.F;
1731
1729
  }
1732
1730
  get attributeId() {
1733
- return this.wb;
1731
+ return this.ub;
1734
1732
  }
1735
1733
  get decoder() {
1736
1734
  return this.l;
@@ -1751,13 +1749,13 @@ var SequentialAttributeDecoder = class {
1751
1749
  // Decodes raw attribute values in their original format.
1752
1750
  decodeValues(pointIds, buffer) {
1753
1751
  const numValues = pointIds.length;
1754
- const entrySize = this.E.byteStride;
1752
+ const entrySize = this.F.byteStride;
1755
1753
  const totalSize = numValues * entrySize;
1756
1754
  const valueData = buffer.decodeBytesView(totalSize);
1757
1755
  if (valueData === void 0) {
1758
1756
  return false;
1759
1757
  }
1760
- this.E.buffer.write(0, valueData, totalSize);
1758
+ this.F.buffer.write(0, valueData, totalSize);
1761
1759
  return true;
1762
1760
  }
1763
1761
  };
@@ -1772,14 +1770,14 @@ function convertSymbolsToSignedInts(input, count, output) {
1772
1770
 
1773
1771
  // src/decoder/compression/entropy/RAnsSymbolDecoder.ts
1774
1772
  var RAnsSymbolDecoder = class {
1775
- yb = 0;
1776
- m;
1773
+ wb = 0;
1774
+ G;
1777
1775
  constructor(uniqueSymbolsBitLength) {
1778
1776
  const unclamped = Math.trunc(3 * uniqueSymbolsBitLength / 2);
1779
- this.m = new RAnsDecoder(unclamped < 12 ? 12 : unclamped > 20 ? 20 : unclamped);
1777
+ this.G = new RAnsDecoder(unclamped < 12 ? 12 : unclamped > 20 ? 20 : unclamped);
1780
1778
  }
1781
1779
  get numSymbols() {
1782
- return this.yb;
1780
+ return this.wb;
1783
1781
  }
1784
1782
  // Initialize the decoder and decode the probability table. expectedCount is
1785
1783
  // the number of symbols the caller will decode (lets short streams skip the
@@ -1787,7 +1785,7 @@ var RAnsSymbolDecoder = class {
1787
1785
  create(buffer, expectedCount = 2147483647) {
1788
1786
  const numSymbols = decodeVarint(buffer);
1789
1787
  if (numSymbols === void 0) return false;
1790
- this.yb = numSymbols;
1788
+ this.wb = numSymbols;
1791
1789
  if (Math.trunc(numSymbols / 64) > buffer.remainingSize) {
1792
1790
  return false;
1793
1791
  }
@@ -1820,7 +1818,7 @@ var RAnsSymbolDecoder = class {
1820
1818
  }
1821
1819
  }
1822
1820
  buffer.advance(pos - startPos);
1823
- return this.m.ransBuildLookUpTable(probabilityTable, numSymbols, expectedCount);
1821
+ return this.G.ransBuildLookUpTable(probabilityTable, numSymbols, expectedCount);
1824
1822
  }
1825
1823
  // Starts decoding, advancing buffer past the encoded data.
1826
1824
  startDecoding(buffer) {
@@ -1831,10 +1829,10 @@ var RAnsSymbolDecoder = class {
1831
1829
  }
1832
1830
  const base = buffer.decodedSize;
1833
1831
  buffer.advance(Number(bytesEncoded));
1834
- return ansReadInit(this.m, buffer.data, base + Number(bytesEncoded), base, this.m.lRansBase, 4);
1832
+ return ansReadInit(this.G, buffer.data, base + Number(bytesEncoded), base, this.G.lRansBase, 4);
1835
1833
  }
1836
1834
  endDecoding() {
1837
- this.m.readEnd();
1835
+ this.G.readEnd();
1838
1836
  }
1839
1837
  };
1840
1838
 
@@ -1862,12 +1860,12 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1862
1860
  if (numValues > 0 && tagDecoder.numSymbols === 0) {
1863
1861
  return false;
1864
1862
  }
1865
- const tagAns = tagDecoder.m;
1863
+ const tagAns = tagDecoder.G;
1866
1864
  srcBuffer.startBitDecoding(false);
1867
- const bd = srcBuffer.la;
1868
- const buf = bd.Ea;
1869
- const byteLength = bd.ka;
1870
- let bitOffset = bd.o;
1865
+ const bd = srcBuffer.ka;
1866
+ const buf = bd.Da;
1867
+ const byteLength = bd.ja;
1868
+ let bitOffset = bd.p;
1871
1869
  let valueId = 0;
1872
1870
  for (let i = 0; i < numValues; i += numComponents) {
1873
1871
  const bitLength = tagAns.ransRead();
@@ -1886,7 +1884,7 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1886
1884
  outValues[valueId++] = value & mask;
1887
1885
  }
1888
1886
  if (j === numComponents) continue;
1889
- bd.o = bitOffset;
1887
+ bd.p = bitOffset;
1890
1888
  for (; j < numComponents; ++j) {
1891
1889
  const val = bd.getBits(bitLength);
1892
1890
  if (val === void 0) {
@@ -1894,9 +1892,9 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1894
1892
  }
1895
1893
  outValues[valueId++] = val;
1896
1894
  }
1897
- bitOffset = bd.o;
1895
+ bitOffset = bd.p;
1898
1896
  } else {
1899
- bd.o = bitOffset;
1897
+ bd.p = bitOffset;
1900
1898
  for (let j = 0; j < numComponents; ++j) {
1901
1899
  const val = bd.getBits(bitLength);
1902
1900
  if (val === void 0) {
@@ -1904,10 +1902,10 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
1904
1902
  }
1905
1903
  outValues[valueId++] = val;
1906
1904
  }
1907
- bitOffset = bd.o;
1905
+ bitOffset = bd.p;
1908
1906
  }
1909
1907
  }
1910
- bd.o = bitOffset;
1908
+ bd.p = bitOffset;
1911
1909
  tagDecoder.endDecoding();
1912
1910
  srcBuffer.endBitDecoding();
1913
1911
  return true;
@@ -1934,15 +1932,15 @@ function decodeRawSymbols(numValues, srcBuffer, outValues) {
1934
1932
  if (decoder === null) {
1935
1933
  return false;
1936
1934
  }
1937
- decoder.m.decodeSymbols(outValues, numValues);
1935
+ decoder.G.decodeSymbols(outValues, numValues);
1938
1936
  decoder.endDecoding();
1939
1937
  return true;
1940
1938
  }
1941
1939
 
1942
1940
  // src/decoder/compression/bit_coders/RAnsBitDecoder.ts
1943
1941
  var RAnsBitDecoder = class {
1944
- Va = new AnsDecoder();
1945
- Wa = 0;
1942
+ oa = new AnsDecoder();
1943
+ pa = 0;
1946
1944
  // ANS_P8_PRECISION - probZero, precomputed
1947
1945
  // Returns false when the data is invalid.
1948
1946
  startDecoding(sourceBuffer) {
@@ -1950,21 +1948,21 @@ var RAnsBitDecoder = class {
1950
1948
  if (probZero === void 0) {
1951
1949
  return false;
1952
1950
  }
1953
- this.Wa = ANS_P8_PRECISION - probZero;
1951
+ this.pa = ANS_P8_PRECISION - probZero;
1954
1952
  const sizeInBytes = decodeVarint(sourceBuffer);
1955
1953
  if (sizeInBytes === void 0 || sizeInBytes > sourceBuffer.remainingSize) {
1956
1954
  return false;
1957
1955
  }
1958
1956
  const base = sourceBuffer.decodedSize;
1959
- if (!ansReadInit(this.Va, sourceBuffer.data, base + sizeInBytes, base, ANS_L_BASE, 3)) {
1957
+ if (!ansReadInit(this.oa, sourceBuffer.data, base + sizeInBytes, base, ANS_L_BASE, 3)) {
1960
1958
  return false;
1961
1959
  }
1962
1960
  sourceBuffer.advance(sizeInBytes);
1963
1961
  return true;
1964
1962
  }
1965
1963
  decodeNextBit() {
1966
- const ans = this.Va;
1967
- const p = this.Wa;
1964
+ const ans = this.oa;
1965
+ const p = this.pa;
1968
1966
  if (ans.state < ANS_L_BASE && ans.bufOffset > ans.bufStart) {
1969
1967
  ans.state = ans.state << 8 | ans.buf[--ans.bufOffset];
1970
1968
  }
@@ -1985,13 +1983,16 @@ var RAnsBitDecoder = class {
1985
1983
 
1986
1984
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeDecoder.ts
1987
1985
  var PredictionSchemeDecoder = class {
1988
- f;
1986
+ e;
1989
1987
  constructor(transform) {
1990
- this.f = transform;
1988
+ this.e = transform;
1991
1989
  }
1992
1990
  /** True if all correction values are guaranteed to be positive. */
1993
1991
  areCorrectionsPositive() {
1994
- return this.f.areCorrectionsPositive();
1992
+ return this.e.areCorrectionsPositive();
1993
+ }
1994
+ boundsValues(limit) {
1995
+ return this.e.boundsValues(limit);
1995
1996
  }
1996
1997
  getNumParentAttributes() {
1997
1998
  return 0;
@@ -2003,7 +2004,7 @@ var PredictionSchemeDecoder = class {
2003
2004
  return false;
2004
2005
  }
2005
2006
  decodePredictionData(buffer) {
2006
- return this.f.decodeTransformData(buffer);
2007
+ return this.e.decodeTransformData(buffer);
2007
2008
  }
2008
2009
  /**
2009
2010
  * Like computeOriginalValues, but inCorr still holds unsigned zigzag-coded
@@ -2060,18 +2061,18 @@ var MAX_NUM_PARALLELOGRAMS = 4;
2060
2061
  var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends MeshPredictionSchemeDecoder {
2061
2062
  // Crease edges stored per context (number of available parallelograms),
2062
2063
  // one list per context up to MAX_NUM_PARALLELOGRAMS.
2063
- Ja = [[], [], [], []];
2064
+ Ia = [[], [], [], []];
2064
2065
  decodePredictionData(buffer) {
2065
2066
  for (let i = 0; i < MAX_NUM_PARALLELOGRAMS; ++i) {
2066
2067
  const numFlags = decodeVarint(buffer);
2067
2068
  if (numFlags === void 0) return false;
2068
2069
  if (numFlags > this.b.cornerTable.numCorners()) return false;
2069
2070
  if (numFlags > 0) {
2070
- this.Ja[i] = new Array(numFlags);
2071
+ this.Ia[i] = new Array(numFlags);
2071
2072
  const decoder = new RAnsBitDecoder();
2072
2073
  if (!decoder.startDecoding(buffer)) return false;
2073
2074
  for (let j = 0; j < numFlags; ++j) {
2074
- this.Ja[i][j] = decoder.decodeNextBit();
2075
+ this.Ia[i][j] = decoder.decodeNextBit();
2075
2076
  }
2076
2077
  decoder.endDecoding();
2077
2078
  }
@@ -2079,12 +2080,12 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2079
2080
  return super.decodePredictionData(buffer);
2080
2081
  }
2081
2082
  computeOriginalValues(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2082
- this.f.init(numComponents);
2083
+ this.e.init(numComponents);
2083
2084
  const predVals = [];
2084
2085
  for (let i = 0; i < MAX_NUM_PARALLELOGRAMS; ++i) {
2085
2086
  predVals.push(new Int32Array(numComponents));
2086
2087
  }
2087
- this.f.computeOriginalValue(predVals[0], 0, inCorr, 0, outData, 0);
2088
+ this.e.computeOriginalValue(predVals[0], 0, inCorr, 0, outData, 0);
2088
2089
  const table = this.b.cornerTable;
2089
2090
  const vertexToDataMap = this.b.vertexToDataMap;
2090
2091
  const oppositeCorners = table.oppositeCornerArray();
@@ -2130,8 +2131,8 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2130
2131
  for (let i = 0; i < numParallelograms; ++i) {
2131
2132
  const context = numParallelograms - 1;
2132
2133
  const pos = isCreaseEdgePos[context]++;
2133
- if (this.Ja[context].length <= pos) return false;
2134
- const isCrease = this.Ja[context][pos];
2134
+ if (this.Ia[context].length <= pos) return false;
2135
+ const isCrease = this.Ia[context][pos];
2135
2136
  if (!isCrease) {
2136
2137
  ++numUsedParallelograms;
2137
2138
  for (let j = 0; j < numComponents; ++j) {
@@ -2143,12 +2144,12 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2143
2144
  const dstOffset = p * numComponents;
2144
2145
  if (numUsedParallelograms === 0) {
2145
2146
  const srcOffset = (p - 1) * numComponents;
2146
- this.f.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2147
+ this.e.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2147
2148
  } else {
2148
2149
  for (let c = 0; c < numComponents; ++c) {
2149
2150
  multiPredVals[c] = multiPredVals[c] / numUsedParallelograms | 0;
2150
2151
  }
2151
- this.f.computeOriginalValue(multiPredVals, 0, inCorr, dstOffset, outData, dstOffset);
2152
+ this.e.computeOriginalValue(multiPredVals, 0, inCorr, dstOffset, outData, dstOffset);
2152
2153
  }
2153
2154
  }
2154
2155
  return true;
@@ -2158,34 +2159,82 @@ var MeshPredictionSchemeConstrainedMultiParallelogramDecoder = class extends Mes
2158
2159
  // src/decoder/compression/attributes/prediction_schemes/MeshPredictionSchemeData.ts
2159
2160
  var MeshPredictionSchemeData = class {
2160
2161
  cornerTable;
2161
- vertexToDataMap;
2162
- dataToCornerMap;
2163
- constructor(cornerTable, dataToCornerMap, vertexToDataMap) {
2162
+ n;
2163
+ constructor(cornerTable, encodingData) {
2164
2164
  this.cornerTable = cornerTable;
2165
- this.vertexToDataMap = vertexToDataMap;
2166
- this.dataToCornerMap = dataToCornerMap;
2165
+ this.n = encodingData;
2166
+ }
2167
+ get vertexToDataMap() {
2168
+ return this.n.vertexToEncodedAttributeValueIndexMap;
2169
+ }
2170
+ get dataToCornerMap() {
2171
+ return this.n.encodedAttributeValueIndexToCornerMap;
2172
+ }
2173
+ // The parallelogram parents of every value: for value p, the data ids of
2174
+ // the opposite corner's vertex and of that face's next and prev vertices
2175
+ // (parents[3p .. 3p+2]), or -1 in parents[3p] when the value is not
2176
+ // parallelogram-predictable (no opposite face, or a parent decoded after
2177
+ // it). The scheme's per-value walk -- corner, opposite corner, three
2178
+ // vertices, three data ids: four dependent random reads -- is thus done
2179
+ // once per traversal and shared by every attribute predicted over it (a
2180
+ // position, a texture coordinate and a colour on one connectivity all use
2181
+ // it), and the prediction loops read it sequentially. Decode-scoped
2182
+ // scratch, cached on the traversal entry.
2183
+ parallelogramParents() {
2184
+ const entry = this.n.cacheEntry;
2185
+ if (entry !== null && entry.parents !== null) {
2186
+ return entry.parents;
2187
+ }
2188
+ const table = this.cornerTable;
2189
+ const oppositeCorners = table.oppositeCornerArray();
2190
+ const cornerToVertex = table.cornerToVertexArray();
2191
+ const vertexToDataMap = this.vertexToDataMap;
2192
+ const dataToCornerMap = this.dataToCornerMap;
2193
+ const numValues = dataToCornerMap.length;
2194
+ const parents = scratchInt32(numValues * 3);
2195
+ if (numValues > 0) parents[0] = -1;
2196
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2197
+ const oci = oppositeCorners[dataToCornerMap[p]];
2198
+ if (oci < 0) {
2199
+ parents[o] = -1;
2200
+ continue;
2201
+ }
2202
+ const rem = oci - (oci / 3 | 0) * 3;
2203
+ const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2204
+ const vertNext = vertexToDataMap[cornerToVertex[rem === 2 ? oci - 2 : oci + 1]];
2205
+ const vertPrev = vertexToDataMap[cornerToVertex[rem === 0 ? oci + 2 : oci - 1]];
2206
+ if (vertOpp < p && vertNext < p && vertPrev < p) {
2207
+ parents[o] = vertOpp;
2208
+ parents[o + 1] = vertNext;
2209
+ parents[o + 2] = vertPrev;
2210
+ } else {
2211
+ parents[o] = -1;
2212
+ }
2213
+ }
2214
+ if (entry !== null) entry.parents = parents;
2215
+ return parents;
2167
2216
  }
2168
2217
  };
2169
2218
 
2170
2219
  // src/decoder/compression/attributes/NormalCompressionUtils.ts
2171
2220
  var OctahedronToolBox = class {
2172
- J = -1;
2173
- qa = -1;
2221
+ L = -1;
2222
+ aa = -1;
2174
2223
  k = -1;
2175
- Xb = 1;
2176
- e = -1;
2224
+ Vb = 1;
2225
+ f = -1;
2177
2226
  // q: quantization bits, valid range 2..30.
2178
2227
  setQuantizationBits(q) {
2179
2228
  if (q < 2 || q > 30) return false;
2180
- this.J = q;
2181
- this.qa = (1 << q) - 1;
2182
- this.k = this.qa - 1;
2183
- this.Xb = Math.fround(2 / Math.fround(this.k));
2184
- this.e = this.k / 2 | 0;
2229
+ this.L = q;
2230
+ this.aa = (1 << q) - 1;
2231
+ this.k = this.aa - 1;
2232
+ this.Vb = Math.fround(2 / Math.fround(this.k));
2233
+ this.f = this.k / 2 | 0;
2185
2234
  return true;
2186
2235
  }
2187
2236
  quantizationBits() {
2188
- return this.J;
2237
+ return this.L;
2189
2238
  }
2190
2239
  // Canonicalizes edge points into consistent quadrants. Writes result into
2191
2240
  // out[0], out[1] (caller-owned reusable 2-element array).
@@ -2193,14 +2242,14 @@ var OctahedronToolBox = class {
2193
2242
  if (s === 0 && t === 0 || s === 0 && t === this.k || s === this.k && t === 0) {
2194
2243
  s = this.k;
2195
2244
  t = this.k;
2196
- } else if (s === 0 && t > this.e) {
2197
- t = this.e - (t - this.e);
2198
- } else if (s === this.k && t < this.e) {
2199
- t = this.e + (this.e - t);
2200
- } else if (t === this.k && s < this.e) {
2201
- s = this.e + (this.e - s);
2202
- } else if (t === 0 && s > this.e) {
2203
- s = this.e - (s - this.e);
2245
+ } else if (s === 0 && t > this.f) {
2246
+ t = this.f - (t - this.f);
2247
+ } else if (s === this.k && t < this.f) {
2248
+ t = this.f + (this.f - t);
2249
+ } else if (t === this.k && s < this.f) {
2250
+ s = this.f + (this.f - s);
2251
+ } else if (t === 0 && s > this.f) {
2252
+ s = this.f - (s - this.f);
2204
2253
  }
2205
2254
  out[0] = s;
2206
2255
  out[1] = t;
@@ -2210,8 +2259,8 @@ var OctahedronToolBox = class {
2210
2259
  integerVectorToQuantizedOctahedralCoords(intVec, out) {
2211
2260
  let s, t;
2212
2261
  if (intVec[0] >= 0) {
2213
- s = intVec[1] + this.e;
2214
- t = intVec[2] + this.e;
2262
+ s = intVec[1] + this.f;
2263
+ t = intVec[2] + this.f;
2215
2264
  } else {
2216
2265
  if (intVec[1] < 0) {
2217
2266
  s = Math.abs(intVec[2]);
@@ -2230,14 +2279,14 @@ var OctahedronToolBox = class {
2230
2279
  canonicalizeIntegerVector(vec) {
2231
2280
  const absSum = Math.abs(vec[0]) + Math.abs(vec[1]) + Math.abs(vec[2]);
2232
2281
  if (absSum === 0) {
2233
- vec[0] = this.e;
2282
+ vec[0] = this.f;
2234
2283
  } else {
2235
- vec[0] = Math.trunc(vec[0] * this.e / absSum);
2236
- vec[1] = Math.trunc(vec[1] * this.e / absSum);
2284
+ vec[0] = Math.trunc(vec[0] * this.f / absSum);
2285
+ vec[1] = Math.trunc(vec[1] * this.f / absSum);
2237
2286
  if (vec[2] >= 0) {
2238
- vec[2] = this.e - Math.abs(vec[0]) - Math.abs(vec[1]);
2287
+ vec[2] = this.f - Math.abs(vec[0]) - Math.abs(vec[1]);
2239
2288
  } else {
2240
- vec[2] = -(this.e - Math.abs(vec[0]) - Math.abs(vec[1]));
2289
+ vec[2] = -(this.f - Math.abs(vec[0]) - Math.abs(vec[1]));
2241
2290
  }
2242
2291
  }
2243
2292
  }
@@ -2283,31 +2332,31 @@ function fillInt32PositionCache(cache, att, map, numEntries, tempPos) {
2283
2332
  }
2284
2333
  }
2285
2334
  var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2335
+ qa = null;
2286
2336
  ra = null;
2287
- sa = null;
2288
2337
  b;
2289
- Xa = new Array(3);
2290
- ta = null;
2338
+ Va = new Array(3);
2339
+ sa = null;
2291
2340
  // flat Int32 positions, indexed by data id
2292
- p = null;
2293
- zb = null;
2341
+ o = null;
2342
+ xb = null;
2294
2343
  // corner -> posCache offset, precomputed
2295
2344
  constructor(meshData) {
2296
2345
  this.b = meshData;
2297
2346
  }
2298
2347
  setPositionAttribute(positionAttribute) {
2299
- this.ra = positionAttribute;
2348
+ this.qa = positionAttribute;
2300
2349
  }
2301
2350
  setEntryToPointIdMap(map) {
2302
- this.sa = map;
2351
+ this.ra = map;
2303
2352
  }
2304
2353
  buildPositionCache(numEntries) {
2305
2354
  const posCache = scratchInt32(numEntries * 3);
2306
- fillInt32PositionCache(posCache, this.ra, this.sa, numEntries, this.Xa);
2307
- this.ta = posCache;
2355
+ fillInt32PositionCache(posCache, this.qa, this.ra, numEntries, this.Va);
2356
+ this.sa = posCache;
2308
2357
  const table = this.b.cornerTable;
2309
2358
  const cornerToVertex = table.cornerToVertexArray();
2310
- this.p = table.oppositeCornerArray();
2359
+ this.o = table.oppositeCornerArray();
2311
2360
  const vertexToDataMap = this.b.vertexToDataMap;
2312
2361
  const nc = cornerToVertex.length;
2313
2362
  const c2o = scratchInt32(nc);
@@ -2315,12 +2364,12 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2315
2364
  const v = cornerToVertex[c];
2316
2365
  c2o[c] = v < 0 ? -1 : vertexToDataMap[v] * 3;
2317
2366
  }
2318
- this.zb = c2o;
2367
+ this.xb = c2o;
2319
2368
  }
2320
2369
  computePredictedValue(cornerId, prediction) {
2321
- const oppositeCorners = this.p;
2322
- const cornerToOffset = this.zb;
2323
- const posCache = this.ta;
2370
+ const oppositeCorners = this.o;
2371
+ const cornerToOffset = this.xb;
2372
+ const posCache = this.sa;
2324
2373
  const centerOffset = cornerToOffset[cornerId];
2325
2374
  const centX = posCache[centerOffset];
2326
2375
  const centY = posCache[centerOffset + 1];
@@ -2398,8 +2447,8 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
2398
2447
  var GEOMETRY_ATTRIBUTE_POSITION = 0;
2399
2448
  var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSchemeDecoder {
2400
2449
  q;
2401
- y = new OctahedronToolBox();
2402
- Ya = new RAnsBitDecoder();
2450
+ w = new OctahedronToolBox();
2451
+ Wa = new RAnsBitDecoder();
2403
2452
  constructor(transform, meshData) {
2404
2453
  super(transform, meshData);
2405
2454
  this.q = new MeshPredictionSchemeGeometricNormalPredictorArea(meshData);
@@ -2417,11 +2466,11 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2417
2466
  return true;
2418
2467
  }
2419
2468
  decodePredictionData(buffer) {
2420
- if (!this.f.decodeTransformData(buffer)) return false;
2421
- return this.Ya.startDecoding(buffer);
2469
+ if (!this.e.decodeTransformData(buffer)) return false;
2470
+ return this.Wa.startDecoding(buffer);
2422
2471
  }
2423
2472
  computeOriginalValues(inCorr, outData, _size, _numComponents, entryToPointIdMap) {
2424
- this.y.setQuantizationBits(this.f.quantizationBits());
2473
+ this.w.setQuantizationBits(this.e.quantizationBits());
2425
2474
  this.q.setEntryToPointIdMap(entryToPointIdMap);
2426
2475
  const cornerMapSize = this.b.dataToCornerMap.length;
2427
2476
  this.q.buildPositionCache(cornerMapSize);
@@ -2430,17 +2479,17 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2430
2479
  for (let dataId = 0; dataId < cornerMapSize; ++dataId) {
2431
2480
  const cornerId = this.b.dataToCornerMap[dataId];
2432
2481
  this.q.computePredictedValue(cornerId, predNormal3D);
2433
- this.y.canonicalizeIntegerVector(predNormal3D);
2434
- if (this.Ya.decodeNextBit()) {
2482
+ this.w.canonicalizeIntegerVector(predNormal3D);
2483
+ if (this.Wa.decodeNextBit()) {
2435
2484
  predNormal3D[0] = -predNormal3D[0];
2436
2485
  predNormal3D[1] = -predNormal3D[1];
2437
2486
  predNormal3D[2] = -predNormal3D[2];
2438
2487
  }
2439
- this.y.integerVectorToQuantizedOctahedralCoords(predNormal3D, predNormalOct);
2488
+ this.w.integerVectorToQuantizedOctahedralCoords(predNormal3D, predNormalOct);
2440
2489
  const dataOffset = dataId * 2;
2441
- this.f.computeOriginalValue(predNormalOct, 0, inCorr, dataOffset, outData, dataOffset);
2490
+ this.e.computeOriginalValue(predNormalOct, 0, inCorr, dataOffset, outData, dataOffset);
2442
2491
  }
2443
- this.Ya.endDecoding();
2492
+ this.Wa.endDecoding();
2444
2493
  return true;
2445
2494
  }
2446
2495
  };
@@ -2449,10 +2498,10 @@ var MeshPredictionSchemeGeometricNormalDecoder = class extends MeshPredictionSch
2449
2498
  var kInvalidCornerIndex3 = -1;
2450
2499
  var MeshPredictionSchemeMultiParallelogramDecoder = class extends MeshPredictionSchemeDecoder {
2451
2500
  computeOriginalValues(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2452
- this.f.init(numComponents);
2501
+ this.e.init(numComponents);
2453
2502
  const predVals = new Int32Array(numComponents);
2454
2503
  const parallelogramPredVals = new Int32Array(numComponents);
2455
- this.f.computeOriginalValue(predVals, 0, inCorr, 0, outData, 0);
2504
+ this.e.computeOriginalValue(predVals, 0, inCorr, 0, outData, 0);
2456
2505
  const table = this.b.cornerTable;
2457
2506
  const vertexToDataMap = this.b.vertexToDataMap;
2458
2507
  const oppositeCorners = table.oppositeCornerArray();
@@ -2489,12 +2538,12 @@ var MeshPredictionSchemeMultiParallelogramDecoder = class extends MeshPrediction
2489
2538
  const dstOffset = p * numComponents;
2490
2539
  if (numParallelograms === 0) {
2491
2540
  const srcOffset = (p - 1) * numComponents;
2492
- this.f.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2541
+ this.e.computeOriginalValue(outData, srcOffset, inCorr, dstOffset, outData, dstOffset);
2493
2542
  } else {
2494
2543
  for (let c = 0; c < numComponents; ++c) {
2495
2544
  predVals[c] = predVals[c] / numParallelograms | 0;
2496
2545
  }
2497
- this.f.computeOriginalValue(predVals, 0, inCorr, dstOffset, outData, dstOffset);
2546
+ this.e.computeOriginalValue(predVals, 0, inCorr, dstOffset, outData, dstOffset);
2498
2547
  }
2499
2548
  }
2500
2549
  return true;
@@ -2506,8 +2555,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2506
2555
  // Zigzag-fused variant: decodes corrections that are still in their unsigned
2507
2556
  // zigzag form, unpacking each one inline.
2508
2557
  computeOriginalValuesZigzag(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
2509
- this.f.init(numComponents);
2510
- return this.Yb(inCorr, outData, numComponents, true);
2558
+ this.e.init(numComponents);
2559
+ return this.Wb(inCorr, outData, numComponents, true);
2511
2560
  }
2512
2561
  // The wrap transform's corrections are zigzag-coded; with `zigzag` set the
2513
2562
  // decode folds the (val >>> 1) ^ -(val & 1) unpacking into each correction
@@ -2515,23 +2564,19 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2515
2564
  // whole array (see computeOriginalValuesZigzag). Every correction is read
2516
2565
  // exactly once before its slot is overwritten, so the in-place aliasing of
2517
2566
  // inCorr and outData is preserved.
2518
- Yb(inCorr, outData, numComponents, zigzag) {
2567
+ Wb(inCorr, outData, numComponents, zigzag) {
2519
2568
  if (numComponents === 2) {
2520
- return this.Zb(inCorr, outData, zigzag);
2569
+ return this.Xb(inCorr, outData, zigzag);
2521
2570
  }
2522
2571
  if (numComponents === 3) {
2523
- return this._b(inCorr, outData, zigzag);
2572
+ return this.Yb(inCorr, outData, zigzag);
2524
2573
  }
2525
2574
  if (numComponents === 4) {
2526
- return this.$b(inCorr, outData, zigzag);
2575
+ return this.Zb(inCorr, outData, zigzag);
2527
2576
  }
2528
- const table = this.b.cornerTable;
2529
- const vertexToDataMap = this.b.vertexToDataMap;
2530
- const oppositeCorners = table.oppositeCornerArray();
2531
- const cornerToVertex = table.cornerToVertexArray();
2532
- const dataToCornerMap = this.b.dataToCornerMap;
2533
- const transform = this.f;
2534
- const minValue = transform.aa;
2577
+ const parents = this.b.parallelogramParents();
2578
+ const transform = this.e;
2579
+ const minValue = transform.T;
2535
2580
  const maxValue = transform.k;
2536
2581
  const maxDif = transform.ba;
2537
2582
  for (let c = 0; c < numComponents; ++c) {
@@ -2550,30 +2595,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2550
2595
  }
2551
2596
  outData[c] = orig;
2552
2597
  }
2553
- const cornerMapSize = dataToCornerMap.length;
2554
- for (let p = 1; p < cornerMapSize; ++p) {
2555
- const cornerId = dataToCornerMap[p];
2598
+ const numValues = this.b.dataToCornerMap.length;
2599
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2556
2600
  const dstOffset = p * numComponents;
2557
- const oci = oppositeCorners[cornerId];
2558
- let hasPrediction = false;
2559
- let vOppOff = 0;
2560
- let vNextOff = 0;
2561
- let vPrevOff = 0;
2562
- if (oci >= 0) {
2563
- const rem = oci - (oci / 3 | 0) * 3;
2564
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2565
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2566
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2567
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2568
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2569
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2570
- vOppOff = vertOpp * numComponents;
2571
- vNextOff = vertNext * numComponents;
2572
- vPrevOff = vertPrev * numComponents;
2573
- hasPrediction = true;
2574
- }
2575
- }
2576
- if (hasPrediction) {
2601
+ const vertOpp = parents[o];
2602
+ if (vertOpp >= 0) {
2603
+ const vOppOff = vertOpp * numComponents;
2604
+ const vNextOff = parents[o + 1] * numComponents;
2605
+ const vPrevOff = parents[o + 2] * numComponents;
2577
2606
  for (let c = 0; c < numComponents; ++c) {
2578
2607
  let pred = outData[vNextOff + c] + outData[vPrevOff + c] - outData[vOppOff + c] | 0;
2579
2608
  if (pred > maxValue) {
@@ -2591,7 +2620,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2591
2620
  outData[dstOffset + c] = orig;
2592
2621
  }
2593
2622
  } else {
2594
- const srcOffset = (p - 1) * numComponents;
2623
+ const srcOffset = dstOffset - numComponents;
2595
2624
  for (let c = 0; c < numComponents; ++c) {
2596
2625
  let pred = outData[srcOffset + c];
2597
2626
  if (pred > maxValue) {
@@ -2612,14 +2641,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2612
2641
  }
2613
2642
  return true;
2614
2643
  }
2615
- Zb(inCorr, outData, zigzag) {
2616
- const table = this.b.cornerTable;
2617
- const vertexToDataMap = this.b.vertexToDataMap;
2618
- const oppositeCorners = table.oppositeCornerArray();
2619
- const cornerToVertex = table.cornerToVertexArray();
2620
- const dataToCornerMap = this.b.dataToCornerMap;
2621
- const transform = this.f;
2622
- const minValue = transform.aa;
2644
+ Xb(inCorr, outData, zigzag) {
2645
+ const parents = this.b.parallelogramParents();
2646
+ const transform = this.e;
2647
+ const minValue = transform.T;
2623
2648
  const maxValue = transform.k;
2624
2649
  const maxDif = transform.ba;
2625
2650
  let pred0 = 0;
@@ -2650,30 +2675,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2650
2675
  }
2651
2676
  outData[0] = orig0;
2652
2677
  outData[1] = orig1;
2653
- const cornerMapSize = dataToCornerMap.length;
2654
- for (let p = 1; p < cornerMapSize; ++p) {
2655
- const cornerId = dataToCornerMap[p];
2678
+ const numValues = this.b.dataToCornerMap.length;
2679
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2656
2680
  const dstOffset = p * 2;
2657
- const oci = oppositeCorners[cornerId];
2658
- let hasPrediction = false;
2659
- let vOppOff = 0;
2660
- let vNextOff = 0;
2661
- let vPrevOff = 0;
2662
- if (oci >= 0) {
2663
- const rem = oci - (oci / 3 | 0) * 3;
2664
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2665
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2666
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2667
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2668
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2669
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2670
- vOppOff = vertOpp * 2;
2671
- vNextOff = vertNext * 2;
2672
- vPrevOff = vertPrev * 2;
2673
- hasPrediction = true;
2674
- }
2675
- }
2676
- if (hasPrediction) {
2681
+ const vertOpp = parents[o];
2682
+ if (vertOpp >= 0) {
2683
+ const vOppOff = vertOpp * 2;
2684
+ const vNextOff = parents[o + 1] * 2;
2685
+ const vPrevOff = parents[o + 2] * 2;
2677
2686
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2678
2687
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2679
2688
  } else {
@@ -2710,14 +2719,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2710
2719
  }
2711
2720
  return true;
2712
2721
  }
2713
- _b(inCorr, outData, zigzag) {
2714
- const table = this.b.cornerTable;
2715
- const vertexToDataMap = this.b.vertexToDataMap;
2716
- const oppositeCorners = table.oppositeCornerArray();
2717
- const cornerToVertex = table.cornerToVertexArray();
2718
- const dataToCornerMap = this.b.dataToCornerMap;
2719
- const transform = this.f;
2720
- const minValue = transform.aa;
2722
+ Yb(inCorr, outData, zigzag) {
2723
+ const parents = this.b.parallelogramParents();
2724
+ const transform = this.e;
2725
+ const minValue = transform.T;
2721
2726
  const maxValue = transform.k;
2722
2727
  const maxDif = transform.ba;
2723
2728
  let pred0 = 0;
@@ -2762,30 +2767,14 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2762
2767
  outData[0] = orig0;
2763
2768
  outData[1] = orig1;
2764
2769
  outData[2] = orig2;
2765
- const cornerMapSize = dataToCornerMap.length;
2766
- for (let p = 1; p < cornerMapSize; ++p) {
2767
- const cornerId = dataToCornerMap[p];
2770
+ const numValues = this.b.dataToCornerMap.length;
2771
+ for (let p = 1, o = 3; p < numValues; ++p, o += 3) {
2768
2772
  const dstOffset = p * 3;
2769
- const oci = oppositeCorners[cornerId];
2770
- let hasPrediction = false;
2771
- let vOppOff = 0;
2772
- let vNextOff = 0;
2773
- let vPrevOff = 0;
2774
- if (oci >= 0) {
2775
- const rem = oci - (oci / 3 | 0) * 3;
2776
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2777
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2778
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2779
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2780
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2781
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2782
- vOppOff = vertOpp * 3;
2783
- vNextOff = vertNext * 3;
2784
- vPrevOff = vertPrev * 3;
2785
- hasPrediction = true;
2786
- }
2787
- }
2788
- if (hasPrediction) {
2773
+ const vertOpp = parents[o];
2774
+ if (vertOpp >= 0) {
2775
+ const vOppOff = vertOpp * 3;
2776
+ const vNextOff = parents[o + 1] * 3;
2777
+ const vPrevOff = parents[o + 2] * 3;
2789
2778
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2790
2779
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2791
2780
  pred2 = outData[vNextOff + 2] + outData[vPrevOff + 2] - outData[vOppOff + 2] | 0;
@@ -2839,14 +2828,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2839
2828
  }
2840
2829
  // Four components: tangents, RGBA colors, skin joints/weights. Same
2841
2830
  // structure as the 2/3-component loops.
2842
- $b(inCorr, outData, zigzag) {
2843
- const table = this.b.cornerTable;
2844
- const vertexToDataMap = this.b.vertexToDataMap;
2845
- const oppositeCorners = table.oppositeCornerArray();
2846
- const cornerToVertex = table.cornerToVertexArray();
2847
- const dataToCornerMap = this.b.dataToCornerMap;
2848
- const transform = this.f;
2849
- const minValue = transform.aa;
2831
+ Zb(inCorr, outData, zigzag) {
2832
+ const parents = this.b.parallelogramParents();
2833
+ const transform = this.e;
2834
+ const minValue = transform.T;
2850
2835
  const maxValue = transform.k;
2851
2836
  const maxDif = transform.ba;
2852
2837
  let pred0 = 0;
@@ -2858,31 +2843,15 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
2858
2843
  let pred1 = pred0;
2859
2844
  let pred2 = pred0;
2860
2845
  let pred3 = pred0;
2861
- const cornerMapSize = dataToCornerMap.length;
2862
- for (let p = 0; p < cornerMapSize; ++p) {
2846
+ const numValues = this.b.dataToCornerMap.length;
2847
+ for (let p = 0, o = 0; p < numValues; ++p, o += 3) {
2863
2848
  const dstOffset = p * 4;
2864
2849
  if (p > 0) {
2865
- const cornerId = dataToCornerMap[p];
2866
- const oci = oppositeCorners[cornerId];
2867
- let hasPrediction = false;
2868
- let vOppOff = 0;
2869
- let vNextOff = 0;
2870
- let vPrevOff = 0;
2871
- if (oci >= 0) {
2872
- const rem = oci - (oci / 3 | 0) * 3;
2873
- const nextOci = rem === 2 ? oci - 2 : oci + 1;
2874
- const prevOci = rem === 0 ? oci + 2 : oci - 1;
2875
- const vertOpp = vertexToDataMap[cornerToVertex[oci]];
2876
- const vertNext = vertexToDataMap[cornerToVertex[nextOci]];
2877
- const vertPrev = vertexToDataMap[cornerToVertex[prevOci]];
2878
- if (vertOpp < p && vertNext < p && vertPrev < p) {
2879
- vOppOff = vertOpp * 4;
2880
- vNextOff = vertNext * 4;
2881
- vPrevOff = vertPrev * 4;
2882
- hasPrediction = true;
2883
- }
2884
- }
2885
- if (hasPrediction) {
2850
+ const vertOpp = parents[o];
2851
+ if (vertOpp >= 0) {
2852
+ const vOppOff = vertOpp * 4;
2853
+ const vNextOff = parents[o + 1] * 4;
2854
+ const vPrevOff = parents[o + 2] * 4;
2886
2855
  pred0 = outData[vNextOff] + outData[vPrevOff] - outData[vOppOff] | 0;
2887
2856
  pred1 = outData[vNextOff + 1] + outData[vPrevOff + 1] - outData[vOppOff + 1] | 0;
2888
2857
  pred2 = outData[vNextOff + 2] + outData[vPrevOff + 2] - outData[vOppOff + 2] | 0;
@@ -2967,39 +2936,39 @@ function bigIntSqrt(value) {
2967
2936
  return x;
2968
2937
  }
2969
2938
  var MeshPredictionSchemeTexCoordsPortablePredictor = class {
2939
+ qa = null;
2970
2940
  ra = null;
2971
- sa = null;
2972
2941
  r = new Int32Array(2);
2973
- Ka = new Uint8Array(0);
2974
- ua = 0;
2942
+ Ja = new Uint8Array(0);
2943
+ ta = 0;
2975
2944
  b;
2976
- Xa = new Array(3);
2945
+ Va = new Array(3);
2977
2946
  // Flat Int32 position cache so fetches are array reads, not convertValue calls.
2978
- ta = null;
2947
+ sa = null;
2979
2948
  h = null;
2980
2949
  constructor(meshData) {
2981
2950
  this.b = meshData;
2982
2951
  }
2983
2952
  setPositionAttribute(positionAttribute) {
2984
- this.ra = positionAttribute;
2953
+ this.qa = positionAttribute;
2985
2954
  }
2986
2955
  setEntryToPointIdMap(map) {
2987
- this.sa = map;
2956
+ this.ra = map;
2988
2957
  }
2989
2958
  get predictedValue() {
2990
2959
  return this.r;
2991
2960
  }
2992
2961
  resizeOrientations(numOrientations) {
2993
- this.Ka = new Uint8Array(numOrientations);
2994
- this.ua = numOrientations;
2962
+ this.Ja = new Uint8Array(numOrientations);
2963
+ this.ta = numOrientations;
2995
2964
  }
2996
2965
  setOrientation(i, v) {
2997
- this.Ka[i] = v ? 1 : 0;
2966
+ this.Ja[i] = v ? 1 : 0;
2998
2967
  }
2999
2968
  buildPositionCache(numEntries) {
3000
2969
  const posCache = new Int32Array(numEntries * 3);
3001
- fillInt32PositionCache(posCache, this.ra, this.sa, numEntries, this.Xa);
3002
- this.ta = posCache;
2970
+ fillInt32PositionCache(posCache, this.qa, this.ra, numEntries, this.Va);
2971
+ this.sa = posCache;
3003
2972
  this.h = this.b.cornerTable.cornerToVertexArray();
3004
2973
  }
3005
2974
  computePredictedValue(cornerId, data, dataId) {
@@ -3022,7 +2991,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3022
2991
  this.r[1] = pUV1;
3023
2992
  return true;
3024
2993
  }
3025
- const posCache = this.ta;
2994
+ const posCache = this.sa;
3026
2995
  let posOffset = dataId * 3;
3027
2996
  const tip0 = posCache[posOffset];
3028
2997
  const tip1 = posCache[posOffset + 1];
@@ -3059,7 +3028,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3059
3028
  const pnAbsMaxG = Math.max(Math.abs(pn0), Math.abs(pn1), Math.abs(pn2));
3060
3029
  const cnDotPnAbs = Math.abs(cnDotPn);
3061
3030
  if (cnNorm2 > SAFE_PRODUCT / pnNorm2Squared || nUVAbsMax > SAFE_PRODUCT / pnNorm2Squared || pnUVAbsMax > 0 && cnDotPnAbs > SAFE_PRODUCT / pnUVAbsMax || pnAbsMaxG > 0 && cnDotPnAbs > SAFE_PRODUCT / pnAbsMaxG) {
3062
- return this.ac(
3031
+ return this._b(
3063
3032
  tip0,
3064
3033
  tip1,
3065
3034
  tip2,
@@ -3091,10 +3060,10 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3091
3060
  const normSquared = Math.floor(Math.sqrt(cxNorm2Squared * pnNorm2Squared));
3092
3061
  const cxUV0 = pnUV1 * normSquared;
3093
3062
  const cxUV1 = -pnUV0 * normSquared;
3094
- if (this.ua === 0) {
3063
+ if (this.ta === 0) {
3095
3064
  return false;
3096
3065
  }
3097
- const orientation = this.Ka[--this.ua];
3066
+ const orientation = this.Ja[--this.ta];
3098
3067
  if (orientation) {
3099
3068
  this.r[0] = Math.trunc((xUV0 + cxUV0) / pnNorm2Squared);
3100
3069
  this.r[1] = Math.trunc((xUV1 + cxUV1) / pnNorm2Squared);
@@ -3129,7 +3098,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3129
3098
  // <uint64_t>, including the uint64 wraparound in IntSqrt(cxNorm2*pnNorm2) and
3130
3099
  // the unsigned add/sub forming the final UV. Returns false in the same
3131
3100
  // overflow cases as the double path so encoder and decoder agree on fallback.
3132
- ac(tip0, tip1, tip2, next0, next1, next2, pn0, pn1, pn2, nUV0, nUV1, pUV0, pUV1, pnNorm2SquaredNum) {
3101
+ _b(tip0, tip1, tip2, next0, next1, next2, pn0, pn1, pn2, nUV0, nUV1, pUV0, pUV1, pnNorm2SquaredNum) {
3133
3102
  const B = BigInt;
3134
3103
  const tip = [B(tip0), B(tip1), B(tip2)];
3135
3104
  const nxt = [B(next0), B(next1), B(next2)];
@@ -3163,8 +3132,8 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3163
3132
  const normSquared = bigIntSqrt(cxNorm2 * pnN2 & MASK64);
3164
3133
  const cxUV0 = B.asIntN(64, pnUV1 * normSquared);
3165
3134
  const cxUV1 = B.asIntN(64, -pnUV0 * normSquared);
3166
- if (this.ua === 0) return false;
3167
- const orientation = this.Ka[--this.ua];
3135
+ if (this.ta === 0) return false;
3136
+ const orientation = this.Ja[--this.ta];
3168
3137
  let s0, s1;
3169
3138
  if (orientation) {
3170
3139
  s0 = B.asUintN(64, B.asUintN(64, xUV0) + B.asUintN(64, cxUV0));
@@ -3220,7 +3189,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3220
3189
  return false;
3221
3190
  }
3222
3191
  this.q.setEntryToPointIdMap(entryToPointIdMap);
3223
- this.f.init(numComponents);
3192
+ this.e.init(numComponents);
3224
3193
  const cornerMapSize = this.b.dataToCornerMap.length;
3225
3194
  this.q.buildPositionCache(cornerMapSize);
3226
3195
  for (let p = 0; p < cornerMapSize; ++p) {
@@ -3229,7 +3198,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3229
3198
  return false;
3230
3199
  }
3231
3200
  const dstOffset = p * numComponents;
3232
- this.f.computeOriginalValue(this.q.predictedValue, 0, inCorr, dstOffset, outData, dstOffset);
3201
+ this.e.computeOriginalValue(this.q.predictedValue, 0, inCorr, dstOffset, outData, dstOffset);
3233
3202
  }
3234
3203
  return true;
3235
3204
  }
@@ -3238,7 +3207,7 @@ var MeshPredictionSchemeTexCoordsPortableDecoder = class extends MeshPredictionS
3238
3207
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeDeltaDecoder.ts
3239
3208
  var PredictionSchemeDeltaDecoder = class extends PredictionSchemeDecoder {
3240
3209
  computeOriginalValues(inCorr, outData, size, numComponents, _entryToPointIdMap) {
3241
- const transform = this.f;
3210
+ const transform = this.e;
3242
3211
  transform.init(numComponents);
3243
3212
  if (transform.computeOriginalValuesDelta) {
3244
3213
  transform.computeOriginalValuesDelta(inCorr, outData, size, numComponents);
@@ -3284,11 +3253,7 @@ function createPredictionSchemeForDecoder(method, attId, decoder, transform) {
3284
3253
  const encodingData = meshDecoder.getAttributeEncodingData(attId);
3285
3254
  if (cornerTable !== null && encodingData !== null) {
3286
3255
  const attCornerTable = meshDecoder.getAttributeCornerTable(attId);
3287
- const meshData = new MeshPredictionSchemeData(
3288
- attCornerTable !== null ? attCornerTable : cornerTable,
3289
- encodingData.encodedAttributeValueIndexToCornerMap,
3290
- encodingData.vertexToEncodedAttributeValueIndexMap
3291
- );
3256
+ const meshData = new MeshPredictionSchemeData(attCornerTable !== null ? attCornerTable : cornerTable, encodingData);
3292
3257
  const ret = createMeshPredictionSchemeDecoder(method, transform, meshData);
3293
3258
  if (ret !== null) return ret;
3294
3259
  }
@@ -3297,22 +3262,25 @@ function createPredictionSchemeForDecoder(method, attId, decoder, transform) {
3297
3262
 
3298
3263
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeWrapDecodingTransform.ts
3299
3264
  var PredictionSchemeWrapDecodingTransform = class {
3300
- w = 0;
3301
- aa = 0;
3265
+ v = 0;
3266
+ T = 0;
3302
3267
  k = 0;
3303
3268
  ba = 0;
3304
3269
  getType() {
3305
3270
  return 1 /* PREDICTION_TRANSFORM_WRAP */;
3306
3271
  }
3307
3272
  init(numComponents) {
3308
- this.w = numComponents;
3273
+ this.v = numComponents;
3309
3274
  }
3310
3275
  areCorrectionsPositive() {
3311
3276
  return false;
3312
3277
  }
3278
+ boundsValues(limit) {
3279
+ return this.k < limit && this.T > -limit;
3280
+ }
3313
3281
  computeOriginalValue(predictedVals, predictedOffset, corrVals, corrOffset, outOriginalVals, outOffset) {
3314
- const nc = this.w;
3315
- const minValue = this.aa;
3282
+ const nc = this.v;
3283
+ const minValue = this.T;
3316
3284
  const maxValue = this.k;
3317
3285
  const maxDif = this.ba;
3318
3286
  for (let i = 0; i < nc; ++i) {
@@ -3338,7 +3306,7 @@ var PredictionSchemeWrapDecodingTransform = class {
3338
3306
  if (maxValue === void 0) return false;
3339
3307
  const dif = maxValue - minValue;
3340
3308
  if (dif < 0 || dif >= 2147483647) return false;
3341
- this.aa = minValue;
3309
+ this.T = minValue;
3342
3310
  this.k = maxValue;
3343
3311
  this.ba = 1 + dif;
3344
3312
  return true;
@@ -3347,39 +3315,39 @@ var PredictionSchemeWrapDecodingTransform = class {
3347
3315
 
3348
3316
  // src/decoder/compression/attributes/SequentialIntegerAttributeDecoder.ts
3349
3317
  var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder {
3350
- ca = null;
3318
+ M = null;
3351
3319
  // Two-phase decode state (see SequentialAttributeDecoder): the parse phase
3352
3320
  // stashes the primed raw-symbol stream here so the controller can batch and
3353
3321
  // pair several attributes' decodes; the finish phase consumes it.
3354
- da = null;
3355
- Za = 0;
3356
- Ab = null;
3322
+ ca = null;
3323
+ Xa = 0;
3324
+ yb = null;
3357
3325
  // Int32 view over the portable attribute's storage (see preparePortableAttribute).
3358
- R = null;
3326
+ U = null;
3359
3327
  // --- Two-phase decode (parse headers / batch symbol decode / finish) ---
3360
3328
  pendingSymbolStream() {
3361
- if (this.da === null) {
3329
+ if (this.ca === null) {
3362
3330
  return null;
3363
3331
  }
3364
- const portableData = this.R;
3332
+ const portableData = this.U;
3365
3333
  return {
3366
- ans: this.da.m,
3367
- out: new Uint32Array(portableData.buffer, portableData.byteOffset, this.Za),
3368
- count: this.Za
3334
+ ans: this.ca.G,
3335
+ out: new Uint32Array(portableData.buffer, portableData.byteOffset, this.Xa),
3336
+ count: this.Xa
3369
3337
  };
3370
3338
  }
3371
3339
  decodePortableAttributeFinish() {
3372
- if (this.da !== null) {
3373
- this.da.endDecoding();
3374
- this.da = null;
3340
+ if (this.ca !== null) {
3341
+ this.ca.endDecoding();
3342
+ this.ca = null;
3375
3343
  }
3376
- return this.bc(this.Ab);
3344
+ return this.$b(this.yb);
3377
3345
  }
3378
3346
  // The parse phase of the integer decode: prediction scheme, portable
3379
3347
  // attribute, the symbol stream (raw streams are deferred to the finish
3380
3348
  // phase) and the prediction data.
3381
3349
  decodeValues(pointIds, buffer) {
3382
- this.Ab = pointIds;
3350
+ this.yb = pointIds;
3383
3351
  let predictionSchemeMethod = buffer.decodeUint8();
3384
3352
  if (predictionSchemeMethod !== void 0) predictionSchemeMethod = predictionSchemeMethod << 24 >> 24;
3385
3353
  if (predictionSchemeMethod === void 0) return false;
@@ -3393,10 +3361,10 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3393
3361
  if (predictionTransformType < -1 /* PREDICTION_TRANSFORM_NONE */ || predictionTransformType >= 4 /* NUM_PREDICTION_SCHEME_TRANSFORM_TYPES */) {
3394
3362
  return false;
3395
3363
  }
3396
- this.ca = this.createIntPredictionScheme(predictionSchemeMethod, predictionTransformType);
3364
+ this.M = this.createIntPredictionScheme(predictionSchemeMethod, predictionTransformType);
3397
3365
  }
3398
- if (this.ca) {
3399
- if (!this.initPredictionScheme(this.ca)) {
3366
+ if (this.M) {
3367
+ if (!this.initPredictionScheme(this.M)) {
3400
3368
  return false;
3401
3369
  }
3402
3370
  }
@@ -3407,7 +3375,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3407
3375
  const numEntries = pointIds.length;
3408
3376
  const numValues = numEntries * numComponents;
3409
3377
  this.preparePortableAttribute(numEntries, numComponents);
3410
- const portableAttributeData = this.R;
3378
+ const portableAttributeData = this.U;
3411
3379
  if (portableAttributeData === null) {
3412
3380
  return false;
3413
3381
  }
@@ -3421,8 +3389,8 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3421
3389
  if (decoder === null) {
3422
3390
  return false;
3423
3391
  }
3424
- this.da = decoder;
3425
- this.Za = numValues;
3392
+ this.ca = decoder;
3393
+ this.Xa = numValues;
3426
3394
  } else if (scheme === 0 /* SYMBOL_CODING_TAGGED */) {
3427
3395
  const outUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
3428
3396
  if (!decodeTaggedSymbols(numValues, numComponents, buffer, outUint32)) {
@@ -3446,25 +3414,25 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3446
3414
  portableAttributeData[i] = val;
3447
3415
  }
3448
3416
  }
3449
- if (this.ca) {
3450
- if (!this.ca.decodePredictionData(buffer)) {
3417
+ if (this.M) {
3418
+ if (!this.M.decodePredictionData(buffer)) {
3451
3419
  return false;
3452
3420
  }
3453
3421
  }
3454
3422
  return true;
3455
3423
  }
3456
3424
  // The post-symbol tail of the decode: zigzag unpacking and prediction.
3457
- bc(pointIds) {
3425
+ $b(pointIds) {
3458
3426
  const numComponents = this.getNumValueComponents();
3459
3427
  const numValues = pointIds.length * numComponents;
3460
- const data = this.R;
3428
+ const data = this.U;
3461
3429
  if (data === null) {
3462
3430
  return false;
3463
3431
  }
3464
3432
  if (numValues === 0) {
3465
3433
  return true;
3466
3434
  }
3467
- const ps = this.ca;
3435
+ const ps = this.M;
3468
3436
  if (ps === null) {
3469
3437
  convertSymbolsToSignedInts(new Uint32Array(data.buffer, data.byteOffset, numValues), numValues, data);
3470
3438
  return true;
@@ -3479,7 +3447,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3479
3447
  return ps.computeOriginalValues(data, data, numValues, numComponents, pointIds);
3480
3448
  }
3481
3449
  transformAttributeToOriginalFormat(pointIds) {
3482
- return this._a(pointIds.length);
3450
+ return this.Ya(pointIds.length);
3483
3451
  }
3484
3452
  // Prediction scheme for decoding integer values; subclasses override for others.
3485
3453
  createIntPredictionScheme(method, transformType) {
@@ -3492,21 +3460,28 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3492
3460
  getNumValueComponents() {
3493
3461
  return this.attribute.numComponents;
3494
3462
  }
3463
+ // Whether the decoded values are known to lie below 2^24 in magnitude (the
3464
+ // range in which the float extraction needs no per-value float32 rounding,
3465
+ // see PointAttribute._lazyFloatValues): true when a prediction transform
3466
+ // clamps them into such a range. Unpredicted values are unbounded.
3467
+ zb() {
3468
+ return this.M !== null && this.M.boundsValues(16777216);
3469
+ }
3495
3470
  // The decoded values stay in the portable attribute; the final attribute
3496
3471
  // only takes its size (see PointAttribute.setLazyInteger and the overrides
3497
3472
  // in the quantization / normal decoders).
3498
- xb(numValues) {
3473
+ vb(numValues) {
3499
3474
  this.attribute.resetLazy(numValues);
3500
3475
  return true;
3501
3476
  }
3502
3477
  // Hands the decoded integer values to the attribute, converted to its
3503
3478
  // integer type on extraction.
3504
- _a(_numValues) {
3479
+ Ya(_numValues) {
3505
3480
  const dt = this.attribute.dataType;
3506
3481
  if (dt < 1 /* INT8 */ || dt > 6 /* UINT32 */) {
3507
3482
  return false;
3508
3483
  }
3509
- this.attribute.setLazyInteger(this.R);
3484
+ this.attribute.setLazyInteger(this.U);
3510
3485
  return true;
3511
3486
  }
3512
3487
  preparePortableAttribute(numEntries, numComponents) {
@@ -3526,23 +3501,27 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3526
3501
  portAtt.uniqueId = this.attribute.uniqueId;
3527
3502
  this.$ = portAtt;
3528
3503
  const data = portAtt.buffer.data;
3529
- this.R = numEntries === 0 ? null : new Int32Array(data.buffer, data.byteOffset + portAtt.byteOffset, numEntries * numComponents);
3504
+ this.U = numEntries === 0 ? null : new Int32Array(data.buffer, data.byteOffset + portAtt.byteOffset, numEntries * numComponents);
3530
3505
  }
3531
3506
  };
3532
3507
 
3533
3508
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeNormalOctahedronTransformBase.ts
3534
3509
  var PredictionSchemeNormalOctahedronTransformBase = class {
3535
- y = new OctahedronToolBox();
3510
+ w = new OctahedronToolBox();
3536
3511
  areCorrectionsPositive() {
3537
3512
  return true;
3538
3513
  }
3514
+ // Outputs are origS/origT + center with origS/origT in [-center, center].
3515
+ boundsValues(limit) {
3516
+ return this.w.aa < limit;
3517
+ }
3539
3518
  /** No-op to fulfill the transform interface. */
3540
3519
  init(_numComponents) {
3541
3520
  }
3542
3521
  quantizationBits() {
3543
- return this.y.quantizationBits();
3522
+ return this.w.quantizationBits();
3544
3523
  }
3545
- Bb(maxQuantizedValue) {
3524
+ Ab(maxQuantizedValue) {
3546
3525
  if (maxQuantizedValue % 2 === 0) return false;
3547
3526
  let q = 0;
3548
3527
  let v = maxQuantizedValue;
@@ -3550,7 +3529,7 @@ var PredictionSchemeNormalOctahedronTransformBase = class {
3550
3529
  v >>>= 1;
3551
3530
  q++;
3552
3531
  }
3553
- return this.y.setQuantizationBits(q);
3532
+ return this.w.setQuantizationBits(q);
3554
3533
  }
3555
3534
  };
3556
3535
 
@@ -3564,14 +3543,14 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
3564
3543
  if (maxQuantizedValue === void 0) return false;
3565
3544
  const centerValue = buffer.decodeInt32();
3566
3545
  if (centerValue === void 0) return false;
3567
- if (!this.Bb(maxQuantizedValue)) return false;
3568
- const q = this.y.quantizationBits();
3546
+ if (!this.Ab(maxQuantizedValue)) return false;
3547
+ const q = this.w.quantizationBits();
3569
3548
  return q >= 2 && q <= 30;
3570
3549
  }
3571
3550
  computeOriginalValue(predVals, predOffset, corrVals, corrOffset, outOrigVals, outOffset) {
3572
- const toolBox = this.y;
3573
- const center = toolBox.e;
3574
- const maxQuantizedValue = toolBox.qa;
3551
+ const toolBox = this.w;
3552
+ const center = toolBox.f;
3553
+ const maxQuantizedValue = toolBox.aa;
3575
3554
  const corrS = corrVals[corrOffset];
3576
3555
  const corrT = corrVals[corrOffset + 1];
3577
3556
  let predS = predVals[predOffset] - center;
@@ -3697,9 +3676,9 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
3697
3676
  // The arithmetic is computeOriginalValue above verbatim -- keep them in
3698
3677
  // sync; only the plumbing differs.
3699
3678
  computeOriginalValuesDelta(inCorr, outData, size, numComponents) {
3700
- const toolBox = this.y;
3701
- const center = toolBox.e;
3702
- const maxQuantizedValue = toolBox.qa;
3679
+ const toolBox = this.w;
3680
+ const center = toolBox.f;
3681
+ const maxQuantizedValue = toolBox.aa;
3703
3682
  let prevS = 0;
3704
3683
  let prevT = 0;
3705
3684
  for (let i = 0; i < size; i += numComponents) {
@@ -3833,12 +3812,12 @@ var PredictionSchemeNormalOctahedronDecodingTransform = class extends Prediction
3833
3812
  decodeTransformData(buffer) {
3834
3813
  const maxQuantizedValue = buffer.decodeInt32();
3835
3814
  if (maxQuantizedValue === void 0) return false;
3836
- return this.Bb(maxQuantizedValue);
3815
+ return this.Ab(maxQuantizedValue);
3837
3816
  }
3838
3817
  computeOriginalValue(predVals, predOffset, corrVals, corrOffset, outOrigVals, outOffset) {
3839
- const toolBox = this.y;
3840
- const center = toolBox.e;
3841
- const maxQuantizedValue = toolBox.qa;
3818
+ const toolBox = this.w;
3819
+ const center = toolBox.f;
3820
+ const maxQuantizedValue = toolBox.aa;
3842
3821
  const predS = predVals[predOffset] - center;
3843
3822
  const predT = predVals[predOffset + 1] - center;
3844
3823
  const corrS = corrVals[corrOffset];
@@ -3917,7 +3896,7 @@ var PredictionSchemeNormalOctahedronDecodingTransform = class extends Prediction
3917
3896
 
3918
3897
  // src/decoder/compression/attributes/SequentialNormalAttributeDecoder.ts
3919
3898
  var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeDecoder {
3920
- J = -1;
3899
+ L = -1;
3921
3900
  init(decoder, attributeId) {
3922
3901
  if (!super.init(decoder, attributeId)) {
3923
3902
  return false;
@@ -3932,15 +3911,19 @@ var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeD
3932
3911
  decodeDataNeededByPortableTransform(_pointIds, buffer) {
3933
3912
  const qBits = buffer.decodeUint8();
3934
3913
  if (qBits === void 0) return false;
3935
- this.J = qBits;
3914
+ this.L = qBits;
3936
3915
  return true;
3937
3916
  }
3938
3917
  // The octahedral-to-unit-vector transform is deferred to extractTo (see
3939
3918
  // PointAttribute.setLazyOctahedron).
3940
- _a(_numPoints) {
3941
- const q = this.J;
3919
+ Ya(_numPoints) {
3920
+ const q = this.L;
3942
3921
  if (q < 2 || q > 30) return false;
3943
- this.attribute.setLazyOctahedron(this.R, Math.fround(2 / Math.fround((1 << q) - 2)));
3922
+ this.attribute.setLazyOctahedron(
3923
+ this.U,
3924
+ Math.fround(2 / Math.fround((1 << q) - 2)),
3925
+ this.zb()
3926
+ );
3944
3927
  return true;
3945
3928
  }
3946
3929
  createIntPredictionScheme(method, transformType) {
@@ -3954,9 +3937,9 @@ var SequentialNormalAttributeDecoder = class extends SequentialIntegerAttributeD
3954
3937
 
3955
3938
  // src/decoder/compression/attributes/SequentialQuantizationAttributeDecoder.ts
3956
3939
  var SequentialQuantizationAttributeDecoder = class extends SequentialIntegerAttributeDecoder {
3957
- J = -1;
3958
- $a = [];
3959
- Cb = 0;
3940
+ L = -1;
3941
+ Za = [];
3942
+ Bb = 0;
3960
3943
  init(decoder, attributeId) {
3961
3944
  if (!super.init(decoder, attributeId)) {
3962
3945
  return false;
@@ -3966,39 +3949,39 @@ var SequentialQuantizationAttributeDecoder = class extends SequentialIntegerAttr
3966
3949
  // The quantization parameters (AttributeQuantizationTransform::DecodeParameters).
3967
3950
  decodeDataNeededByPortableTransform(_pointIds, buffer) {
3968
3951
  const numComponents = this.attribute.numComponents;
3969
- this.$a = new Array(numComponents);
3952
+ this.Za = new Array(numComponents);
3970
3953
  for (let i = 0; i < numComponents; i++) {
3971
3954
  const val = buffer.decodeFloat32();
3972
3955
  if (val === void 0) return false;
3973
- this.$a[i] = val;
3956
+ this.Za[i] = val;
3974
3957
  }
3975
3958
  const range = buffer.decodeFloat32();
3976
3959
  if (range === void 0) return false;
3977
- this.Cb = range;
3960
+ this.Bb = range;
3978
3961
  const qBits = buffer.decodeUint8();
3979
3962
  if (qBits === void 0 || qBits < 1 || qBits > 30) return false;
3980
- this.J = qBits;
3963
+ this.L = qBits;
3981
3964
  return true;
3982
3965
  }
3983
3966
  // Dequantization is deferred to extractTo (see PointAttribute.setLazyQuantized).
3984
- _a(_numValues) {
3985
- const maxQuantizedValue = (1 << this.J >>> 0) - 1;
3967
+ Ya(_numValues) {
3968
+ const maxQuantizedValue = (1 << this.L >>> 0) - 1;
3986
3969
  if (maxQuantizedValue <= 0) return false;
3987
- const delta = Math.fround(this.Cb / Math.fround(maxQuantizedValue));
3988
- this.attribute.setLazyQuantized(this.R, this.$a, delta);
3970
+ const delta = Math.fround(this.Bb / Math.fround(maxQuantizedValue));
3971
+ this.attribute.setLazyQuantized(this.U, this.Za, delta, this.zb());
3989
3972
  return true;
3990
3973
  }
3991
3974
  };
3992
3975
 
3993
3976
  // src/decoder/compression/attributes/SequentialAttributeDecodersController.ts
3994
3977
  var SequentialAttributeDecodersController = class extends AttributesDecoder {
3995
- va = [];
3978
+ ua = [];
3996
3979
  // Replaced by the sequencer's output in _prepareSequence.
3997
- La = new Int32Array(0);
3998
- S;
3980
+ Ka = new Int32Array(0);
3981
+ V;
3999
3982
  constructor(sequencer) {
4000
3983
  super();
4001
- this.S = sequencer;
3984
+ this.V = sequencer;
4002
3985
  }
4003
3986
  decodeAttributesDecoderData(buffer) {
4004
3987
  if (!super.decodeAttributesDecoderData(buffer)) {
@@ -4012,19 +3995,19 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4012
3995
  if (decoder === null || !decoder.init(this.getDecoder(), this.getAttributeId(i))) {
4013
3996
  return false;
4014
3997
  }
4015
- this.va[i] = decoder;
3998
+ this.ua[i] = decoder;
4016
3999
  }
4017
4000
  return true;
4018
4001
  }
4019
- cc() {
4020
- if (!this.S.generateSequence()) {
4002
+ ac() {
4003
+ if (!this.V.generateSequence()) {
4021
4004
  return false;
4022
4005
  }
4023
- this.La = this.S.getOutputPointIds();
4006
+ this.Ka = this.V.getOutputPointIds();
4024
4007
  const numAttributes = this.getNumAttributes();
4025
4008
  for (let i = 0; i < numAttributes; i++) {
4026
4009
  const pa = this.getDecoder().pointCloud().attribute(this.getAttributeId(i));
4027
- if (!this.S.updatePointToAttributeIndexMapping(pa)) {
4010
+ if (!this.V.updatePointToAttributeIndexMapping(pa)) {
4028
4011
  return false;
4029
4012
  }
4030
4013
  }
@@ -4038,24 +4021,24 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4038
4021
  // of the finish work reads the buffer, and dependents only read parent
4039
4022
  // portable VALUES in finish, so ordering and output stay identical.
4040
4023
  decodeAttributesParse(buffer) {
4041
- if (!this.cc()) {
4024
+ if (!this.ac()) {
4042
4025
  return false;
4043
4026
  }
4044
- const decoders = this.va;
4027
+ const decoders = this.ua;
4045
4028
  for (let i = 0; i < decoders.length; i++) {
4046
- if (!decoders[i].decodePortableAttributeParse(this.La, buffer)) {
4029
+ if (!decoders[i].decodePortableAttributeParse(this.Ka, buffer)) {
4047
4030
  return false;
4048
4031
  }
4049
4032
  }
4050
4033
  for (let i = 0; i < decoders.length; i++) {
4051
- if (!decoders[i].decodeDataNeededByPortableTransform(this.La, buffer)) {
4034
+ if (!decoders[i].decodeDataNeededByPortableTransform(this.Ka, buffer)) {
4052
4035
  return false;
4053
4036
  }
4054
4037
  }
4055
4038
  return true;
4056
4039
  }
4057
4040
  collectPendingSymbolStreams(out) {
4058
- const decoders = this.va;
4041
+ const decoders = this.ua;
4059
4042
  for (let i = 0; i < decoders.length; i++) {
4060
4043
  const pending = decoders[i].pendingSymbolStream();
4061
4044
  if (pending !== null) {
@@ -4064,14 +4047,14 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4064
4047
  }
4065
4048
  }
4066
4049
  decodeAttributesFinish() {
4067
- const decoders = this.va;
4050
+ const decoders = this.ua;
4068
4051
  for (let i = 0; i < decoders.length; i++) {
4069
4052
  if (!decoders[i].decodePortableAttributeFinish()) {
4070
4053
  return false;
4071
4054
  }
4072
4055
  }
4073
4056
  for (let i = 0; i < decoders.length; i++) {
4074
- if (!decoders[i].transformAttributeToOriginalFormat(this.La)) {
4057
+ if (!decoders[i].transformAttributeToOriginalFormat(this.Ka)) {
4075
4058
  return false;
4076
4059
  }
4077
4060
  }
@@ -4082,7 +4065,7 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4082
4065
  if (locId < 0) {
4083
4066
  return null;
4084
4067
  }
4085
- return this.va[locId].getPortableAttribute();
4068
+ return this.ua[locId].getPortableAttribute();
4086
4069
  }
4087
4070
  createSequentialDecoder(decoderType) {
4088
4071
  switch (decoderType) {
@@ -4118,30 +4101,30 @@ var TopologySplitEventData = class {
4118
4101
  // src/decoder/compression/mesh/traverser/DepthFirstTraverser.ts
4119
4102
  var kInvalidCornerIndex4 = -1;
4120
4103
  var kInvalidFaceIndex = -1;
4121
- var kInvalidVertexIndex2 = -1;
4104
+ var kInvalidVertexIndex = -1;
4122
4105
  var DepthFirstTraverser = class {
4123
4106
  a = null;
4124
- wa = null;
4125
- T = null;
4126
- Db = [];
4127
- ea = 0;
4107
+ va = null;
4108
+ W = null;
4109
+ Cb = [];
4110
+ da = 0;
4128
4111
  // Identifies the traversal order for the shared traversal cache
4129
4112
  // (MESH_TRAVERSAL_DEPTH_FIRST). See MeshTraversalSequencer.
4130
- Eb = 0;
4113
+ Db = 0;
4131
4114
  // The sequencer derives the point id sequence from the corner map after
4132
4115
  // the traversal (see traverseFromCorner).
4133
4116
  emitsPointIds = false;
4134
4117
  h = null;
4135
- p = null;
4136
- Fb = null;
4137
- F = 0;
4118
+ o = null;
4119
+ y = null;
4120
+ H = 0;
4138
4121
  init(cornerTable, observer) {
4139
4122
  this.a = cornerTable;
4140
- this.wa = observer;
4123
+ this.va = observer;
4141
4124
  this.h = cornerTable.cornerToVertexArray();
4142
- this.p = cornerTable.oppositeCornerArray();
4143
- this.Fb = cornerTable.vertexLeftmostCornerArray();
4144
- this.F = cornerTable.numCorners();
4125
+ this.o = cornerTable.oppositeCornerArray();
4126
+ this.y = cornerTable.vertexOnBoundaryArray();
4127
+ this.H = cornerTable.numCorners();
4145
4128
  }
4146
4129
  cornerTable() {
4147
4130
  return this.a;
@@ -4155,8 +4138,8 @@ var DepthFirstTraverser = class {
4155
4138
  // Decode-scoped scratch: released in bulk at the end of the decode.
4156
4139
  onTraversalStart() {
4157
4140
  const cornerTable = this.a;
4158
- this.T = scratchUint8Zeroed(cornerTable.numFaces());
4159
- this.Db = scratchInt32(this.F);
4141
+ this.W = scratchUint8Zeroed(cornerTable.numFaces());
4142
+ this.Cb = scratchInt32(this.H);
4160
4143
  }
4161
4144
  // Traverses every face, seeding a new traversal at the first corner of each
4162
4145
  // face not yet reached. The visited check lives here rather than behind a
@@ -4165,8 +4148,8 @@ var DepthFirstTraverser = class {
4165
4148
  // was measurable next to the traversal itself.
4166
4149
  traverseAll() {
4167
4150
  const numFaces = this.a.numFaces();
4168
- const isFaceVisited = this.T;
4169
- for (let f = 0; f < numFaces && this.ea < numFaces; ++f) {
4151
+ const isFaceVisited = this.W;
4152
+ for (let f = 0; f < numFaces && this.da < numFaces; ++f) {
4170
4153
  if (isFaceVisited[f] === 0 && !this.traverseFromCorner(3 * f)) {
4171
4154
  return false;
4172
4155
  }
@@ -4174,19 +4157,19 @@ var DepthFirstTraverser = class {
4174
4157
  return true;
4175
4158
  }
4176
4159
  traverseFromCorner(cornerId) {
4177
- if (this.T[cornerId / 3 | 0]) {
4160
+ if (this.W[cornerId / 3 | 0]) {
4178
4161
  return true;
4179
4162
  }
4180
- const isFaceVisited = this.T;
4181
- const observer = this.wa;
4163
+ const isFaceVisited = this.W;
4164
+ const observer = this.va;
4182
4165
  const cornerToVertex = this.h;
4183
- const oppositeCorners = this.p;
4184
- const vertexLeftmost = this.Fb;
4185
- const stack = this.Db;
4186
- let numVisitedFaces = this.ea;
4187
- const encodingData = observer.z;
4188
- const encodedToCornerMap = observer.ab;
4189
- const vertexToEncodedMap = observer.bb;
4166
+ const oppositeCorners = this.o;
4167
+ const vertexOnBoundary = this.y;
4168
+ const stack = this.Cb;
4169
+ let numVisitedFaces = this.da;
4170
+ const encodingData = observer.n;
4171
+ const encodedToCornerMap = observer._a;
4172
+ const vertexToEncodedMap = observer.$a;
4190
4173
  let numValues = encodingData.numValues;
4191
4174
  let stackSize = 0;
4192
4175
  stack[stackSize++] = cornerId;
@@ -4194,7 +4177,7 @@ var DepthFirstTraverser = class {
4194
4177
  const prevCorner = cornerId % 3 === 0 ? cornerId + 2 : cornerId - 1;
4195
4178
  const nextVert = cornerToVertex[nextCorner];
4196
4179
  const prevVert = cornerToVertex[prevCorner];
4197
- if (nextVert === kInvalidVertexIndex2 || prevVert === kInvalidVertexIndex2) {
4180
+ if (nextVert === kInvalidVertexIndex || prevVert === kInvalidVertexIndex) {
4198
4181
  return false;
4199
4182
  }
4200
4183
  if (vertexToEncodedMap[nextVert] < 0) {
@@ -4216,22 +4199,16 @@ var DepthFirstTraverser = class {
4216
4199
  isFaceVisited[faceId] = 1;
4217
4200
  numVisitedFaces++;
4218
4201
  const vertId = cornerToVertex[cornerId];
4219
- if (vertId === kInvalidVertexIndex2) {
4202
+ if (vertId === kInvalidVertexIndex) {
4220
4203
  encodingData.numValues = numValues;
4221
4204
  return false;
4222
4205
  }
4223
4206
  const faceBase = faceId * 3;
4224
4207
  const nextCornerId = cornerId === faceBase + 2 ? faceBase : cornerId + 1;
4225
4208
  if (vertexToEncodedMap[vertId] < 0) {
4226
- const lc = vertexLeftmost[vertId];
4227
- let onBoundary = true;
4228
- if (lc >= 0) {
4229
- const nextLc = lc % 3 === 2 ? lc - 2 : lc + 1;
4230
- onBoundary = oppositeCorners[nextLc] < 0;
4231
- }
4232
4209
  encodedToCornerMap[numValues] = cornerId;
4233
4210
  vertexToEncodedMap[vertId] = numValues++;
4234
- if (!onBoundary) {
4211
+ if (vertexOnBoundary[vertId] === 0) {
4235
4212
  cornerId = oppositeCorners[nextCornerId];
4236
4213
  faceId = cornerId / 3 | 0;
4237
4214
  continue;
@@ -4264,7 +4241,7 @@ var DepthFirstTraverser = class {
4264
4241
  }
4265
4242
  }
4266
4243
  }
4267
- this.ea = numVisitedFaces;
4244
+ this.da = numVisitedFaces;
4268
4245
  encodingData.numValues = numValues;
4269
4246
  return true;
4270
4247
  }
@@ -4276,51 +4253,51 @@ var kInvalidFaceIndex2 = -1;
4276
4253
  var kMaxPriority = 3;
4277
4254
  var MaxPredictionDegreeTraverser = class {
4278
4255
  a = null;
4279
- wa = null;
4280
- T = null;
4281
- cb = null;
4282
- ea = 0;
4256
+ va = null;
4257
+ W = null;
4258
+ ab = null;
4259
+ da = 0;
4283
4260
  // One stack (bucket) per priority level [0, kMaxPriority).
4284
- Ma = null;
4285
- U = 0;
4261
+ La = null;
4262
+ X = 0;
4286
4263
  // Prediction degree accumulated per vertex during traversal.
4287
- db = null;
4264
+ bb = null;
4288
4265
  // Flat connectivity arrays (see DepthFirstTraverser for why).
4289
4266
  h = null;
4290
- p = null;
4267
+ o = null;
4291
4268
  // Identifies the traversal order for the shared traversal cache
4292
4269
  // (MESH_TRAVERSAL_PREDICTION_DEGREE). See MeshTraversalSequencer.
4293
- Eb = 1;
4270
+ Db = 1;
4294
4271
  // Point ids are appended through the observer as vertices are visited.
4295
4272
  emitsPointIds = true;
4296
4273
  init(cornerTable, observer) {
4297
4274
  this.a = cornerTable;
4298
- this.wa = observer;
4299
- this.T = new Uint8Array(cornerTable.numFaces());
4300
- this.cb = new Uint8Array(cornerTable.numVertices());
4275
+ this.va = observer;
4276
+ this.W = new Uint8Array(cornerTable.numFaces());
4277
+ this.ab = new Uint8Array(cornerTable.numVertices());
4301
4278
  this.h = cornerTable.cornerToVertexArray();
4302
- this.p = cornerTable.oppositeCornerArray();
4303
- this.Ma = [[], [], []];
4279
+ this.o = cornerTable.oppositeCornerArray();
4280
+ this.La = [[], [], []];
4304
4281
  }
4305
4282
  cornerTable() {
4306
4283
  return this.a;
4307
4284
  }
4308
4285
  // corner is always valid (>= 0) where these are used.
4309
- Gb(c) {
4286
+ Eb(c) {
4310
4287
  return c % 3 === 2 ? c - 2 : c + 1;
4311
4288
  }
4312
- Hb(c) {
4289
+ Fb(c) {
4313
4290
  return c % 3 === 0 ? c + 2 : c - 1;
4314
4291
  }
4315
4292
  onTraversalStart() {
4316
- this.db = new Int32Array(this.a.numVertices());
4293
+ this.bb = new Int32Array(this.a.numVertices());
4317
4294
  }
4318
4295
  // Same contract as DepthFirstTraverser.traverseAll. Seeds every face
4319
4296
  // through traverseFromCorner (which re-checks the first face's vertices),
4320
4297
  // exactly as the sequencer's loop always has.
4321
4298
  traverseAll() {
4322
4299
  const numFaces = this.a.numFaces();
4323
- for (let f = 0; f < numFaces && this.ea < numFaces; ++f) {
4300
+ for (let f = 0; f < numFaces && this.da < numFaces; ++f) {
4324
4301
  if (!this.traverseFromCorner(3 * f)) {
4325
4302
  return false;
4326
4303
  }
@@ -4329,11 +4306,11 @@ var MaxPredictionDegreeTraverser = class {
4329
4306
  }
4330
4307
  // Returns the priority of traversing the edge leading to cornerId. Mutates
4331
4308
  // the prediction degree of the destination vertex.
4332
- Ib(cornerId) {
4309
+ Gb(cornerId) {
4333
4310
  const vTip = this.h[cornerId];
4334
4311
  let priority = 0;
4335
- if (!this.cb[vTip]) {
4336
- const degree = ++this.db[vTip];
4312
+ if (!this.ab[vTip]) {
4313
+ const degree = ++this.bb[vTip];
4337
4314
  priority = degree > 1 ? 1 : 2;
4338
4315
  }
4339
4316
  if (priority >= kMaxPriority) {
@@ -4341,38 +4318,38 @@ var MaxPredictionDegreeTraverser = class {
4341
4318
  }
4342
4319
  return priority;
4343
4320
  }
4344
- Jb(ci, priority) {
4345
- this.Ma[priority].push(ci);
4346
- if (priority < this.U) {
4347
- this.U = priority;
4321
+ Hb(ci, priority) {
4322
+ this.La[priority].push(ci);
4323
+ if (priority < this.X) {
4324
+ this.X = priority;
4348
4325
  }
4349
4326
  }
4350
4327
  // Retrieves the next available corner to traverse, processed by priority.
4351
4328
  // Returns kInvalidCornerIndex when no corner is available.
4352
- dc() {
4353
- for (let i = this.U; i < kMaxPriority; ++i) {
4354
- const stack = this.Ma[i];
4329
+ bc() {
4330
+ for (let i = this.X; i < kMaxPriority; ++i) {
4331
+ const stack = this.La[i];
4355
4332
  if (stack.length > 0) {
4356
4333
  const ret = stack.pop();
4357
- this.U = i;
4334
+ this.X = i;
4358
4335
  return ret;
4359
4336
  }
4360
4337
  }
4361
4338
  return kInvalidCornerIndex5;
4362
4339
  }
4363
4340
  traverseFromCorner(cornerId) {
4364
- if (this.db.length === 0) {
4341
+ if (this.bb.length === 0) {
4365
4342
  return true;
4366
4343
  }
4367
4344
  const cornerToVertex = this.h;
4368
- const oppositeCorners = this.p;
4369
- const isFaceVisited = this.T;
4370
- const isVertexVisited = this.cb;
4371
- const observer = this.wa;
4372
- this.Ma[0].push(cornerId);
4373
- this.U = 0;
4374
- const firstNext = this.Gb(cornerId);
4375
- const firstPrev = this.Hb(cornerId);
4345
+ const oppositeCorners = this.o;
4346
+ const isFaceVisited = this.W;
4347
+ const isVertexVisited = this.ab;
4348
+ const observer = this.va;
4349
+ this.La[0].push(cornerId);
4350
+ this.X = 0;
4351
+ const firstNext = this.Eb(cornerId);
4352
+ const firstPrev = this.Fb(cornerId);
4376
4353
  const nextVert = cornerToVertex[firstNext];
4377
4354
  const prevVert = cornerToVertex[firstPrev];
4378
4355
  if (!isVertexVisited[nextVert]) {
@@ -4388,7 +4365,7 @@ var MaxPredictionDegreeTraverser = class {
4388
4365
  isVertexVisited[tipVertex] = 1;
4389
4366
  observer.onNewVertexVisited(tipVertex, cornerId);
4390
4367
  }
4391
- while ((cornerId = this.dc()) !== kInvalidCornerIndex5) {
4368
+ while ((cornerId = this.bc()) !== kInvalidCornerIndex5) {
4392
4369
  let faceId = cornerId / 3 | 0;
4393
4370
  if (isFaceVisited[faceId]) {
4394
4371
  continue;
@@ -4396,34 +4373,34 @@ var MaxPredictionDegreeTraverser = class {
4396
4373
  while (true) {
4397
4374
  faceId = cornerId / 3 | 0;
4398
4375
  isFaceVisited[faceId] = 1;
4399
- this.ea++;
4376
+ this.da++;
4400
4377
  const vertId = cornerToVertex[cornerId];
4401
4378
  if (!isVertexVisited[vertId]) {
4402
4379
  isVertexVisited[vertId] = 1;
4403
4380
  observer.onNewVertexVisited(vertId, cornerId);
4404
4381
  }
4405
- const rightCornerId = oppositeCorners[this.Gb(cornerId)];
4406
- const leftCornerId = oppositeCorners[this.Hb(cornerId)];
4382
+ const rightCornerId = oppositeCorners[this.Eb(cornerId)];
4383
+ const leftCornerId = oppositeCorners[this.Fb(cornerId)];
4407
4384
  const rightFaceId = rightCornerId === kInvalidCornerIndex5 ? kInvalidFaceIndex2 : rightCornerId / 3 | 0;
4408
4385
  const leftFaceId = leftCornerId === kInvalidCornerIndex5 ? kInvalidFaceIndex2 : leftCornerId / 3 | 0;
4409
4386
  const isRightFaceVisited = rightFaceId === kInvalidFaceIndex2 || isFaceVisited[rightFaceId] !== 0;
4410
4387
  const isLeftFaceVisited = leftFaceId === kInvalidFaceIndex2 || isFaceVisited[leftFaceId] !== 0;
4411
4388
  if (!isLeftFaceVisited) {
4412
- const priority = this.Ib(leftCornerId);
4413
- if (isRightFaceVisited && priority <= this.U) {
4389
+ const priority = this.Gb(leftCornerId);
4390
+ if (isRightFaceVisited && priority <= this.X) {
4414
4391
  cornerId = leftCornerId;
4415
4392
  continue;
4416
4393
  } else {
4417
- this.Jb(leftCornerId, priority);
4394
+ this.Hb(leftCornerId, priority);
4418
4395
  }
4419
4396
  }
4420
4397
  if (!isRightFaceVisited) {
4421
- const priority = this.Ib(rightCornerId);
4422
- if (priority <= this.U) {
4398
+ const priority = this.Gb(rightCornerId);
4399
+ if (priority <= this.X) {
4423
4400
  cornerId = rightCornerId;
4424
4401
  continue;
4425
4402
  } else {
4426
- this.Jb(rightCornerId, priority);
4403
+ this.Hb(rightCornerId, priority);
4427
4404
  }
4428
4405
  }
4429
4406
  break;
@@ -4435,67 +4412,67 @@ var MaxPredictionDegreeTraverser = class {
4435
4412
 
4436
4413
  // src/decoder/compression/mesh/traverser/MeshAttributeIndicesEncodingObserver.ts
4437
4414
  var MeshAttributeIndicesEncodingObserver = class {
4438
- z;
4439
- S;
4440
- bb;
4441
- ab;
4442
- Kb;
4415
+ n;
4416
+ V;
4417
+ $a;
4418
+ _a;
4419
+ Ib;
4443
4420
  constructor(mesh, sequencer, encodingData) {
4444
- this.z = encodingData;
4445
- this.S = sequencer;
4446
- this.bb = encodingData.vertexToEncodedAttributeValueIndexMap;
4447
- this.ab = encodingData.encodedAttributeValueIndexToCornerMap;
4448
- this.Kb = mesh.faces_;
4421
+ this.n = encodingData;
4422
+ this.V = sequencer;
4423
+ this.$a = encodingData.vertexToEncodedAttributeValueIndexMap;
4424
+ this._a = encodingData.encodedAttributeValueIndexToCornerMap;
4425
+ this.Ib = mesh.faces_;
4449
4426
  }
4450
4427
  onNewVertexVisited(vertex, corner) {
4451
- const pointId = this.Kb[corner];
4452
- this.S.addPointId(pointId);
4453
- const numValues = this.z.numValues;
4454
- this.ab[numValues] = corner;
4455
- this.bb[vertex] = numValues;
4456
- this.z.numValues++;
4428
+ const pointId = this.Ib[corner];
4429
+ this.V.addPointId(pointId);
4430
+ const numValues = this.n.numValues;
4431
+ this._a[numValues] = corner;
4432
+ this.$a[vertex] = numValues;
4433
+ this.n.numValues++;
4457
4434
  }
4458
4435
  };
4459
4436
 
4460
4437
  // src/decoder/compression/mesh/traverser/MeshTraversalSequencer.ts
4461
4438
  var MeshTraversalSequencer = class {
4462
- D;
4463
- z;
4464
- xa = null;
4439
+ C;
4440
+ n;
4441
+ wa = null;
4465
4442
  u = new Int32Array(0);
4466
- ya = 0;
4443
+ xa = 0;
4467
4444
  // Per-decode cache, keyed by corner table, shared across the attribute
4468
4445
  // decoders of one mesh (see MeshEdgebreakerDecoderImpl).
4469
- eb;
4446
+ cb;
4470
4447
  // The cache entry the last generateSequence resolved to (hit or store);
4471
4448
  // carries the shared indicesMap.
4472
- fb = null;
4449
+ db = null;
4473
4450
  // One representative corner per point id, when the connectivity decoder
4474
4451
  // recorded them (see MeshEdgebreakerDecoderImpl._assignAttributeVerticesAndPoints).
4475
- fa;
4452
+ ea;
4476
4453
  constructor(mesh, encodingData, traversalCache, pointCorner) {
4477
- this.D = mesh;
4478
- this.z = encodingData;
4479
- this.eb = traversalCache;
4480
- this.fa = pointCorner;
4454
+ this.C = mesh;
4455
+ this.n = encodingData;
4456
+ this.cb = traversalCache;
4457
+ this.ea = pointCorner;
4481
4458
  }
4482
4459
  setTraverser(traverser) {
4483
- this.xa = traverser;
4460
+ this.wa = traverser;
4484
4461
  }
4485
4462
  generateSequence() {
4486
- const cornerTable = this.xa.cornerTable();
4487
- const methodId = this.xa.Eb;
4463
+ const cornerTable = this.wa.cornerTable();
4464
+ const methodId = this.wa.Db;
4488
4465
  const cacheKey = cornerTable.cornerToVertexArray();
4489
- const encodingData = this.z;
4490
- let byMethod = this.eb.get(cacheKey);
4466
+ const encodingData = this.n;
4467
+ let byMethod = this.cb.get(cacheKey);
4491
4468
  const cached = byMethod && byMethod.get(methodId);
4492
4469
  if (cached !== void 0) {
4493
4470
  this.u = cached.pointIds;
4494
- encodingData.adoptTraversalResult(cached.vertexMap, cached.cornerMap, cached.numValues);
4495
- this.fb = cached;
4471
+ encodingData.adoptTraversalResult(cached);
4472
+ this.db = cached;
4496
4473
  return true;
4497
4474
  }
4498
- if (!this.ec()) {
4475
+ if (!this.cc()) {
4499
4476
  return false;
4500
4477
  }
4501
4478
  const numValues = encodingData.numValues;
@@ -4507,39 +4484,41 @@ var MeshTraversalSequencer = class {
4507
4484
  }
4508
4485
  if (byMethod === void 0) {
4509
4486
  byMethod = /* @__PURE__ */ new Map();
4510
- this.eb.set(cacheKey, byMethod);
4487
+ this.cb.set(cacheKey, byMethod);
4511
4488
  }
4512
4489
  const entry = {
4513
4490
  pointIds: this.u,
4514
4491
  vertexMap: encodingData.vertexToEncodedAttributeValueIndexMap,
4515
4492
  cornerMap: encodingData.encodedAttributeValueIndexToCornerMap,
4516
4493
  numValues,
4517
- indicesMap: null
4494
+ indicesMap: null,
4495
+ parents: null
4518
4496
  };
4519
4497
  byMethod.set(methodId, entry);
4520
- this.fb = entry;
4498
+ encodingData.cacheEntry = entry;
4499
+ this.db = entry;
4521
4500
  return true;
4522
4501
  }
4523
4502
  getOutputPointIds() {
4524
4503
  return this.u;
4525
4504
  }
4526
4505
  addPointId(pointId) {
4527
- this.u[this.ya++] = pointId;
4506
+ this.u[this.xa++] = pointId;
4528
4507
  }
4529
4508
  updatePointToAttributeIndexMapping(attribute) {
4530
- const entry = this.fb;
4509
+ const entry = this.db;
4531
4510
  if (entry !== null && entry.indicesMap !== null) {
4532
4511
  attribute.setExplicitMappingShared(entry.indicesMap);
4533
4512
  return true;
4534
4513
  }
4535
- const cornerTable = this.xa.cornerTable();
4536
- const numFaces = this.D.numFaces();
4537
- const numPoints = this.D.numPoints();
4514
+ const cornerTable = this.wa.cornerTable();
4515
+ const numFaces = this.C.numFaces();
4516
+ const numPoints = this.C.numPoints();
4538
4517
  attribute.setExplicitMappingUnfilled(numPoints);
4539
4518
  const cornerToVertex = cornerTable.cornerToVertexArray();
4540
- const vertexToAttEntry = this.z.vertexToEncodedAttributeValueIndexMap;
4519
+ const vertexToAttEntry = this.n.vertexToEncodedAttributeValueIndexMap;
4541
4520
  const indicesMap = attribute.indicesMap;
4542
- const pointCorner = this.fa;
4521
+ const pointCorner = this.ea;
4543
4522
  if (pointCorner !== null) {
4544
4523
  for (let p = 0; p < numPoints; ++p) {
4545
4524
  const vertId = cornerToVertex[pointCorner[p]];
@@ -4554,7 +4533,7 @@ var MeshTraversalSequencer = class {
4554
4533
  }
4555
4534
  } else {
4556
4535
  const numCorners = numFaces * 3;
4557
- const faces = this.D.faces_;
4536
+ const faces = this.C.faces_;
4558
4537
  for (let ci = 0; ci < numCorners; ++ci) {
4559
4538
  const vertId = cornerToVertex[ci];
4560
4539
  if (vertId < 0) {
@@ -4573,26 +4552,26 @@ var MeshTraversalSequencer = class {
4573
4552
  }
4574
4553
  return true;
4575
4554
  }
4576
- ec() {
4577
- this.ya = 0;
4578
- this.u = scratchInt32(this.D.numPoints());
4579
- const traverser = this.xa;
4555
+ cc() {
4556
+ this.xa = 0;
4557
+ this.u = scratchInt32(this.C.numPoints());
4558
+ const traverser = this.wa;
4580
4559
  traverser.onTraversalStart();
4581
4560
  if (!traverser.traverseAll()) {
4582
4561
  return false;
4583
4562
  }
4584
4563
  if (!traverser.emitsPointIds) {
4585
- const numValues = this.z.numValues;
4586
- const cornerMap = this.z.encodedAttributeValueIndexToCornerMap;
4587
- const faces = this.D.faces_;
4564
+ const numValues = this.n.numValues;
4565
+ const cornerMap = this.n.encodedAttributeValueIndexToCornerMap;
4566
+ const faces = this.C.faces_;
4588
4567
  const outPointIds = this.u;
4589
4568
  for (let i = 0; i < numValues; ++i) {
4590
4569
  outPointIds[i] = faces[cornerMap[i]];
4591
4570
  }
4592
- this.ya = numValues;
4571
+ this.xa = numValues;
4593
4572
  }
4594
- if (this.ya < this.u.length) {
4595
- this.u = this.u.subarray(0, this.ya);
4573
+ if (this.xa < this.u.length) {
4574
+ this.u = this.u.subarray(0, this.xa);
4596
4575
  }
4597
4576
  return true;
4598
4577
  }
@@ -4603,30 +4582,30 @@ var kInvalidCornerIndex6 = -1;
4603
4582
  var MeshEdgebreakerDecoderImpl = class {
4604
4583
  l;
4605
4584
  a = null;
4606
- K = [];
4607
- ga = new Uint8Array(0);
4608
- V = 0;
4609
- gb = new MeshAttributeIndicesEncodingData();
4610
- Lb = -1;
4585
+ N = [];
4586
+ fa = new Uint8Array(0);
4587
+ Y = 0;
4588
+ eb = new MeshAttributeIndicesEncodingData();
4589
+ Jb = -1;
4611
4590
  // Cache of vertex-traversal results keyed by corner table, so attributes
4612
4591
  // sharing connectivity traverse once.
4613
- fc = /* @__PURE__ */ new Map();
4592
+ dc = /* @__PURE__ */ new Map();
4614
4593
  g = [];
4615
- G;
4594
+ I;
4616
4595
  // One corner per point id (decode-scoped scratch), filled by
4617
4596
  // _assignAttributeVerticesAndPoints; null when points are the base vertices.
4618
- fa = null;
4597
+ ea = null;
4619
4598
  // Corners on a boundary edge, counted by _decodeAttributeConnectivities.
4620
- Mb = 0;
4599
+ Kb = 0;
4621
4600
  constructor(decoder, TraversalDecoderClass) {
4622
4601
  this.l = decoder;
4623
- this.G = new TraversalDecoderClass();
4602
+ this.I = new TraversalDecoderClass();
4624
4603
  }
4625
4604
  getCornerTable() {
4626
4605
  return this.a;
4627
4606
  }
4628
4607
  // The attribute data set whose attributes decoder owns attId, if any.
4629
- Nb(attId) {
4608
+ Lb(attId) {
4630
4609
  for (let i = 0; i < this.g.length; ++i) {
4631
4610
  const ad = this.g[i];
4632
4611
  if (ad.decoderId < 0 || ad.decoderId >= this.l.numAttributesDecoders()) {
@@ -4642,12 +4621,12 @@ var MeshEdgebreakerDecoderImpl = class {
4642
4621
  return null;
4643
4622
  }
4644
4623
  getAttributeCornerTable(attId) {
4645
- const ad = this.Nb(attId);
4624
+ const ad = this.Lb(attId);
4646
4625
  return ad !== null && ad.isConnectivityUsed ? ad.connectivityData : null;
4647
4626
  }
4648
4627
  getAttributeEncodingData(attId) {
4649
- const ad = this.Nb(attId);
4650
- return ad !== null ? ad.encodingData : this.gb;
4628
+ const ad = this.Lb(attId);
4629
+ return ad !== null ? ad.encodingData : this.eb;
4651
4630
  }
4652
4631
  createAttributesDecoder(attDecoderId) {
4653
4632
  const buffer = this.l.buffer();
@@ -4665,10 +4644,10 @@ var MeshEdgebreakerDecoderImpl = class {
4665
4644
  }
4666
4645
  this.g[attDataId].decoderId = attDecoderId;
4667
4646
  } else {
4668
- if (this.Lb >= 0) {
4647
+ if (this.Jb >= 0) {
4669
4648
  return false;
4670
4649
  }
4671
- this.Lb = attDecoderId;
4650
+ this.Jb = attDecoderId;
4672
4651
  }
4673
4652
  const traversalMethod = buffer.decodeUint8();
4674
4653
  if (traversalMethod === void 0 || traversalMethod >= 2 /* NUM_TRAVERSAL_METHODS */) {
@@ -4678,7 +4657,7 @@ var MeshEdgebreakerDecoderImpl = class {
4678
4657
  let cornerTable;
4679
4658
  if (decoderType === 0 /* MESH_VERTEX_ATTRIBUTE */) {
4680
4659
  if (attDataId < 0) {
4681
- encodingData = this.gb;
4660
+ encodingData = this.eb;
4682
4661
  } else {
4683
4662
  encodingData = this.g[attDataId].encodingData;
4684
4663
  this.g[attDataId].isConnectivityUsed = false;
@@ -4689,12 +4668,12 @@ var MeshEdgebreakerDecoderImpl = class {
4689
4668
  return false;
4690
4669
  }
4691
4670
  const ad = this.g[attDataId];
4692
- if (ad.noInteriorSeams) this.gc(ad);
4671
+ if (ad.noInteriorSeams) this.ec(ad);
4693
4672
  encodingData = ad.encodingData;
4694
4673
  cornerTable = ad.connectivityData;
4695
4674
  }
4696
4675
  const mesh = this.l.mesh();
4697
- const sequencer = new MeshTraversalSequencer(mesh, encodingData, this.fc, this.fa);
4676
+ const sequencer = new MeshTraversalSequencer(mesh, encodingData, this.dc, this.ea);
4698
4677
  const observer = new MeshAttributeIndicesEncodingObserver(mesh, sequencer, encodingData);
4699
4678
  const traverser = traversalMethod === 1 /* MESH_TRAVERSAL_PREDICTION_DEGREE */ ? new MaxPredictionDegreeTraverser() : new DepthFirstTraverser();
4700
4679
  traverser.init(cornerTable, observer);
@@ -4705,17 +4684,17 @@ var MeshEdgebreakerDecoderImpl = class {
4705
4684
  const buffer = this.l.buffer();
4706
4685
  const numEncodedVertices = decodeVarint(buffer);
4707
4686
  if (numEncodedVertices === void 0) return false;
4708
- this.V = numEncodedVertices;
4687
+ this.Y = numEncodedVertices;
4709
4688
  const numFaces = decodeVarint(buffer);
4710
4689
  if (numFaces === void 0) return false;
4711
4690
  if (numFaces > 2147483647 / 3) {
4712
4691
  return false;
4713
4692
  }
4714
- if (this.V > numFaces * 3) {
4693
+ if (this.Y > numFaces * 3) {
4715
4694
  return false;
4716
4695
  }
4717
4696
  const minNumFaceEdges = Math.floor(3 * numFaces / 2);
4718
- const maxNumVertexEdges = this.V * (this.V - 1) / 2;
4697
+ const maxNumVertexEdges = this.Y * (this.Y - 1) / 2;
4719
4698
  if (maxNumVertexEdges < minNumFaceEdges) {
4720
4699
  return false;
4721
4700
  }
@@ -4742,29 +4721,31 @@ var MeshEdgebreakerDecoderImpl = class {
4742
4721
  ad.numSeamCorners = 0;
4743
4722
  this.g.push(ad);
4744
4723
  }
4745
- this.a.reset(numFaces, this.V + numEncodedSplitSymbols);
4746
- this.ga = scratchUint8Filled(this.V + numEncodedSplitSymbols, 1);
4747
- if (!this.hc(buffer)) {
4724
+ this.a.reset(numFaces, this.Y + numEncodedSplitSymbols);
4725
+ this.fa = scratchUint8Filled(this.Y + numEncodedSplitSymbols, 1);
4726
+ if (!this.fc(buffer)) {
4748
4727
  return false;
4749
4728
  }
4750
- this.G.init(this);
4751
- this.G.setNumEncodedVertices(this.V + numEncodedSplitSymbols);
4752
- this.G.setNumAttributeData(numAttributeData);
4729
+ this.I.init(this);
4730
+ this.I.setNumEncodedVertices(this.Y + numEncodedSplitSymbols);
4731
+ this.I.setNumAttributeData(numAttributeData);
4753
4732
  const traversalEndBuffer = new DecoderBuffer();
4754
- if (!this.G.start(traversalEndBuffer)) {
4733
+ if (!this.I.start(traversalEndBuffer)) {
4755
4734
  return false;
4756
4735
  }
4757
- const numConnectivityVerts = this.ic(numEncodedSymbols);
4736
+ const numConnectivityVerts = this.gc(numEncodedSymbols);
4758
4737
  if (numConnectivityVerts === -1) {
4759
4738
  return false;
4760
4739
  }
4761
4740
  buffer.init(traversalEndBuffer.dataHead, traversalEndBuffer.remainingSize);
4741
+ this.a.finishBoundaries();
4762
4742
  if (this.g.length > 0) {
4763
- this.jc();
4743
+ this.hc();
4764
4744
  }
4765
- this.G.done();
4766
- const numBoundaryCorners = this.Mb;
4745
+ this.I.done();
4746
+ const numBoundaryCorners = this.Kb;
4767
4747
  const distinctTables = [];
4748
+ const seamEdgeCounts = [];
4768
4749
  const adoptions = [];
4769
4750
  let previousConnectivityData = null;
4770
4751
  let previousSeamCorners = null;
@@ -4791,25 +4772,25 @@ var MeshEdgebreakerDecoderImpl = class {
4791
4772
  adoptions.push(connectivityData, previousConnectivityData);
4792
4773
  } else {
4793
4774
  connectivityData.initEmpty(this.a);
4794
- connectivityData.reserveSeamEdges(seamCount);
4795
4775
  for (let s = 0; s < seamCount; ++s) {
4796
4776
  connectivityData.addSeamEdge(seamCorners[s]);
4797
4777
  }
4798
4778
  distinctTables.push(connectivityData);
4779
+ seamEdgeCounts.push(seamCount);
4799
4780
  }
4800
4781
  previousConnectivityData = connectivityData;
4801
4782
  previousSeamCorners = seamCorners;
4802
4783
  previousSeamCount = seamCount;
4803
4784
  }
4804
4785
  if (this.g.length === 0) {
4805
- this.kc(numConnectivityVerts);
4806
- } else if (!this.lc(distinctTables)) {
4786
+ this.ic(numConnectivityVerts);
4787
+ } else if (!this.jc(distinctTables, seamEdgeCounts)) {
4807
4788
  return false;
4808
4789
  }
4809
4790
  for (let i = 0; i < adoptions.length; i += 2) {
4810
4791
  adoptions[i].adoptFrom(adoptions[i + 1]);
4811
4792
  }
4812
- this.gb.init(this.a.numVertices());
4793
+ this.eb.init(this.a.numVertices());
4813
4794
  for (let i = 0; i < this.g.length; ++i) {
4814
4795
  let attConnectivityVerts = this.g[i].connectivityData.numVertices();
4815
4796
  if (attConnectivityVerts < this.a.numVertices()) {
@@ -4819,11 +4800,11 @@ var MeshEdgebreakerDecoderImpl = class {
4819
4800
  }
4820
4801
  return true;
4821
4802
  }
4822
- mc(encoderSymbolId, outResult) {
4823
- if (this.K.length === 0) {
4803
+ kc(encoderSymbolId, outResult) {
4804
+ if (this.N.length === 0) {
4824
4805
  return false;
4825
4806
  }
4826
- const back = this.K[this.K.length - 1];
4807
+ const back = this.N[this.N.length - 1];
4827
4808
  if (back.sourceSymbolId > encoderSymbolId) {
4828
4809
  outResult.encoderSplitSymbolId = -1;
4829
4810
  return true;
@@ -4833,24 +4814,24 @@ var MeshEdgebreakerDecoderImpl = class {
4833
4814
  }
4834
4815
  outResult.faceEdge = back.sourceEdge;
4835
4816
  outResult.encoderSplitSymbolId = back.splitSymbolId;
4836
- this.K.pop();
4817
+ this.N.pop();
4837
4818
  return true;
4838
4819
  }
4839
- ic(numSymbols) {
4840
- const activeCornerStack = scratchInt32(numSymbols + this.K.length + 16);
4820
+ gc(numSymbols) {
4821
+ const activeCornerStack = scratchInt32(numSymbols + this.N.length + 16);
4841
4822
  let activeCornerStackSize = 0;
4842
4823
  const topologySplitActiveCorners = /* @__PURE__ */ new Map();
4843
4824
  const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
4844
4825
  const invalidVertices = [];
4845
4826
  const removeInvalidVertices = this.g.length === 0;
4846
- let maxNumVertices = this.ga.length;
4827
+ let maxNumVertices = this.fa.length;
4847
4828
  let numFacesDecoded = 0;
4848
4829
  const cornerToVertex = this.a.h;
4849
- const oppositeCorners = this.a.p;
4830
+ const oppositeCorners = this.a.o;
4850
4831
  const vc = this.a;
4851
- let vertexCorners = vc.v;
4852
- const isVertHole = this.ga;
4853
- const traversalDecoder = this.G;
4832
+ let vertexCorners = vc.s;
4833
+ const isVertHole = this.fa;
4834
+ const traversalDecoder = this.I;
4854
4835
  for (let symbolId = 0; symbolId < numSymbols; ++symbolId) {
4855
4836
  const faceIndex = numFacesDecoded++;
4856
4837
  let checkTopologySplit = false;
@@ -4902,13 +4883,13 @@ var MeshEdgebreakerDecoderImpl = class {
4902
4883
  oppositeCorners[oppCorner] = cornerA;
4903
4884
  oppositeCorners[cornerA] = oppCorner;
4904
4885
  let newVertIndex;
4905
- if (vc.j < vertexCorners.length) {
4906
- newVertIndex = vc.j++;
4886
+ if (vc.i < vertexCorners.length) {
4887
+ newVertIndex = vc.i++;
4907
4888
  } else {
4908
4889
  newVertIndex = vc.addNewVertex();
4909
- vertexCorners = vc.v;
4890
+ vertexCorners = vc.s;
4910
4891
  }
4911
- if (vc.j > maxNumVertices) return -1;
4892
+ if (vc.i > maxNumVertices) return -1;
4912
4893
  cornerToVertex[oppCorner] = newVertIndex;
4913
4894
  vertexCorners[newVertIndex] = oppCorner;
4914
4895
  const pA = cornerA % 3 === 0 ? cornerA + 2 : cornerA - 1;
@@ -4969,16 +4950,16 @@ var MeshEdgebreakerDecoderImpl = class {
4969
4950
  } else if (symbol === TOPOLOGY_E) {
4970
4951
  const corner = 3 * faceIndex;
4971
4952
  let firstVertIndex;
4972
- if (vc.j + 3 <= vertexCorners.length) {
4973
- firstVertIndex = vc.j;
4974
- vc.j += 3;
4953
+ if (vc.i + 3 <= vertexCorners.length) {
4954
+ firstVertIndex = vc.i;
4955
+ vc.i += 3;
4975
4956
  } else {
4976
4957
  firstVertIndex = vc.addNewVertex();
4977
4958
  vc.addNewVertex();
4978
4959
  vc.addNewVertex();
4979
- vertexCorners = vc.v;
4960
+ vertexCorners = vc.s;
4980
4961
  }
4981
- if (vc.j > maxNumVertices) return -1;
4962
+ if (vc.i > maxNumVertices) return -1;
4982
4963
  cornerToVertex[corner] = firstVertIndex;
4983
4964
  cornerToVertex[corner + 1] = firstVertIndex + 1;
4984
4965
  cornerToVertex[corner + 2] = firstVertIndex + 2;
@@ -4991,9 +4972,9 @@ var MeshEdgebreakerDecoderImpl = class {
4991
4972
  return -1;
4992
4973
  }
4993
4974
  traversalDecoder.newActiveCornerReached(activeCornerStack[activeCornerStackSize - 1]);
4994
- if (checkTopologySplit && this.K.length > 0) {
4975
+ if (checkTopologySplit && this.N.length > 0) {
4995
4976
  const encoderSymbolId = numSymbols - symbolId - 1;
4996
- while (this.mc(encoderSymbolId, splitResult)) {
4977
+ while (this.kc(encoderSymbolId, splitResult)) {
4997
4978
  if (splitResult.encoderSplitSymbolId < 0) return -1;
4998
4979
  const actTopCorner = activeCornerStack[activeCornerStackSize - 1];
4999
4980
  let newActiveCorner;
@@ -5007,27 +4988,27 @@ var MeshEdgebreakerDecoderImpl = class {
5007
4988
  }
5008
4989
  }
5009
4990
  }
5010
- if (vc.j > maxNumVertices) {
4991
+ if (vc.i > maxNumVertices) {
5011
4992
  return -1;
5012
4993
  }
5013
- numFacesDecoded = this.nc(activeCornerStack, activeCornerStackSize, numFacesDecoded);
4994
+ numFacesDecoded = this.lc(activeCornerStack, activeCornerStackSize, numFacesDecoded);
5014
4995
  if (numFacesDecoded === -1) {
5015
4996
  return -1;
5016
4997
  }
5017
4998
  if (numFacesDecoded !== this.a.numFaces()) {
5018
4999
  return -1;
5019
5000
  }
5020
- return this.oc(invalidVertices);
5001
+ return this.mc(invalidVertices);
5021
5002
  }
5022
5003
  // Connects the remaining active-stack corners to newly decoded start faces.
5023
5004
  // Returns the updated decoded-face count, or -1 on malformed input.
5024
- nc(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
5005
+ lc(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
5025
5006
  const ct = this.a;
5026
- const oppositeCorners = ct.p;
5007
+ const oppositeCorners = ct.o;
5027
5008
  const cornerToVertex = ct.h;
5028
- const vertexCorners = ct.v;
5029
- const isVertHole = this.ga;
5030
- const traversalDecoder = this.G;
5009
+ const vertexCorners = ct.s;
5010
+ const isVertHole = this.fa;
5011
+ const traversalDecoder = this.I;
5031
5012
  const numCorners = ct.numCorners();
5032
5013
  const numFaces = ct.numFaces();
5033
5014
  const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
@@ -5075,11 +5056,11 @@ var MeshEdgebreakerDecoderImpl = class {
5075
5056
  // Removes invalid (isolated) vertices by swapping them with the last valid
5076
5057
  // vertex in the table, matching C++ mesh_edgebreaker_decoder_impl.cc (the
5077
5058
  // forward iteration order matters). Returns the final vertex count, or -1.
5078
- oc(invalidVertices) {
5059
+ mc(invalidVertices) {
5079
5060
  const ct = this.a;
5080
5061
  const cornerToVertex = ct.h;
5081
- const vertexCorners = ct.v;
5082
- const isVertHole = this.ga;
5062
+ const vertexCorners = ct.s;
5063
+ const isVertHole = this.fa;
5083
5064
  const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
5084
5065
  let numVertices = ct.numVertices();
5085
5066
  for (let ivIdx = 0; ivIdx < invalidVertices.length; ++ivIdx) {
@@ -5121,7 +5102,7 @@ var MeshEdgebreakerDecoderImpl = class {
5121
5102
  }
5122
5103
  // Hole events were removed from the bitstream in 2.1; for 2.2 this only
5123
5104
  // decodes the inline topology-split events.
5124
- hc(decoderBuffer) {
5105
+ fc(decoderBuffer) {
5125
5106
  const numTopologySplits = decodeVarint(decoderBuffer);
5126
5107
  if (numTopologySplits === void 0) return false;
5127
5108
  if (numTopologySplits > 0) {
@@ -5139,12 +5120,12 @@ var MeshEdgebreakerDecoderImpl = class {
5139
5120
  if (delta2 > eventData.sourceSymbolId) return false;
5140
5121
  eventData.splitSymbolId = eventData.sourceSymbolId - delta2;
5141
5122
  lastSourceSymbolId = eventData.sourceSymbolId;
5142
- this.K.push(eventData);
5123
+ this.N.push(eventData);
5143
5124
  }
5144
5125
  decoderBuffer.startBitDecoding(false);
5145
5126
  for (let i = 0; i < numTopologySplits; ++i) {
5146
5127
  const edgeData = decoderBuffer.decodeLeastSignificantBits32(1);
5147
- this.K[i].sourceEdge = edgeData & 1;
5128
+ this.N[i].sourceEdge = edgeData & 1;
5148
5129
  }
5149
5130
  decoderBuffer.endBitDecoding();
5150
5131
  }
@@ -5162,11 +5143,11 @@ var MeshEdgebreakerDecoderImpl = class {
5162
5143
  // the face's base corner -- is just `oppCorner >= faceBaseCorner`, since the
5163
5144
  // base corner is a multiple of 3. That removes the per-corner division; the
5164
5145
  // invalid-corner case (-1) is still handled by the branch above it.
5165
- jc() {
5146
+ hc() {
5166
5147
  const oppositeCorners = this.a.oppositeCornerArray();
5167
5148
  const attributeData = this.g;
5168
5149
  const numAttrData = attributeData.length;
5169
- const connectivityDecoders = this.G.Ob;
5150
+ const connectivityDecoders = this.I.Mb;
5170
5151
  const numCorners = this.a.numCorners();
5171
5152
  const candidates = scratchInt32(numCorners);
5172
5153
  let numCandidates = 0;
@@ -5185,42 +5166,24 @@ var MeshEdgebreakerDecoderImpl = class {
5185
5166
  numCandidates -= (opp | corner - opp - 1) >> 31;
5186
5167
  numBoundaryCorners -= opp >> 31;
5187
5168
  }
5188
- this.Mb = numBoundaryCorners;
5189
- for (let i = 0; i < numAttrData; ++i) {
5190
- const ad = attributeData[i];
5191
- const seamCorners = ad.attributeSeamCorners;
5192
- let numSeamCorners = ad.numSeamCorners;
5193
- const decoder = connectivityDecoders[i];
5194
- const ans = decoder.Va;
5195
- const p = decoder.Wa;
5196
- const buf = ans.buf;
5197
- const bufStart = ans.bufStart;
5198
- let state = ans.state;
5199
- let bufOffset = ans.bufOffset;
5200
- for (let n = 0; n < numCandidates; ++n) {
5201
- const cc = candidates[n];
5202
- if (cc < 0) {
5203
- seamCorners[numSeamCorners++] = ~cc;
5204
- continue;
5205
- }
5206
- if (state < ANS_L_BASE && bufOffset > bufStart) {
5207
- state = state << 8 | buf[--bufOffset];
5208
- }
5209
- const rem = state & 255;
5210
- const xn = (state >>> 8) * p;
5211
- const mask = rem - p >> 31;
5212
- const stateIfZero = state - xn - p;
5213
- state = stateIfZero + (mask & xn + rem - stateIfZero);
5214
- seamCorners[numSeamCorners] = cc;
5215
- numSeamCorners -= mask;
5216
- }
5217
- ans.state = state;
5218
- ans.bufOffset = bufOffset;
5219
- ad.numSeamCorners = numSeamCorners;
5169
+ this.Kb = numBoundaryCorners;
5170
+ let i = 0;
5171
+ for (; i + 2 <= numAttrData; i += 2) {
5172
+ decodeSeamBits2(
5173
+ candidates,
5174
+ numCandidates,
5175
+ attributeData[i],
5176
+ connectivityDecoders[i],
5177
+ attributeData[i + 1],
5178
+ connectivityDecoders[i + 1]
5179
+ );
5180
+ }
5181
+ if (i < numAttrData) {
5182
+ decodeSeamBits1(candidates, numCandidates, attributeData[i], connectivityDecoders[i]);
5220
5183
  }
5221
5184
  }
5222
5185
  // Position-only connectivity: vertex indices equal point indices.
5223
- kc(numConnectivityVerts) {
5186
+ ic(numConnectivityVerts) {
5224
5187
  const mesh = this.l.mesh();
5225
5188
  const ct = this.a;
5226
5189
  mesh.setNumFaces(ct.numFaces());
@@ -5230,58 +5193,48 @@ var MeshEdgebreakerDecoderImpl = class {
5230
5193
  for (let c = 0; c < numCorners; ++c) {
5231
5194
  faces[c] = baseCornerToVertex[c];
5232
5195
  }
5233
- this.fa = null;
5196
+ this.ea = null;
5234
5197
  this.l.pointCloud().setNumPoints(numConnectivityVerts);
5235
5198
  }
5236
- // Builds an attribute corner table whose only seams are boundary edges (see
5237
- // decodeConnectivity), for a per-corner decoder that asked for it. With no
5238
- // interior seam every vertex ring is one attribute vertex, numbered in
5239
- // vertex order with isolated vertices skipped -- what the ring walk in
5240
- // _assignAttributeVerticesAndPoints assigns such a table, without the walk.
5241
- gc(ad) {
5242
- const ct = this.a;
5243
- const table = ad.connectivityData;
5244
- table.initEmpty(ct);
5245
- table.reserveSeamEdges(ad.numSeamCorners);
5246
- for (let s = 0; s < ad.numSeamCorners; ++s) table.addSeamEdge(ad.attributeSeamCorners[s]);
5247
- const numVertices = ct.numVertices();
5248
- const numCorners = ct.numCorners();
5249
- const vertexLeftmost = ct.vertexLeftmostCornerArray();
5250
- const cornerToVertex = ct.cornerToVertexArray();
5251
- const vertexIds = scratchInt32(numVertices);
5252
- const leftMost = scratchInt32(numVertices);
5253
- let numAttVertices = 0;
5254
- for (let v = 0; v < numVertices; ++v) {
5255
- const c = vertexLeftmost[v];
5256
- vertexIds[v] = c === kInvalidCornerIndex6 ? -1 : numAttVertices;
5257
- if (c !== kInvalidCornerIndex6) leftMost[numAttVertices++] = c;
5258
- }
5259
- const c2v = table.Z;
5260
- for (let c = 0; c < numCorners; ++c) c2v[c] = vertexIds[cornerToVertex[c]];
5261
- table.setRecomputedVertices(leftMost, numAttVertices);
5199
+ // Sets up an attribute corner table whose only seams are boundary edges
5200
+ // (see decodeConnectivity), for a per-corner decoder that asked for it:
5201
+ // the base connectivity itself.
5202
+ ec(ad) {
5203
+ ad.connectivityData.initAsBase(this.a);
5262
5204
  ad.noInteriorSeams = false;
5263
5205
  }
5264
- // One walk around every vertex ring that (a) numbers the attribute vertices
5265
- // of every distinct attribute corner table (C++ MeshAttributeCornerTable::
5266
- // RecomputeVertices, one per table) and (b) assigns the mesh's point ids
5267
- // (C++ AssignPointsToCorners). Each of those is a per-vertex procedure that
5268
- // only reads the ring's own corners and its table's running counter, so
5269
- // running them side by side on one buffered ring produces exactly the ids
5270
- // the separate passes would -- while the ring's corner chain (a serial,
5271
- // cache-missing pointer chase through swingRight) is followed once instead
5272
- // of once per table plus once for the points. Also records one corner per
5273
- // point (_pointCorner) so point-to-value maps can be built per point rather
5274
- // than per corner (see MeshTraversalSequencer).
5206
+ // One walk around the ring of every seam vertex that (a) numbers the
5207
+ // attribute vertices of every distinct attribute corner table (C++
5208
+ // MeshAttributeCornerTable::RecomputeVertices, one per table) and (b)
5209
+ // assigns the mesh's point ids (C++ AssignPointsToCorners). Each of those
5210
+ // is a per-vertex procedure that only reads the ring's own corners and its
5211
+ // table's running counter, so running them side by side on one buffered
5212
+ // ring produces exactly the ids the separate passes would -- while the
5213
+ // ring's corner chain (a serial, cache-missing pointer chase through
5214
+ // swingRight) is followed once instead of once per table plus once for the
5215
+ // points. Also records one corner per point (_pointCorner) so
5216
+ // point-to-value maps can be built per point rather than per corner (see
5217
+ // MeshTraversalSequencer).
5218
+ //
5219
+ // A vertex on no table's seam -- interior or on a boundary -- is one
5220
+ // attribute vertex per table and one point whatever its ring holds (the
5221
+ // C++ passes swing right from its leftmost corner and never meet a split),
5222
+ // so it needs no walk at all: every table starts as a copy of the base
5223
+ // numbering (see MeshAttributeCornerTable.initEmpty), its point id is taken
5224
+ // in vertex order here, and its corners get that id in a sequential pass
5225
+ // after the loop (or none at all, when the points turn out to be the base
5226
+ // vertices). Attribute vertex ids need not be compact (only their identity
5227
+ // is ever used), so a seam vertex keeps its base id for its first
5228
+ // sub-vertex and the further sub-vertices take fresh ids past the base
5229
+ // vertex count; the ring walk only rewrites those corners.
5275
5230
  //
5276
5231
  // The buffered ring makes the swing-left prefix of the seam-vertex recompute
5277
5232
  // an index walk: swingLeft(ring[j]) is ring[j - 1] (the opposite table is
5278
- // symmetric), and for a closed ring ring[k - 1] when j is 0. An open ring
5279
- // whose leftmost corner still has a left neighbor (never the case for the
5280
- // corner table the edgebreaker decoder builds, which keeps the left-most
5281
- // corner of every boundary vertex, but allowed for by the C++ code) is
5282
- // extended leftwards first, so the walk covers exactly the corners the
5283
- // separate passes would have reached.
5284
- lc(tables) {
5233
+ // symmetric), and for a closed ring ring[k - 1] when j is 0. The C++ walks
5234
+ // start at the vertex's leftmost corner and only ever swing right from it
5235
+ // (or left through the seam-aware table, which stops at the boundary), so
5236
+ // an open ring is walked from that corner too.
5237
+ jc(tables, seamEdgeCounts) {
5285
5238
  const mesh = this.l.mesh();
5286
5239
  const ct = this.a;
5287
5240
  mesh.setNumFaces(ct.numFaces());
@@ -5290,18 +5243,23 @@ var MeshEdgebreakerDecoderImpl = class {
5290
5243
  const faces = mesh.faces_;
5291
5244
  const vertexLeftmost = ct.vertexLeftmostCornerArray();
5292
5245
  const baseOpposite = ct.oppositeCornerArray();
5293
- const isVertHole = this.ga;
5246
+ const baseCornerToVertex = ct.cornerToVertexArray();
5247
+ const isVertHole = this.fa;
5248
+ const baseOnBoundary = ct.vertexOnBoundaryArray();
5294
5249
  const numTables = tables.length;
5295
5250
  const attCornerToVertex = new Array(numTables);
5296
- const edgeOnSeam = new Array(numTables);
5251
+ const attOpposite = new Array(numTables);
5297
5252
  const vertexOnSeam = new Array(numTables);
5298
- const leftMostMaps = new Array(numTables);
5299
- const numAttVertices = new Int32Array(numTables);
5253
+ const onBoundaryMaps = new Array(numTables);
5254
+ const numExtraVertices = new Int32Array(numTables);
5300
5255
  for (let t = 0; t < numTables; ++t) {
5301
- attCornerToVertex[t] = tables[t].Z;
5302
- edgeOnSeam[t] = tables[t].Y;
5303
- vertexOnSeam[t] = tables[t].ma;
5304
- leftMostMaps[t] = scratchInt32(numCorners);
5256
+ attCornerToVertex[t] = tables[t].S;
5257
+ attOpposite[t] = tables[t].E;
5258
+ vertexOnSeam[t] = tables[t].la;
5259
+ const onBoundary = scratchUint8(numVertices + 2 * seamEdgeCounts[t]);
5260
+ onBoundary.set(baseOnBoundary);
5261
+ onBoundary.fill(1, numVertices);
5262
+ onBoundaryMaps[t] = onBoundary;
5305
5263
  }
5306
5264
  const ring = scratchInt32(numCorners);
5307
5265
  const ringNext = scratchInt32(numCorners);
@@ -5309,12 +5267,10 @@ var MeshEdgebreakerDecoderImpl = class {
5309
5267
  const idChange = scratchUint8Zeroed(numCorners);
5310
5268
  let numPoints = 0;
5311
5269
  const plainPointId = scratchInt32(numVertices);
5312
- const plainVertIds = new Array(numTables);
5313
- for (let t = 0; t < numTables; ++t) plainVertIds[t] = scratchInt32(numVertices);
5270
+ let numWalked = 0;
5314
5271
  for (let v = 0; v < numVertices; ++v) {
5315
5272
  const c = vertexLeftmost[v];
5316
5273
  if (c === kInvalidCornerIndex6) continue;
5317
- const hole = isVertHole[v] !== 0;
5318
5274
  let anySeam = false;
5319
5275
  for (let t = 0; t < numTables; ++t) {
5320
5276
  if (vertexOnSeam[t][v] !== 0) {
@@ -5322,20 +5278,14 @@ var MeshEdgebreakerDecoderImpl = class {
5322
5278
  break;
5323
5279
  }
5324
5280
  }
5325
- if (!hole && !anySeam) {
5326
- for (let t = 0; t < numTables; ++t) {
5327
- const vertId = numAttVertices[t];
5328
- leftMostMaps[t][vertId] = c;
5329
- plainVertIds[t][v] = vertId;
5330
- numAttVertices[t] = vertId + 1;
5331
- }
5281
+ if (!anySeam) {
5332
5282
  const pointId2 = numPoints++;
5333
5283
  pointCorner[pointId2] = c;
5334
5284
  plainPointId[v] = pointId2;
5335
5285
  continue;
5336
5286
  }
5337
5287
  plainPointId[v] = -1;
5338
- let start = 0;
5288
+ numWalked++;
5339
5289
  let k = 0;
5340
5290
  let actC = c;
5341
5291
  for (; ; ) {
@@ -5352,50 +5302,14 @@ var MeshEdgebreakerDecoderImpl = class {
5352
5302
  if (k === numCorners) return false;
5353
5303
  }
5354
5304
  const closed = actC === c;
5355
- if (!closed) {
5356
- const o = baseOpposite[ringNext[0]];
5357
- let left = o < 0 ? kInvalidCornerIndex6 : o % 3 === 2 ? o - 2 : o + 1;
5358
- if (left !== kInvalidCornerIndex6) {
5359
- let m = 0;
5360
- let cur = left;
5361
- while (cur !== kInvalidCornerIndex6 && cur !== c) {
5362
- if (k + ++m > numCorners) return false;
5363
- const ln = cur % 3 === 2 ? cur - 2 : cur + 1;
5364
- const lo = baseOpposite[ln];
5365
- cur = lo < 0 ? kInvalidCornerIndex6 : lo % 3 === 2 ? lo - 2 : lo + 1;
5366
- }
5367
- for (let j2 = k - 1; j2 >= 0; --j2) {
5368
- ring[j2 + m] = ring[j2];
5369
- ringNext[j2 + m] = ringNext[j2];
5370
- }
5371
- cur = left;
5372
- for (let i = 1; i <= m; ++i) {
5373
- const ln = cur % 3 === 2 ? cur - 2 : cur + 1;
5374
- ring[m - i] = cur;
5375
- ringNext[m - i] = ln;
5376
- const lo = baseOpposite[ln];
5377
- cur = lo < 0 ? kInvalidCornerIndex6 : lo % 3 === 2 ? lo - 2 : lo + 1;
5378
- }
5379
- start = m;
5380
- k += m;
5381
- }
5382
- }
5383
5305
  const end = k;
5384
5306
  for (let t = 0; t < numTables; ++t) {
5307
+ if (vertexOnSeam[t][v] === 0) continue;
5385
5308
  const c2v = attCornerToVertex[t];
5386
- const leftMostMap = leftMostMaps[t];
5387
- let vertId = numAttVertices[t];
5388
- if (vertexOnSeam[t][v] === 0) {
5389
- leftMostMap[vertId] = c;
5390
- for (let j3 = start; j3 < end; ++j3) c2v[ring[j3]] = vertId;
5391
- numAttVertices[t] = vertId + 1;
5392
- continue;
5393
- }
5394
- const isEdgeOnSeam = edgeOnSeam[t];
5395
- let j2 = start;
5309
+ const opposite = attOpposite[t];
5310
+ let j2 = 0;
5396
5311
  for (; ; ) {
5397
- const rn = ringNext[j2];
5398
- if (isEdgeOnSeam[rn] !== 0 || baseOpposite[rn] < 0) break;
5312
+ if (opposite[ringNext[j2]] < 0) break;
5399
5313
  if (j2 > 0) {
5400
5314
  --j2;
5401
5315
  } else if (closed) {
@@ -5403,39 +5317,39 @@ var MeshEdgebreakerDecoderImpl = class {
5403
5317
  } else {
5404
5318
  break;
5405
5319
  }
5406
- if (j2 === start) return false;
5320
+ if (j2 === 0) return false;
5407
5321
  }
5408
5322
  const first = ring[j2];
5409
- const firstVertId = vertId;
5410
- c2v[first] = vertId;
5411
- leftMostMap[vertId] = first;
5323
+ let vertId = v;
5324
+ onBoundaryMaps[t][v] = 1;
5325
+ let numExtra = numExtraVertices[t];
5412
5326
  const steps2 = closed ? end - 1 : end - 1 - j2;
5413
5327
  for (let s = 0; s < steps2; ++s) {
5414
5328
  if (++j2 === end) j2 = 0;
5415
5329
  const rc = ring[j2];
5416
- if (isEdgeOnSeam[ringNext[j2]] !== 0) {
5417
- leftMostMap[++vertId] = rc;
5330
+ if (opposite[ringNext[j2]] < 0) {
5331
+ vertId = numVertices + numExtra++;
5418
5332
  idChange[rc] = 1;
5419
5333
  }
5420
5334
  c2v[rc] = vertId;
5421
5335
  }
5422
- if (vertId !== firstVertId) idChange[first] = 1;
5423
- numAttVertices[t] = vertId + 1;
5336
+ if (vertId !== v) idChange[first] = 1;
5337
+ numExtraVertices[t] = numExtra;
5424
5338
  }
5425
- let j = start;
5426
- if (!hole) {
5339
+ let j = 0;
5340
+ if (isVertHole[v] === 0) {
5427
5341
  for (let t = 0; t < numTables; ++t) {
5428
5342
  if (vertexOnSeam[t][v] === 0) continue;
5429
5343
  const c2v = attCornerToVertex[t];
5430
5344
  const vertId = c2v[c];
5431
- let jj = start;
5345
+ let jj = 0;
5432
5346
  let found = false;
5433
5347
  for (; ; ) {
5434
5348
  if (++jj === end) {
5435
5349
  if (!closed) return false;
5436
5350
  jj = 0;
5437
5351
  }
5438
- if (jj === start) break;
5352
+ if (jj === 0) break;
5439
5353
  if (c2v[ring[jj]] !== vertId) {
5440
5354
  found = true;
5441
5355
  break;
@@ -5461,38 +5375,125 @@ var MeshEdgebreakerDecoderImpl = class {
5461
5375
  faces[rc] = pointId;
5462
5376
  }
5463
5377
  }
5464
- const baseCornerToVertex = ct.cornerToVertexArray();
5465
- for (let c = 0; c < numCorners; ++c) {
5466
- const v = baseCornerToVertex[c];
5467
- const pointId = plainPointId[v];
5468
- if (pointId < 0) continue;
5469
- faces[c] = pointId;
5470
- for (let t = 0; t < numTables; ++t) attCornerToVertex[t][c] = plainVertIds[t][v];
5378
+ if (numWalked === 0 && numPoints === numVertices) {
5379
+ faces.set(baseCornerToVertex);
5380
+ } else {
5381
+ for (let c = 0; c < numCorners; ++c) {
5382
+ const pointId = plainPointId[baseCornerToVertex[c]];
5383
+ if (pointId >= 0) faces[c] = pointId;
5384
+ }
5471
5385
  }
5472
5386
  for (let t = 0; t < numTables; ++t) {
5473
- tables[t].setRecomputedVertices(leftMostMaps[t], numAttVertices[t]);
5387
+ tables[t].setRecomputedVertices(onBoundaryMaps[t], numVertices + numExtraVertices[t]);
5474
5388
  }
5475
- this.fa = pointCorner;
5389
+ this.ea = pointCorner;
5476
5390
  this.l.pointCloud().setNumPoints(numPoints);
5477
5391
  return true;
5478
5392
  }
5479
5393
  };
5394
+ function decodeSeamBits1(candidates, numCandidates, ad, decoder) {
5395
+ const seamCorners = ad.attributeSeamCorners;
5396
+ let numSeamCorners = ad.numSeamCorners;
5397
+ const ans = decoder.oa;
5398
+ const p = decoder.pa;
5399
+ const buf = ans.buf;
5400
+ const bufStart = ans.bufStart;
5401
+ let state = ans.state;
5402
+ let bufOffset = ans.bufOffset;
5403
+ for (let n = 0; n < numCandidates; ++n) {
5404
+ const cc = candidates[n];
5405
+ if (cc < 0) {
5406
+ seamCorners[numSeamCorners++] = ~cc;
5407
+ continue;
5408
+ }
5409
+ if (state < ANS_L_BASE && bufOffset > bufStart) {
5410
+ state = state << 8 | buf[--bufOffset];
5411
+ }
5412
+ const rem = state & 255;
5413
+ const xn = (state >>> 8) * p;
5414
+ const mask = rem - p >> 31;
5415
+ const stateIfZero = state - xn - p;
5416
+ state = stateIfZero + (mask & xn + rem - stateIfZero);
5417
+ seamCorners[numSeamCorners] = cc;
5418
+ numSeamCorners -= mask;
5419
+ }
5420
+ ans.state = state;
5421
+ ans.bufOffset = bufOffset;
5422
+ ad.numSeamCorners = numSeamCorners;
5423
+ }
5424
+ function decodeSeamBits2(candidates, numCandidates, ad0, decoder0, ad1, decoder1) {
5425
+ const seam0 = ad0.attributeSeamCorners;
5426
+ const seam1 = ad1.attributeSeamCorners;
5427
+ let num0 = ad0.numSeamCorners;
5428
+ let num1 = ad1.numSeamCorners;
5429
+ const ans0 = decoder0.oa;
5430
+ const ans1 = decoder1.oa;
5431
+ const p0 = decoder0.pa;
5432
+ const p1 = decoder1.pa;
5433
+ const buf0 = ans0.buf;
5434
+ const buf1 = ans1.buf;
5435
+ const start0 = ans0.bufStart;
5436
+ const start1 = ans1.bufStart;
5437
+ let state0 = ans0.state;
5438
+ let state1 = ans1.state;
5439
+ let off0 = ans0.bufOffset;
5440
+ let off1 = ans1.bufOffset;
5441
+ for (let n = 0; n < numCandidates; ++n) {
5442
+ const cc = candidates[n];
5443
+ if (cc < 0) {
5444
+ seam0[num0++] = ~cc;
5445
+ seam1[num1++] = ~cc;
5446
+ continue;
5447
+ }
5448
+ if (state0 < ANS_L_BASE && off0 > start0) {
5449
+ state0 = state0 << 8 | buf0[--off0];
5450
+ }
5451
+ if (state1 < ANS_L_BASE && off1 > start1) {
5452
+ state1 = state1 << 8 | buf1[--off1];
5453
+ }
5454
+ const rem0 = state0 & 255;
5455
+ const rem1 = state1 & 255;
5456
+ const xn0 = (state0 >>> 8) * p0;
5457
+ const xn1 = (state1 >>> 8) * p1;
5458
+ const mask0 = rem0 - p0 >> 31;
5459
+ const mask1 = rem1 - p1 >> 31;
5460
+ const zero0 = state0 - xn0 - p0;
5461
+ const zero1 = state1 - xn1 - p1;
5462
+ state0 = zero0 + (mask0 & xn0 + rem0 - zero0);
5463
+ state1 = zero1 + (mask1 & xn1 + rem1 - zero1);
5464
+ seam0[num0] = cc;
5465
+ seam1[num1] = cc;
5466
+ num0 -= mask0;
5467
+ num1 -= mask1;
5468
+ }
5469
+ ans0.state = state0;
5470
+ ans0.bufOffset = off0;
5471
+ ad0.numSeamCorners = num0;
5472
+ ans1.state = state1;
5473
+ ans1.bufOffset = off1;
5474
+ ad1.numSeamCorners = num1;
5475
+ }
5480
5476
  var MeshAttributeIndicesEncodingData = class {
5481
5477
  vertexToEncodedAttributeValueIndexMap = new Int32Array(0);
5482
5478
  encodedAttributeValueIndexToCornerMap = new Int32Array(0);
5483
5479
  numValues = 0;
5480
+ // The traversal cache entry the maps came from (see MeshTraversalSequencer);
5481
+ // carries what later passes derive from the traversal and share.
5482
+ cacheEntry = null;
5484
5483
  init(numVertices) {
5485
5484
  this.vertexToEncodedAttributeValueIndexMap = scratchInt32Filled(numVertices, -1);
5486
5485
  this.encodedAttributeValueIndexToCornerMap = scratchInt32(numVertices);
5487
5486
  this.numValues = 0;
5487
+ this.cacheEntry = null;
5488
5488
  }
5489
5489
  // Adopts a traversal result from an identical corner table, avoiding a
5490
5490
  // redundant traversal. The maps depend only on connectivity and are read-only
5491
5491
  // downstream, so sharing is safe.
5492
- adoptTraversalResult(vertexToEncodedMap, encodedToCornerMap, numValues) {
5493
- this.vertexToEncodedAttributeValueIndexMap = vertexToEncodedMap;
5494
- this.encodedAttributeValueIndexToCornerMap = encodedToCornerMap;
5495
- this.numValues = numValues;
5492
+ adoptTraversalResult(entry) {
5493
+ this.vertexToEncodedAttributeValueIndexMap = entry.vertexMap;
5494
+ this.encodedAttributeValueIndexToCornerMap = entry.cornerMap;
5495
+ this.numValues = entry.numValues;
5496
+ this.cacheEntry = entry;
5496
5497
  }
5497
5498
  };
5498
5499
  var AttributeData = class {
@@ -5507,31 +5508,36 @@ var AttributeData = class {
5507
5508
  noInteriorSeams = false;
5508
5509
  };
5509
5510
  var CornerTable = class {
5510
- Pb = 0;
5511
- F = 0;
5512
- j = 0;
5511
+ Nb = 0;
5512
+ H = 0;
5513
+ i = 0;
5513
5514
  h = null;
5514
5515
  // corner -> vertex
5515
- p = null;
5516
+ o = null;
5516
5517
  // corner -> opposite corner
5517
- v = null;
5518
+ s = null;
5518
5519
  // vertex -> left-most corner
5520
+ // vertex -> 1 when its fan is open (C++ IsOnBoundary: the edge left of
5521
+ // the left-most corner has no opposite face), computed once after the
5522
+ // connectivity decode (see finishBoundaries) for the traversals, whose
5523
+ // critical path would otherwise chase two dependent loads per new vertex.
5524
+ y = null;
5519
5525
  reset(numFaces, numVertices) {
5520
- this.Pb = numFaces;
5521
- this.F = numFaces * 3;
5522
- this.j = 0;
5523
- this.h = scratchInt32Filled(this.F, -1);
5524
- this.p = scratchInt32Filled(this.F, -1);
5525
- this.v = scratchInt32Filled(numVertices, -1);
5526
+ this.Nb = numFaces;
5527
+ this.H = numFaces * 3;
5528
+ this.i = 0;
5529
+ this.h = scratchInt32Filled(this.H, -1);
5530
+ this.o = scratchInt32Filled(this.H, -1);
5531
+ this.s = scratchInt32Filled(numVertices, -1);
5526
5532
  }
5527
5533
  numFaces() {
5528
- return this.Pb;
5534
+ return this.Nb;
5529
5535
  }
5530
5536
  numCorners() {
5531
- return this.F;
5537
+ return this.H;
5532
5538
  }
5533
5539
  numVertices() {
5534
- return this.j;
5540
+ return this.i;
5535
5541
  }
5536
5542
  next(corner) {
5537
5543
  if (corner < 0) return -1;
@@ -5544,34 +5550,50 @@ var CornerTable = class {
5544
5550
  return rem === 0 ? corner + 2 : corner - 1;
5545
5551
  }
5546
5552
  vertex(corner) {
5547
- if (corner < 0 || corner >= this.F) return -1;
5553
+ if (corner < 0 || corner >= this.H) return -1;
5548
5554
  return this.h[corner];
5549
5555
  }
5550
5556
  opposite(corner) {
5551
- if (corner < 0 || corner >= this.F) return -1;
5552
- return this.p[corner];
5557
+ if (corner < 0 || corner >= this.H) return -1;
5558
+ return this.o[corner];
5553
5559
  }
5554
5560
  // Flat-array accessors; let callers avoid polymorphic per-corner dispatch.
5555
5561
  cornerToVertexArray() {
5556
5562
  return this.h;
5557
5563
  }
5558
5564
  oppositeCornerArray() {
5559
- return this.p;
5565
+ return this.o;
5560
5566
  }
5561
5567
  vertexLeftmostCornerArray() {
5562
- return this.v;
5568
+ return this.s;
5569
+ }
5570
+ vertexOnBoundaryArray() {
5571
+ return this.y;
5572
+ }
5573
+ // Derives _vertexOnBoundary from the finished connectivity (decode-scoped
5574
+ // scratch). Isolated vertices count as boundary; they are never traversed.
5575
+ finishBoundaries() {
5576
+ const numVertices = this.i;
5577
+ const vertexCorners = this.s;
5578
+ const oppositeCorners = this.o;
5579
+ const onBoundary = scratchUint8(numVertices);
5580
+ for (let v = 0; v < numVertices; ++v) {
5581
+ const lc = vertexCorners[v];
5582
+ onBoundary[v] = lc < 0 || oppositeCorners[lc % 3 === 2 ? lc - 2 : lc + 1] < 0 ? 1 : 0;
5583
+ }
5584
+ this.y = onBoundary;
5563
5585
  }
5564
5586
  // Mirrors C++ CornerTable::AddNewVertex() (push_back(kInvalidCornerIndex)).
5565
5587
  addNewVertex() {
5566
- const newVertex = this.j;
5567
- this.j++;
5568
- if (newVertex >= this.v.length) {
5569
- const newCapacity = Math.max(newVertex + 1, this.v.length * 2, 64);
5588
+ const newVertex = this.i;
5589
+ this.i++;
5590
+ if (newVertex >= this.s.length) {
5591
+ const newCapacity = Math.max(newVertex + 1, this.s.length * 2, 64);
5570
5592
  const newArr = scratchInt32Filled(newCapacity, -1);
5571
- newArr.set(this.v);
5572
- this.v = newArr;
5593
+ newArr.set(this.s);
5594
+ this.s = newArr;
5573
5595
  }
5574
- this.v[newVertex] = -1;
5596
+ this.s[newVertex] = -1;
5575
5597
  return newVertex;
5576
5598
  }
5577
5599
  // Next corner around a vertex, CCW. SwingLeft(c) = Next(Opposite(Next(c))).
@@ -5593,14 +5615,14 @@ var CornerTable = class {
5593
5615
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalDecoder.ts
5594
5616
  var MeshEdgebreakerTraversalDecoder = class {
5595
5617
  c = new DecoderBuffer();
5596
- H = new DecoderBuffer();
5597
- hb = null;
5598
- Ob = [];
5599
- Qb = 0;
5618
+ J = new DecoderBuffer();
5619
+ fb = null;
5620
+ Mb = [];
5621
+ Ob = 0;
5600
5622
  // _symbolBuffer's bit cursor, captured once bit decoding starts: decodeSymbol
5601
5623
  // runs per decoded face and would otherwise reach it through two property
5602
5624
  // loads and a method call per read.
5603
- Rb = null;
5625
+ Pb = null;
5604
5626
  init(decoder) {
5605
5627
  const srcBuffer = decoder.l.buffer();
5606
5628
  this.c.init(srcBuffer.dataHead, srcBuffer.remainingSize);
@@ -5609,7 +5631,7 @@ var MeshEdgebreakerTraversalDecoder = class {
5609
5631
  setNumEncodedVertices(_numVertices) {
5610
5632
  }
5611
5633
  setNumAttributeData(numData) {
5612
- this.Qb = numData;
5634
+ this.Ob = numData;
5613
5635
  }
5614
5636
  // Sets outBuffer to the data encoded after the traversal section.
5615
5637
  start(outBuffer) {
@@ -5626,29 +5648,29 @@ var MeshEdgebreakerTraversalDecoder = class {
5626
5648
  return true;
5627
5649
  }
5628
5650
  decodeStartFaceConfiguration() {
5629
- return this.hb.decodeNextBit();
5651
+ return this.fb.decodeNextBit();
5630
5652
  }
5631
5653
  decodeSymbol() {
5632
- const bd = this.Rb;
5654
+ const bd = this.Pb;
5633
5655
  if (bd !== null) {
5634
- const buf = bd.Ea;
5635
- const off = bd.o;
5656
+ const buf = bd.Da;
5657
+ const off = bd.p;
5636
5658
  const byteOffset = off >> 3;
5637
- if (byteOffset + 4 < bd.ka) {
5659
+ if (byteOffset + 4 < bd.ja) {
5638
5660
  const bits = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> (off & 7) & 7;
5639
5661
  if ((bits & 1) === TOPOLOGY_C) {
5640
- bd.o = off + 1;
5662
+ bd.p = off + 1;
5641
5663
  return TOPOLOGY_C;
5642
5664
  }
5643
- bd.o = off + 3;
5665
+ bd.p = off + 3;
5644
5666
  return bits;
5645
5667
  }
5646
5668
  }
5647
- let symbol = this.H.decodeLeastSignificantBits32(1);
5669
+ let symbol = this.J.decodeLeastSignificantBits32(1);
5648
5670
  if (symbol === TOPOLOGY_C) {
5649
5671
  return symbol;
5650
5672
  }
5651
- const symbolSuffix = this.H.decodeLeastSignificantBits32(2);
5673
+ const symbolSuffix = this.J.decodeLeastSignificantBits32(2);
5652
5674
  symbol |= symbolSuffix << 1;
5653
5675
  return symbol;
5654
5676
  }
@@ -5657,18 +5679,18 @@ var MeshEdgebreakerTraversalDecoder = class {
5657
5679
  mergeVertices(_dest, _source) {
5658
5680
  }
5659
5681
  done() {
5660
- if (this.H.bitDecoderActive) {
5661
- this.H.endBitDecoding();
5682
+ if (this.J.bitDecoderActive) {
5683
+ this.J.endBitDecoding();
5662
5684
  }
5663
5685
  }
5664
5686
  decodeTraversalSymbols() {
5665
- this.H.init(this.c.dataHead, this.c.remainingSize);
5666
- const traversalSize = this.H.startBitDecoding(true);
5687
+ this.J.init(this.c.dataHead, this.c.remainingSize);
5688
+ const traversalSize = this.J.startBitDecoding(true);
5667
5689
  if (traversalSize === void 0) {
5668
5690
  return false;
5669
5691
  }
5670
- this.Rb = this.H.la;
5671
- this.c.init(this.H.dataHead, this.H.remainingSize);
5692
+ this.Pb = this.J.ka;
5693
+ this.c.init(this.J.dataHead, this.J.remainingSize);
5672
5694
  if (traversalSize > this.c.remainingSize) {
5673
5695
  return false;
5674
5696
  }
@@ -5677,19 +5699,19 @@ var MeshEdgebreakerTraversalDecoder = class {
5677
5699
  }
5678
5700
  decodeStartFaces() {
5679
5701
  try {
5680
- this.hb = new RAnsBitDecoder();
5681
- return this.hb.startDecoding(this.c);
5702
+ this.fb = new RAnsBitDecoder();
5703
+ return this.fb.startDecoding(this.c);
5682
5704
  } catch {
5683
5705
  return false;
5684
5706
  }
5685
5707
  }
5686
5708
  decodeAttributeSeams() {
5687
- for (let i = 0; i < this.Qb; ++i) {
5709
+ for (let i = 0; i < this.Ob; ++i) {
5688
5710
  const decoder = new RAnsBitDecoder();
5689
5711
  if (!decoder.startDecoding(this.c)) {
5690
5712
  return false;
5691
5713
  }
5692
- this.Ob.push(decoder);
5714
+ this.Mb.push(decoder);
5693
5715
  }
5694
5716
  return true;
5695
5717
  }
@@ -5698,17 +5720,17 @@ var MeshEdgebreakerTraversalDecoder = class {
5698
5720
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalPredictiveDecoder.ts
5699
5721
  var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTraversalDecoder {
5700
5722
  a = null;
5701
- j = 0;
5723
+ i = 0;
5702
5724
  x = -1;
5703
- ha = -1;
5704
- i = [];
5705
- ib = null;
5725
+ ga = -1;
5726
+ j = [];
5727
+ gb = null;
5706
5728
  init(decoder) {
5707
5729
  super.init(decoder);
5708
5730
  this.a = decoder.getCornerTable();
5709
5731
  }
5710
5732
  setNumEncodedVertices(numVertices) {
5711
- this.j = numVertices;
5733
+ this.i = numVertices;
5712
5734
  }
5713
5735
  start(outBuffer) {
5714
5736
  if (!super.start(outBuffer)) {
@@ -5718,18 +5740,18 @@ var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTra
5718
5740
  if (numSplitSymbols === void 0 || numSplitSymbols < 0) {
5719
5741
  return false;
5720
5742
  }
5721
- if (numSplitSymbols >= this.j) {
5743
+ if (numSplitSymbols >= this.i) {
5722
5744
  return false;
5723
5745
  }
5724
- this.i = new Array(this.j).fill(0);
5725
- this.ib = new RAnsBitDecoder();
5726
- return this.ib.startDecoding(outBuffer);
5746
+ this.j = new Array(this.i).fill(0);
5747
+ this.gb = new RAnsBitDecoder();
5748
+ return this.gb.startDecoding(outBuffer);
5727
5749
  }
5728
5750
  decodeSymbol() {
5729
- if (this.ha !== -1) {
5730
- if (this.ib.decodeNextBit()) {
5731
- this.x = this.ha;
5732
- return this.ha;
5751
+ if (this.ga !== -1) {
5752
+ if (this.gb.decodeNextBit()) {
5753
+ this.x = this.ga;
5754
+ return this.ga;
5733
5755
  }
5734
5756
  }
5735
5757
  this.x = super.decodeSymbol();
@@ -5742,55 +5764,55 @@ var MeshEdgebreakerTraversalPredictiveDecoder = class extends MeshEdgebreakerTra
5742
5764
  switch (this.x) {
5743
5765
  case TOPOLOGY_C:
5744
5766
  case TOPOLOGY_S:
5745
- this.i[ct.vertex(next)] += 1;
5746
- this.i[ct.vertex(prev)] += 1;
5767
+ this.j[ct.vertex(next)] += 1;
5768
+ this.j[ct.vertex(prev)] += 1;
5747
5769
  break;
5748
5770
  case TOPOLOGY_R:
5749
- this.i[ct.vertex(corner)] += 1;
5750
- this.i[ct.vertex(next)] += 1;
5751
- this.i[ct.vertex(prev)] += 2;
5771
+ this.j[ct.vertex(corner)] += 1;
5772
+ this.j[ct.vertex(next)] += 1;
5773
+ this.j[ct.vertex(prev)] += 2;
5752
5774
  break;
5753
5775
  case TOPOLOGY_L:
5754
- this.i[ct.vertex(corner)] += 1;
5755
- this.i[ct.vertex(next)] += 2;
5756
- this.i[ct.vertex(prev)] += 1;
5776
+ this.j[ct.vertex(corner)] += 1;
5777
+ this.j[ct.vertex(next)] += 2;
5778
+ this.j[ct.vertex(prev)] += 1;
5757
5779
  break;
5758
5780
  case TOPOLOGY_E:
5759
- this.i[ct.vertex(corner)] += 2;
5760
- this.i[ct.vertex(next)] += 2;
5761
- this.i[ct.vertex(prev)] += 2;
5781
+ this.j[ct.vertex(corner)] += 2;
5782
+ this.j[ct.vertex(next)] += 2;
5783
+ this.j[ct.vertex(prev)] += 2;
5762
5784
  break;
5763
5785
  default:
5764
5786
  break;
5765
5787
  }
5766
5788
  if (this.x === TOPOLOGY_C || this.x === TOPOLOGY_R) {
5767
5789
  const pivot = ct.vertex(ct.next(corner));
5768
- if (this.i[pivot] < 6) {
5769
- this.ha = TOPOLOGY_R;
5790
+ if (this.j[pivot] < 6) {
5791
+ this.ga = TOPOLOGY_R;
5770
5792
  } else {
5771
- this.ha = TOPOLOGY_C;
5793
+ this.ga = TOPOLOGY_C;
5772
5794
  }
5773
5795
  } else {
5774
- this.ha = -1;
5796
+ this.ga = -1;
5775
5797
  }
5776
5798
  }
5777
5799
  mergeVertices(dest, source) {
5778
- this.i[dest] += this.i[source];
5800
+ this.j[dest] += this.j[source];
5779
5801
  }
5780
5802
  };
5781
5803
 
5782
5804
  // src/decoder/compression/mesh/MeshEdgebreakerTraversalValenceDecoder.ts
5783
5805
  var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraversalDecoder {
5784
5806
  a = null;
5785
- j = 0;
5807
+ i = 0;
5786
5808
  x = -1;
5787
- Na = -1;
5788
- Oa = 2;
5789
- jb = 7;
5790
- i = new Int32Array(0);
5791
- ia = [];
5809
+ Ma = -1;
5810
+ Na = 2;
5811
+ hb = 7;
5812
+ j = new Int32Array(0);
5813
+ ha = [];
5792
5814
  // Int32Array, not number[]: read and written once per decoded symbol.
5793
- za = new Int32Array(0);
5815
+ ya = new Int32Array(0);
5794
5816
  // corner -> vertex of _cornerTable, cached at init(); the array is created
5795
5817
  // once by CornerTable.reset() before the traversal decoder is initialized and
5796
5818
  // never replaced, so the per-symbol hot path can read it without two property
@@ -5802,7 +5824,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5802
5824
  this.h = this.a.h;
5803
5825
  }
5804
5826
  setNumEncodedVertices(numVertices) {
5805
- this.j = numVertices;
5827
+ this.i = numVertices;
5806
5828
  }
5807
5829
  start(outBuffer) {
5808
5830
  if (!this.decodeStartFaces()) {
@@ -5812,11 +5834,12 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5812
5834
  return false;
5813
5835
  }
5814
5836
  outBuffer.init(this.c.dataHead, this.c.remainingSize);
5815
- this.i = scratchInt32Filled(this.j, 0);
5816
- const numUniqueValences = this.jb - this.Oa + 1;
5817
- this.ia = new Array(numUniqueValences);
5818
- this.za = new Int32Array(numUniqueValences);
5837
+ this.j = scratchInt32Filled(this.i, 0);
5838
+ const numUniqueValences = this.hb - this.Na + 1;
5839
+ this.ha = new Array(numUniqueValences);
5840
+ this.ya = new Int32Array(numUniqueValences);
5819
5841
  const pending = [];
5842
+ const streams = [];
5820
5843
  for (let i = 0; i < numUniqueValences; ++i) {
5821
5844
  const numSymbols = decodeVarint(outBuffer);
5822
5845
  if (numSymbols === void 0) {
@@ -5826,13 +5849,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5826
5849
  return false;
5827
5850
  }
5828
5851
  if (numSymbols > 0) {
5829
- this.ia[i] = scratchUint32(numSymbols);
5852
+ this.ha[i] = scratchUint32(numSymbols);
5830
5853
  const scheme = outBuffer.decodeUint8();
5831
5854
  if (scheme === 0 /* SYMBOL_CODING_TAGGED */) {
5832
- if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this.ia[i])) {
5855
+ if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this.ha[i])) {
5833
5856
  return false;
5834
5857
  }
5835
- this.za[i] = numSymbols;
5858
+ this.ya[i] = numSymbols;
5836
5859
  continue;
5837
5860
  }
5838
5861
  if (scheme !== 1 /* SYMBOL_CODING_RAW */) {
@@ -5852,56 +5875,25 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5852
5875
  if (!decoder.startDecoding(outBuffer)) {
5853
5876
  return false;
5854
5877
  }
5855
- pending.push({ decoder, out: this.ia[i], count: numSymbols });
5856
- this.za[i] = numSymbols;
5878
+ pending.push(decoder);
5879
+ streams.push({ ans: decoder.G, out: this.ha[i], count: numSymbols });
5880
+ this.ya[i] = numSymbols;
5857
5881
  } else {
5858
- this.ia[i] = new Uint32Array(0);
5859
- this.za[i] = 0;
5860
- }
5861
- }
5862
- const lockstep = pending.filter((entry) => !entry.decoder.m.coarse);
5863
- let p = 0;
5864
- while (lockstep.length - p >= 3) {
5865
- const a = lockstep[p];
5866
- const b = lockstep[p + 1];
5867
- const c = lockstep[p + 2];
5868
- ransDecodeSymbolsTrioU16(
5869
- a.decoder.m,
5870
- a.out,
5871
- a.count,
5872
- b.decoder.m,
5873
- b.out,
5874
- b.count,
5875
- c.decoder.m,
5876
- c.out,
5877
- c.count
5878
- );
5879
- p += 3;
5880
- }
5881
- if (lockstep.length - p === 2) {
5882
- const a = lockstep[p];
5883
- const b = lockstep[p + 1];
5884
- ransDecodeSymbolsPairU16(a.decoder.m, a.out, a.count, b.decoder.m, b.out, b.count);
5885
- p += 2;
5886
- }
5887
- for (; p < lockstep.length; ++p) {
5888
- lockstep[p].decoder.m.decodeSymbols(lockstep[p].out, lockstep[p].count);
5889
- }
5890
- for (const entry of pending) {
5891
- if (entry.decoder.m.coarse) {
5892
- entry.decoder.m.decodeSymbols(entry.out, entry.count);
5882
+ this.ha[i] = new Uint32Array(0);
5883
+ this.ya[i] = 0;
5893
5884
  }
5894
- entry.decoder.endDecoding();
5895
5885
  }
5886
+ ransDecodeStreams(streams);
5887
+ for (const decoder of pending) decoder.endDecoding();
5896
5888
  return true;
5897
5889
  }
5898
5890
  decodeSymbol() {
5899
- if (this.Na !== -1) {
5900
- const contextCounter = --this.za[this.Na];
5891
+ if (this.Ma !== -1) {
5892
+ const contextCounter = --this.ya[this.Ma];
5901
5893
  if (contextCounter < 0) {
5902
5894
  return TOPOLOGY_INVALID;
5903
5895
  }
5904
- const symbolId = this.ia[this.Na][contextCounter];
5896
+ const symbolId = this.ha[this.Ma][contextCounter];
5905
5897
  if (symbolId > 4) {
5906
5898
  return TOPOLOGY_INVALID;
5907
5899
  }
@@ -5913,7 +5905,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5913
5905
  }
5914
5906
  newActiveCornerReached(corner) {
5915
5907
  const cornerToVertex = this.h;
5916
- const valences = this.i;
5908
+ const valences = this.j;
5917
5909
  const next = corner % 3 === 2 ? corner - 2 : corner + 1;
5918
5910
  const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
5919
5911
  const vertNext = cornerToVertex[next];
@@ -5944,32 +5936,32 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
5944
5936
  }
5945
5937
  const activeValence = valences[vertNext];
5946
5938
  let clampedValence;
5947
- if (activeValence < this.Oa) {
5948
- clampedValence = this.Oa;
5949
- } else if (activeValence > this.jb) {
5950
- clampedValence = this.jb;
5939
+ if (activeValence < this.Na) {
5940
+ clampedValence = this.Na;
5941
+ } else if (activeValence > this.hb) {
5942
+ clampedValence = this.hb;
5951
5943
  } else {
5952
5944
  clampedValence = activeValence;
5953
5945
  }
5954
- this.Na = clampedValence - this.Oa;
5946
+ this.Ma = clampedValence - this.Na;
5955
5947
  }
5956
5948
  mergeVertices(dest, source) {
5957
- this.i[dest] += this.i[source];
5949
+ this.j[dest] += this.j[source];
5958
5950
  }
5959
5951
  };
5960
5952
 
5961
5953
  // src/decoder/compression/mesh/MeshEdgebreakerDecoder.ts
5962
5954
  var MeshEdgebreakerDecoder = class extends MeshDecoder {
5963
5955
  // Set by initializeDecoder(), which runs before anything below is reached.
5964
- ja = null;
5956
+ ia = null;
5965
5957
  getCornerTable() {
5966
- return this.ja.getCornerTable();
5958
+ return this.ia.getCornerTable();
5967
5959
  }
5968
5960
  getAttributeCornerTable(attId) {
5969
- return this.ja.getAttributeCornerTable(attId);
5961
+ return this.ia.getAttributeCornerTable(attId);
5970
5962
  }
5971
5963
  getAttributeEncodingData(attId) {
5972
- return this.ja.getAttributeEncodingData(attId);
5964
+ return this.ia.getAttributeEncodingData(attId);
5973
5965
  }
5974
5966
  initializeDecoder() {
5975
5967
  const traversalDecoderType = this.buffer().decodeUint8();
@@ -5977,30 +5969,30 @@ var MeshEdgebreakerDecoder = class extends MeshDecoder {
5977
5969
  if (TraversalDecoderClass === null) {
5978
5970
  return false;
5979
5971
  }
5980
- this.ja = new MeshEdgebreakerDecoderImpl(this, TraversalDecoderClass);
5972
+ this.ia = new MeshEdgebreakerDecoderImpl(this, TraversalDecoderClass);
5981
5973
  return true;
5982
5974
  }
5983
5975
  createAttributesDecoder(attDecoderId) {
5984
- return this.ja.createAttributesDecoder(attDecoderId);
5976
+ return this.ia.createAttributesDecoder(attDecoderId);
5985
5977
  }
5986
5978
  decodeConnectivity() {
5987
- return this.ja.decodeConnectivity();
5979
+ return this.ia.decodeConnectivity();
5988
5980
  }
5989
5981
  };
5990
5982
 
5991
5983
  // src/decoder/compression/attributes/LinearSequencer.ts
5992
5984
  var LinearSequencer = class {
5993
- Pa;
5985
+ Oa;
5994
5986
  u = new Int32Array(0);
5995
5987
  constructor(numPoints) {
5996
- this.Pa = numPoints;
5988
+ this.Oa = numPoints;
5997
5989
  }
5998
5990
  generateSequence() {
5999
- if (this.Pa < 0) {
5991
+ if (this.Oa < 0) {
6000
5992
  return false;
6001
5993
  }
6002
- const ids = new Int32Array(this.Pa);
6003
- for (let i = 0; i < this.Pa; ++i) {
5994
+ const ids = new Int32Array(this.Oa);
5995
+ for (let i = 0; i < this.Oa; ++i) {
6004
5996
  ids[i] = i;
6005
5997
  }
6006
5998
  this.u = ids;
@@ -6034,7 +6026,7 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6034
6026
  return false;
6035
6027
  }
6036
6028
  if (connectivityMethod === 0) {
6037
- if (!this.pc(numFaces)) {
6029
+ if (!this.nc(numFaces)) {
6038
6030
  return false;
6039
6031
  }
6040
6032
  } else {
@@ -6073,7 +6065,7 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6073
6065
  new SequentialAttributeDecodersController(new LinearSequencer(this.pointCloud().numPoints()))
6074
6066
  );
6075
6067
  }
6076
- pc(numFaces) {
6068
+ nc(numFaces) {
6077
6069
  const numIndices = numFaces * 3;
6078
6070
  const indicesBuffer = new Uint32Array(numIndices);
6079
6071
  if (!decodeSymbols(numIndices, 1, this.buffer(), indicesBuffer)) {