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