minidraco 0.4.0 → 0.5.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 +11 -10
- package/dist/index.js +311 -57
- package/dist/three.js +311 -57
- package/dist/worker.js +311 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,16 +43,17 @@ Median across an 18-model corpus vs [draco.js](https://github.com/mrdoob/draco.j
|
|
|
43
43
|
[draco3d](https://www.npmjs.com/package/draco3d) wasm decoder (full results in
|
|
44
44
|
[BENCH.md](https://github.com/verekia/minidraco/blob/main/BENCH.md)):
|
|
45
45
|
|
|
46
|
-
| benchmark
|
|
47
|
-
|
|
|
48
|
-
| single-threaded decode — bun (JSC)
|
|
49
|
-
| single-threaded decode — Chrome (V8)
|
|
50
|
-
| `GLTFLoader.parse`, worker pool — Chrome (V8) | 🟢 1.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
| benchmark | vs draco.js | vs draco3d wasm |
|
|
47
|
+
| -------------------------------------------------- | --------------- | --------------- |
|
|
48
|
+
| single-threaded decode — bun (JSC) | 🟢 1.27× faster | 🟢 1.38× faster |
|
|
49
|
+
| single-threaded decode — Chrome (V8) | 🟢 1.29× faster | 🟢 1.11× faster |
|
|
50
|
+
| `GLTFLoader.parse`, warm worker pool — Chrome (V8) | 🟢 1.62× faster | ⚪ even |
|
|
51
|
+
| `GLTFLoader.parse`, cold first load — Chrome (V8) | 🟢 1.31× faster | ⚪ even |
|
|
52
|
+
|
|
53
|
+
Faster than draco.js across the corpus, ahead of the wasm decoder single-threaded, and even with
|
|
54
|
+
it in a real `GLTFLoader.parse` with the main thread left free — both warm and on the first load
|
|
55
|
+
of a session, where minidraco's worker pool is still JIT-warming while the wasm decoder is
|
|
56
|
+
fetching and compiling its module (no `draco_decoder.wasm` to host or download here).
|
|
56
57
|
|
|
57
58
|
## Download size
|
|
58
59
|
|
package/dist/index.js
CHANGED
|
@@ -1264,6 +1264,8 @@ var MetadataDecoder = class {
|
|
|
1264
1264
|
var ANS_P8_PRECISION = 256;
|
|
1265
1265
|
var ANS_L_BASE = 4096;
|
|
1266
1266
|
var ANS_IO_BASE = 256;
|
|
1267
|
+
var COARSE_STREAM_FACTOR = 8;
|
|
1268
|
+
var COARSE_BUCKET_BITS = 8;
|
|
1267
1269
|
function memGetLe16(buf, offset) {
|
|
1268
1270
|
return buf[offset] | buf[offset + 1] << 8;
|
|
1269
1271
|
}
|
|
@@ -1341,6 +1343,13 @@ var RAnsDecoder = class {
|
|
|
1341
1343
|
lutTable;
|
|
1342
1344
|
probTable;
|
|
1343
1345
|
cumProbTable;
|
|
1346
|
+
// Short-stream mode (see ransBuildLookUpTable): no full-precision lut; a
|
|
1347
|
+
// 256-entry bucket table narrows each lookup to a symbol range that a short
|
|
1348
|
+
// cumProb scan finishes. cumProbTable then carries one extra trailing entry
|
|
1349
|
+
// (== ransPrecision) so the scan needs no bounds check.
|
|
1350
|
+
coarse;
|
|
1351
|
+
bucketShift;
|
|
1352
|
+
bucketTable;
|
|
1344
1353
|
buf;
|
|
1345
1354
|
bufOffset;
|
|
1346
1355
|
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
@@ -1355,6 +1364,9 @@ var RAnsDecoder = class {
|
|
|
1355
1364
|
this.lutTable = null;
|
|
1356
1365
|
this.probTable = null;
|
|
1357
1366
|
this.cumProbTable = null;
|
|
1367
|
+
this.coarse = false;
|
|
1368
|
+
this.bucketShift = 0;
|
|
1369
|
+
this.bucketTable = null;
|
|
1358
1370
|
this.buf = null;
|
|
1359
1371
|
this.bufOffset = 0;
|
|
1360
1372
|
this.bufStart = 0;
|
|
@@ -1414,6 +1426,10 @@ var RAnsDecoder = class {
|
|
|
1414
1426
|
tablePool.push(this.cumProbTable);
|
|
1415
1427
|
this.cumProbTable = null;
|
|
1416
1428
|
}
|
|
1429
|
+
if (this.bucketTable !== null) {
|
|
1430
|
+
tablePool.push(this.bucketTable);
|
|
1431
|
+
this.bucketTable = null;
|
|
1432
|
+
}
|
|
1417
1433
|
return this.state === this.lRansBase;
|
|
1418
1434
|
}
|
|
1419
1435
|
ransRead() {
|
|
@@ -1427,7 +1443,14 @@ var RAnsDecoder = class {
|
|
|
1427
1443
|
}
|
|
1428
1444
|
const quo = state >>> this.ransPrecisionBits;
|
|
1429
1445
|
const rem = state & this.ransPrecisionMask;
|
|
1430
|
-
|
|
1446
|
+
let symbol;
|
|
1447
|
+
if (this.coarse) {
|
|
1448
|
+
const cumProbTable = this.cumProbTable;
|
|
1449
|
+
symbol = this.bucketTable[rem >> this.bucketShift];
|
|
1450
|
+
while (cumProbTable[symbol + 1] <= rem) symbol++;
|
|
1451
|
+
} else {
|
|
1452
|
+
symbol = this.lutTable[rem];
|
|
1453
|
+
}
|
|
1431
1454
|
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
1432
1455
|
this.bufOffset = bufOffset;
|
|
1433
1456
|
return symbol;
|
|
@@ -1439,6 +1462,10 @@ var RAnsDecoder = class {
|
|
|
1439
1462
|
// once here so each loop body stays monomorphic on its concrete type. The
|
|
1440
1463
|
// three bodies are intentionally identical copies.
|
|
1441
1464
|
decodeSymbols(out, count) {
|
|
1465
|
+
if (this.coarse) {
|
|
1466
|
+
this._decodeSymbolsCoarse(out, count);
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1442
1469
|
const lutTable = this.lutTable;
|
|
1443
1470
|
if (lutTable instanceof Uint8Array) {
|
|
1444
1471
|
this._decodeSymbolsU8(out, count, lutTable);
|
|
@@ -1492,6 +1519,33 @@ var RAnsDecoder = class {
|
|
|
1492
1519
|
this.state = state;
|
|
1493
1520
|
this.bufOffset = bufOffset;
|
|
1494
1521
|
}
|
|
1522
|
+
// Short-stream loop: bucket table + cumProb scan instead of the full lut.
|
|
1523
|
+
// Same state arithmetic as the lut loops, so the output is identical.
|
|
1524
|
+
_decodeSymbolsCoarse(out, count) {
|
|
1525
|
+
const buf = this.buf;
|
|
1526
|
+
const lRansBase = this.lRansBase;
|
|
1527
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1528
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1529
|
+
const probTable = this.probTable;
|
|
1530
|
+
const cumProbTable = this.cumProbTable;
|
|
1531
|
+
const bucketTable = this.bucketTable;
|
|
1532
|
+
const bucketShift = this.bucketShift;
|
|
1533
|
+
let state = this.state;
|
|
1534
|
+
let bufOffset = this.bufOffset;
|
|
1535
|
+
const bufStart = this.bufStart;
|
|
1536
|
+
for (let i = 0; i < count; ++i) {
|
|
1537
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1538
|
+
state = state << 8 | buf[--bufOffset];
|
|
1539
|
+
}
|
|
1540
|
+
const rem = state & ransPrecisionMask;
|
|
1541
|
+
let symbol = bucketTable[rem >> bucketShift];
|
|
1542
|
+
while (cumProbTable[symbol + 1] <= rem) symbol++;
|
|
1543
|
+
out[i] = symbol;
|
|
1544
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1545
|
+
}
|
|
1546
|
+
this.state = state;
|
|
1547
|
+
this.bufOffset = bufOffset;
|
|
1548
|
+
}
|
|
1495
1549
|
_decodeSymbolsU32(out, count, lutTable) {
|
|
1496
1550
|
const buf = this.buf;
|
|
1497
1551
|
const lRansBase = this.lRansBase;
|
|
@@ -1514,23 +1568,62 @@ var RAnsDecoder = class {
|
|
|
1514
1568
|
this.state = state;
|
|
1515
1569
|
this.bufOffset = bufOffset;
|
|
1516
1570
|
}
|
|
1517
|
-
// Builds the
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1571
|
+
// Builds the decoding tables. Returns false on bad input data.
|
|
1572
|
+
//
|
|
1573
|
+
// expectedCount is how many symbols the caller will decode from this stream.
|
|
1574
|
+
// The full lut has ransPrecision (>= 4096) entries, and a primitive-heavy
|
|
1575
|
+
// file builds thousands of them to decode a few dozen symbols each -- on such
|
|
1576
|
+
// files the table builds cost more than the decodes. Short streams therefore
|
|
1577
|
+
// get a coarse 256-entry bucket table (symbol at the start of each
|
|
1578
|
+
// precision/256-wide bucket) and finish each lookup with a scan of the
|
|
1579
|
+
// cumulative probabilities; long streams keep the exact lut, whose per-symbol
|
|
1580
|
+
// cost is lower.
|
|
1581
|
+
ransBuildLookUpTable(tokenProbs, numSymbols, expectedCount = 2147483647) {
|
|
1582
|
+
const ransPrecision = this.ransPrecision;
|
|
1583
|
+
const coarse = numSymbols <= 65535 && expectedCount * COARSE_STREAM_FACTOR < ransPrecision;
|
|
1584
|
+
this.coarse = coarse;
|
|
1521
1585
|
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
1522
|
-
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
1523
|
-
this.lutTable = lutTable;
|
|
1586
|
+
const cumProbTable = acquirePooled(Uint32Array, numSymbols + 1);
|
|
1524
1587
|
this.probTable = probTable;
|
|
1525
1588
|
this.cumProbTable = cumProbTable;
|
|
1526
1589
|
let cumProb = 0;
|
|
1590
|
+
if (coarse) {
|
|
1591
|
+
this.lutTable = null;
|
|
1592
|
+
for (let i = 0; i < numSymbols; ++i) {
|
|
1593
|
+
const prob = tokenProbs[i];
|
|
1594
|
+
probTable[i] = prob;
|
|
1595
|
+
cumProbTable[i] = cumProb;
|
|
1596
|
+
cumProb += prob;
|
|
1597
|
+
if (cumProb > ransPrecision) {
|
|
1598
|
+
return false;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
if (cumProb !== ransPrecision) {
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
cumProbTable[numSymbols] = ransPrecision;
|
|
1605
|
+
const bucketShift = this.ransPrecisionBits - COARSE_BUCKET_BITS;
|
|
1606
|
+
const bucketTable = acquirePooled(Uint16Array, 1 << COARSE_BUCKET_BITS);
|
|
1607
|
+
this.bucketShift = bucketShift;
|
|
1608
|
+
this.bucketTable = bucketTable;
|
|
1609
|
+
let symbol = 0;
|
|
1610
|
+
for (let b = 0; b < 1 << COARSE_BUCKET_BITS; ++b) {
|
|
1611
|
+
const rem = b << bucketShift;
|
|
1612
|
+
while (cumProbTable[symbol + 1] <= rem) symbol++;
|
|
1613
|
+
bucketTable[b] = symbol;
|
|
1614
|
+
}
|
|
1615
|
+
return true;
|
|
1616
|
+
}
|
|
1617
|
+
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
1618
|
+
const lutTable = acquirePooled(LutArray, ransPrecision);
|
|
1619
|
+
this.lutTable = lutTable;
|
|
1527
1620
|
let actProb = 0;
|
|
1528
1621
|
for (let i = 0; i < numSymbols; ++i) {
|
|
1529
1622
|
const prob = tokenProbs[i];
|
|
1530
1623
|
probTable[i] = prob;
|
|
1531
1624
|
cumProbTable[i] = cumProb;
|
|
1532
1625
|
cumProb += prob;
|
|
1533
|
-
if (cumProb >
|
|
1626
|
+
if (cumProb > ransPrecision) {
|
|
1534
1627
|
return false;
|
|
1535
1628
|
}
|
|
1536
1629
|
if (prob < 32) {
|
|
@@ -1542,9 +1635,10 @@ var RAnsDecoder = class {
|
|
|
1542
1635
|
}
|
|
1543
1636
|
actProb = cumProb;
|
|
1544
1637
|
}
|
|
1545
|
-
if (cumProb !==
|
|
1638
|
+
if (cumProb !== ransPrecision) {
|
|
1546
1639
|
return false;
|
|
1547
1640
|
}
|
|
1641
|
+
cumProbTable[numSymbols] = ransPrecision;
|
|
1548
1642
|
return true;
|
|
1549
1643
|
}
|
|
1550
1644
|
};
|
|
@@ -1993,14 +2087,18 @@ var PointCloudDecoder = class _PointCloudDecoder {
|
|
|
1993
2087
|
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
1994
2088
|
decoders[i2].collectPendingSymbolStreams(pending);
|
|
1995
2089
|
}
|
|
2090
|
+
const paired = pending.filter((stream) => !stream.ans.coarse);
|
|
1996
2091
|
let i = 0;
|
|
1997
|
-
for (; i + 1 <
|
|
1998
|
-
const a =
|
|
1999
|
-
const b =
|
|
2092
|
+
for (; i + 1 < paired.length; i += 2) {
|
|
2093
|
+
const a = paired[i];
|
|
2094
|
+
const b = paired[i + 1];
|
|
2000
2095
|
ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
|
|
2001
2096
|
}
|
|
2002
|
-
if (i <
|
|
2003
|
-
|
|
2097
|
+
if (i < paired.length) {
|
|
2098
|
+
paired[i].ans.decodeSymbols(paired[i].out, paired[i].count);
|
|
2099
|
+
}
|
|
2100
|
+
for (const stream of pending) {
|
|
2101
|
+
if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
|
|
2004
2102
|
}
|
|
2005
2103
|
for (let k = 0; k < decoders.length; k++) {
|
|
2006
2104
|
if (!decoders[k].decodeAttributesFinish()) {
|
|
@@ -2570,8 +2668,10 @@ var RAnsSymbolDecoder = class {
|
|
|
2570
2668
|
get numSymbols() {
|
|
2571
2669
|
return this.numSymbols_;
|
|
2572
2670
|
}
|
|
2573
|
-
// Initialize the decoder and decode the probability table.
|
|
2574
|
-
|
|
2671
|
+
// Initialize the decoder and decode the probability table. expectedCount is
|
|
2672
|
+
// the number of symbols the caller will decode (lets short streams skip the
|
|
2673
|
+
// full lookup table; see RAnsDecoder.ransBuildLookUpTable).
|
|
2674
|
+
create(buffer, expectedCount = 2147483647) {
|
|
2575
2675
|
if (buffer.bitstreamVersion === 0) {
|
|
2576
2676
|
return false;
|
|
2577
2677
|
}
|
|
@@ -2612,7 +2712,7 @@ var RAnsSymbolDecoder = class {
|
|
|
2612
2712
|
}
|
|
2613
2713
|
}
|
|
2614
2714
|
buffer.advance(pos - startPos);
|
|
2615
|
-
if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_)) {
|
|
2715
|
+
if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_, expectedCount)) {
|
|
2616
2716
|
return false;
|
|
2617
2717
|
}
|
|
2618
2718
|
return true;
|
|
@@ -2654,7 +2754,7 @@ function decodeSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
|
2654
2754
|
}
|
|
2655
2755
|
function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
2656
2756
|
const tagDecoder = new RAnsSymbolDecoder(5);
|
|
2657
|
-
if (!tagDecoder.create(srcBuffer)) {
|
|
2757
|
+
if (!tagDecoder.create(srcBuffer, Math.ceil(numValues / numComponents))) {
|
|
2658
2758
|
return false;
|
|
2659
2759
|
}
|
|
2660
2760
|
if (!tagDecoder.startDecoding(srcBuffer)) {
|
|
@@ -2719,7 +2819,7 @@ function parseRawSymbolStream(numValues, srcBuffer) {
|
|
|
2719
2819
|
return null;
|
|
2720
2820
|
}
|
|
2721
2821
|
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
2722
|
-
if (!decoder.create(srcBuffer)) {
|
|
2822
|
+
if (!decoder.create(srcBuffer, numValues)) {
|
|
2723
2823
|
return null;
|
|
2724
2824
|
}
|
|
2725
2825
|
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
@@ -2732,7 +2832,7 @@ function parseRawSymbolStream(numValues, srcBuffer) {
|
|
|
2732
2832
|
}
|
|
2733
2833
|
function decodeRawSymbolsInternal(uniqueSymbolsBitLength, numValues, srcBuffer, outValues) {
|
|
2734
2834
|
const decoder = new RAnsSymbolDecoder(uniqueSymbolsBitLength);
|
|
2735
|
-
if (!decoder.create(srcBuffer)) {
|
|
2835
|
+
if (!decoder.create(srcBuffer, numValues)) {
|
|
2736
2836
|
return false;
|
|
2737
2837
|
}
|
|
2738
2838
|
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
@@ -4234,11 +4334,16 @@ var PredictionSchemeDeltaDecoder = class extends PredictionSchemeDecoder {
|
|
|
4234
4334
|
return true;
|
|
4235
4335
|
}
|
|
4236
4336
|
computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
|
|
4237
|
-
this._transform
|
|
4337
|
+
const transform = this._transform;
|
|
4338
|
+
transform.init(numComponents);
|
|
4339
|
+
if (transform.computeOriginalValuesDelta) {
|
|
4340
|
+
transform.computeOriginalValuesDelta(inCorr, outData, size, numComponents);
|
|
4341
|
+
return true;
|
|
4342
|
+
}
|
|
4238
4343
|
const zeroVals = new Int32Array(numComponents);
|
|
4239
|
-
|
|
4344
|
+
transform.computeOriginalValue(zeroVals, 0, inCorr, 0, outData, 0);
|
|
4240
4345
|
for (let i = numComponents; i < size; i += numComponents) {
|
|
4241
|
-
|
|
4346
|
+
transform.computeOriginalValue(outData, i - numComponents, inCorr, i, outData, i);
|
|
4242
4347
|
}
|
|
4243
4348
|
return true;
|
|
4244
4349
|
}
|
|
@@ -4779,7 +4884,6 @@ var AttributeTransform = class {
|
|
|
4779
4884
|
// src/decoder/attributes/AttributeOctahedronTransform.ts
|
|
4780
4885
|
var AttributeOctahedronTransform = class extends AttributeTransform {
|
|
4781
4886
|
_quantizationBits;
|
|
4782
|
-
_tmpVec;
|
|
4783
4887
|
constructor() {
|
|
4784
4888
|
super();
|
|
4785
4889
|
this._quantizationBits = -1;
|
|
@@ -4811,15 +4915,30 @@ var AttributeOctahedronTransform = class extends AttributeTransform {
|
|
|
4811
4915
|
const srcI32 = new Int32Array(srcAddr.buffer, srcAddr.byteOffset, numPoints * 2);
|
|
4812
4916
|
const dstAddr = targetAttribute.getAddress(0);
|
|
4813
4917
|
const dstF32 = new Float32Array(dstAddr.buffer, dstAddr.byteOffset, numPoints * 3);
|
|
4814
|
-
const
|
|
4918
|
+
const fround = Math.fround;
|
|
4919
|
+
const scale = toolBox._dequantizationScale;
|
|
4815
4920
|
let si = 0;
|
|
4816
4921
|
let di = 0;
|
|
4817
4922
|
for (let i = 0; i < numPoints; i++) {
|
|
4818
|
-
|
|
4923
|
+
let y = fround(fround(fround(srcI32[si]) * scale) - 1);
|
|
4924
|
+
let z = fround(fround(fround(srcI32[si + 1]) * scale) - 1);
|
|
4819
4925
|
si += 2;
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4926
|
+
const x = fround(fround(1 - Math.abs(y)) - Math.abs(z));
|
|
4927
|
+
let xOffset = -x;
|
|
4928
|
+
if (xOffset < 0) xOffset = 0;
|
|
4929
|
+
y = fround(y + (y < 0 ? xOffset : -xOffset));
|
|
4930
|
+
z = fround(z + (z < 0 ? xOffset : -xOffset));
|
|
4931
|
+
const normSquared = fround(fround(fround(x * x) + fround(y * y)) + fround(z * z));
|
|
4932
|
+
if (normSquared < 1e-6) {
|
|
4933
|
+
dstF32[di] = 0;
|
|
4934
|
+
dstF32[di + 1] = 0;
|
|
4935
|
+
dstF32[di + 2] = 0;
|
|
4936
|
+
} else {
|
|
4937
|
+
const d = fround(1 / fround(Math.sqrt(normSquared)));
|
|
4938
|
+
dstF32[di] = fround(x * d);
|
|
4939
|
+
dstF32[di + 1] = fround(y * d);
|
|
4940
|
+
dstF32[di + 2] = fround(z * d);
|
|
4941
|
+
}
|
|
4823
4942
|
di += 3;
|
|
4824
4943
|
}
|
|
4825
4944
|
return true;
|
|
@@ -4989,6 +5108,140 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
|
|
|
4989
5108
|
outOrigVals[outOffset] = origS + center;
|
|
4990
5109
|
outOrigVals[outOffset + 1] = origT + center;
|
|
4991
5110
|
}
|
|
5111
|
+
// Fused delta loop for PredictionSchemeDeltaDecoder: the whole
|
|
5112
|
+
// value[i] = original(value[i-1], corr[i]) chain in one call, with the
|
|
5113
|
+
// toolbox fields hoisted to locals and the previous output carried in
|
|
5114
|
+
// locals. This is the hot path for PREDICTION_DIFFERENCE normals (one call
|
|
5115
|
+
// per value through the interface was ~8% of decode time on the bundles).
|
|
5116
|
+
// The arithmetic is computeOriginalValue above verbatim -- keep them in
|
|
5117
|
+
// sync; only the plumbing differs.
|
|
5118
|
+
computeOriginalValuesDelta(inCorr, outData, size, numComponents) {
|
|
5119
|
+
const toolBox = this._octahedronToolBox;
|
|
5120
|
+
const center = toolBox._centerValue;
|
|
5121
|
+
const maxQuantizedValue = toolBox._maxQuantizedValue;
|
|
5122
|
+
let prevS = 0;
|
|
5123
|
+
let prevT = 0;
|
|
5124
|
+
for (let i = 0; i < size; i += numComponents) {
|
|
5125
|
+
const corrS = inCorr[i];
|
|
5126
|
+
const corrT = inCorr[i + 1];
|
|
5127
|
+
let predS = prevS - center;
|
|
5128
|
+
let predT = prevT - center;
|
|
5129
|
+
const predIsInDiamond = Math.abs(predS) + Math.abs(predT) <= center;
|
|
5130
|
+
if (!predIsInDiamond) {
|
|
5131
|
+
let signS = 0;
|
|
5132
|
+
let signT = 0;
|
|
5133
|
+
if (predS >= 0 && predT >= 0) {
|
|
5134
|
+
signS = 1;
|
|
5135
|
+
signT = 1;
|
|
5136
|
+
} else if (predS <= 0 && predT <= 0) {
|
|
5137
|
+
signS = -1;
|
|
5138
|
+
signT = -1;
|
|
5139
|
+
} else {
|
|
5140
|
+
signS = predS > 0 ? 1 : -1;
|
|
5141
|
+
signT = predT > 0 ? 1 : -1;
|
|
5142
|
+
}
|
|
5143
|
+
const cornerPointS = signS * center;
|
|
5144
|
+
const cornerPointT = signT * center;
|
|
5145
|
+
let us = predS * 2 - cornerPointS | 0;
|
|
5146
|
+
let ut = predT * 2 - cornerPointT | 0;
|
|
5147
|
+
if (signS * signT >= 0) {
|
|
5148
|
+
const temp = us;
|
|
5149
|
+
us = -ut;
|
|
5150
|
+
ut = -temp;
|
|
5151
|
+
} else {
|
|
5152
|
+
const temp = us;
|
|
5153
|
+
us = ut;
|
|
5154
|
+
ut = temp;
|
|
5155
|
+
}
|
|
5156
|
+
predS = (us + cornerPointS) / 2 | 0;
|
|
5157
|
+
predT = (ut + cornerPointT) / 2 | 0;
|
|
5158
|
+
}
|
|
5159
|
+
const predIsInBottomLeft = predS === 0 && predT === 0 || predS < 0 && predT <= 0;
|
|
5160
|
+
let rotationCount = 0;
|
|
5161
|
+
if (predS === 0) {
|
|
5162
|
+
if (predT > 0) rotationCount = 3;
|
|
5163
|
+
else if (predT < 0) rotationCount = 1;
|
|
5164
|
+
} else if (predS > 0) {
|
|
5165
|
+
if (predT >= 0) rotationCount = 2;
|
|
5166
|
+
else rotationCount = 1;
|
|
5167
|
+
} else {
|
|
5168
|
+
if (predT > 0) rotationCount = 3;
|
|
5169
|
+
}
|
|
5170
|
+
if (!predIsInBottomLeft) {
|
|
5171
|
+
const s = predS, t = predT;
|
|
5172
|
+
switch (rotationCount) {
|
|
5173
|
+
case 1:
|
|
5174
|
+
predS = t;
|
|
5175
|
+
predT = -s | 0;
|
|
5176
|
+
break;
|
|
5177
|
+
case 2:
|
|
5178
|
+
predS = -s | 0;
|
|
5179
|
+
predT = -t | 0;
|
|
5180
|
+
break;
|
|
5181
|
+
case 3:
|
|
5182
|
+
predS = -t | 0;
|
|
5183
|
+
predT = s;
|
|
5184
|
+
break;
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
let origS = predS + corrS | 0;
|
|
5188
|
+
if (origS > center) origS -= maxQuantizedValue;
|
|
5189
|
+
else if (origS < -center) origS += maxQuantizedValue;
|
|
5190
|
+
let origT = predT + corrT | 0;
|
|
5191
|
+
if (origT > center) origT -= maxQuantizedValue;
|
|
5192
|
+
else if (origT < -center) origT += maxQuantizedValue;
|
|
5193
|
+
if (!predIsInBottomLeft) {
|
|
5194
|
+
const s = origS, t = origT;
|
|
5195
|
+
switch (4 - rotationCount & 3) {
|
|
5196
|
+
case 1:
|
|
5197
|
+
origS = t;
|
|
5198
|
+
origT = -s | 0;
|
|
5199
|
+
break;
|
|
5200
|
+
case 2:
|
|
5201
|
+
origS = -s | 0;
|
|
5202
|
+
origT = -t | 0;
|
|
5203
|
+
break;
|
|
5204
|
+
case 3:
|
|
5205
|
+
origS = -t | 0;
|
|
5206
|
+
origT = s;
|
|
5207
|
+
break;
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
if (!predIsInDiamond) {
|
|
5211
|
+
let signS = 0;
|
|
5212
|
+
let signT = 0;
|
|
5213
|
+
if (origS >= 0 && origT >= 0) {
|
|
5214
|
+
signS = 1;
|
|
5215
|
+
signT = 1;
|
|
5216
|
+
} else if (origS <= 0 && origT <= 0) {
|
|
5217
|
+
signS = -1;
|
|
5218
|
+
signT = -1;
|
|
5219
|
+
} else {
|
|
5220
|
+
signS = origS > 0 ? 1 : -1;
|
|
5221
|
+
signT = origT > 0 ? 1 : -1;
|
|
5222
|
+
}
|
|
5223
|
+
const cornerPointS = signS * center;
|
|
5224
|
+
const cornerPointT = signT * center;
|
|
5225
|
+
let us = origS * 2 - cornerPointS | 0;
|
|
5226
|
+
let ut = origT * 2 - cornerPointT | 0;
|
|
5227
|
+
if (signS * signT >= 0) {
|
|
5228
|
+
const temp = us;
|
|
5229
|
+
us = -ut;
|
|
5230
|
+
ut = -temp;
|
|
5231
|
+
} else {
|
|
5232
|
+
const temp = us;
|
|
5233
|
+
us = ut;
|
|
5234
|
+
ut = temp;
|
|
5235
|
+
}
|
|
5236
|
+
origS = (us + cornerPointS) / 2 | 0;
|
|
5237
|
+
origT = (ut + cornerPointT) / 2 | 0;
|
|
5238
|
+
}
|
|
5239
|
+
prevS = origS + center | 0;
|
|
5240
|
+
prevT = origT + center | 0;
|
|
5241
|
+
outData[i] = prevS;
|
|
5242
|
+
outData[i + 1] = prevT;
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
4992
5245
|
};
|
|
4993
5246
|
|
|
4994
5247
|
// src/decoder/compression/attributes/prediction_schemes/PredictionSchemeNormalOctahedronDecodingTransform.ts
|
|
@@ -7223,7 +7476,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
7223
7476
|
return false;
|
|
7224
7477
|
}
|
|
7225
7478
|
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
7226
|
-
if (!decoder.create(outBuffer)) {
|
|
7479
|
+
if (!decoder.create(outBuffer, numSymbols)) {
|
|
7227
7480
|
return false;
|
|
7228
7481
|
}
|
|
7229
7482
|
if (decoder.numSymbols === 0) {
|
|
@@ -7239,37 +7492,38 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
7239
7492
|
this._contextCounters[i] = 0;
|
|
7240
7493
|
}
|
|
7241
7494
|
}
|
|
7242
|
-
const
|
|
7495
|
+
const lockstep = pending.filter((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
|
|
7243
7496
|
let p = 0;
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
p += 3;
|
|
7261
|
-
}
|
|
7262
|
-
if (pending.length - p === 2) {
|
|
7263
|
-
const a = pending[p];
|
|
7264
|
-
const b = pending[p + 1];
|
|
7265
|
-
ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
|
|
7266
|
-
p += 2;
|
|
7267
|
-
}
|
|
7497
|
+
while (lockstep.length - p >= 3) {
|
|
7498
|
+
const a = lockstep[p];
|
|
7499
|
+
const b = lockstep[p + 1];
|
|
7500
|
+
const c = lockstep[p + 2];
|
|
7501
|
+
ransDecodeSymbolsTrioU8(
|
|
7502
|
+
a.decoder.ans_,
|
|
7503
|
+
a.out,
|
|
7504
|
+
a.count,
|
|
7505
|
+
b.decoder.ans_,
|
|
7506
|
+
b.out,
|
|
7507
|
+
b.count,
|
|
7508
|
+
c.decoder.ans_,
|
|
7509
|
+
c.out,
|
|
7510
|
+
c.count
|
|
7511
|
+
);
|
|
7512
|
+
p += 3;
|
|
7268
7513
|
}
|
|
7269
|
-
|
|
7270
|
-
|
|
7514
|
+
if (lockstep.length - p === 2) {
|
|
7515
|
+
const a = lockstep[p];
|
|
7516
|
+
const b = lockstep[p + 1];
|
|
7517
|
+
ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
|
|
7518
|
+
p += 2;
|
|
7519
|
+
}
|
|
7520
|
+
for (; p < lockstep.length; ++p) {
|
|
7521
|
+
lockstep[p].decoder.ans_.decodeSymbols(lockstep[p].out, lockstep[p].count);
|
|
7271
7522
|
}
|
|
7272
7523
|
for (const entry of pending) {
|
|
7524
|
+
if (!(entry.decoder.ans_.lutTable instanceof Uint8Array)) {
|
|
7525
|
+
entry.decoder.ans_.decodeSymbols(entry.out, entry.count);
|
|
7526
|
+
}
|
|
7273
7527
|
entry.decoder.endDecoding();
|
|
7274
7528
|
}
|
|
7275
7529
|
return true;
|