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