minidraco 0.1.1 → 0.3.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
@@ -1,281 +1,155 @@
1
- // src/decoder/core/Macros.ts
2
- function bitstreamVersion(major, minor) {
3
- return (major & 255) << 8 | minor & 255;
1
+ // src/decoder/core/DracoTypes.ts
2
+ var DataType = {
3
+ INVALID: 0,
4
+ INT8: 1,
5
+ UINT8: 2,
6
+ INT16: 3,
7
+ UINT16: 4,
8
+ INT32: 5,
9
+ UINT32: 6,
10
+ INT64: 7,
11
+ UINT64: 8,
12
+ FLOAT32: 9,
13
+ FLOAT64: 10,
14
+ BOOL: 11,
15
+ TYPES_COUNT: 12
16
+ };
17
+ function dataTypeLength(dt) {
18
+ switch (dt) {
19
+ case DataType.INT8:
20
+ case DataType.UINT8:
21
+ return 1;
22
+ case DataType.INT16:
23
+ case DataType.UINT16:
24
+ return 2;
25
+ case DataType.INT32:
26
+ case DataType.UINT32:
27
+ return 4;
28
+ case DataType.INT64:
29
+ case DataType.UINT64:
30
+ return 8;
31
+ case DataType.FLOAT32:
32
+ return 4;
33
+ case DataType.FLOAT64:
34
+ return 8;
35
+ case DataType.BOOL:
36
+ return 1;
37
+ default:
38
+ return -1;
39
+ }
4
40
  }
5
41
 
6
- // src/decoder/core/BitUtils.ts
7
- function convertSymbolsToSignedInts(input, count, output) {
8
- for (let i = 0; i < count; i++) {
9
- const val = input[i];
10
- output[i] = val >>> 1 ^ -(val & 1);
42
+ // src/decoder/attributes/GeometryAttribute.ts
43
+ var Type = {
44
+ INVALID: -1,
45
+ POSITION: 0,
46
+ NORMAL: 1,
47
+ COLOR: 2,
48
+ TEX_COORD: 3,
49
+ GENERIC: 4,
50
+ NAMED_ATTRIBUTES_COUNT: 5
51
+ };
52
+ var GeometryAttribute = class {
53
+ _buffer;
54
+ _numComponents;
55
+ _dataType;
56
+ _normalized;
57
+ _byteStride;
58
+ _byteOffset;
59
+ _attributeType;
60
+ _uniqueId;
61
+ constructor() {
62
+ this._buffer = null;
63
+ this._numComponents = 1;
64
+ this._dataType = DataType.FLOAT32;
65
+ this._normalized = false;
66
+ this._byteStride = 0;
67
+ this._byteOffset = 0;
68
+ this._attributeType = Type.INVALID;
69
+ this._uniqueId = 0;
11
70
  }
12
- }
13
- function convertSymbolToSignedInt(val) {
14
- const isPositive = (val & 1) === 0;
15
- val >>>= 1;
16
- if (isPositive) {
17
- return val;
71
+ init(attributeType, buffer, numComponents, dataType, normalized, byteStride, byteOffset) {
72
+ this._buffer = buffer;
73
+ this._numComponents = numComponents;
74
+ this._dataType = dataType;
75
+ this._normalized = normalized;
76
+ this._byteStride = byteStride;
77
+ this._byteOffset = byteOffset;
78
+ this._attributeType = attributeType;
18
79
  }
19
- return -val - 1;
20
- }
21
-
22
- // src/decoder/core/VarintDecoding.ts
23
- function decodeVarintUnsigned(buffer, maxBytes) {
24
- let result = 0;
25
- for (let i = 0; i < maxBytes; i++) {
26
- const byte = buffer.decodeUint8();
27
- if (byte === void 0) return void 0;
28
- if (byte & 128) {
29
- const bytes = [byte & 127];
30
- let done = false;
31
- for (let j = i + 1; j < maxBytes; j++) {
32
- const next = buffer.decodeUint8();
33
- if (next === void 0) return void 0;
34
- if (next & 128) {
35
- bytes.push(next & 127);
36
- } else {
37
- bytes.push(next);
38
- done = true;
39
- break;
40
- }
41
- }
42
- if (!done) return void 0;
43
- result = bytes[bytes.length - 1];
44
- for (let k = bytes.length - 2; k >= 0; k--) {
45
- result = result * 128 + bytes[k];
46
- }
47
- return result;
80
+ // Returns a Uint8Array view of the buffer starting at the attribute entry.
81
+ getAddress(attIndex) {
82
+ const bytePos = this._byteOffset + this._byteStride * attIndex;
83
+ return this._buffer.data.subarray(bytePos);
84
+ }
85
+ copyFrom(srcAtt) {
86
+ this._numComponents = srcAtt._numComponents;
87
+ this._dataType = srcAtt._dataType;
88
+ this._normalized = srcAtt._normalized;
89
+ this._byteStride = srcAtt._byteStride;
90
+ this._byteOffset = srcAtt._byteOffset;
91
+ this._attributeType = srcAtt._attributeType;
92
+ this._uniqueId = srcAtt._uniqueId;
93
+ if (srcAtt._buffer === null) {
94
+ this._buffer = null;
48
95
  } else {
49
- return byte;
96
+ if (this._buffer === null) {
97
+ return false;
98
+ }
99
+ this._buffer.update(srcAtt._buffer.data, srcAtt._buffer.dataSize);
50
100
  }
101
+ return true;
51
102
  }
52
- return void 0;
53
- }
54
- function decodeVarint(buffer, signed = false) {
55
- const maxBytes = 10;
56
- const value = decodeVarintUnsigned(buffer, maxBytes);
57
- if (value === void 0) return void 0;
58
- if (signed) {
59
- return convertSymbolToSignedInt(value);
103
+ resetBuffer(buffer, byteStride, byteOffset) {
104
+ this._buffer = buffer;
105
+ this._byteStride = byteStride;
106
+ this._byteOffset = byteOffset;
60
107
  }
61
- return value;
62
- }
63
-
64
- // src/decoder/core/DecoderBuffer.ts
65
- var BitDecoder = class {
66
- _bitBuffer;
67
- _bitOffset;
68
- _byteLength;
69
- constructor() {
70
- this._bitBuffer = null;
71
- this._bitOffset = 0;
72
- this._byteLength = 0;
108
+ get attributeType() {
109
+ return this._attributeType;
73
110
  }
74
- reset(uint8Array, byteLength) {
75
- this._bitBuffer = uint8Array;
76
- this._byteLength = byteLength;
77
- this._bitOffset = 0;
111
+ get dataType() {
112
+ return this._dataType;
78
113
  }
79
- bitsDecoded() {
80
- return this._bitOffset;
114
+ get numComponents() {
115
+ return this._numComponents;
81
116
  }
82
- getBits(nbits) {
83
- if (nbits > 32) return void 0;
84
- const buf = this._bitBuffer;
85
- let off = this._bitOffset;
86
- const byteOffset = off >> 3;
87
- const bitShift = off & 7;
88
- if (byteOffset + 4 < this._byteLength) {
89
- const val = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> 0;
90
- let result;
91
- if (nbits > 32 - bitShift) {
92
- const val2 = buf[byteOffset + 4];
93
- const low = val >>> bitShift;
94
- const high = val2 << 32 - bitShift;
95
- result = (low | high) >>> 0;
96
- } else {
97
- result = val >>> bitShift;
98
- }
99
- this._bitOffset = off + nbits;
100
- return nbits === 32 ? result : result & (1 << nbits) - 1;
101
- }
102
- let value = 0;
103
- let bitsRead = 0;
104
- let currOff = off;
105
- while (bitsRead < nbits) {
106
- const bOff = currOff >> 3;
107
- if (bOff >= this._byteLength) break;
108
- const bShift = currOff & 7;
109
- const bitsAvail = 8 - bShift;
110
- const bitsNeeded = nbits - bitsRead;
111
- const bitsToRead = bitsAvail < bitsNeeded ? bitsAvail : bitsNeeded;
112
- const mask = (1 << bitsToRead) - 1;
113
- value |= (buf[bOff] >> bShift & mask) << bitsRead;
114
- bitsRead += bitsToRead;
115
- currOff += bitsToRead;
116
- }
117
- this._bitOffset = currOff;
118
- return value;
117
+ get buffer() {
118
+ return this._buffer;
119
+ }
120
+ get byteStride() {
121
+ return this._byteStride;
122
+ }
123
+ get byteOffset() {
124
+ return this._byteOffset;
125
+ }
126
+ get uniqueId() {
127
+ return this._uniqueId;
128
+ }
129
+ set uniqueId(id) {
130
+ this._uniqueId = id;
119
131
  }
120
132
  };
121
- var DecoderBuffer = class {
122
- _data;
123
- _dataView;
124
- _dataSize;
125
- _pos;
126
- _bitDecoder;
127
- _bitMode;
128
- _bitstreamVersion;
133
+
134
+ // src/decoder/point_cloud/PointCloud.ts
135
+ var NAMED_ATTRIBUTES_COUNT = 8;
136
+ var PointCloud = class {
137
+ num_points_;
138
+ attributes_;
139
+ named_attribute_index_;
129
140
  constructor() {
130
- this._data = null;
131
- this._dataView = null;
132
- this._dataSize = 0;
133
- this._pos = 0;
134
- this._bitDecoder = new BitDecoder();
135
- this._bitMode = false;
136
- this._bitstreamVersion = 0;
137
- }
138
- init(data, dataSize, version) {
139
- if (data instanceof ArrayBuffer) {
140
- this._data = new Uint8Array(data);
141
- } else if (data instanceof Uint8Array) {
142
- this._data = data;
143
- } else {
144
- this._data = new Uint8Array(data);
141
+ this.num_points_ = 0;
142
+ this.attributes_ = [];
143
+ this.named_attribute_index_ = [];
144
+ for (let i = 0; i < NAMED_ATTRIBUTES_COUNT; ++i) {
145
+ this.named_attribute_index_.push([]);
145
146
  }
146
- this._dataView = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);
147
- this._dataSize = dataSize !== void 0 ? dataSize : this._data.length;
148
- this._pos = 0;
149
- if (version !== void 0) {
150
- this._bitstreamVersion = version;
147
+ }
148
+ numNamedAttributes(type) {
149
+ if (type < 0 || type >= NAMED_ATTRIBUTES_COUNT) {
150
+ return 0;
151
151
  }
152
- }
153
- // Typed little-endian reads.
154
- decodeUint8() {
155
- if (this._pos + 1 > this._dataSize) return void 0;
156
- const val = this._data[this._pos];
157
- this._pos += 1;
158
- return val;
159
- }
160
- decodeInt8() {
161
- if (this._pos + 1 > this._dataSize) return void 0;
162
- const val = this._dataView.getInt8(this._pos);
163
- this._pos += 1;
164
- return val;
165
- }
166
- decodeUint16() {
167
- if (this._pos + 2 > this._dataSize) return void 0;
168
- const val = this._dataView.getUint16(this._pos, true);
169
- this._pos += 2;
170
- return val;
171
- }
172
- decodeUint32() {
173
- if (this._pos + 4 > this._dataSize) return void 0;
174
- const val = this._dataView.getUint32(this._pos, true);
175
- this._pos += 4;
176
- return val;
177
- }
178
- decodeInt32() {
179
- if (this._pos + 4 > this._dataSize) return void 0;
180
- const val = this._dataView.getInt32(this._pos, true);
181
- this._pos += 4;
182
- return val;
183
- }
184
- decodeFloat32() {
185
- if (this._pos + 4 > this._dataSize) return void 0;
186
- const val = this._dataView.getFloat32(this._pos, true);
187
- this._pos += 4;
188
- return val;
189
- }
190
- decodeUint64() {
191
- if (this._pos + 8 > this._dataSize) return void 0;
192
- const lo = this._dataView.getUint32(this._pos, true);
193
- const hi = this._dataView.getUint32(this._pos + 4, true);
194
- this._pos += 8;
195
- return hi * 4294967296 + lo;
196
- }
197
- decodeBytes(size) {
198
- if (this._pos + size > this._dataSize) return void 0;
199
- const result = this._data.slice(this._pos, this._pos + size);
200
- this._pos += size;
201
- return result;
202
- }
203
- startBitDecoding(decodeSize) {
204
- let outSize = 0;
205
- if (decodeSize) {
206
- if (this._bitstreamVersion < bitstreamVersion(2, 2)) {
207
- outSize = this.decodeUint64();
208
- if (outSize === void 0) return void 0;
209
- } else {
210
- outSize = decodeVarint(this, false);
211
- if (outSize === void 0) return void 0;
212
- }
213
- }
214
- this._bitMode = true;
215
- this._bitDecoder.reset(this._data.subarray(this._pos), this._dataSize - this._pos);
216
- return outSize;
217
- }
218
- endBitDecoding() {
219
- this._bitMode = false;
220
- const bitsDecoded = this._bitDecoder.bitsDecoded();
221
- const bytesDecoded = Math.ceil(bitsDecoded / 8);
222
- this._pos += bytesDecoded;
223
- }
224
- decodeLeastSignificantBits32(nbits) {
225
- if (!this._bitMode) return void 0;
226
- return this._bitDecoder.getBits(nbits);
227
- }
228
- decodeVarintUint32() {
229
- return decodeVarint(this, false);
230
- }
231
- decodeVarintUint64() {
232
- return decodeVarint(this, false);
233
- }
234
- advance(bytes) {
235
- this._pos += bytes;
236
- }
237
- get bitstreamVersion() {
238
- return this._bitstreamVersion;
239
- }
240
- set bitstreamVersion(v) {
241
- this._bitstreamVersion = v;
242
- }
243
- get data() {
244
- return this._data;
245
- }
246
- get dataHead() {
247
- return this._data.subarray(this._pos);
248
- }
249
- get remainingSize() {
250
- return this._dataSize - this._pos;
251
- }
252
- get decodedSize() {
253
- return this._pos;
254
- }
255
- get bitDecoderActive() {
256
- return this._bitMode;
257
- }
258
- };
259
-
260
- // src/decoder/point_cloud/PointCloud.ts
261
- var NAMED_ATTRIBUTES_COUNT = 8;
262
- var PointCloud = class {
263
- num_points_;
264
- attributes_;
265
- named_attribute_index_;
266
- constructor() {
267
- this.num_points_ = 0;
268
- this.attributes_ = [];
269
- this.named_attribute_index_ = [];
270
- for (let i = 0; i < NAMED_ATTRIBUTES_COUNT; ++i) {
271
- this.named_attribute_index_.push([]);
272
- }
273
- }
274
- numNamedAttributes(type) {
275
- if (type < 0 || type >= NAMED_ATTRIBUTES_COUNT) {
276
- return 0;
277
- }
278
- return this.named_attribute_index_[type].length;
152
+ return this.named_attribute_index_[type].length;
279
153
  }
280
154
  getNamedAttributeId(type, i) {
281
155
  if (i === void 0) i = 0;
@@ -356,25 +230,17 @@ var Mesh = class extends PointCloud {
356
230
  this.numFaces_ = 0;
357
231
  this.attribute_data_ = [];
358
232
  }
359
- _ensureFaceCapacity(numFaces) {
360
- if (this.faces_.length >= numFaces * 3) {
361
- return;
362
- }
363
- const grown = new Int32Array(numFaces * 3);
364
- grown.set(this.faces_);
365
- this.faces_ = grown;
366
- }
367
- addFace(face) {
368
- const f = this.numFaces_;
369
- this._ensureFaceCapacity(f + 1);
370
- const o = f * 3;
371
- this.faces_[o] = face[0];
372
- this.faces_[o + 1] = face[1];
373
- this.faces_[o + 2] = face[2];
374
- this.numFaces_ = f + 1;
375
- }
233
+ // Sizes faces_ to hold numFaces faces. Called once per decode, before any
234
+ // face index is written (edgebreaker: _assignPointsToCorners; sequential:
235
+ // decodeConnectivity), so the buffer is allocated exactly here — the
236
+ // decoders fill faces_ directly rather than appending face-by-face.
376
237
  setNumFaces(numFaces) {
377
- this._ensureFaceCapacity(numFaces);
238
+ const needed = numFaces * 3;
239
+ if (this.faces_.length < needed) {
240
+ const grown = new Int32Array(needed);
241
+ grown.set(this.faces_);
242
+ this.faces_ = grown;
243
+ }
378
244
  this.numFaces_ = numFaces;
379
245
  }
380
246
  numFaces() {
@@ -393,1248 +259,1401 @@ var Mesh = class extends PointCloud {
393
259
  }
394
260
  };
395
261
 
396
- // src/decoder/compression/config/CompressionShared.ts
397
- var kDracoPointCloudBitstreamVersionMajor = 2;
398
- var kDracoPointCloudBitstreamVersionMinor = 3;
399
- var kDracoMeshBitstreamVersionMajor = 2;
400
- var kDracoMeshBitstreamVersionMinor = 2;
401
- function DRACO_BITSTREAM_VERSION(major, minor) {
402
- return major << 8 | minor;
403
- }
404
- var EncodedGeometryType = {
405
- INVALID_GEOMETRY_TYPE: -1,
406
- POINT_CLOUD: 0,
407
- TRIANGULAR_MESH: 1,
408
- NUM_ENCODED_GEOMETRY_TYPES: 2
409
- };
410
- var MeshEncoderMethod = {
411
- MESH_SEQUENTIAL_ENCODING: 0,
412
- MESH_EDGEBREAKER_ENCODING: 1
413
- };
414
- var SequentialAttributeEncoderType = {
415
- SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC: 0,
416
- SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER: 1,
417
- SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION: 2,
418
- SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS: 3
419
- };
420
- var PredictionSchemeMethod = {
421
- PREDICTION_NONE: -2,
422
- PREDICTION_UNDEFINED: -1,
423
- PREDICTION_DIFFERENCE: 0,
424
- MESH_PREDICTION_PARALLELOGRAM: 1,
425
- MESH_PREDICTION_MULTI_PARALLELOGRAM: 2,
426
- MESH_PREDICTION_TEX_COORDS_DEPRECATED: 3,
427
- MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM: 4,
428
- MESH_PREDICTION_TEX_COORDS_PORTABLE: 5,
429
- MESH_PREDICTION_GEOMETRIC_NORMAL: 6,
430
- NUM_PREDICTION_SCHEMES: 7
431
- };
432
- var PredictionSchemeTransformType = {
433
- PREDICTION_TRANSFORM_NONE: -1,
434
- PREDICTION_TRANSFORM_DELTA: 0,
435
- PREDICTION_TRANSFORM_WRAP: 1,
436
- PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON: 2,
437
- PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED: 3,
438
- NUM_PREDICTION_SCHEME_TRANSFORM_TYPES: 4
439
- };
440
- var MeshTraversalMethod = {
441
- MESH_TRAVERSAL_DEPTH_FIRST: 0,
442
- MESH_TRAVERSAL_PREDICTION_DEGREE: 1,
443
- NUM_TRAVERSAL_METHODS: 2
444
- };
445
- var MeshEdgebreakerConnectivityEncodingMethod = {
446
- MESH_EDGEBREAKER_STANDARD_ENCODING: 0,
447
- MESH_EDGEBREAKER_PREDICTIVE_ENCODING: 1,
448
- // Deprecated.
449
- MESH_EDGEBREAKER_VALENCE_ENCODING: 2
450
- };
451
- var DracoHeader = class {
452
- dracoString;
453
- versionMajor;
454
- versionMinor;
455
- encoderType;
456
- encoderMethod;
457
- flags;
458
- constructor() {
459
- this.dracoString = new Int8Array(5);
460
- this.versionMajor = 0;
461
- this.versionMinor = 0;
462
- this.encoderType = 0;
463
- this.encoderMethod = 0;
464
- this.flags = 0;
465
- }
466
- };
467
- var NormalPredictionMode = {
468
- ONE_TRIANGLE: 0,
469
- // To be deprecated.
470
- TRIANGLE_AREA: 1
471
- };
472
- var SymbolCodingMethod = {
473
- SYMBOL_CODING_TAGGED: 0,
474
- SYMBOL_CODING_RAW: 1,
475
- NUM_SYMBOL_CODING_METHODS: 2
476
- };
477
- var METADATA_FLAG_MASK = 32768;
478
-
479
- // src/decoder/compression/config/DracoOptions.ts
480
- var DracoOptions = class {
481
- _globalOptions;
482
- _attributeOptions;
262
+ // src/decoder/core/DataBuffer.ts
263
+ var DataBuffer = class {
264
+ _data;
483
265
  constructor() {
484
- this._globalOptions = /* @__PURE__ */ new Map();
485
- this._attributeOptions = /* @__PURE__ */ new Map();
266
+ this._data = new Uint8Array(0);
486
267
  }
487
- getGlobalBool(name, defaultVal) {
488
- if (this._globalOptions.has(name)) {
489
- return !!this._globalOptions.get(name);
268
+ update(data, size, offset = 0) {
269
+ if (data === null || data === void 0) {
270
+ if (size + offset < 0) return false;
271
+ this._resize(size + offset);
272
+ } else {
273
+ if (size < 0) return false;
274
+ if (size + offset > this._data.length) {
275
+ this._resize(size + offset);
276
+ }
277
+ const view = data;
278
+ const src = new Uint8Array(view.buffer || data, view.byteOffset || 0, size);
279
+ this._data.set(src, offset);
490
280
  }
491
- return defaultVal;
281
+ return true;
492
282
  }
493
- findAttributeOptions(attKey) {
494
- if (this._attributeOptions.has(attKey)) {
495
- return this._attributeOptions.get(attKey);
496
- }
497
- return null;
283
+ resize(newSize) {
284
+ this._resize(newSize);
498
285
  }
499
- getAttributeBool(attKey, name, defaultVal) {
500
- const attOpts = this.findAttributeOptions(attKey);
501
- if (attOpts !== null && attOpts.has(name)) {
502
- return !!attOpts.get(name);
286
+ write(bytePos, inArray, dataSize) {
287
+ if (inArray instanceof Uint8Array) {
288
+ this._data.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
289
+ return;
503
290
  }
504
- return this.getGlobalBool(name, defaultVal);
291
+ const view = inArray;
292
+ const src = new Uint8Array(view.buffer || inArray, view.byteOffset || 0, dataSize);
293
+ this._data.set(src, bytePos);
505
294
  }
506
- };
507
-
508
- // src/decoder/compression/config/DecoderOptions.ts
509
- var DecoderOptions = class extends DracoOptions {
510
- constructor() {
511
- super();
295
+ get data() {
296
+ return this._data;
512
297
  }
513
- };
514
-
515
- // src/decoder/core/Status.ts
516
- var StatusCode = {
517
- OK: 0,
518
- DRACO_ERROR: -1,
519
- IO_ERROR: -2,
520
- INVALID_PARAMETER: -3,
521
- UNSUPPORTED_VERSION: -4,
522
- UNKNOWN_VERSION: -5,
523
- UNSUPPORTED_FEATURE: -6
524
- };
525
- var Status = class {
526
- code;
527
- errorMsg;
528
- constructor(code = StatusCode.OK, errorMsg = "") {
529
- this.code = code;
530
- this.errorMsg = errorMsg;
298
+ get dataSize() {
299
+ return this._data.length;
531
300
  }
532
- ok() {
533
- return this.code === StatusCode.OK;
301
+ _resize(newSize) {
302
+ if (newSize === this._data.length) return;
303
+ const newData = new Uint8Array(newSize);
304
+ newData.set(this._data.subarray(0, Math.min(this._data.length, newSize)));
305
+ this._data = newData;
534
306
  }
535
307
  };
536
- function okStatus() {
537
- return new Status(StatusCode.OK);
538
- }
539
308
 
540
- // src/decoder/metadata/MetadataDecoder.ts
541
- var kMaxSubmetadataLevel = 1e3;
542
- var MetadataDecoder = class {
543
- buffer_;
544
- constructor() {
545
- this.buffer_ = null;
309
+ // src/decoder/attributes/GeometryIndices.ts
310
+ var kInvalidAttributeValueIndex = 4294967295 >>> 0;
311
+
312
+ // src/decoder/attributes/PointAttribute.ts
313
+ var PointAttribute = class extends GeometryAttribute {
314
+ _identityMapping;
315
+ _numUniqueEntries;
316
+ _indicesMap;
317
+ _attributeBuffer;
318
+ _attributeTransformData;
319
+ // Lazily-created cached views over the attribute buffer.
320
+ _cachedFloat32View;
321
+ _cachedFloat32Buffer;
322
+ _cachedInt32View;
323
+ _cachedInt32Buffer;
324
+ _cachedUint32View;
325
+ _cachedUint32Buffer;
326
+ _cachedUint16View;
327
+ _cachedUint16Buffer;
328
+ _cachedInt16View;
329
+ _cachedInt16Buffer;
330
+ _cachedUint8View;
331
+ _cachedUint8Buffer;
332
+ _cachedInt8View;
333
+ _cachedInt8Buffer;
334
+ _cachedFloat64View;
335
+ _cachedFloat64Buffer;
336
+ _cachedDataView;
337
+ _cachedDVBuffer;
338
+ constructor(geometryAttribute) {
339
+ super();
340
+ this._identityMapping = false;
341
+ this._numUniqueEntries = 0;
342
+ this._indicesMap = [];
343
+ this._attributeBuffer = null;
344
+ this._attributeTransformData = null;
345
+ if (geometryAttribute instanceof GeometryAttribute) {
346
+ this._buffer = geometryAttribute._buffer;
347
+ this._numComponents = geometryAttribute._numComponents;
348
+ this._dataType = geometryAttribute._dataType;
349
+ this._normalized = geometryAttribute._normalized;
350
+ this._byteStride = geometryAttribute._byteStride;
351
+ this._byteOffset = geometryAttribute._byteOffset;
352
+ this._attributeType = geometryAttribute._attributeType;
353
+ this._uniqueId = geometryAttribute._uniqueId;
354
+ }
546
355
  }
547
- // Skips per-attribute metadata followed by the geometry-level metadata.
548
- skipGeometryMetadata(inBuffer) {
549
- this.buffer_ = inBuffer;
550
- const numAttMetadata = decodeVarint(this.buffer_);
551
- if (numAttMetadata === void 0) {
552
- return false;
356
+ // Intentionally shadows GeometryAttribute.init with a different signature (matches draco.js / C++ source).
357
+ // @ts-expect-error -- signature intentionally differs from the base class, as in the source.
358
+ init(attributeType, numComponents, dataType, normalized, numAttributeValues) {
359
+ this._attributeBuffer = new DataBuffer();
360
+ const byteStride = dataTypeLength(dataType) * numComponents;
361
+ super.init(attributeType, this._attributeBuffer, numComponents, dataType, normalized, byteStride, 0);
362
+ this.reset(numAttributeValues);
363
+ this.setIdentityMapping();
364
+ }
365
+ reset(numAttributeValues) {
366
+ if (this._attributeBuffer === null) {
367
+ this._attributeBuffer = new DataBuffer();
553
368
  }
554
- for (let i = 0; i < numAttMetadata; ++i) {
555
- if (decodeVarint(this.buffer_) === void 0) {
556
- return false;
557
- }
558
- if (!this._skipMetadata(0)) {
559
- return false;
560
- }
369
+ const entrySize = dataTypeLength(this.dataType) * this.numComponents;
370
+ this._attributeBuffer.update(null, numAttributeValues * entrySize);
371
+ this.resetBuffer(this._attributeBuffer, entrySize, 0);
372
+ this._numUniqueEntries = numAttributeValues;
373
+ return true;
374
+ }
375
+ get size() {
376
+ return this._numUniqueEntries;
377
+ }
378
+ mappedIndex(pointIndex) {
379
+ if (this._identityMapping) {
380
+ return pointIndex;
561
381
  }
562
- return this._skipMetadata(0);
382
+ return this._indicesMap[pointIndex];
563
383
  }
564
- // Discards one metadata block (key-value entries plus nested sub-metadata).
565
- // Sub-blocks read depth-first in stream order, matching the C++ stack traversal.
566
- _skipMetadata(level) {
567
- if (level > kMaxSubmetadataLevel) {
568
- return false;
384
+ get isMappingIdentity() {
385
+ return this._identityMapping;
386
+ }
387
+ get indicesMapSize() {
388
+ if (this._identityMapping) {
389
+ return 0;
569
390
  }
570
- const numEntries = decodeVarint(this.buffer_);
571
- if (numEntries === void 0) {
572
- return false;
391
+ return this._indicesMap.length;
392
+ }
393
+ // Direct access to the explicit point->value index map (Uint32Array after
394
+ // setExplicitMapping). Lets hot mapping loops write entries without a
395
+ // per-entry setPointMapEntry() dispatch.
396
+ get indicesMap() {
397
+ return this._indicesMap;
398
+ }
399
+ // Implicit mapping: point index equals attribute entry index.
400
+ setIdentityMapping() {
401
+ this._identityMapping = true;
402
+ this._indicesMap = [];
403
+ }
404
+ setExplicitMapping(numPoints) {
405
+ this._identityMapping = false;
406
+ this._indicesMap = new Uint32Array(numPoints);
407
+ this._indicesMap.fill(kInvalidAttributeValueIndex);
408
+ }
409
+ // Like setExplicitMapping but skips the invalid-index fill. Only for callers
410
+ // that provably write every entry right away (the fill was ~4% of decode
411
+ // time on primitive-heavy files). The array still starts zeroed by the
412
+ // engine, so a buggy caller reads valid-looking zeros — hence opt-in.
413
+ setExplicitMappingUnfilled(numPoints) {
414
+ this._identityMapping = false;
415
+ this._indicesMap = new Uint32Array(numPoints);
416
+ }
417
+ setAttributeTransformData(transformData) {
418
+ this._attributeTransformData = transformData;
419
+ }
420
+ // Mirrors C++ PointAttribute::ConvertValue<T>().
421
+ convertValue(attIndex, outVal) {
422
+ const bytePos = this._byteOffset + this._byteStride * attIndex;
423
+ const bufData = this._buffer.data;
424
+ const dt = this._dataType;
425
+ const nc = this._numComponents;
426
+ if (dt === DataType.FLOAT32) {
427
+ if (this._cachedFloat32View === void 0 || this._cachedFloat32Buffer !== bufData.buffer) {
428
+ this._cachedFloat32Buffer = bufData.buffer;
429
+ this._cachedFloat32View = new Float32Array(bufData.buffer);
430
+ }
431
+ const baseIndex = bufData.byteOffset + bytePos >> 2;
432
+ for (let i = 0; i < nc; ++i) {
433
+ outVal[i] = this._cachedFloat32View[baseIndex + i];
434
+ }
435
+ return;
573
436
  }
574
- for (let i = 0; i < numEntries; ++i) {
575
- if (!this._skipEntry()) {
576
- return false;
437
+ if (dt === DataType.INT32) {
438
+ if (this._cachedInt32View === void 0 || this._cachedInt32Buffer !== bufData.buffer) {
439
+ this._cachedInt32Buffer = bufData.buffer;
440
+ this._cachedInt32View = new Int32Array(bufData.buffer);
441
+ }
442
+ const baseIndex = bufData.byteOffset + bytePos >> 2;
443
+ for (let i = 0; i < nc; ++i) {
444
+ outVal[i] = this._cachedInt32View[baseIndex + i];
577
445
  }
446
+ return;
578
447
  }
579
- const numSubMetadata = decodeVarint(this.buffer_);
580
- if (numSubMetadata === void 0) {
581
- return false;
448
+ if (dt === DataType.UINT32) {
449
+ if (this._cachedUint32View === void 0 || this._cachedUint32Buffer !== bufData.buffer) {
450
+ this._cachedUint32Buffer = bufData.buffer;
451
+ this._cachedUint32View = new Uint32Array(bufData.buffer);
452
+ }
453
+ const baseIndex = bufData.byteOffset + bytePos >> 2;
454
+ for (let i = 0; i < nc; ++i) {
455
+ outVal[i] = this._cachedUint32View[baseIndex + i];
456
+ }
457
+ return;
582
458
  }
583
- if (numSubMetadata > this.buffer_.remainingSize) {
584
- return false;
459
+ if (this._cachedDataView === void 0 || this._cachedDVBuffer !== bufData.buffer) {
460
+ this._cachedDVBuffer = bufData.buffer;
461
+ this._cachedDataView = new DataView(bufData.buffer, bufData.byteOffset, bufData.byteLength);
585
462
  }
586
- for (let i = 0; i < numSubMetadata; ++i) {
587
- if (!this._skipName()) {
588
- return false;
589
- }
590
- if (!this._skipMetadata(level + 1)) {
591
- return false;
463
+ const dv = this._cachedDataView;
464
+ for (let i = 0; i < nc; ++i) {
465
+ switch (dt) {
466
+ case DataType.INT8:
467
+ outVal[i] = dv.getInt8(bytePos + i);
468
+ break;
469
+ case DataType.UINT8:
470
+ outVal[i] = dv.getUint8(bytePos + i);
471
+ break;
472
+ case DataType.INT16:
473
+ outVal[i] = dv.getInt16(bytePos + i * 2, true);
474
+ break;
475
+ case DataType.UINT16:
476
+ outVal[i] = dv.getUint16(bytePos + i * 2, true);
477
+ break;
478
+ case DataType.INT32:
479
+ outVal[i] = dv.getInt32(bytePos + i * 4, true);
480
+ break;
481
+ case DataType.UINT32:
482
+ outVal[i] = dv.getUint32(bytePos + i * 4, true);
483
+ break;
484
+ case DataType.FLOAT64:
485
+ outVal[i] = dv.getFloat64(bytePos + i * 8, true);
486
+ break;
487
+ default:
488
+ outVal[i] = 0;
489
+ break;
592
490
  }
593
491
  }
594
- return true;
595
492
  }
596
- // Skips a key-value entry: name then a length-prefixed value.
597
- _skipEntry() {
598
- if (!this._skipName()) {
599
- return false;
493
+ // Flat-array extraction of all values into one output typed array (avoids the
494
+ // per-point temp-array copy via cached typed-array views over the buffer).
495
+ extractTo(OutputTypedArray, numPoints) {
496
+ const numComponents = this._numComponents;
497
+ const array = new OutputTypedArray(numPoints * numComponents);
498
+ if (this._buffer == null || this._buffer.data == null || numPoints === 0) {
499
+ return array;
600
500
  }
601
- const dataSize = decodeVarint(this.buffer_);
602
- if (dataSize === void 0 || dataSize === 0) {
603
- return false;
501
+ const bufData = this._buffer.data;
502
+ const dt = this._dataType;
503
+ const isIdentity = this._identityMapping;
504
+ const indicesMap = this._indicesMap;
505
+ const byteStride = this._byteStride;
506
+ const byteOffset = this._byteOffset;
507
+ let srcView = null;
508
+ let shift = 0;
509
+ if (dt === DataType.FLOAT32) {
510
+ if (this._cachedFloat32View === void 0 || this._cachedFloat32Buffer !== bufData.buffer) {
511
+ this._cachedFloat32Buffer = bufData.buffer;
512
+ this._cachedFloat32View = new Float32Array(bufData.buffer);
513
+ }
514
+ srcView = this._cachedFloat32View;
515
+ shift = 2;
516
+ } else if (dt === DataType.INT32) {
517
+ if (this._cachedInt32View === void 0 || this._cachedInt32Buffer !== bufData.buffer) {
518
+ this._cachedInt32Buffer = bufData.buffer;
519
+ this._cachedInt32View = new Int32Array(bufData.buffer);
520
+ }
521
+ srcView = this._cachedInt32View;
522
+ shift = 2;
523
+ } else if (dt === DataType.UINT32) {
524
+ if (this._cachedUint32View === void 0 || this._cachedUint32Buffer !== bufData.buffer) {
525
+ this._cachedUint32Buffer = bufData.buffer;
526
+ this._cachedUint32View = new Uint32Array(bufData.buffer);
527
+ }
528
+ srcView = this._cachedUint32View;
529
+ shift = 2;
530
+ } else if (dt === DataType.UINT16) {
531
+ if (this._cachedUint16View === void 0 || this._cachedUint16Buffer !== bufData.buffer) {
532
+ this._cachedUint16Buffer = bufData.buffer;
533
+ this._cachedUint16View = new Uint16Array(bufData.buffer);
534
+ }
535
+ srcView = this._cachedUint16View;
536
+ shift = 1;
537
+ } else if (dt === DataType.INT16) {
538
+ if (this._cachedInt16View === void 0 || this._cachedInt16Buffer !== bufData.buffer) {
539
+ this._cachedInt16Buffer = bufData.buffer;
540
+ this._cachedInt16View = new Int16Array(bufData.buffer);
541
+ }
542
+ srcView = this._cachedInt16View;
543
+ shift = 1;
544
+ } else if (dt === DataType.UINT8) {
545
+ if (this._cachedUint8View === void 0 || this._cachedUint8Buffer !== bufData.buffer) {
546
+ this._cachedUint8Buffer = bufData.buffer;
547
+ this._cachedUint8View = new Uint8Array(bufData.buffer);
548
+ }
549
+ srcView = this._cachedUint8View;
550
+ shift = 0;
551
+ } else if (dt === DataType.INT8) {
552
+ if (this._cachedInt8View === void 0 || this._cachedInt8Buffer !== bufData.buffer) {
553
+ this._cachedInt8Buffer = bufData.buffer;
554
+ this._cachedInt8View = new Int8Array(bufData.buffer);
555
+ }
556
+ srcView = this._cachedInt8View;
557
+ shift = 0;
558
+ } else if (dt === DataType.FLOAT64) {
559
+ if (this._cachedFloat64View === void 0 || this._cachedFloat64Buffer !== bufData.buffer) {
560
+ this._cachedFloat64Buffer = bufData.buffer;
561
+ this._cachedFloat64View = new Float64Array(bufData.buffer);
562
+ }
563
+ srcView = this._cachedFloat64View;
564
+ shift = 3;
604
565
  }
605
- if (dataSize > this.buffer_.remainingSize) {
606
- return false;
566
+ if (srcView !== null) {
567
+ const srcStart = bufData.byteOffset + byteOffset >> shift;
568
+ const strideElements = byteStride >> shift;
569
+ if (isIdentity && strideElements === numComponents) {
570
+ const srcEnd = srcStart + numPoints * numComponents;
571
+ if (srcView.constructor === OutputTypedArray) {
572
+ array.set(srcView.subarray(srcStart, srcEnd));
573
+ return array;
574
+ }
575
+ }
576
+ if (isIdentity) {
577
+ let dst = 0;
578
+ for (let i = 0; i < numPoints; i++) {
579
+ const srcOffset = srcStart + i * strideElements;
580
+ for (let j = 0; j < numComponents; j++) {
581
+ array[dst + j] = srcView[srcOffset + j];
582
+ }
583
+ dst += numComponents;
584
+ }
585
+ } else if (numComponents === 3) {
586
+ let dst = 0;
587
+ for (let i = 0; i < numPoints; i++) {
588
+ const srcOffset = srcStart + indicesMap[i] * strideElements;
589
+ array[dst] = srcView[srcOffset];
590
+ array[dst + 1] = srcView[srcOffset + 1];
591
+ array[dst + 2] = srcView[srcOffset + 2];
592
+ dst += 3;
593
+ }
594
+ } else if (numComponents === 2) {
595
+ let dst = 0;
596
+ for (let i = 0; i < numPoints; i++) {
597
+ const srcOffset = srcStart + indicesMap[i] * strideElements;
598
+ array[dst] = srcView[srcOffset];
599
+ array[dst + 1] = srcView[srcOffset + 1];
600
+ dst += 2;
601
+ }
602
+ } else if (numComponents === 4) {
603
+ let dst = 0;
604
+ for (let i = 0; i < numPoints; i++) {
605
+ const srcOffset = srcStart + indicesMap[i] * strideElements;
606
+ array[dst] = srcView[srcOffset];
607
+ array[dst + 1] = srcView[srcOffset + 1];
608
+ array[dst + 2] = srcView[srcOffset + 2];
609
+ array[dst + 3] = srcView[srcOffset + 3];
610
+ dst += 4;
611
+ }
612
+ } else if (numComponents === 1) {
613
+ let dst = 0;
614
+ for (let i = 0; i < numPoints; i++) {
615
+ array[dst++] = srcView[srcStart + indicesMap[i] * strideElements];
616
+ }
617
+ } else {
618
+ let dst = 0;
619
+ for (let i = 0; i < numPoints; i++) {
620
+ const srcOffset = srcStart + indicesMap[i] * strideElements;
621
+ for (let j = 0; j < numComponents; j++) {
622
+ array[dst + j] = srcView[srcOffset + j];
623
+ }
624
+ dst += numComponents;
625
+ }
626
+ }
627
+ return array;
628
+ }
629
+ const temp = new Array(numComponents);
630
+ for (let i = 0; i < numPoints; i++) {
631
+ const attIndex = isIdentity ? i : indicesMap[i];
632
+ this.convertValue(attIndex, temp);
633
+ const dstOffset = i * numComponents;
634
+ for (let j = 0; j < numComponents; j++) {
635
+ array[dstOffset + j] = temp[j];
636
+ }
607
637
  }
608
- return this.buffer_.decodeBytes(dataSize) !== void 0;
638
+ return array;
609
639
  }
610
- // Skips a name (uint8 length prefix followed by that many bytes).
611
- _skipName() {
612
- const nameLen = this.buffer_.decodeUint8();
613
- if (nameLen === void 0) {
614
- return false;
640
+ // Intentionally returns void while the base class returns boolean (matches the source's shape).
641
+ // @ts-expect-error -- return type intentionally differs from the base class, as in the source.
642
+ copyFrom(srcAtt) {
643
+ if (this.buffer === null) {
644
+ this._attributeBuffer = new DataBuffer();
645
+ this.resetBuffer(this._attributeBuffer, 0, 0);
615
646
  }
616
- if (nameLen === 0) {
617
- return true;
647
+ if (!super.copyFrom(srcAtt)) {
648
+ return;
649
+ }
650
+ this._identityMapping = srcAtt._identityMapping;
651
+ this._numUniqueEntries = srcAtt._numUniqueEntries;
652
+ this._indicesMap = srcAtt._indicesMap.slice();
653
+ if (srcAtt._attributeTransformData) {
654
+ this._attributeTransformData = srcAtt._attributeTransformData;
655
+ } else {
656
+ this._attributeTransformData = null;
618
657
  }
619
- return this.buffer_.decodeBytes(nameLen) !== void 0;
620
658
  }
621
659
  };
622
660
 
623
- // src/decoder/compression/point_cloud/PointCloudDecoder.ts
624
- var PointCloudDecoder = class _PointCloudDecoder {
625
- _pointCloud;
626
- _buffer;
627
- _versionMajor;
628
- _versionMinor;
629
- _options;
630
- _attributesDecoders;
631
- _attributeToDecoderMap;
632
- constructor() {
633
- this._pointCloud = null;
634
- this._buffer = null;
635
- this._versionMajor = 0;
636
- this._versionMinor = 0;
637
- this._options = null;
638
- this._attributesDecoders = [];
639
- this._attributeToDecoderMap = [];
661
+ // src/decoder/core/Macros.ts
662
+ function bitstreamVersion(major, minor) {
663
+ return (major & 255) << 8 | minor & 255;
664
+ }
665
+
666
+ // src/decoder/core/BitUtils.ts
667
+ function convertSymbolsToSignedInts(input, count, output) {
668
+ for (let i = 0; i < count; i++) {
669
+ const val = input[i];
670
+ output[i] = val >>> 1 ^ -(val & 1);
640
671
  }
641
- getGeometryType() {
642
- return EncodedGeometryType.POINT_CLOUD;
672
+ }
673
+ function convertSymbolToSignedInt(val) {
674
+ const isPositive = (val & 1) === 0;
675
+ val >>>= 1;
676
+ if (isPositive) {
677
+ return val;
643
678
  }
644
- // Returns a Status; on success outHeader is populated.
645
- static decodeHeader(buffer, outHeader) {
646
- const kIoErrorMsg = "Failed to parse Draco header.";
647
- const bytes = buffer.decodeBytes(5);
648
- if (bytes === void 0) {
649
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
650
- }
651
- for (let i = 0; i < 5; i++) {
652
- outHeader.dracoString[i] = bytes[i];
653
- }
654
- const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
655
- if (magic !== "DRACO") {
656
- return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
657
- }
658
- const versionMajor = buffer.decodeUint8();
659
- if (versionMajor === void 0) {
660
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
661
- }
662
- outHeader.versionMajor = versionMajor;
663
- const versionMinor = buffer.decodeUint8();
664
- if (versionMinor === void 0) {
665
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
666
- }
667
- outHeader.versionMinor = versionMinor;
668
- const encoderType = buffer.decodeUint8();
669
- if (encoderType === void 0) {
670
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
671
- }
672
- outHeader.encoderType = encoderType;
673
- const encoderMethod = buffer.decodeUint8();
674
- if (encoderMethod === void 0) {
675
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
679
+ return -val - 1;
680
+ }
681
+
682
+ // src/decoder/core/VarintDecoding.ts
683
+ function decodeVarintUnsigned(buffer, maxBytes) {
684
+ let result = 0;
685
+ let multiplier = 1;
686
+ for (let i = 0; i < maxBytes; i++) {
687
+ const byte = buffer.decodeUint8();
688
+ if (byte === void 0) return void 0;
689
+ if (byte & 128) {
690
+ result += (byte & 127) * multiplier;
691
+ multiplier *= 128;
692
+ } else {
693
+ return result + byte * multiplier;
676
694
  }
677
- outHeader.encoderMethod = encoderMethod;
678
- const flags = buffer.decodeUint16();
679
- if (flags === void 0) {
680
- return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
681
- }
682
- outHeader.flags = flags;
683
- return okStatus();
684
695
  }
685
- // Main entry point for point cloud decoding.
686
- decode(options, inBuffer, outPointCloud) {
687
- this._options = options;
688
- this._buffer = inBuffer;
689
- this._pointCloud = outPointCloud;
690
- const header = new DracoHeader();
691
- const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
692
- if (!headerStatus.ok()) {
693
- return headerStatus;
694
- }
695
- if (header.encoderType !== this.getGeometryType()) {
696
- return new Status(StatusCode.DRACO_ERROR, "Using incompatible decoder for the input geometry.");
697
- }
698
- this._versionMajor = header.versionMajor;
699
- this._versionMinor = header.versionMinor;
700
- const maxSupportedMajorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor : kDracoMeshBitstreamVersionMajor;
701
- const maxSupportedMinorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor;
702
- if (this._versionMajor < 1 || this._versionMajor > maxSupportedMajorVersion) {
703
- return new Status(StatusCode.UNKNOWN_VERSION, "Unknown major version.");
704
- }
705
- if (this._versionMajor === maxSupportedMajorVersion && this._versionMinor > maxSupportedMinorVersion) {
706
- return new Status(StatusCode.UNKNOWN_VERSION, "Unknown minor version.");
707
- }
708
- this._buffer.bitstreamVersion = DRACO_BITSTREAM_VERSION(this._versionMajor, this._versionMinor);
709
- if (header.encoderType === EncodedGeometryType.TRIANGULAR_MESH && this._buffer.bitstreamVersion < DRACO_BITSTREAM_VERSION(2, 2)) {
710
- return new Status(
711
- StatusCode.UNKNOWN_VERSION,
712
- "Unsupported bitstream version (only Draco 2.2 meshes are supported)."
713
- );
714
- }
715
- if (header.flags & METADATA_FLAG_MASK) {
716
- const metadataStatus = this._decodeMetadata();
717
- if (!metadataStatus.ok()) {
718
- return metadataStatus;
696
+ return void 0;
697
+ }
698
+ function decodeVarint(buffer, signed = false) {
699
+ const maxBytes = 10;
700
+ const value = decodeVarintUnsigned(buffer, maxBytes);
701
+ if (value === void 0) return void 0;
702
+ if (signed) {
703
+ return convertSymbolToSignedInt(value);
704
+ }
705
+ return value;
706
+ }
707
+
708
+ // src/decoder/core/DecoderBuffer.ts
709
+ var BitDecoder = class {
710
+ _bitBuffer;
711
+ _bitOffset;
712
+ _byteLength;
713
+ constructor() {
714
+ this._bitBuffer = null;
715
+ this._bitOffset = 0;
716
+ this._byteLength = 0;
717
+ }
718
+ reset(uint8Array, byteLength) {
719
+ this._bitBuffer = uint8Array;
720
+ this._byteLength = byteLength;
721
+ this._bitOffset = 0;
722
+ }
723
+ bitsDecoded() {
724
+ return this._bitOffset;
725
+ }
726
+ getBits(nbits) {
727
+ if (nbits > 32) return void 0;
728
+ const buf = this._bitBuffer;
729
+ let off = this._bitOffset;
730
+ const byteOffset = off >> 3;
731
+ const bitShift = off & 7;
732
+ if (byteOffset + 4 < this._byteLength) {
733
+ const val = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> 0;
734
+ let result;
735
+ if (nbits > 32 - bitShift) {
736
+ const val2 = buf[byteOffset + 4];
737
+ const low = val >>> bitShift;
738
+ const high = val2 << 32 - bitShift;
739
+ result = (low | high) >>> 0;
740
+ } else {
741
+ result = val >>> bitShift;
719
742
  }
743
+ this._bitOffset = off + nbits;
744
+ return nbits === 32 ? result : result & (1 << nbits) - 1;
720
745
  }
721
- if (!this.initializeDecoder()) {
722
- return new Status(StatusCode.DRACO_ERROR, "Failed to initialize the decoder.");
723
- }
724
- if (!this.decodeGeometryData()) {
725
- return new Status(StatusCode.DRACO_ERROR, "Failed to decode geometry data.");
726
- }
727
- if (!this.decodePointAttributes()) {
728
- return new Status(StatusCode.DRACO_ERROR, "Failed to decode point attributes.");
746
+ let value = 0;
747
+ let bitsRead = 0;
748
+ let currOff = off;
749
+ while (bitsRead < nbits) {
750
+ const bOff = currOff >> 3;
751
+ if (bOff >= this._byteLength) return void 0;
752
+ const bShift = currOff & 7;
753
+ const bitsAvail = 8 - bShift;
754
+ const bitsNeeded = nbits - bitsRead;
755
+ const bitsToRead = bitsAvail < bitsNeeded ? bitsAvail : bitsNeeded;
756
+ const mask = (1 << bitsToRead) - 1;
757
+ value |= (buf[bOff] >> bShift & mask) << bitsRead;
758
+ bitsRead += bitsToRead;
759
+ currOff += bitsToRead;
729
760
  }
730
- return okStatus();
761
+ this._bitOffset = currOff;
762
+ return value;
731
763
  }
732
- bitstreamVersion() {
733
- return DRACO_BITSTREAM_VERSION(this._versionMajor, this._versionMinor);
764
+ };
765
+ var DecoderBuffer = class {
766
+ _data;
767
+ _dataView;
768
+ _dataSize;
769
+ _pos;
770
+ _bitDecoder;
771
+ _bitMode;
772
+ _bitstreamVersion;
773
+ constructor() {
774
+ this._data = null;
775
+ this._dataView = null;
776
+ this._dataSize = 0;
777
+ this._pos = 0;
778
+ this._bitDecoder = new BitDecoder();
779
+ this._bitMode = false;
780
+ this._bitstreamVersion = 0;
734
781
  }
735
- setAttributesDecoder(attDecoderId, decoder) {
736
- if (attDecoderId < 0) {
737
- return false;
782
+ init(data, dataSize, version) {
783
+ if (data instanceof ArrayBuffer) {
784
+ this._data = new Uint8Array(data);
785
+ } else if (data instanceof Uint8Array) {
786
+ this._data = data;
787
+ } else {
788
+ this._data = new Uint8Array(data);
738
789
  }
739
- while (this._attributesDecoders.length <= attDecoderId) {
740
- this._attributesDecoders.push(null);
790
+ this._dataView = new DataView(this._data.buffer, this._data.byteOffset, this._data.byteLength);
791
+ this._dataSize = dataSize !== void 0 ? dataSize : this._data.length;
792
+ this._pos = 0;
793
+ if (version !== void 0) {
794
+ this._bitstreamVersion = version;
741
795
  }
742
- this._attributesDecoders[attDecoderId] = decoder;
743
- return true;
744
796
  }
745
- getPortableAttribute(parentAttId) {
746
- if (parentAttId < 0 || parentAttId >= this._pointCloud.numAttributes()) {
747
- return null;
748
- }
749
- const parentAttDecoderId = this._attributeToDecoderMap[parentAttId];
750
- return this._attributesDecoders[parentAttDecoderId].getPortableAttribute(parentAttId);
797
+ // Typed little-endian reads.
798
+ decodeUint8() {
799
+ if (this._pos + 1 > this._dataSize) return void 0;
800
+ const val = this._data[this._pos];
801
+ this._pos += 1;
802
+ return val;
751
803
  }
752
- attributesDecoder(decId) {
753
- return this._attributesDecoders[decId];
804
+ decodeInt8() {
805
+ if (this._pos + 1 > this._dataSize) return void 0;
806
+ const val = this._dataView.getInt8(this._pos);
807
+ this._pos += 1;
808
+ return val;
754
809
  }
755
- numAttributesDecoders() {
756
- return this._attributesDecoders.length;
810
+ decodeUint16() {
811
+ if (this._pos + 2 > this._dataSize) return void 0;
812
+ const val = this._dataView.getUint16(this._pos, true);
813
+ this._pos += 2;
814
+ return val;
757
815
  }
758
- pointCloud() {
759
- return this._pointCloud;
816
+ decodeUint32() {
817
+ if (this._pos + 4 > this._dataSize) return void 0;
818
+ const val = this._dataView.getUint32(this._pos, true);
819
+ this._pos += 4;
820
+ return val;
760
821
  }
761
- buffer() {
762
- return this._buffer;
822
+ decodeInt32() {
823
+ if (this._pos + 4 > this._dataSize) return void 0;
824
+ const val = this._dataView.getInt32(this._pos, true);
825
+ this._pos += 4;
826
+ return val;
763
827
  }
764
- options() {
765
- return this._options;
828
+ decodeFloat32() {
829
+ if (this._pos + 4 > this._dataSize) return void 0;
830
+ const val = this._dataView.getFloat32(this._pos, true);
831
+ this._pos += 4;
832
+ return val;
766
833
  }
767
- // -- Protected virtual methods (override in subclasses) --
768
- initializeDecoder() {
769
- return true;
834
+ decodeUint64() {
835
+ if (this._pos + 8 > this._dataSize) return void 0;
836
+ const lo = this._dataView.getUint32(this._pos, true);
837
+ const hi = this._dataView.getUint32(this._pos + 4, true);
838
+ this._pos += 8;
839
+ return hi * 4294967296 + lo;
770
840
  }
771
- // Must be implemented by derived classes.
772
- createAttributesDecoder(_attDecoderId) {
773
- return false;
841
+ decodeBytes(size) {
842
+ if (this._pos + size > this._dataSize) return void 0;
843
+ const result = this._data.slice(this._pos, this._pos + size);
844
+ this._pos += size;
845
+ return result;
774
846
  }
775
- decodeGeometryData() {
776
- return true;
847
+ // Zero-copy variant of decodeBytes: a view into the stream, only valid until
848
+ // the caller's next chance to mutate the buffer — copy out before keeping it.
849
+ decodeBytesView(size) {
850
+ if (this._pos + size > this._dataSize) return void 0;
851
+ const result = this._data.subarray(this._pos, this._pos + size);
852
+ this._pos += size;
853
+ return result;
777
854
  }
778
- decodePointAttributes() {
779
- const numAttributesDecoders = this._buffer.decodeUint8();
780
- if (numAttributesDecoders === void 0) {
781
- return false;
782
- }
783
- for (let i = 0; i < numAttributesDecoders; ++i) {
784
- if (!this.createAttributesDecoder(i)) {
785
- return false;
786
- }
787
- }
788
- for (let i = 0; i < this._attributesDecoders.length; ++i) {
789
- if (!this._attributesDecoders[i].init(this, this._pointCloud)) {
790
- return false;
791
- }
792
- }
793
- for (let i = 0; i < numAttributesDecoders; ++i) {
794
- if (!this._attributesDecoders[i].decodeAttributesDecoderData(this._buffer)) {
795
- return false;
796
- }
797
- }
798
- for (let i = 0; i < numAttributesDecoders; ++i) {
799
- const numAttributes = this._attributesDecoders[i].getNumAttributes();
800
- for (let j = 0; j < numAttributes; ++j) {
801
- const attId = this._attributesDecoders[i].getAttributeId(j);
802
- while (this._attributeToDecoderMap.length <= attId) {
803
- this._attributeToDecoderMap.push(0);
804
- }
805
- this._attributeToDecoderMap[attId] = i;
855
+ startBitDecoding(decodeSize) {
856
+ let outSize = 0;
857
+ if (decodeSize) {
858
+ if (this._bitstreamVersion < bitstreamVersion(2, 2)) {
859
+ outSize = this.decodeUint64();
860
+ if (outSize === void 0) return void 0;
861
+ } else {
862
+ outSize = decodeVarint(this, false);
863
+ if (outSize === void 0) return void 0;
806
864
  }
807
865
  }
808
- if (!this.decodeAllAttributes()) {
809
- return false;
810
- }
811
- if (!this.onAttributesDecoded()) {
812
- return false;
813
- }
814
- return true;
866
+ this._bitMode = true;
867
+ this._bitDecoder.reset(this._data.subarray(this._pos), this._dataSize - this._pos);
868
+ return outSize;
815
869
  }
816
- decodeAllAttributes() {
817
- for (let i = 0; i < this._attributesDecoders.length; i++) {
818
- if (!this._attributesDecoders[i].decodeAttributes(this._buffer)) {
819
- return false;
820
- }
821
- }
822
- return true;
870
+ endBitDecoding() {
871
+ this._bitMode = false;
872
+ const bitsDecoded = this._bitDecoder.bitsDecoded();
873
+ const bytesDecoded = Math.ceil(bitsDecoded / 8);
874
+ this._pos += bytesDecoded;
823
875
  }
824
- onAttributesDecoded() {
825
- return true;
876
+ decodeLeastSignificantBits32(nbits) {
877
+ if (!this._bitMode) return void 0;
878
+ return this._bitDecoder.getBits(nbits);
826
879
  }
827
- _decodeMetadata() {
828
- const metadataDecoder = new MetadataDecoder();
829
- if (!metadataDecoder.skipGeometryMetadata(this._buffer)) {
830
- return new Status(StatusCode.DRACO_ERROR, "Failed to decode metadata.");
831
- }
832
- return okStatus();
880
+ decodeVarintUint32() {
881
+ return decodeVarint(this, false);
833
882
  }
834
- };
835
-
836
- // src/decoder/compression/mesh/MeshDecoder.ts
837
- var MeshDecoder = class extends PointCloudDecoder {
838
- _mesh;
839
- constructor() {
840
- super();
841
- this._mesh = null;
883
+ decodeVarintUint64() {
884
+ return decodeVarint(this, false);
842
885
  }
843
- getGeometryType() {
844
- return EncodedGeometryType.TRIANGULAR_MESH;
886
+ advance(bytes) {
887
+ this._pos += bytes;
845
888
  }
846
- decodeMesh(options, inBuffer, outMesh) {
847
- this._mesh = outMesh;
848
- return this.decode(options, inBuffer, outMesh);
889
+ get bitstreamVersion() {
890
+ return this._bitstreamVersion;
849
891
  }
850
- getCornerTable() {
851
- return null;
892
+ set bitstreamVersion(v) {
893
+ this._bitstreamVersion = v;
852
894
  }
853
- getAttributeCornerTable(_attId) {
854
- return null;
895
+ get data() {
896
+ return this._data;
855
897
  }
856
- getAttributeEncodingData(_attId) {
857
- return null;
898
+ get dataHead() {
899
+ return this._data.subarray(this._pos);
858
900
  }
859
- mesh() {
860
- return this._mesh;
901
+ get remainingSize() {
902
+ return this._dataSize - this._pos;
861
903
  }
862
- decodeGeometryData() {
863
- if (this._mesh === null) {
864
- return false;
865
- }
866
- if (!this.decodeConnectivity()) {
867
- return false;
868
- }
869
- return super.decodeGeometryData();
904
+ get decodedSize() {
905
+ return this._pos;
870
906
  }
871
- // Overridden by derived classes.
872
- decodeConnectivity() {
873
- return false;
907
+ get bitDecoderActive() {
908
+ return this._bitMode;
874
909
  }
875
910
  };
876
911
 
877
- // src/decoder/mesh/MeshAttributeCornerTable.ts
878
- var kInvalidCornerIndex = -1;
879
- var kInvalidVertexIndex = -1;
880
- var MeshAttributeCornerTable = class {
881
- is_edge_on_seam_;
882
- is_vertex_on_seam_;
883
- no_interior_seams_;
884
- corner_to_vertex_map_;
885
- vertex_to_left_most_corner_map_;
886
- vertex_to_attribute_entry_id_map_;
887
- corner_table_;
888
- // Lazily built; see oppositeCornerArray.
889
- _effectiveOpposite;
890
- // Every corner passed to addSeamEdge (may contain duplicates); lets
891
- // oppositeCornerArray patch seams without scanning every corner's flag.
892
- _seamCorners;
912
+ // src/decoder/core/ScratchArena.ts
913
+ var freeInt32 = [];
914
+ var freeUint8 = [];
915
+ var borrowedInt32 = [];
916
+ var borrowedUint8 = [];
917
+ var acquire = (free, borrowed, size) => {
918
+ for (let i = free.length - 1; i >= 0; --i) {
919
+ const buffer = free[i];
920
+ if (buffer.length >= size) {
921
+ free[i] = free[free.length - 1];
922
+ free.pop();
923
+ borrowed.push(buffer);
924
+ return buffer;
925
+ }
926
+ }
927
+ return null;
928
+ };
929
+ var scratchInt32 = (size) => {
930
+ const pooled = acquire(freeInt32, borrowedInt32, size);
931
+ if (pooled !== null) return pooled.subarray(0, size);
932
+ const fresh = new Int32Array(size);
933
+ borrowedInt32.push(fresh);
934
+ return fresh;
935
+ };
936
+ var scratchUint8Zeroed = (size) => {
937
+ const pooled = acquire(freeUint8, borrowedUint8, size);
938
+ if (pooled !== null) {
939
+ const view = pooled.subarray(0, size);
940
+ view.fill(0);
941
+ return view;
942
+ }
943
+ const fresh = new Uint8Array(size);
944
+ borrowedUint8.push(fresh);
945
+ return fresh;
946
+ };
947
+ var releaseScratch = () => {
948
+ for (const buffer of borrowedInt32) freeInt32.push(buffer);
949
+ for (const buffer of borrowedUint8) freeUint8.push(buffer);
950
+ borrowedInt32.length = 0;
951
+ borrowedUint8.length = 0;
952
+ };
953
+
954
+ // src/decoder/compression/config/CompressionShared.ts
955
+ var kDracoPointCloudBitstreamVersionMajor = 2;
956
+ var kDracoPointCloudBitstreamVersionMinor = 3;
957
+ var kDracoMeshBitstreamVersionMajor = 2;
958
+ var kDracoMeshBitstreamVersionMinor = 2;
959
+ function DRACO_BITSTREAM_VERSION(major, minor) {
960
+ return major << 8 | minor;
961
+ }
962
+ var EncodedGeometryType = {
963
+ INVALID_GEOMETRY_TYPE: -1,
964
+ POINT_CLOUD: 0,
965
+ TRIANGULAR_MESH: 1,
966
+ NUM_ENCODED_GEOMETRY_TYPES: 2
967
+ };
968
+ var MeshEncoderMethod = {
969
+ MESH_SEQUENTIAL_ENCODING: 0,
970
+ MESH_EDGEBREAKER_ENCODING: 1
971
+ };
972
+ var SequentialAttributeEncoderType = {
973
+ SEQUENTIAL_ATTRIBUTE_ENCODER_GENERIC: 0,
974
+ SEQUENTIAL_ATTRIBUTE_ENCODER_INTEGER: 1,
975
+ SEQUENTIAL_ATTRIBUTE_ENCODER_QUANTIZATION: 2,
976
+ SEQUENTIAL_ATTRIBUTE_ENCODER_NORMALS: 3
977
+ };
978
+ var PredictionSchemeMethod = {
979
+ PREDICTION_NONE: -2,
980
+ PREDICTION_UNDEFINED: -1,
981
+ PREDICTION_DIFFERENCE: 0,
982
+ MESH_PREDICTION_PARALLELOGRAM: 1,
983
+ MESH_PREDICTION_MULTI_PARALLELOGRAM: 2,
984
+ MESH_PREDICTION_TEX_COORDS_DEPRECATED: 3,
985
+ MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM: 4,
986
+ MESH_PREDICTION_TEX_COORDS_PORTABLE: 5,
987
+ MESH_PREDICTION_GEOMETRIC_NORMAL: 6,
988
+ NUM_PREDICTION_SCHEMES: 7
989
+ };
990
+ var PredictionSchemeTransformType = {
991
+ PREDICTION_TRANSFORM_NONE: -1,
992
+ PREDICTION_TRANSFORM_DELTA: 0,
993
+ PREDICTION_TRANSFORM_WRAP: 1,
994
+ PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON: 2,
995
+ PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED: 3,
996
+ NUM_PREDICTION_SCHEME_TRANSFORM_TYPES: 4
997
+ };
998
+ var MeshTraversalMethod = {
999
+ MESH_TRAVERSAL_DEPTH_FIRST: 0,
1000
+ MESH_TRAVERSAL_PREDICTION_DEGREE: 1,
1001
+ NUM_TRAVERSAL_METHODS: 2
1002
+ };
1003
+ var MeshEdgebreakerConnectivityEncodingMethod = {
1004
+ MESH_EDGEBREAKER_STANDARD_ENCODING: 0,
1005
+ MESH_EDGEBREAKER_PREDICTIVE_ENCODING: 1,
1006
+ // Deprecated.
1007
+ MESH_EDGEBREAKER_VALENCE_ENCODING: 2
1008
+ };
1009
+ var DracoHeader = class {
1010
+ dracoString;
1011
+ versionMajor;
1012
+ versionMinor;
1013
+ encoderType;
1014
+ encoderMethod;
1015
+ flags;
893
1016
  constructor() {
894
- this.is_edge_on_seam_ = [];
895
- this.is_vertex_on_seam_ = [];
896
- this.no_interior_seams_ = true;
897
- this.corner_to_vertex_map_ = [];
898
- this.vertex_to_left_most_corner_map_ = [];
899
- this.vertex_to_attribute_entry_id_map_ = [];
900
- this.corner_table_ = null;
901
- this._effectiveOpposite = null;
902
- this._seamCorners = [];
1017
+ this.dracoString = new Int8Array(5);
1018
+ this.versionMajor = 0;
1019
+ this.versionMinor = 0;
1020
+ this.encoderType = 0;
1021
+ this.encoderMethod = 0;
1022
+ this.flags = 0;
903
1023
  }
904
- initEmpty(table) {
905
- if (table === null) {
906
- return false;
1024
+ };
1025
+ var NormalPredictionMode = {
1026
+ ONE_TRIANGLE: 0,
1027
+ // To be deprecated.
1028
+ TRIANGLE_AREA: 1
1029
+ };
1030
+ var SymbolCodingMethod = {
1031
+ SYMBOL_CODING_TAGGED: 0,
1032
+ SYMBOL_CODING_RAW: 1,
1033
+ NUM_SYMBOL_CODING_METHODS: 2
1034
+ };
1035
+ var METADATA_FLAG_MASK = 32768;
1036
+
1037
+ // src/decoder/compression/config/DracoOptions.ts
1038
+ var DracoOptions = class {
1039
+ _globalOptions;
1040
+ _attributeOptions;
1041
+ constructor() {
1042
+ this._globalOptions = /* @__PURE__ */ new Map();
1043
+ this._attributeOptions = /* @__PURE__ */ new Map();
1044
+ }
1045
+ getGlobalBool(name, defaultVal) {
1046
+ if (this._globalOptions.has(name)) {
1047
+ return !!this._globalOptions.get(name);
907
1048
  }
908
- this.is_edge_on_seam_ = new Uint8Array(table.numCorners());
909
- this.is_vertex_on_seam_ = new Uint8Array(table.numVertices());
910
- this.corner_to_vertex_map_ = new Int32Array(table.numCorners()).fill(kInvalidVertexIndex);
911
- this.vertex_to_attribute_entry_id_map_ = [];
912
- this.vertex_to_left_most_corner_map_ = [];
913
- this._effectiveOpposite = null;
914
- this._seamCorners = [];
915
- this.corner_table_ = table;
916
- this.no_interior_seams_ = true;
917
- return true;
1049
+ return defaultVal;
918
1050
  }
919
- addSeamEdge(c) {
920
- const cornerToVertex = this.corner_table_.cornerToVertexArray();
921
- const oppositeCorners = this.corner_table_.oppositeCornerArray();
922
- const isEdge = this.is_edge_on_seam_;
923
- const isVert = this.is_vertex_on_seam_;
924
- isEdge[c] = 1;
925
- this._seamCorners.push(c);
926
- let rem = c - (c / 3 | 0) * 3;
927
- isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
928
- isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
929
- const oppCorner = oppositeCorners[c];
930
- if (oppCorner !== kInvalidCornerIndex) {
931
- this.no_interior_seams_ = false;
932
- isEdge[oppCorner] = 1;
933
- this._seamCorners.push(oppCorner);
934
- rem = oppCorner - (oppCorner / 3 | 0) * 3;
935
- isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
936
- isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
1051
+ findAttributeOptions(attKey) {
1052
+ if (this._attributeOptions.has(attKey)) {
1053
+ return this._attributeOptions.get(attKey);
937
1054
  }
1055
+ return null;
938
1056
  }
939
- recomputeVertices(_cornerTable, _vertexIds) {
940
- return this._recomputeVerticesInternal();
1057
+ getAttributeBool(attKey, name, defaultVal) {
1058
+ const attOpts = this.findAttributeOptions(attKey);
1059
+ if (attOpts !== null && attOpts.has(name)) {
1060
+ return !!attOpts.get(name);
1061
+ }
1062
+ return this.getGlobalBool(name, defaultVal);
941
1063
  }
942
- // Only the C++ RecomputeVertices(nullptr, nullptr) path: the decoder always
943
- // rebuilds the attribute-vertex maps from connectivity alone.
944
- _recomputeVerticesInternal() {
945
- const ct = this.corner_table_;
946
- const numCorners = ct.numCorners();
947
- const numBaseVertices = ct.numVertices();
948
- const leftMostMap = new Int32Array(numCorners);
949
- const cornerToVertex = this.corner_to_vertex_map_;
950
- const isVertexOnSeam = this.is_vertex_on_seam_;
951
- const isEdgeOnSeam = this.is_edge_on_seam_;
952
- const seamOpp = this.oppositeCornerArray();
953
- const baseOpp = ct.oppositeCornerArray();
954
- const vertexLeftmost = ct.vertexLeftmostCornerArray();
955
- let numNewVertices = 0;
956
- for (let v = 0; v < numBaseVertices; ++v) {
957
- const c = vertexLeftmost[v];
958
- if (c === kInvalidCornerIndex) continue;
959
- if (!isVertexOnSeam[v]) {
960
- const firstVertId = numNewVertices++;
961
- leftMostMap[firstVertId] = c;
962
- cornerToVertex[c] = firstVertId;
963
- let pv = c % 3 === 0 ? c + 2 : c - 1;
964
- let bopp = baseOpp[pv];
965
- let actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
966
- while (actC !== kInvalidCornerIndex && actC !== c) {
967
- cornerToVertex[actC] = firstVertId;
968
- pv = actC % 3 === 0 ? actC + 2 : actC - 1;
969
- bopp = baseOpp[pv];
970
- actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
971
- }
972
- } else {
973
- let firstVertId = numNewVertices++;
974
- let firstC = c;
975
- let actC;
976
- let nx = firstC % 3 === 2 ? firstC - 2 : firstC + 1;
977
- let opp = seamOpp[nx];
978
- actC = opp < 0 ? kInvalidCornerIndex : opp % 3 === 2 ? opp - 2 : opp + 1;
979
- while (actC !== kInvalidCornerIndex) {
980
- firstC = actC;
981
- nx = firstC % 3 === 2 ? firstC - 2 : firstC + 1;
982
- opp = seamOpp[nx];
983
- actC = opp < 0 ? kInvalidCornerIndex : opp % 3 === 2 ? opp - 2 : opp + 1;
984
- if (actC === c) return false;
985
- }
986
- cornerToVertex[firstC] = firstVertId;
987
- leftMostMap[firstVertId] = firstC;
988
- let pv = firstC % 3 === 0 ? firstC + 2 : firstC - 1;
989
- let bopp = baseOpp[pv];
990
- actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
991
- while (actC !== kInvalidCornerIndex && actC !== firstC) {
992
- const nAct = actC % 3 === 2 ? actC - 2 : actC + 1;
993
- if (isEdgeOnSeam[nAct]) {
994
- firstVertId = numNewVertices++;
995
- leftMostMap[firstVertId] = actC;
996
- }
997
- cornerToVertex[actC] = firstVertId;
998
- pv = actC % 3 === 0 ? actC + 2 : actC - 1;
999
- bopp = baseOpp[pv];
1000
- actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
1001
- }
1002
- }
1003
- }
1004
- this.vertex_to_attribute_entry_id_map_ = new Int32Array(numNewVertices);
1005
- this.vertex_to_left_most_corner_map_ = leftMostMap.subarray(0, numNewVertices);
1006
- return true;
1007
- }
1008
- isCornerOppositeToSeamEdge(corner) {
1009
- return this.is_edge_on_seam_[corner];
1010
- }
1011
- opposite(corner) {
1012
- if (corner === kInvalidCornerIndex || this.isCornerOppositeToSeamEdge(corner)) {
1013
- return kInvalidCornerIndex;
1014
- }
1015
- return this.corner_table_.opposite(corner);
1016
- }
1017
- next(corner) {
1018
- return this.corner_table_.next(corner);
1019
- }
1020
- previous(corner) {
1021
- return this.corner_table_.previous(corner);
1022
- }
1023
- swingRight(corner) {
1024
- return this.previous(this.opposite(this.previous(corner)));
1025
- }
1026
- swingLeft(corner) {
1027
- return this.next(this.opposite(this.next(corner)));
1028
- }
1029
- numVertices() {
1030
- return this.vertex_to_attribute_entry_id_map_.length;
1031
- }
1032
- numFaces() {
1033
- return this.corner_table_.numFaces();
1034
- }
1035
- numCorners() {
1036
- return this.corner_table_.numCorners();
1037
- }
1038
- vertex(corner) {
1039
- return this.confidentVertex(corner);
1040
- }
1041
- confidentVertex(corner) {
1042
- return this.corner_to_vertex_map_[corner];
1043
- }
1044
- leftMostCorner(v) {
1045
- return this.vertex_to_left_most_corner_map_[v];
1064
+ };
1065
+
1066
+ // src/decoder/compression/config/DecoderOptions.ts
1067
+ var DecoderOptions = class extends DracoOptions {
1068
+ constructor() {
1069
+ super();
1046
1070
  }
1047
- face(corner) {
1048
- return this.corner_table_.face(corner);
1071
+ };
1072
+
1073
+ // src/decoder/core/Status.ts
1074
+ var StatusCode = {
1075
+ OK: 0,
1076
+ DRACO_ERROR: -1,
1077
+ IO_ERROR: -2,
1078
+ INVALID_PARAMETER: -3,
1079
+ UNSUPPORTED_VERSION: -4,
1080
+ UNKNOWN_VERSION: -5,
1081
+ UNSUPPORTED_FEATURE: -6
1082
+ };
1083
+ var Status = class {
1084
+ code;
1085
+ errorMsg;
1086
+ constructor(code = StatusCode.OK, errorMsg = "") {
1087
+ this.code = code;
1088
+ this.errorMsg = errorMsg;
1049
1089
  }
1050
- firstCorner(faceIndex) {
1051
- return this.corner_table_.firstCorner(faceIndex);
1090
+ ok() {
1091
+ return this.code === StatusCode.OK;
1052
1092
  }
1053
- allCorners(faceIndex) {
1054
- return this.corner_table_.allCorners(faceIndex);
1093
+ };
1094
+ function okStatus() {
1095
+ return new Status(StatusCode.OK);
1096
+ }
1097
+
1098
+ // src/decoder/metadata/MetadataDecoder.ts
1099
+ var kMaxSubmetadataLevel = 1e3;
1100
+ var MetadataDecoder = class {
1101
+ buffer_;
1102
+ constructor() {
1103
+ this.buffer_ = null;
1055
1104
  }
1056
- // --- Flat-array accessors: let DepthFirstTraverser avoid per-corner dispatch. ---
1057
- cornerToVertexArray() {
1058
- return this.corner_to_vertex_map_;
1105
+ // Skips per-attribute metadata followed by the geometry-level metadata.
1106
+ skipGeometryMetadata(inBuffer) {
1107
+ this.buffer_ = inBuffer;
1108
+ const numAttMetadata = decodeVarint(this.buffer_);
1109
+ if (numAttMetadata === void 0) {
1110
+ return false;
1111
+ }
1112
+ for (let i = 0; i < numAttMetadata; ++i) {
1113
+ if (decodeVarint(this.buffer_) === void 0) {
1114
+ return false;
1115
+ }
1116
+ if (!this._skipMetadata(0)) {
1117
+ return false;
1118
+ }
1119
+ }
1120
+ return this._skipMetadata(0);
1059
1121
  }
1060
- // Seam-aware opposite corners (seam edges -> -1), matching opposite(). Cached on
1061
- // first use; seams and connectivity are finalized before traversal, so it's stable.
1062
- oppositeCornerArray() {
1063
- if (this._effectiveOpposite === null) {
1064
- const nc = this.corner_table_.numCorners();
1065
- const base = this.corner_table_.oppositeCornerArray();
1066
- const seamCorners = this._seamCorners;
1067
- if (seamCorners.length === 0) {
1068
- this._effectiveOpposite = base;
1069
- } else {
1070
- const eff = base.slice(0, nc);
1071
- for (let i = 0, l = seamCorners.length; i < l; ++i) {
1072
- eff[seamCorners[i]] = kInvalidCornerIndex;
1073
- }
1074
- this._effectiveOpposite = eff;
1122
+ // Discards one metadata block (key-value entries plus nested sub-metadata).
1123
+ // Sub-blocks read depth-first in stream order, matching the C++ stack traversal.
1124
+ _skipMetadata(level) {
1125
+ if (level > kMaxSubmetadataLevel) {
1126
+ return false;
1127
+ }
1128
+ const numEntries = decodeVarint(this.buffer_);
1129
+ if (numEntries === void 0) {
1130
+ return false;
1131
+ }
1132
+ for (let i = 0; i < numEntries; ++i) {
1133
+ if (!this._skipEntry()) {
1134
+ return false;
1075
1135
  }
1076
1136
  }
1077
- return this._effectiveOpposite;
1137
+ const numSubMetadata = decodeVarint(this.buffer_);
1138
+ if (numSubMetadata === void 0) {
1139
+ return false;
1140
+ }
1141
+ if (numSubMetadata > this.buffer_.remainingSize) {
1142
+ return false;
1143
+ }
1144
+ for (let i = 0; i < numSubMetadata; ++i) {
1145
+ if (!this._skipName()) {
1146
+ return false;
1147
+ }
1148
+ if (!this._skipMetadata(level + 1)) {
1149
+ return false;
1150
+ }
1151
+ }
1152
+ return true;
1078
1153
  }
1079
- vertexLeftmostCornerArray() {
1080
- return this.vertex_to_left_most_corner_map_;
1154
+ // Skips a key-value entry: name then a length-prefixed value.
1155
+ _skipEntry() {
1156
+ if (!this._skipName()) {
1157
+ return false;
1158
+ }
1159
+ const dataSize = decodeVarint(this.buffer_);
1160
+ if (dataSize === void 0 || dataSize === 0) {
1161
+ return false;
1162
+ }
1163
+ return this._skipBytes(dataSize);
1081
1164
  }
1082
- // Per-base-vertex seam flag (Uint8Array); exposed so hot dedup loops inline the lookup.
1083
- vertexOnSeamArray() {
1084
- return this.is_vertex_on_seam_;
1165
+ // Skips a name (uint8 length prefix followed by that many bytes).
1166
+ _skipName() {
1167
+ const nameLen = this.buffer_.decodeUint8();
1168
+ if (nameLen === void 0) {
1169
+ return false;
1170
+ }
1171
+ if (nameLen === 0) {
1172
+ return true;
1173
+ }
1174
+ return this._skipBytes(nameLen);
1085
1175
  }
1086
- hasSameSeams(other) {
1087
- if (other === null || other === void 0) return false;
1088
- const seamA = this.is_edge_on_seam_;
1089
- const seamB = other.is_edge_on_seam_;
1090
- if (seamA.length !== seamB.length) return false;
1091
- for (let i = 0, l = seamA.length; i < l; ++i) {
1092
- if (seamA[i] !== seamB[i]) return false;
1176
+ _skipBytes(size) {
1177
+ if (size > this.buffer_.remainingSize) {
1178
+ return false;
1093
1179
  }
1180
+ this.buffer_.advance(size);
1094
1181
  return true;
1095
1182
  }
1096
- adoptVertexRecompute(other) {
1097
- this.corner_to_vertex_map_ = other.corner_to_vertex_map_;
1098
- this.vertex_to_attribute_entry_id_map_ = other.vertex_to_attribute_entry_id_map_;
1099
- this.vertex_to_left_most_corner_map_ = other.vertex_to_left_most_corner_map_;
1100
- this.no_interior_seams_ = other.no_interior_seams_;
1101
- this._effectiveOpposite = other._effectiveOpposite;
1102
- this._seamCorners = other._seamCorners;
1103
- }
1104
- isDegenerated(faceIndex) {
1105
- return this.corner_table_.isDegenerated(faceIndex);
1106
- }
1107
1183
  };
1108
1184
 
1109
- // src/decoder/core/DracoTypes.ts
1110
- var DataType = {
1111
- INVALID: 0,
1112
- INT8: 1,
1113
- UINT8: 2,
1114
- INT16: 3,
1115
- UINT16: 4,
1116
- INT32: 5,
1117
- UINT32: 6,
1118
- INT64: 7,
1119
- UINT64: 8,
1120
- FLOAT32: 9,
1121
- FLOAT64: 10,
1122
- BOOL: 11,
1123
- TYPES_COUNT: 12
1124
- };
1125
- function dataTypeLength(dt) {
1126
- switch (dt) {
1127
- case DataType.INT8:
1128
- case DataType.UINT8:
1129
- return 1;
1130
- case DataType.INT16:
1131
- case DataType.UINT16:
1132
- return 2;
1133
- case DataType.INT32:
1134
- case DataType.UINT32:
1135
- return 4;
1136
- case DataType.INT64:
1137
- case DataType.UINT64:
1138
- return 8;
1139
- case DataType.FLOAT32:
1140
- return 4;
1141
- case DataType.FLOAT64:
1142
- return 8;
1143
- case DataType.BOOL:
1144
- return 1;
1145
- default:
1146
- return -1;
1147
- }
1148
- }
1149
-
1150
- // src/decoder/attributes/GeometryAttribute.ts
1151
- var Type = {
1152
- INVALID: -1,
1153
- POSITION: 0,
1154
- NORMAL: 1,
1155
- COLOR: 2,
1156
- TEX_COORD: 3,
1157
- GENERIC: 4,
1158
- NAMED_ATTRIBUTES_COUNT: 5
1159
- };
1160
- var GeometryAttribute = class {
1185
+ // src/decoder/compression/point_cloud/PointCloudDecoder.ts
1186
+ var PointCloudDecoder = class _PointCloudDecoder {
1187
+ _pointCloud;
1161
1188
  _buffer;
1162
- _numComponents;
1163
- _dataType;
1164
- _normalized;
1165
- _byteStride;
1166
- _byteOffset;
1167
- _attributeType;
1168
- _uniqueId;
1189
+ _versionMajor;
1190
+ _versionMinor;
1191
+ _options;
1192
+ _attributesDecoders;
1193
+ _attributeToDecoderMap;
1169
1194
  constructor() {
1195
+ this._pointCloud = null;
1170
1196
  this._buffer = null;
1171
- this._numComponents = 1;
1172
- this._dataType = DataType.FLOAT32;
1173
- this._normalized = false;
1174
- this._byteStride = 0;
1175
- this._byteOffset = 0;
1176
- this._attributeType = Type.INVALID;
1177
- this._uniqueId = 0;
1197
+ this._versionMajor = 0;
1198
+ this._versionMinor = 0;
1199
+ this._options = null;
1200
+ this._attributesDecoders = [];
1201
+ this._attributeToDecoderMap = [];
1178
1202
  }
1179
- init(attributeType, buffer, numComponents, dataType, normalized, byteStride, byteOffset) {
1180
- this._buffer = buffer;
1181
- this._numComponents = numComponents;
1182
- this._dataType = dataType;
1183
- this._normalized = normalized;
1184
- this._byteStride = byteStride;
1185
- this._byteOffset = byteOffset;
1186
- this._attributeType = attributeType;
1203
+ getGeometryType() {
1204
+ return EncodedGeometryType.POINT_CLOUD;
1187
1205
  }
1188
- // Returns a Uint8Array view of the buffer starting at the attribute entry.
1189
- getAddress(attIndex) {
1190
- const bytePos = this._byteOffset + this._byteStride * attIndex;
1191
- return this._buffer.data.subarray(bytePos);
1206
+ // Returns a Status; on success outHeader is populated.
1207
+ static decodeHeader(buffer, outHeader) {
1208
+ const kIoErrorMsg = "Failed to parse Draco header.";
1209
+ const bytes = buffer.decodeBytes(5);
1210
+ if (bytes === void 0) {
1211
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1212
+ }
1213
+ for (let i = 0; i < 5; i++) {
1214
+ outHeader.dracoString[i] = bytes[i];
1215
+ }
1216
+ const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
1217
+ if (magic !== "DRACO") {
1218
+ return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
1219
+ }
1220
+ const versionMajor = buffer.decodeUint8();
1221
+ if (versionMajor === void 0) {
1222
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1223
+ }
1224
+ outHeader.versionMajor = versionMajor;
1225
+ const versionMinor = buffer.decodeUint8();
1226
+ if (versionMinor === void 0) {
1227
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1228
+ }
1229
+ outHeader.versionMinor = versionMinor;
1230
+ const encoderType = buffer.decodeUint8();
1231
+ if (encoderType === void 0) {
1232
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1233
+ }
1234
+ outHeader.encoderType = encoderType;
1235
+ const encoderMethod = buffer.decodeUint8();
1236
+ if (encoderMethod === void 0) {
1237
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1238
+ }
1239
+ outHeader.encoderMethod = encoderMethod;
1240
+ const flags = buffer.decodeUint16();
1241
+ if (flags === void 0) {
1242
+ return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
1243
+ }
1244
+ outHeader.flags = flags;
1245
+ return okStatus();
1192
1246
  }
1193
- copyFrom(srcAtt) {
1194
- this._numComponents = srcAtt._numComponents;
1195
- this._dataType = srcAtt._dataType;
1196
- this._normalized = srcAtt._normalized;
1197
- this._byteStride = srcAtt._byteStride;
1198
- this._byteOffset = srcAtt._byteOffset;
1199
- this._attributeType = srcAtt._attributeType;
1200
- this._uniqueId = srcAtt._uniqueId;
1201
- if (srcAtt._buffer === null) {
1202
- this._buffer = null;
1203
- } else {
1204
- if (this._buffer === null) {
1205
- return false;
1247
+ // Main entry point for point cloud decoding.
1248
+ decode(options, inBuffer, outPointCloud) {
1249
+ this._options = options;
1250
+ this._buffer = inBuffer;
1251
+ this._pointCloud = outPointCloud;
1252
+ const header = new DracoHeader();
1253
+ const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
1254
+ if (!headerStatus.ok()) {
1255
+ return headerStatus;
1256
+ }
1257
+ if (header.encoderType !== this.getGeometryType()) {
1258
+ return new Status(StatusCode.DRACO_ERROR, "Using incompatible decoder for the input geometry.");
1259
+ }
1260
+ this._versionMajor = header.versionMajor;
1261
+ this._versionMinor = header.versionMinor;
1262
+ const maxSupportedMajorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor : kDracoMeshBitstreamVersionMajor;
1263
+ const maxSupportedMinorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor;
1264
+ if (this._versionMajor < 1 || this._versionMajor > maxSupportedMajorVersion) {
1265
+ return new Status(StatusCode.UNKNOWN_VERSION, "Unknown major version.");
1266
+ }
1267
+ if (this._versionMajor === maxSupportedMajorVersion && this._versionMinor > maxSupportedMinorVersion) {
1268
+ return new Status(StatusCode.UNKNOWN_VERSION, "Unknown minor version.");
1269
+ }
1270
+ this._buffer.bitstreamVersion = DRACO_BITSTREAM_VERSION(this._versionMajor, this._versionMinor);
1271
+ if (header.encoderType === EncodedGeometryType.TRIANGULAR_MESH && this._buffer.bitstreamVersion < DRACO_BITSTREAM_VERSION(2, 2)) {
1272
+ return new Status(
1273
+ StatusCode.UNKNOWN_VERSION,
1274
+ "Unsupported bitstream version (only Draco 2.2 meshes are supported)."
1275
+ );
1276
+ }
1277
+ if (header.flags & METADATA_FLAG_MASK) {
1278
+ const metadataStatus = this._decodeMetadata();
1279
+ if (!metadataStatus.ok()) {
1280
+ return metadataStatus;
1206
1281
  }
1207
- this._buffer.update(srcAtt._buffer.data, srcAtt._buffer.dataSize);
1208
1282
  }
1283
+ if (!this.initializeDecoder()) {
1284
+ return new Status(StatusCode.DRACO_ERROR, "Failed to initialize the decoder.");
1285
+ }
1286
+ if (!this.decodeGeometryData()) {
1287
+ return new Status(StatusCode.DRACO_ERROR, "Failed to decode geometry data.");
1288
+ }
1289
+ if (!this.decodePointAttributes()) {
1290
+ return new Status(StatusCode.DRACO_ERROR, "Failed to decode point attributes.");
1291
+ }
1292
+ return okStatus();
1293
+ }
1294
+ bitstreamVersion() {
1295
+ return DRACO_BITSTREAM_VERSION(this._versionMajor, this._versionMinor);
1296
+ }
1297
+ setAttributesDecoder(attDecoderId, decoder) {
1298
+ if (attDecoderId < 0) {
1299
+ return false;
1300
+ }
1301
+ while (this._attributesDecoders.length <= attDecoderId) {
1302
+ this._attributesDecoders.push(null);
1303
+ }
1304
+ this._attributesDecoders[attDecoderId] = decoder;
1209
1305
  return true;
1210
1306
  }
1211
- resetBuffer(buffer, byteStride, byteOffset) {
1212
- this._buffer = buffer;
1213
- this._byteStride = byteStride;
1214
- this._byteOffset = byteOffset;
1307
+ getPortableAttribute(parentAttId) {
1308
+ if (parentAttId < 0 || parentAttId >= this._pointCloud.numAttributes()) {
1309
+ return null;
1310
+ }
1311
+ const parentAttDecoderId = this._attributeToDecoderMap[parentAttId];
1312
+ return this._attributesDecoders[parentAttDecoderId].getPortableAttribute(parentAttId);
1215
1313
  }
1216
- get attributeType() {
1217
- return this._attributeType;
1314
+ attributesDecoder(decId) {
1315
+ return this._attributesDecoders[decId];
1218
1316
  }
1219
- get dataType() {
1220
- return this._dataType;
1317
+ numAttributesDecoders() {
1318
+ return this._attributesDecoders.length;
1221
1319
  }
1222
- get numComponents() {
1223
- return this._numComponents;
1320
+ pointCloud() {
1321
+ return this._pointCloud;
1224
1322
  }
1225
- get buffer() {
1323
+ buffer() {
1226
1324
  return this._buffer;
1227
1325
  }
1228
- get byteStride() {
1229
- return this._byteStride;
1230
- }
1231
- get byteOffset() {
1232
- return this._byteOffset;
1326
+ options() {
1327
+ return this._options;
1233
1328
  }
1234
- get uniqueId() {
1235
- return this._uniqueId;
1329
+ // -- Protected virtual methods (override in subclasses) --
1330
+ initializeDecoder() {
1331
+ return true;
1236
1332
  }
1237
- set uniqueId(id) {
1238
- this._uniqueId = id;
1333
+ // Must be implemented by derived classes.
1334
+ createAttributesDecoder(_attDecoderId) {
1335
+ return false;
1239
1336
  }
1240
- };
1241
-
1242
- // src/decoder/core/DataBuffer.ts
1243
- var DataBuffer = class {
1244
- _data;
1245
- constructor() {
1246
- this._data = new Uint8Array(0);
1337
+ decodeGeometryData() {
1338
+ return true;
1247
1339
  }
1248
- update(data, size, offset = 0) {
1249
- if (data === null || data === void 0) {
1250
- if (size + offset < 0) return false;
1251
- this._resize(size + offset);
1252
- } else {
1253
- if (size < 0) return false;
1254
- if (size + offset > this._data.length) {
1255
- this._resize(size + offset);
1340
+ decodePointAttributes() {
1341
+ const numAttributesDecoders = this._buffer.decodeUint8();
1342
+ if (numAttributesDecoders === void 0) {
1343
+ return false;
1344
+ }
1345
+ for (let i = 0; i < numAttributesDecoders; ++i) {
1346
+ if (!this.createAttributesDecoder(i)) {
1347
+ return false;
1256
1348
  }
1257
- const view = data;
1258
- const src = new Uint8Array(view.buffer || data, view.byteOffset || 0, size);
1259
- this._data.set(src, offset);
1260
1349
  }
1261
- return true;
1262
- }
1263
- resize(newSize) {
1264
- this._resize(newSize);
1265
- }
1266
- write(bytePos, inArray, dataSize) {
1267
- if (inArray instanceof Uint8Array) {
1268
- this._data.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
1269
- return;
1350
+ for (let i = 0; i < this._attributesDecoders.length; ++i) {
1351
+ if (!this._attributesDecoders[i].init(this, this._pointCloud)) {
1352
+ return false;
1353
+ }
1270
1354
  }
1271
- const view = inArray;
1272
- const src = new Uint8Array(view.buffer || inArray, view.byteOffset || 0, dataSize);
1273
- this._data.set(src, bytePos);
1274
- }
1275
- get data() {
1276
- return this._data;
1277
- }
1278
- get dataSize() {
1279
- return this._data.length;
1280
- }
1281
- _resize(newSize) {
1282
- if (newSize === this._data.length) return;
1283
- const newData = new Uint8Array(newSize);
1284
- newData.set(this._data.subarray(0, Math.min(this._data.length, newSize)));
1285
- this._data = newData;
1286
- }
1287
- };
1288
-
1289
- // src/decoder/attributes/GeometryIndices.ts
1290
- var kInvalidAttributeValueIndex = 4294967295 >>> 0;
1291
-
1292
- // src/decoder/attributes/PointAttribute.ts
1293
- var PointAttribute = class extends GeometryAttribute {
1294
- _identityMapping;
1295
- _numUniqueEntries;
1296
- _indicesMap;
1297
- _attributeBuffer;
1298
- _attributeTransformData;
1299
- // Lazily-created cached views over the attribute buffer.
1300
- _cachedFloat32View;
1301
- _cachedFloat32Buffer;
1302
- _cachedInt32View;
1303
- _cachedInt32Buffer;
1304
- _cachedUint32View;
1305
- _cachedUint32Buffer;
1306
- _cachedUint16View;
1307
- _cachedUint16Buffer;
1308
- _cachedInt16View;
1309
- _cachedInt16Buffer;
1310
- _cachedUint8View;
1311
- _cachedUint8Buffer;
1312
- _cachedInt8View;
1313
- _cachedInt8Buffer;
1314
- _cachedFloat64View;
1315
- _cachedFloat64Buffer;
1316
- _cachedDataView;
1317
- _cachedDVBuffer;
1318
- constructor(geometryAttribute) {
1319
- super();
1320
- this._identityMapping = false;
1321
- this._numUniqueEntries = 0;
1322
- this._indicesMap = [];
1323
- this._attributeBuffer = null;
1324
- this._attributeTransformData = null;
1325
- if (geometryAttribute instanceof GeometryAttribute) {
1326
- this._buffer = geometryAttribute._buffer;
1327
- this._numComponents = geometryAttribute._numComponents;
1328
- this._dataType = geometryAttribute._dataType;
1329
- this._normalized = geometryAttribute._normalized;
1330
- this._byteStride = geometryAttribute._byteStride;
1331
- this._byteOffset = geometryAttribute._byteOffset;
1332
- this._attributeType = geometryAttribute._attributeType;
1333
- this._uniqueId = geometryAttribute._uniqueId;
1355
+ for (let i = 0; i < numAttributesDecoders; ++i) {
1356
+ if (!this._attributesDecoders[i].decodeAttributesDecoderData(this._buffer)) {
1357
+ return false;
1358
+ }
1334
1359
  }
1360
+ for (let i = 0; i < numAttributesDecoders; ++i) {
1361
+ const numAttributes = this._attributesDecoders[i].getNumAttributes();
1362
+ for (let j = 0; j < numAttributes; ++j) {
1363
+ const attId = this._attributesDecoders[i].getAttributeId(j);
1364
+ while (this._attributeToDecoderMap.length <= attId) {
1365
+ this._attributeToDecoderMap.push(0);
1366
+ }
1367
+ this._attributeToDecoderMap[attId] = i;
1368
+ }
1369
+ }
1370
+ if (!this.decodeAllAttributes()) {
1371
+ return false;
1372
+ }
1373
+ if (!this.onAttributesDecoded()) {
1374
+ return false;
1375
+ }
1376
+ return true;
1335
1377
  }
1336
- // Intentionally shadows GeometryAttribute.init with a different signature (matches draco.js / C++ source).
1337
- // @ts-expect-error -- signature intentionally differs from the base class, as in the source.
1338
- init(attributeType, numComponents, dataType, normalized, numAttributeValues) {
1339
- this._attributeBuffer = new DataBuffer();
1340
- const byteStride = dataTypeLength(dataType) * numComponents;
1341
- super.init(attributeType, this._attributeBuffer, numComponents, dataType, normalized, byteStride, 0);
1342
- this.reset(numAttributeValues);
1343
- this.setIdentityMapping();
1344
- }
1345
- reset(numAttributeValues) {
1346
- if (this._attributeBuffer === null) {
1347
- this._attributeBuffer = new DataBuffer();
1378
+ decodeAllAttributes() {
1379
+ for (let i = 0; i < this._attributesDecoders.length; i++) {
1380
+ if (!this._attributesDecoders[i].decodeAttributes(this._buffer)) {
1381
+ return false;
1382
+ }
1348
1383
  }
1349
- const entrySize = dataTypeLength(this.dataType) * this.numComponents;
1350
- this._attributeBuffer.update(null, numAttributeValues * entrySize);
1351
- this.resetBuffer(this._attributeBuffer, entrySize, 0);
1352
- this._numUniqueEntries = numAttributeValues;
1353
1384
  return true;
1354
1385
  }
1355
- get size() {
1356
- return this._numUniqueEntries;
1386
+ onAttributesDecoded() {
1387
+ return true;
1357
1388
  }
1358
- mappedIndex(pointIndex) {
1359
- if (this._identityMapping) {
1360
- return pointIndex;
1389
+ _decodeMetadata() {
1390
+ const metadataDecoder = new MetadataDecoder();
1391
+ if (!metadataDecoder.skipGeometryMetadata(this._buffer)) {
1392
+ return new Status(StatusCode.DRACO_ERROR, "Failed to decode metadata.");
1361
1393
  }
1362
- return this._indicesMap[pointIndex];
1394
+ return okStatus();
1363
1395
  }
1364
- get isMappingIdentity() {
1365
- return this._identityMapping;
1396
+ };
1397
+
1398
+ // src/decoder/compression/mesh/MeshDecoder.ts
1399
+ var MeshDecoder = class extends PointCloudDecoder {
1400
+ _mesh;
1401
+ constructor() {
1402
+ super();
1403
+ this._mesh = null;
1366
1404
  }
1367
- get indicesMapSize() {
1368
- if (this._identityMapping) {
1369
- return 0;
1370
- }
1371
- return this._indicesMap.length;
1405
+ getGeometryType() {
1406
+ return EncodedGeometryType.TRIANGULAR_MESH;
1372
1407
  }
1373
- // Direct access to the explicit point->value index map (Uint32Array after
1374
- // setExplicitMapping). Lets hot mapping loops write entries without a
1375
- // per-entry setPointMapEntry() dispatch.
1376
- get indicesMap() {
1377
- return this._indicesMap;
1408
+ decodeMesh(options, inBuffer, outMesh) {
1409
+ this._mesh = outMesh;
1410
+ return this.decode(options, inBuffer, outMesh);
1378
1411
  }
1379
- // Implicit mapping: point index equals attribute entry index.
1380
- setIdentityMapping() {
1381
- this._identityMapping = true;
1382
- this._indicesMap = [];
1412
+ getCornerTable() {
1413
+ return null;
1383
1414
  }
1384
- setExplicitMapping(numPoints) {
1385
- this._identityMapping = false;
1386
- this._indicesMap = new Uint32Array(numPoints);
1387
- this._indicesMap.fill(kInvalidAttributeValueIndex);
1415
+ getAttributeCornerTable(_attId) {
1416
+ return null;
1388
1417
  }
1389
- // Like setExplicitMapping but skips the invalid-index fill. Only for callers
1390
- // that provably write every entry right away (the fill was ~4% of decode
1391
- // time on primitive-heavy files). The array still starts zeroed by the
1392
- // engine, so a buggy caller reads valid-looking zeros — hence opt-in.
1393
- setExplicitMappingUnfilled(numPoints) {
1394
- this._identityMapping = false;
1395
- this._indicesMap = new Uint32Array(numPoints);
1418
+ getAttributeEncodingData(_attId) {
1419
+ return null;
1396
1420
  }
1397
- setAttributeTransformData(transformData) {
1398
- this._attributeTransformData = transformData;
1421
+ mesh() {
1422
+ return this._mesh;
1399
1423
  }
1400
- // Mirrors C++ PointAttribute::ConvertValue<T>().
1401
- convertValue(attIndex, outVal) {
1402
- const bytePos = this._byteOffset + this._byteStride * attIndex;
1403
- const bufData = this._buffer.data;
1404
- const dt = this._dataType;
1405
- const nc = this._numComponents;
1406
- if (dt === DataType.FLOAT32) {
1407
- if (this._cachedFloat32View === void 0 || this._cachedFloat32Buffer !== bufData.buffer) {
1408
- this._cachedFloat32Buffer = bufData.buffer;
1409
- this._cachedFloat32View = new Float32Array(bufData.buffer);
1410
- }
1411
- const baseIndex = bufData.byteOffset + bytePos >> 2;
1412
- for (let i = 0; i < nc; ++i) {
1413
- outVal[i] = this._cachedFloat32View[baseIndex + i];
1414
- }
1415
- return;
1416
- }
1417
- if (dt === DataType.INT32) {
1418
- if (this._cachedInt32View === void 0 || this._cachedInt32Buffer !== bufData.buffer) {
1419
- this._cachedInt32Buffer = bufData.buffer;
1420
- this._cachedInt32View = new Int32Array(bufData.buffer);
1421
- }
1422
- const baseIndex = bufData.byteOffset + bytePos >> 2;
1423
- for (let i = 0; i < nc; ++i) {
1424
- outVal[i] = this._cachedInt32View[baseIndex + i];
1425
- }
1426
- return;
1427
- }
1428
- if (dt === DataType.UINT32) {
1429
- if (this._cachedUint32View === void 0 || this._cachedUint32Buffer !== bufData.buffer) {
1430
- this._cachedUint32Buffer = bufData.buffer;
1431
- this._cachedUint32View = new Uint32Array(bufData.buffer);
1432
- }
1433
- const baseIndex = bufData.byteOffset + bytePos >> 2;
1434
- for (let i = 0; i < nc; ++i) {
1435
- outVal[i] = this._cachedUint32View[baseIndex + i];
1436
- }
1437
- return;
1438
- }
1439
- if (this._cachedDataView === void 0 || this._cachedDVBuffer !== bufData.buffer) {
1440
- this._cachedDVBuffer = bufData.buffer;
1441
- this._cachedDataView = new DataView(bufData.buffer, bufData.byteOffset, bufData.byteLength);
1424
+ decodeGeometryData() {
1425
+ if (this._mesh === null) {
1426
+ return false;
1442
1427
  }
1443
- const dv = this._cachedDataView;
1444
- for (let i = 0; i < nc; ++i) {
1445
- switch (dt) {
1446
- case DataType.INT8:
1447
- outVal[i] = dv.getInt8(bytePos + i);
1448
- break;
1449
- case DataType.UINT8:
1450
- outVal[i] = dv.getUint8(bytePos + i);
1451
- break;
1452
- case DataType.INT16:
1453
- outVal[i] = dv.getInt16(bytePos + i * 2, true);
1454
- break;
1455
- case DataType.UINT16:
1456
- outVal[i] = dv.getUint16(bytePos + i * 2, true);
1457
- break;
1458
- case DataType.INT32:
1459
- outVal[i] = dv.getInt32(bytePos + i * 4, true);
1460
- break;
1461
- case DataType.UINT32:
1462
- outVal[i] = dv.getUint32(bytePos + i * 4, true);
1463
- break;
1464
- case DataType.FLOAT64:
1465
- outVal[i] = dv.getFloat64(bytePos + i * 8, true);
1466
- break;
1467
- default:
1468
- outVal[i] = 0;
1469
- break;
1470
- }
1428
+ if (!this.decodeConnectivity()) {
1429
+ return false;
1471
1430
  }
1431
+ return super.decodeGeometryData();
1472
1432
  }
1473
- // Flat-array extraction of all values into one output typed array (avoids the
1474
- // per-point temp-array copy via cached typed-array views over the buffer).
1475
- extractTo(OutputTypedArray, numPoints) {
1476
- const numComponents = this._numComponents;
1477
- const array = new OutputTypedArray(numPoints * numComponents);
1478
- if (this._buffer == null || this._buffer.data == null || numPoints === 0) {
1479
- return array;
1433
+ // Overridden by derived classes.
1434
+ decodeConnectivity() {
1435
+ return false;
1436
+ }
1437
+ };
1438
+
1439
+ // src/decoder/mesh/MeshAttributeCornerTable.ts
1440
+ var kInvalidCornerIndex = -1;
1441
+ var kInvalidVertexIndex = -1;
1442
+ var MeshAttributeCornerTable = class {
1443
+ is_edge_on_seam_;
1444
+ is_vertex_on_seam_;
1445
+ no_interior_seams_;
1446
+ corner_to_vertex_map_;
1447
+ vertex_to_left_most_corner_map_;
1448
+ vertex_to_attribute_entry_id_map_;
1449
+ corner_table_;
1450
+ // Lazily built; see oppositeCornerArray.
1451
+ _effectiveOpposite;
1452
+ // Every corner passed to addSeamEdge (may contain duplicates); lets
1453
+ // oppositeCornerArray patch seams without scanning every corner's flag.
1454
+ _seamCorners;
1455
+ constructor() {
1456
+ this.is_edge_on_seam_ = [];
1457
+ this.is_vertex_on_seam_ = [];
1458
+ this.no_interior_seams_ = true;
1459
+ this.corner_to_vertex_map_ = [];
1460
+ this.vertex_to_left_most_corner_map_ = [];
1461
+ this.vertex_to_attribute_entry_id_map_ = [];
1462
+ this.corner_table_ = null;
1463
+ this._effectiveOpposite = null;
1464
+ this._seamCorners = [];
1465
+ }
1466
+ initEmpty(table) {
1467
+ if (table === null) {
1468
+ return false;
1480
1469
  }
1481
- const bufData = this._buffer.data;
1482
- const dt = this._dataType;
1483
- const isIdentity = this._identityMapping;
1484
- const indicesMap = this._indicesMap;
1485
- const byteStride = this._byteStride;
1486
- const byteOffset = this._byteOffset;
1487
- let srcView = null;
1488
- let shift = 0;
1489
- if (dt === DataType.FLOAT32) {
1490
- if (this._cachedFloat32View === void 0 || this._cachedFloat32Buffer !== bufData.buffer) {
1491
- this._cachedFloat32Buffer = bufData.buffer;
1492
- this._cachedFloat32View = new Float32Array(bufData.buffer);
1493
- }
1494
- srcView = this._cachedFloat32View;
1495
- shift = 2;
1496
- } else if (dt === DataType.INT32) {
1497
- if (this._cachedInt32View === void 0 || this._cachedInt32Buffer !== bufData.buffer) {
1498
- this._cachedInt32Buffer = bufData.buffer;
1499
- this._cachedInt32View = new Int32Array(bufData.buffer);
1500
- }
1501
- srcView = this._cachedInt32View;
1502
- shift = 2;
1503
- } else if (dt === DataType.UINT32) {
1504
- if (this._cachedUint32View === void 0 || this._cachedUint32Buffer !== bufData.buffer) {
1505
- this._cachedUint32Buffer = bufData.buffer;
1506
- this._cachedUint32View = new Uint32Array(bufData.buffer);
1507
- }
1508
- srcView = this._cachedUint32View;
1509
- shift = 2;
1510
- } else if (dt === DataType.UINT16) {
1511
- if (this._cachedUint16View === void 0 || this._cachedUint16Buffer !== bufData.buffer) {
1512
- this._cachedUint16Buffer = bufData.buffer;
1513
- this._cachedUint16View = new Uint16Array(bufData.buffer);
1514
- }
1515
- srcView = this._cachedUint16View;
1516
- shift = 1;
1517
- } else if (dt === DataType.INT16) {
1518
- if (this._cachedInt16View === void 0 || this._cachedInt16Buffer !== bufData.buffer) {
1519
- this._cachedInt16Buffer = bufData.buffer;
1520
- this._cachedInt16View = new Int16Array(bufData.buffer);
1521
- }
1522
- srcView = this._cachedInt16View;
1523
- shift = 1;
1524
- } else if (dt === DataType.UINT8) {
1525
- if (this._cachedUint8View === void 0 || this._cachedUint8Buffer !== bufData.buffer) {
1526
- this._cachedUint8Buffer = bufData.buffer;
1527
- this._cachedUint8View = new Uint8Array(bufData.buffer);
1528
- }
1529
- srcView = this._cachedUint8View;
1530
- shift = 0;
1531
- } else if (dt === DataType.INT8) {
1532
- if (this._cachedInt8View === void 0 || this._cachedInt8Buffer !== bufData.buffer) {
1533
- this._cachedInt8Buffer = bufData.buffer;
1534
- this._cachedInt8View = new Int8Array(bufData.buffer);
1535
- }
1536
- srcView = this._cachedInt8View;
1537
- shift = 0;
1538
- } else if (dt === DataType.FLOAT64) {
1539
- if (this._cachedFloat64View === void 0 || this._cachedFloat64Buffer !== bufData.buffer) {
1540
- this._cachedFloat64Buffer = bufData.buffer;
1541
- this._cachedFloat64View = new Float64Array(bufData.buffer);
1542
- }
1543
- srcView = this._cachedFloat64View;
1544
- shift = 3;
1470
+ this.is_edge_on_seam_ = new Uint8Array(table.numCorners());
1471
+ this.is_vertex_on_seam_ = new Uint8Array(table.numVertices());
1472
+ this.corner_to_vertex_map_ = new Int32Array(table.numCorners()).fill(kInvalidVertexIndex);
1473
+ this.vertex_to_attribute_entry_id_map_ = [];
1474
+ this.vertex_to_left_most_corner_map_ = [];
1475
+ this._effectiveOpposite = null;
1476
+ this._seamCorners = [];
1477
+ this.corner_table_ = table;
1478
+ this.no_interior_seams_ = true;
1479
+ return true;
1480
+ }
1481
+ addSeamEdge(c) {
1482
+ const cornerToVertex = this.corner_table_.cornerToVertexArray();
1483
+ const oppositeCorners = this.corner_table_.oppositeCornerArray();
1484
+ const isEdge = this.is_edge_on_seam_;
1485
+ const isVert = this.is_vertex_on_seam_;
1486
+ isEdge[c] = 1;
1487
+ this._seamCorners.push(c);
1488
+ let rem = c - (c / 3 | 0) * 3;
1489
+ isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
1490
+ isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
1491
+ const oppCorner = oppositeCorners[c];
1492
+ if (oppCorner !== kInvalidCornerIndex) {
1493
+ this.no_interior_seams_ = false;
1494
+ isEdge[oppCorner] = 1;
1495
+ this._seamCorners.push(oppCorner);
1496
+ rem = oppCorner - (oppCorner / 3 | 0) * 3;
1497
+ isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
1498
+ isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
1545
1499
  }
1546
- if (srcView !== null) {
1547
- const srcStart = bufData.byteOffset + byteOffset >> shift;
1548
- const strideElements = byteStride >> shift;
1549
- if (isIdentity && strideElements === numComponents) {
1550
- const srcEnd = srcStart + numPoints * numComponents;
1551
- if (srcView.constructor === OutputTypedArray) {
1552
- array.set(srcView.subarray(srcStart, srcEnd));
1553
- return array;
1554
- }
1555
- }
1556
- if (isIdentity) {
1557
- let dst = 0;
1558
- for (let i = 0; i < numPoints; i++) {
1559
- const srcOffset = srcStart + i * strideElements;
1560
- for (let j = 0; j < numComponents; j++) {
1561
- array[dst + j] = srcView[srcOffset + j];
1562
- }
1563
- dst += numComponents;
1564
- }
1565
- } else if (numComponents === 3) {
1566
- let dst = 0;
1567
- for (let i = 0; i < numPoints; i++) {
1568
- const srcOffset = srcStart + indicesMap[i] * strideElements;
1569
- array[dst] = srcView[srcOffset];
1570
- array[dst + 1] = srcView[srcOffset + 1];
1571
- array[dst + 2] = srcView[srcOffset + 2];
1572
- dst += 3;
1573
- }
1574
- } else if (numComponents === 2) {
1575
- let dst = 0;
1576
- for (let i = 0; i < numPoints; i++) {
1577
- const srcOffset = srcStart + indicesMap[i] * strideElements;
1578
- array[dst] = srcView[srcOffset];
1579
- array[dst + 1] = srcView[srcOffset + 1];
1580
- dst += 2;
1581
- }
1582
- } else if (numComponents === 4) {
1583
- let dst = 0;
1584
- for (let i = 0; i < numPoints; i++) {
1585
- const srcOffset = srcStart + indicesMap[i] * strideElements;
1586
- array[dst] = srcView[srcOffset];
1587
- array[dst + 1] = srcView[srcOffset + 1];
1588
- array[dst + 2] = srcView[srcOffset + 2];
1589
- array[dst + 3] = srcView[srcOffset + 3];
1590
- dst += 4;
1591
- }
1592
- } else if (numComponents === 1) {
1593
- let dst = 0;
1594
- for (let i = 0; i < numPoints; i++) {
1595
- array[dst++] = srcView[srcStart + indicesMap[i] * strideElements];
1500
+ }
1501
+ recomputeVertices(_cornerTable, _vertexIds) {
1502
+ return this._recomputeVerticesInternal();
1503
+ }
1504
+ // Only the C++ RecomputeVertices(nullptr, nullptr) path: the decoder always
1505
+ // rebuilds the attribute-vertex maps from connectivity alone.
1506
+ _recomputeVerticesInternal() {
1507
+ const ct = this.corner_table_;
1508
+ const numCorners = ct.numCorners();
1509
+ const numBaseVertices = ct.numVertices();
1510
+ const leftMostMap = new Int32Array(numCorners);
1511
+ const cornerToVertex = this.corner_to_vertex_map_;
1512
+ const isVertexOnSeam = this.is_vertex_on_seam_;
1513
+ const isEdgeOnSeam = this.is_edge_on_seam_;
1514
+ const seamOpp = this.oppositeCornerArray();
1515
+ const baseOpp = ct.oppositeCornerArray();
1516
+ const vertexLeftmost = ct.vertexLeftmostCornerArray();
1517
+ let numNewVertices = 0;
1518
+ for (let v = 0; v < numBaseVertices; ++v) {
1519
+ const c = vertexLeftmost[v];
1520
+ if (c === kInvalidCornerIndex) continue;
1521
+ if (!isVertexOnSeam[v]) {
1522
+ const firstVertId = numNewVertices++;
1523
+ leftMostMap[firstVertId] = c;
1524
+ cornerToVertex[c] = firstVertId;
1525
+ let pv = c % 3 === 0 ? c + 2 : c - 1;
1526
+ let bopp = baseOpp[pv];
1527
+ let actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
1528
+ while (actC !== kInvalidCornerIndex && actC !== c) {
1529
+ cornerToVertex[actC] = firstVertId;
1530
+ pv = actC % 3 === 0 ? actC + 2 : actC - 1;
1531
+ bopp = baseOpp[pv];
1532
+ actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
1596
1533
  }
1597
1534
  } else {
1598
- let dst = 0;
1599
- for (let i = 0; i < numPoints; i++) {
1600
- const srcOffset = srcStart + indicesMap[i] * strideElements;
1601
- for (let j = 0; j < numComponents; j++) {
1602
- array[dst + j] = srcView[srcOffset + j];
1535
+ let firstVertId = numNewVertices++;
1536
+ let firstC = c;
1537
+ let actC;
1538
+ let nx = firstC % 3 === 2 ? firstC - 2 : firstC + 1;
1539
+ let opp = seamOpp[nx];
1540
+ actC = opp < 0 ? kInvalidCornerIndex : opp % 3 === 2 ? opp - 2 : opp + 1;
1541
+ while (actC !== kInvalidCornerIndex) {
1542
+ firstC = actC;
1543
+ nx = firstC % 3 === 2 ? firstC - 2 : firstC + 1;
1544
+ opp = seamOpp[nx];
1545
+ actC = opp < 0 ? kInvalidCornerIndex : opp % 3 === 2 ? opp - 2 : opp + 1;
1546
+ if (actC === c) return false;
1547
+ }
1548
+ cornerToVertex[firstC] = firstVertId;
1549
+ leftMostMap[firstVertId] = firstC;
1550
+ let pv = firstC % 3 === 0 ? firstC + 2 : firstC - 1;
1551
+ let bopp = baseOpp[pv];
1552
+ actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
1553
+ while (actC !== kInvalidCornerIndex && actC !== firstC) {
1554
+ const nAct = actC % 3 === 2 ? actC - 2 : actC + 1;
1555
+ if (isEdgeOnSeam[nAct]) {
1556
+ firstVertId = numNewVertices++;
1557
+ leftMostMap[firstVertId] = actC;
1603
1558
  }
1604
- dst += numComponents;
1559
+ cornerToVertex[actC] = firstVertId;
1560
+ pv = actC % 3 === 0 ? actC + 2 : actC - 1;
1561
+ bopp = baseOpp[pv];
1562
+ actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
1605
1563
  }
1606
1564
  }
1607
- return array;
1608
- }
1609
- const temp = new Array(numComponents);
1610
- for (let i = 0; i < numPoints; i++) {
1611
- const attIndex = isIdentity ? i : indicesMap[i];
1612
- this.convertValue(attIndex, temp);
1613
- const dstOffset = i * numComponents;
1614
- for (let j = 0; j < numComponents; j++) {
1615
- array[dstOffset + j] = temp[j];
1616
- }
1617
1565
  }
1618
- return array;
1566
+ this.vertex_to_attribute_entry_id_map_ = new Int32Array(numNewVertices);
1567
+ this.vertex_to_left_most_corner_map_ = leftMostMap.subarray(0, numNewVertices);
1568
+ return true;
1619
1569
  }
1620
- // Intentionally returns void while the base class returns boolean (matches the source's shape).
1621
- // @ts-expect-error -- return type intentionally differs from the base class, as in the source.
1622
- copyFrom(srcAtt) {
1623
- if (this.buffer === null) {
1624
- this._attributeBuffer = new DataBuffer();
1625
- this.resetBuffer(this._attributeBuffer, 0, 0);
1570
+ isCornerOppositeToSeamEdge(corner) {
1571
+ return this.is_edge_on_seam_[corner];
1572
+ }
1573
+ opposite(corner) {
1574
+ if (corner === kInvalidCornerIndex || this.isCornerOppositeToSeamEdge(corner)) {
1575
+ return kInvalidCornerIndex;
1626
1576
  }
1627
- if (!super.copyFrom(srcAtt)) {
1628
- return;
1577
+ return this.corner_table_.opposite(corner);
1578
+ }
1579
+ next(corner) {
1580
+ return this.corner_table_.next(corner);
1581
+ }
1582
+ previous(corner) {
1583
+ return this.corner_table_.previous(corner);
1584
+ }
1585
+ swingRight(corner) {
1586
+ return this.previous(this.opposite(this.previous(corner)));
1587
+ }
1588
+ swingLeft(corner) {
1589
+ return this.next(this.opposite(this.next(corner)));
1590
+ }
1591
+ numVertices() {
1592
+ return this.vertex_to_attribute_entry_id_map_.length;
1593
+ }
1594
+ numFaces() {
1595
+ return this.corner_table_.numFaces();
1596
+ }
1597
+ numCorners() {
1598
+ return this.corner_table_.numCorners();
1599
+ }
1600
+ vertex(corner) {
1601
+ return this.confidentVertex(corner);
1602
+ }
1603
+ confidentVertex(corner) {
1604
+ return this.corner_to_vertex_map_[corner];
1605
+ }
1606
+ leftMostCorner(v) {
1607
+ return this.vertex_to_left_most_corner_map_[v];
1608
+ }
1609
+ // --- Flat-array accessors: let DepthFirstTraverser avoid per-corner dispatch. ---
1610
+ cornerToVertexArray() {
1611
+ return this.corner_to_vertex_map_;
1612
+ }
1613
+ // Seam-aware opposite corners (seam edges -> -1), matching opposite(). Cached on
1614
+ // first use; seams and connectivity are finalized before traversal, so it's stable.
1615
+ oppositeCornerArray() {
1616
+ if (this._effectiveOpposite === null) {
1617
+ const nc = this.corner_table_.numCorners();
1618
+ const base = this.corner_table_.oppositeCornerArray();
1619
+ const seamCorners = this._seamCorners;
1620
+ if (seamCorners.length === 0) {
1621
+ this._effectiveOpposite = base;
1622
+ } else {
1623
+ const eff = scratchInt32(nc);
1624
+ eff.set(base.length === nc ? base : base.subarray(0, nc));
1625
+ for (let i = 0, l = seamCorners.length; i < l; ++i) {
1626
+ eff[seamCorners[i]] = kInvalidCornerIndex;
1627
+ }
1628
+ this._effectiveOpposite = eff;
1629
+ }
1629
1630
  }
1630
- this._identityMapping = srcAtt._identityMapping;
1631
- this._numUniqueEntries = srcAtt._numUniqueEntries;
1632
- this._indicesMap = srcAtt._indicesMap.slice();
1633
- if (srcAtt._attributeTransformData) {
1634
- this._attributeTransformData = srcAtt._attributeTransformData;
1635
- } else {
1636
- this._attributeTransformData = null;
1631
+ return this._effectiveOpposite;
1632
+ }
1633
+ vertexLeftmostCornerArray() {
1634
+ return this.vertex_to_left_most_corner_map_;
1635
+ }
1636
+ // Per-base-vertex seam flag (Uint8Array); exposed so hot dedup loops inline the lookup.
1637
+ vertexOnSeamArray() {
1638
+ return this.is_vertex_on_seam_;
1639
+ }
1640
+ hasSameSeams(other) {
1641
+ if (other === null || other === void 0) return false;
1642
+ const seamA = this.is_edge_on_seam_;
1643
+ const seamB = other.is_edge_on_seam_;
1644
+ if (seamA.length !== seamB.length) return false;
1645
+ for (let i = 0, l = seamA.length; i < l; ++i) {
1646
+ if (seamA[i] !== seamB[i]) return false;
1637
1647
  }
1648
+ return true;
1649
+ }
1650
+ adoptVertexRecompute(other) {
1651
+ this.corner_to_vertex_map_ = other.corner_to_vertex_map_;
1652
+ this.vertex_to_attribute_entry_id_map_ = other.vertex_to_attribute_entry_id_map_;
1653
+ this.vertex_to_left_most_corner_map_ = other.vertex_to_left_most_corner_map_;
1654
+ this.no_interior_seams_ = other.no_interior_seams_;
1655
+ this._effectiveOpposite = other._effectiveOpposite;
1656
+ this._seamCorners = other._seamCorners;
1638
1657
  }
1639
1658
  };
1640
1659
 
@@ -1851,15 +1870,12 @@ var SequentialAttributeDecoder = class {
1851
1870
  decodeValues(pointIds, buffer) {
1852
1871
  const numValues = pointIds.length;
1853
1872
  const entrySize = this._attribute.byteStride;
1854
- let outBytePos = 0;
1855
- for (let i = 0; i < numValues; i++) {
1856
- const valueData = buffer.decodeBytes(entrySize);
1857
- if (valueData === void 0) {
1858
- return false;
1859
- }
1860
- this._attribute.buffer.write(outBytePos, valueData, entrySize);
1861
- outBytePos += entrySize;
1873
+ const totalSize = numValues * entrySize;
1874
+ const valueData = buffer.decodeBytesView(totalSize);
1875
+ if (valueData === void 0) {
1876
+ return false;
1862
1877
  }
1878
+ this._attribute.buffer.write(0, valueData, totalSize);
1863
1879
  return true;
1864
1880
  }
1865
1881
  setPortableAttribute(att) {
@@ -1997,6 +2013,9 @@ var RAnsDecoder = class {
1997
2013
  this.bufOffset = offset - 3;
1998
2014
  this.state = memGetLe24(buf, offset - 3) & 4194303;
1999
2015
  } else if (x === 3) {
2016
+ if (offset - base < 4) {
2017
+ return 1;
2018
+ }
2000
2019
  this.bufOffset = offset - 4;
2001
2020
  this.state = memGetLe32(buf, offset - 4) & 1073741823;
2002
2021
  } else {
@@ -2041,12 +2060,69 @@ var RAnsDecoder = class {
2041
2060
  }
2042
2061
  // Batch ransRead() into out[0..count): all fields hoisted to locals, state
2043
2062
  // written back once. Removes per-symbol property reads and call indirection.
2063
+ // lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
2064
+ // which would make the hot lutTable[rem] access site polymorphic — dispatch
2065
+ // once here so each loop body stays monomorphic on its concrete type. The
2066
+ // three bodies are intentionally identical copies.
2044
2067
  decodeSymbols(out, count) {
2068
+ const lutTable = this.lutTable;
2069
+ if (lutTable instanceof Uint8Array) {
2070
+ this._decodeSymbolsU8(out, count, lutTable);
2071
+ } else if (lutTable instanceof Uint16Array) {
2072
+ this._decodeSymbolsU16(out, count, lutTable);
2073
+ } else {
2074
+ this._decodeSymbolsU32(out, count, lutTable);
2075
+ }
2076
+ }
2077
+ _decodeSymbolsU8(out, count, lutTable) {
2078
+ const buf = this.buf;
2079
+ const lRansBase = this.lRansBase;
2080
+ const ransPrecisionBits = this.ransPrecisionBits;
2081
+ const ransPrecisionMask = this.ransPrecisionMask;
2082
+ const probTable = this.probTable;
2083
+ const cumProbTable = this.cumProbTable;
2084
+ let state = this.state;
2085
+ let bufOffset = this.bufOffset;
2086
+ const bufStart = this.bufStart;
2087
+ for (let i = 0; i < count; ++i) {
2088
+ while (state < lRansBase && bufOffset > bufStart) {
2089
+ state = state << 8 | buf[--bufOffset];
2090
+ }
2091
+ const rem = state & ransPrecisionMask;
2092
+ const symbol = lutTable[rem];
2093
+ out[i] = symbol;
2094
+ state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
2095
+ }
2096
+ this.state = state;
2097
+ this.bufOffset = bufOffset;
2098
+ }
2099
+ _decodeSymbolsU16(out, count, lutTable) {
2100
+ const buf = this.buf;
2101
+ const lRansBase = this.lRansBase;
2102
+ const ransPrecisionBits = this.ransPrecisionBits;
2103
+ const ransPrecisionMask = this.ransPrecisionMask;
2104
+ const probTable = this.probTable;
2105
+ const cumProbTable = this.cumProbTable;
2106
+ let state = this.state;
2107
+ let bufOffset = this.bufOffset;
2108
+ const bufStart = this.bufStart;
2109
+ for (let i = 0; i < count; ++i) {
2110
+ while (state < lRansBase && bufOffset > bufStart) {
2111
+ state = state << 8 | buf[--bufOffset];
2112
+ }
2113
+ const rem = state & ransPrecisionMask;
2114
+ const symbol = lutTable[rem];
2115
+ out[i] = symbol;
2116
+ state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
2117
+ }
2118
+ this.state = state;
2119
+ this.bufOffset = bufOffset;
2120
+ }
2121
+ _decodeSymbolsU32(out, count, lutTable) {
2045
2122
  const buf = this.buf;
2046
2123
  const lRansBase = this.lRansBase;
2047
2124
  const ransPrecisionBits = this.ransPrecisionBits;
2048
2125
  const ransPrecisionMask = this.ransPrecisionMask;
2049
- const lutTable = this.lutTable;
2050
2126
  const probTable = this.probTable;
2051
2127
  const cumProbTable = this.cumProbTable;
2052
2128
  let state = this.state;
@@ -2107,16 +2183,12 @@ function computeRAnsPrecisionFromUniqueSymbolsBitLength(symbolsBitLength) {
2107
2183
  return unclamped;
2108
2184
  }
2109
2185
  var RAnsSymbolDecoder = class {
2110
- uniqueSymbolsBitLength_;
2111
2186
  ransPrecisionBits_;
2112
- ransPrecision_;
2113
2187
  probabilityTable_;
2114
2188
  numSymbols_;
2115
2189
  ans_;
2116
2190
  constructor(uniqueSymbolsBitLength) {
2117
- this.uniqueSymbolsBitLength_ = uniqueSymbolsBitLength;
2118
2191
  this.ransPrecisionBits_ = computeRAnsPrecisionFromUniqueSymbolsBitLength(uniqueSymbolsBitLength);
2119
- this.ransPrecision_ = 1 << this.ransPrecisionBits_;
2120
2192
  this.probabilityTable_ = null;
2121
2193
  this.numSymbols_ = 0;
2122
2194
  this.ans_ = new RAnsDecoder(this.ransPrecisionBits_);
@@ -3528,8 +3600,7 @@ var MeshPredictionSchemeTexCoordsPortablePredictor = class {
3528
3600
  }
3529
3601
  const xUV0 = nUV0 * pnNorm2Squared + cnDotPn * pnUV0;
3530
3602
  const xUV1 = nUV1 * pnNorm2Squared + cnDotPn * pnUV1;
3531
- const pnAbsMax = Math.max(Math.abs(pn0), Math.abs(pn1), Math.abs(pn2));
3532
- if (pnAbsMax > 0 && Math.abs(cnDotPn) > INT64_MAX / pnAbsMax) {
3603
+ if (pnAbsMaxG > 0 && cnDotPnAbs > INT64_MAX / pnAbsMaxG) {
3533
3604
  return false;
3534
3605
  }
3535
3606
  const xPos0 = next0 + Math.trunc(cnDotPn * pn0 / pnNorm2Squared);
@@ -3897,7 +3968,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3897
3968
  if (portableAttributeData.byteLength < 4 * numValues) {
3898
3969
  return false;
3899
3970
  }
3900
- const bytes = buffer.decodeBytes(4 * numValues);
3971
+ const bytes = buffer.decodeBytesView(4 * numValues);
3901
3972
  if (bytes === void 0) return false;
3902
3973
  const srcView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
3903
3974
  for (let i = 0; i < numValues; i++) {
@@ -3907,12 +3978,13 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
3907
3978
  if (buffer.remainingSize < numBytes * numValues) {
3908
3979
  return false;
3909
3980
  }
3981
+ const bytes = buffer.decodeBytesView(numBytes * numValues);
3982
+ if (bytes === void 0) return false;
3910
3983
  for (let i = 0; i < numValues; i++) {
3911
- const valueBytes = buffer.decodeBytes(numBytes);
3912
- if (valueBytes === void 0) return false;
3913
3984
  let val = 0;
3985
+ const valueOffset = i * numBytes;
3914
3986
  for (let b = 0; b < numBytes; b++) {
3915
- val |= valueBytes[b] << b * 8;
3987
+ val |= bytes[valueOffset + b] << b * 8;
3916
3988
  }
3917
3989
  portableAttributeData[i] = val;
3918
3990
  }
@@ -4574,15 +4646,6 @@ var AttributeQuantizationTransform = class _AttributeQuantizationTransform exten
4574
4646
  }
4575
4647
  return true;
4576
4648
  }
4577
- get quantizationBits() {
4578
- return this._quantizationBits;
4579
- }
4580
- get range() {
4581
- return this._range;
4582
- }
4583
- minValue(axis) {
4584
- return this._minValues[axis];
4585
- }
4586
4649
  static _isQuantizationValid(quantizationBits) {
4587
4650
  return quantizationBits >= 1 && quantizationBits <= 30;
4588
4651
  }
@@ -4661,7 +4724,7 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
4661
4724
  if (!this._sequencer) {
4662
4725
  return false;
4663
4726
  }
4664
- if (!this._sequencer.generateSequence(this._pointIds)) {
4727
+ if (!this._sequencer.generateSequence()) {
4665
4728
  return false;
4666
4729
  }
4667
4730
  this._pointIds = this._sequencer.getOutputPointIds();
@@ -4785,19 +4848,29 @@ var DepthFirstTraverser = class {
4785
4848
  init(cornerTable, observer) {
4786
4849
  this._cornerTable = cornerTable;
4787
4850
  this._observer = observer;
4788
- this._isFaceVisited = new Uint8Array(cornerTable.numFaces());
4789
- this._isVertexVisited = new Uint8Array(cornerTable.numVertices());
4851
+ this._isFaceVisited = null;
4852
+ this._isVertexVisited = null;
4790
4853
  this._numVisitedFaces = 0;
4791
4854
  this._cornerToVertex = cornerTable.cornerToVertexArray();
4792
4855
  this._oppositeCorners = cornerTable.oppositeCornerArray();
4793
4856
  this._vertexLeftmost = cornerTable.vertexLeftmostCornerArray();
4794
4857
  this._numCorners = cornerTable.numCorners();
4795
- this._cornerTraversalStack = new Int32Array(this._numCorners);
4796
4858
  }
4797
4859
  cornerTable() {
4798
4860
  return this._cornerTable;
4799
4861
  }
4862
+ // Scratch buffers are set up here rather than in init() so a shared-traversal
4863
+ // -cache hit — where generateSequence returns before any traversal — skips
4864
+ // this entirely, including the visited-flag zero-fill (worth ~0.5% on the
4865
+ // 488-primitive manablade-static bundle, which shares attribute corner tables across
4866
+ // primitives). Uint8Array (0/1) instead of Array(bool): these flags are read
4867
+ // and written on every corner of the hottest decode loop (traverseFromCorner).
4868
+ // Decode-scoped scratch: released in bulk at the end of the decode.
4800
4869
  onTraversalStart() {
4870
+ const cornerTable = this._cornerTable;
4871
+ this._isFaceVisited = scratchUint8Zeroed(cornerTable.numFaces());
4872
+ this._isVertexVisited = scratchUint8Zeroed(cornerTable.numVertices());
4873
+ this._cornerTraversalStack = scratchInt32(this._numCorners);
4801
4874
  }
4802
4875
  onTraversalEnd() {
4803
4876
  }
@@ -4813,6 +4886,14 @@ var DepthFirstTraverser = class {
4813
4886
  const vertexLeftmost = this._vertexLeftmost;
4814
4887
  const stack = this._cornerTraversalStack;
4815
4888
  let numVisitedFaces = this._numVisitedFaces;
4889
+ const sequencer = observer._sequencer;
4890
+ const encodingData = observer._encodingData;
4891
+ const obsFaces = observer._faces;
4892
+ const encodedToCornerMap = observer._encodedToCornerMap;
4893
+ const vertexToEncodedMap = observer._vertexToEncodedMap;
4894
+ const outPointIds = sequencer._outPointIds;
4895
+ let numOutPoints = sequencer._numOutPoints;
4896
+ let numValues = encodingData.numValues;
4816
4897
  let stackSize = 0;
4817
4898
  stack[stackSize++] = cornerId;
4818
4899
  const nextCorner = cornerId % 3 === 2 ? cornerId - 2 : cornerId + 1;
@@ -4824,11 +4905,15 @@ var DepthFirstTraverser = class {
4824
4905
  }
4825
4906
  if (!isVertexVisited[nextVert]) {
4826
4907
  isVertexVisited[nextVert] = 1;
4827
- observer.onNewVertexVisited(nextVert, nextCorner);
4908
+ outPointIds[numOutPoints++] = obsFaces[nextCorner];
4909
+ encodedToCornerMap[numValues] = nextCorner;
4910
+ vertexToEncodedMap[nextVert] = numValues++;
4828
4911
  }
4829
4912
  if (!isVertexVisited[prevVert]) {
4830
4913
  isVertexVisited[prevVert] = 1;
4831
- observer.onNewVertexVisited(prevVert, prevCorner);
4914
+ outPointIds[numOutPoints++] = obsFaces[prevCorner];
4915
+ encodedToCornerMap[numValues] = prevCorner;
4916
+ vertexToEncodedMap[prevVert] = numValues++;
4832
4917
  }
4833
4918
  while (stackSize > 0) {
4834
4919
  cornerId = stack[stackSize - 1];
@@ -4842,6 +4927,8 @@ var DepthFirstTraverser = class {
4842
4927
  numVisitedFaces++;
4843
4928
  const vertId = cornerToVertex[cornerId];
4844
4929
  if (vertId === kInvalidVertexIndex2) {
4930
+ sequencer._numOutPoints = numOutPoints;
4931
+ encodingData.numValues = numValues;
4845
4932
  return false;
4846
4933
  }
4847
4934
  if (!isVertexVisited[vertId]) {
@@ -4852,7 +4939,9 @@ var DepthFirstTraverser = class {
4852
4939
  onBoundary = oppositeCorners[nextLc] < 0;
4853
4940
  }
4854
4941
  isVertexVisited[vertId] = 1;
4855
- observer.onNewVertexVisited(vertId, cornerId);
4942
+ outPointIds[numOutPoints++] = obsFaces[cornerId];
4943
+ encodedToCornerMap[numValues] = cornerId;
4944
+ vertexToEncodedMap[vertId] = numValues++;
4856
4945
  if (!onBoundary) {
4857
4946
  const nextCornerId2 = cornerId % 3 === 2 ? cornerId - 2 : cornerId + 1;
4858
4947
  cornerId = oppositeCorners[nextCornerId2];
@@ -4889,6 +4978,8 @@ var DepthFirstTraverser = class {
4889
4978
  }
4890
4979
  }
4891
4980
  this._numVisitedFaces = numVisitedFaces;
4981
+ sequencer._numOutPoints = numOutPoints;
4982
+ encodingData.numValues = numValues;
4892
4983
  return true;
4893
4984
  }
4894
4985
  };
@@ -5101,7 +5192,7 @@ var MeshTraversalSequencer = class {
5101
5192
  setTraverser(traverser) {
5102
5193
  this._traverser = traverser;
5103
5194
  }
5104
- generateSequence(_outPointIds) {
5195
+ generateSequence() {
5105
5196
  const cornerTable = this._traverser.cornerTable();
5106
5197
  const methodId = this._traverser._traversalMethodId;
5107
5198
  const cacheKey = cornerTable.cornerToVertexArray();
@@ -5439,7 +5530,7 @@ var MeshEdgebreakerDecoderImpl = class {
5439
5530
  return true;
5440
5531
  }
5441
5532
  _decodeConnectivity(numSymbols) {
5442
- const activeCornerStack = new Int32Array(numSymbols + this._topologySplitData.length + 16);
5533
+ const activeCornerStack = scratchInt32(numSymbols + this._topologySplitData.length + 16);
5443
5534
  let activeCornerStackSize = 0;
5444
5535
  const topologySplitActiveCorners = /* @__PURE__ */ new Map();
5445
5536
  const invalidVertices = [];
@@ -6040,7 +6131,8 @@ var CornerTable = class {
6040
6131
  const newVertex = this._numVertices;
6041
6132
  this._numVertices++;
6042
6133
  if (newVertex >= this._vertexCorners.length) {
6043
- const newArr = new Int32Array(this._vertexCorners.length + 64);
6134
+ const newCapacity = Math.max(newVertex + 1, this._vertexCorners.length * 2, 64);
6135
+ const newArr = new Int32Array(newCapacity);
6044
6136
  newArr.fill(-1);
6045
6137
  newArr.set(this._vertexCorners);
6046
6138
  this._vertexCorners = newArr;
@@ -6303,7 +6395,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
6303
6395
  this._activeContext = -1;
6304
6396
  this._minValence = 2;
6305
6397
  this._maxValence = 7;
6306
- this._vertexValences = [];
6398
+ this._vertexValences = new Int32Array(0);
6307
6399
  this._contextSymbols = [];
6308
6400
  this._contextCounters = [];
6309
6401
  }
@@ -6327,7 +6419,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
6327
6419
  if (this._numVertices < 0) {
6328
6420
  return false;
6329
6421
  }
6330
- this._vertexValences = new Array(this._numVertices).fill(0);
6422
+ this._vertexValences = new Int32Array(this._numVertices);
6331
6423
  const numUniqueValences = this._maxValence - this._minValence + 1;
6332
6424
  this._contextSymbols = new Array(numUniqueValences);
6333
6425
  this._contextCounters = new Array(numUniqueValences);
@@ -6369,34 +6461,37 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
6369
6461
  return this._lastSymbol;
6370
6462
  }
6371
6463
  newActiveCornerReached(corner) {
6372
- const ct = this._cornerTable;
6373
- const next = ct.next(corner);
6374
- const prev = ct.previous(corner);
6464
+ const cornerToVertex = this._cornerTable._cornerToVertex;
6465
+ const valences = this._vertexValences;
6466
+ const next = corner % 3 === 2 ? corner - 2 : corner + 1;
6467
+ const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
6468
+ const vertNext = cornerToVertex[next];
6469
+ const vertPrev = cornerToVertex[prev];
6375
6470
  switch (this._lastSymbol) {
6376
6471
  case TOPOLOGY_C:
6377
6472
  case TOPOLOGY_S:
6378
- this._vertexValences[ct.vertex(next)] += 1;
6379
- this._vertexValences[ct.vertex(prev)] += 1;
6473
+ valences[vertNext] += 1;
6474
+ valences[vertPrev] += 1;
6380
6475
  break;
6381
6476
  case TOPOLOGY_R:
6382
- this._vertexValences[ct.vertex(corner)] += 1;
6383
- this._vertexValences[ct.vertex(next)] += 1;
6384
- this._vertexValences[ct.vertex(prev)] += 2;
6477
+ valences[cornerToVertex[corner]] += 1;
6478
+ valences[vertNext] += 1;
6479
+ valences[vertPrev] += 2;
6385
6480
  break;
6386
6481
  case TOPOLOGY_L:
6387
- this._vertexValences[ct.vertex(corner)] += 1;
6388
- this._vertexValences[ct.vertex(next)] += 2;
6389
- this._vertexValences[ct.vertex(prev)] += 1;
6482
+ valences[cornerToVertex[corner]] += 1;
6483
+ valences[vertNext] += 2;
6484
+ valences[vertPrev] += 1;
6390
6485
  break;
6391
6486
  case TOPOLOGY_E:
6392
- this._vertexValences[ct.vertex(corner)] += 2;
6393
- this._vertexValences[ct.vertex(next)] += 2;
6394
- this._vertexValences[ct.vertex(prev)] += 2;
6487
+ valences[cornerToVertex[corner]] += 2;
6488
+ valences[vertNext] += 2;
6489
+ valences[vertPrev] += 2;
6395
6490
  break;
6396
6491
  default:
6397
6492
  break;
6398
6493
  }
6399
- const activeValence = this._vertexValences[ct.vertex(next)];
6494
+ const activeValence = valences[vertNext];
6400
6495
  let clampedValence;
6401
6496
  if (activeValence < this._minValence) {
6402
6497
  clampedValence = this._minValence;
@@ -6515,45 +6610,30 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6515
6610
  return false;
6516
6611
  }
6517
6612
  } else {
6613
+ const mesh = this.mesh();
6614
+ mesh.setNumFaces(numFaces);
6615
+ const faces = mesh.faces_;
6616
+ const numIndices = numFaces * 3;
6617
+ const buffer = this.buffer();
6518
6618
  if (numPoints < 256) {
6519
- for (let i = 0; i < numFaces; ++i) {
6520
- const face = [0, 0, 0];
6521
- for (let j = 0; j < 3; ++j) {
6522
- const val = this.buffer().decodeUint8();
6523
- if (val === void 0) return false;
6524
- face[j] = val;
6525
- }
6526
- this.mesh().addFace(face);
6527
- }
6619
+ const src = buffer.decodeBytesView(numIndices);
6620
+ if (src === void 0) return false;
6621
+ for (let i = 0; i < numIndices; ++i) faces[i] = src[i];
6528
6622
  } else if (numPoints < 1 << 16) {
6529
- for (let i = 0; i < numFaces; ++i) {
6530
- const face = [0, 0, 0];
6531
- for (let j = 0; j < 3; ++j) {
6532
- const val = this.buffer().decodeUint16();
6533
- if (val === void 0) return false;
6534
- face[j] = val;
6535
- }
6536
- this.mesh().addFace(face);
6537
- }
6623
+ const src = buffer.decodeBytesView(numIndices * 2);
6624
+ if (src === void 0) return false;
6625
+ for (let i = 0; i < numIndices; ++i) faces[i] = src[i * 2] | src[i * 2 + 1] << 8;
6538
6626
  } else if (numPoints < 1 << 21) {
6539
- for (let i = 0; i < numFaces; ++i) {
6540
- const face = [0, 0, 0];
6541
- for (let j = 0; j < 3; ++j) {
6542
- const val = decodeVarint(this.buffer());
6543
- if (val === void 0) return false;
6544
- face[j] = val;
6545
- }
6546
- this.mesh().addFace(face);
6627
+ for (let i = 0; i < numIndices; ++i) {
6628
+ const val = decodeVarint(buffer);
6629
+ if (val === void 0) return false;
6630
+ faces[i] = val;
6547
6631
  }
6548
6632
  } else {
6549
- for (let i = 0; i < numFaces; ++i) {
6550
- const face = [0, 0, 0];
6551
- for (let j = 0; j < 3; ++j) {
6552
- const val = this.buffer().decodeUint32();
6553
- if (val === void 0) return false;
6554
- face[j] = val;
6555
- }
6556
- this.mesh().addFace(face);
6633
+ const src = buffer.decodeBytesView(numIndices * 4);
6634
+ if (src === void 0) return false;
6635
+ for (let i = 0; i < numIndices; ++i) {
6636
+ faces[i] = src[i * 4] | src[i * 4 + 1] << 8 | src[i * 4 + 2] << 16 | src[i * 4 + 3] << 24;
6557
6637
  }
6558
6638
  }
6559
6639
  }
@@ -6567,32 +6647,31 @@ var MeshSequentialDecoder = class extends MeshDecoder {
6567
6647
  );
6568
6648
  }
6569
6649
  _decodeAndDecompressIndices(numFaces) {
6570
- const indicesBuffer = new Uint32Array(numFaces * 3);
6571
- if (!decodeSymbols(numFaces * 3, 1, this.buffer(), indicesBuffer)) {
6650
+ const numIndices = numFaces * 3;
6651
+ const indicesBuffer = new Uint32Array(numIndices);
6652
+ if (!decodeSymbols(numIndices, 1, this.buffer(), indicesBuffer)) {
6572
6653
  return false;
6573
6654
  }
6655
+ const mesh = this.mesh();
6656
+ mesh.setNumFaces(numFaces);
6657
+ const faces = mesh.faces_;
6574
6658
  let lastIndexValue = 0;
6575
- let vertexIndex = 0;
6576
- for (let i = 0; i < numFaces; ++i) {
6577
- const face = [0, 0, 0];
6578
- for (let j = 0; j < 3; ++j) {
6579
- const encodedVal = indicesBuffer[vertexIndex++];
6580
- let indexDiff = encodedVal >>> 1;
6581
- if (encodedVal & 1) {
6582
- if (indexDiff > lastIndexValue) {
6583
- return false;
6584
- }
6585
- indexDiff = -indexDiff;
6586
- } else {
6587
- if (indexDiff > 2147483647 - lastIndexValue) {
6588
- return false;
6589
- }
6659
+ for (let i = 0; i < numIndices; ++i) {
6660
+ const encodedVal = indicesBuffer[i];
6661
+ let indexDiff = encodedVal >>> 1;
6662
+ if (encodedVal & 1) {
6663
+ if (indexDiff > lastIndexValue) {
6664
+ return false;
6665
+ }
6666
+ indexDiff = -indexDiff;
6667
+ } else {
6668
+ if (indexDiff > 2147483647 - lastIndexValue) {
6669
+ return false;
6590
6670
  }
6591
- const indexValue = indexDiff + lastIndexValue | 0;
6592
- face[j] = indexValue;
6593
- lastIndexValue = indexValue;
6594
6671
  }
6595
- this.mesh().addFace(face);
6672
+ const indexValue = indexDiff + lastIndexValue | 0;
6673
+ faces[i] = indexValue;
6674
+ lastIndexValue = indexValue;
6596
6675
  }
6597
6676
  return true;
6598
6677
  }
@@ -6650,9 +6729,15 @@ var Decoder = class {
6650
6729
  if (result.header.encoderType !== EncodedGeometryType.TRIANGULAR_MESH) {
6651
6730
  return { ok: false, message: "Input is not a mesh." };
6652
6731
  }
6653
- const decoder = createMeshDecoder(result.header.encoderMethod);
6654
- const status = decoder.decodeMesh(this.options_, inBuffer, outGeometry);
6655
- return { ok: status.ok(), message: status.errorMsg };
6732
+ try {
6733
+ const decoder = createMeshDecoder(result.header.encoderMethod);
6734
+ const status = decoder.decodeMesh(this.options_, inBuffer, outGeometry);
6735
+ return { ok: status.ok(), message: status.errorMsg };
6736
+ } catch (error) {
6737
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
6738
+ } finally {
6739
+ releaseScratch();
6740
+ }
6656
6741
  }
6657
6742
  options() {
6658
6743
  return this.options_;
@@ -6663,21 +6748,15 @@ var Decoder = class {
6663
6748
  var decodeDracoMesh = (data) => {
6664
6749
  const buffer = new DecoderBuffer();
6665
6750
  buffer.init(data, data.length);
6666
- if (Decoder.getEncodedGeometryType(buffer) !== EncodedGeometryType.TRIANGULAR_MESH) {
6667
- throw new Error("minidraco: Input is not a Draco triangular mesh.");
6668
- }
6669
6751
  const decoder = new Decoder();
6670
6752
  const result = decoder.decodeMeshFromBuffer(buffer);
6671
6753
  if (!result.ok || result.mesh === null) {
6672
- throw new Error(`minidraco: ${result.message}`);
6754
+ const message = result.message === "Input is not a mesh." ? "Input is not a Draco triangular mesh." : result.message;
6755
+ throw new Error(`minidraco: ${message}`);
6673
6756
  }
6674
6757
  return result.mesh;
6675
6758
  };
6676
6759
  export {
6677
- DataType,
6678
- Decoder,
6679
- DecoderBuffer,
6680
- EncodedGeometryType,
6681
6760
  Type as GeometryAttributeType,
6682
6761
  Mesh,
6683
6762
  PointAttribute,