minidraco 0.3.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 +12 -12
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1729 -645
- package/dist/three.d.ts +10 -1
- package/dist/three.js +1727 -643
- package/dist/worker.js +1729 -645
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -259,6 +259,90 @@ var Mesh = class extends PointCloud {
|
|
|
259
259
|
}
|
|
260
260
|
};
|
|
261
261
|
|
|
262
|
+
// src/decoder/core/ScratchArena.ts
|
|
263
|
+
var MAX_CLASS = 28;
|
|
264
|
+
var freeInt32 = [];
|
|
265
|
+
var freeUint32 = [];
|
|
266
|
+
var freeUint8 = [];
|
|
267
|
+
for (let i = 0; i <= MAX_CLASS; ++i) {
|
|
268
|
+
freeInt32.push([]);
|
|
269
|
+
freeUint32.push([]);
|
|
270
|
+
freeUint8.push([]);
|
|
271
|
+
}
|
|
272
|
+
var borrowedInt32 = [];
|
|
273
|
+
var borrowedUint32 = [];
|
|
274
|
+
var borrowedUint8 = [];
|
|
275
|
+
var sizeClass = (size) => size <= 1 ? 0 : 32 - Math.clz32(size - 1);
|
|
276
|
+
var takeInt32 = (size) => {
|
|
277
|
+
const k = sizeClass(size);
|
|
278
|
+
if (k > MAX_CLASS) return new Int32Array(size);
|
|
279
|
+
const bucket = freeInt32[k];
|
|
280
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Int32Array(size);
|
|
281
|
+
if (pooled.length < size) pooled = new Int32Array(1 << k);
|
|
282
|
+
borrowedInt32.push(pooled);
|
|
283
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
284
|
+
};
|
|
285
|
+
var takeUint32 = (size) => {
|
|
286
|
+
const k = sizeClass(size);
|
|
287
|
+
if (k > MAX_CLASS) return new Uint32Array(size);
|
|
288
|
+
const bucket = freeUint32[k];
|
|
289
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint32Array(size);
|
|
290
|
+
if (pooled.length < size) pooled = new Uint32Array(1 << k);
|
|
291
|
+
borrowedUint32.push(pooled);
|
|
292
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
293
|
+
};
|
|
294
|
+
var byteCapacity = (size) => size < 8 ? 8 : size + 7 & ~7;
|
|
295
|
+
var takeUint8 = (size) => {
|
|
296
|
+
const capacity = byteCapacity(size);
|
|
297
|
+
const k = sizeClass(capacity);
|
|
298
|
+
if (k > MAX_CLASS) return new Uint8Array(capacity);
|
|
299
|
+
const bucket = freeUint8[k];
|
|
300
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint8Array(capacity);
|
|
301
|
+
if (pooled.length < size) pooled = new Uint8Array(1 << k);
|
|
302
|
+
borrowedUint8.push(pooled);
|
|
303
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
304
|
+
};
|
|
305
|
+
var scratchInt32 = (size) => takeInt32(size);
|
|
306
|
+
var scratchInt32Filled = (size, value) => {
|
|
307
|
+
const view = takeInt32(size);
|
|
308
|
+
view.fill(value);
|
|
309
|
+
return view;
|
|
310
|
+
};
|
|
311
|
+
var scratchUint32 = (size) => takeUint32(size);
|
|
312
|
+
var scratchUint32Zeroed = (size) => {
|
|
313
|
+
const view = takeUint32(size);
|
|
314
|
+
view.fill(0);
|
|
315
|
+
return view;
|
|
316
|
+
};
|
|
317
|
+
var scratchUint8 = (size) => takeUint8(size);
|
|
318
|
+
var scratchUint8Zeroed = (size) => {
|
|
319
|
+
const view = takeUint8(size);
|
|
320
|
+
view.fill(0);
|
|
321
|
+
return view;
|
|
322
|
+
};
|
|
323
|
+
var scratchUint8Filled = (size, value) => {
|
|
324
|
+
const view = takeUint8(size);
|
|
325
|
+
view.fill(value);
|
|
326
|
+
return view;
|
|
327
|
+
};
|
|
328
|
+
var releaseScratch = () => {
|
|
329
|
+
for (let i = 0; i < borrowedInt32.length; ++i) {
|
|
330
|
+
const buffer = borrowedInt32[i];
|
|
331
|
+
freeInt32[sizeClass(buffer.length)].push(buffer);
|
|
332
|
+
}
|
|
333
|
+
for (let i = 0; i < borrowedUint32.length; ++i) {
|
|
334
|
+
const buffer = borrowedUint32[i];
|
|
335
|
+
freeUint32[sizeClass(buffer.length)].push(buffer);
|
|
336
|
+
}
|
|
337
|
+
for (let i = 0; i < borrowedUint8.length; ++i) {
|
|
338
|
+
const buffer = borrowedUint8[i];
|
|
339
|
+
freeUint8[sizeClass(buffer.length)].push(buffer);
|
|
340
|
+
}
|
|
341
|
+
borrowedInt32.length = 0;
|
|
342
|
+
borrowedUint32.length = 0;
|
|
343
|
+
borrowedUint8.length = 0;
|
|
344
|
+
};
|
|
345
|
+
|
|
262
346
|
// src/decoder/core/DataBuffer.ts
|
|
263
347
|
var DataBuffer = class {
|
|
264
348
|
_data;
|
|
@@ -283,6 +367,15 @@ var DataBuffer = class {
|
|
|
283
367
|
resize(newSize) {
|
|
284
368
|
this._resize(newSize);
|
|
285
369
|
}
|
|
370
|
+
// Replaces the contents with a decode-scoped scratch buffer of exactly
|
|
371
|
+
// `size` bytes; the previous contents are dropped and the new ones are
|
|
372
|
+
// arbitrary, so every byte must be written before it is read. Only for
|
|
373
|
+
// buffers that never outlive the decode (see ScratchArena) — the portable
|
|
374
|
+
// attributes the integer decoders build and discard per attribute are the
|
|
375
|
+
// one caller, and their per-primitive allocation showed up in profiles.
|
|
376
|
+
adoptScratch(size) {
|
|
377
|
+
this._data = scratchUint8(size);
|
|
378
|
+
}
|
|
286
379
|
write(bytePos, inArray, dataSize) {
|
|
287
380
|
if (inArray instanceof Uint8Array) {
|
|
288
381
|
this._data.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
|
|
@@ -372,6 +465,19 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
372
465
|
this._numUniqueEntries = numAttributeValues;
|
|
373
466
|
return true;
|
|
374
467
|
}
|
|
468
|
+
// Like reset(), but backs the attribute with decode-scoped scratch memory.
|
|
469
|
+
// Only valid for attributes that never escape the decode and whose every
|
|
470
|
+
// byte is written before it is read (see DataBuffer.adoptScratch).
|
|
471
|
+
resetScratch(numAttributeValues) {
|
|
472
|
+
if (this._attributeBuffer === null) {
|
|
473
|
+
this._attributeBuffer = new DataBuffer();
|
|
474
|
+
}
|
|
475
|
+
const entrySize = dataTypeLength(this.dataType) * this.numComponents;
|
|
476
|
+
this._attributeBuffer.adoptScratch(numAttributeValues * entrySize);
|
|
477
|
+
this.resetBuffer(this._attributeBuffer, entrySize, 0);
|
|
478
|
+
this._numUniqueEntries = numAttributeValues;
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
375
481
|
get size() {
|
|
376
482
|
return this._numUniqueEntries;
|
|
377
483
|
}
|
|
@@ -414,6 +520,20 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
414
520
|
this._identityMapping = false;
|
|
415
521
|
this._indicesMap = new Uint32Array(numPoints);
|
|
416
522
|
}
|
|
523
|
+
// Adopts an already-computed map, shared with other attributes of the same
|
|
524
|
+
// mesh. The map must be treated as read-only from here on (reads go through
|
|
525
|
+
// mappedIndex/extractTo; copyFrom slices).
|
|
526
|
+
setExplicitMappingShared(map) {
|
|
527
|
+
this._identityMapping = false;
|
|
528
|
+
this._indicesMap = map;
|
|
529
|
+
}
|
|
530
|
+
// Like setExplicitMappingUnfilled, but from decode-scoped scratch. Only for
|
|
531
|
+
// attributes that never escape the decode (see ScratchArena) -- the portable
|
|
532
|
+
// attributes the sequential decoders build and discard.
|
|
533
|
+
setExplicitMappingScratch(numPoints) {
|
|
534
|
+
this._identityMapping = false;
|
|
535
|
+
this._indicesMap = scratchUint32(numPoints);
|
|
536
|
+
}
|
|
417
537
|
setAttributeTransformData(transformData) {
|
|
418
538
|
this._attributeTransformData = transformData;
|
|
419
539
|
}
|
|
@@ -909,48 +1029,6 @@ var DecoderBuffer = class {
|
|
|
909
1029
|
}
|
|
910
1030
|
};
|
|
911
1031
|
|
|
912
|
-
// src/decoder/core/ScratchArena.ts
|
|
913
|
-
var freeInt32 = [];
|
|
914
|
-
var freeUint8 = [];
|
|
915
|
-
var borrowedInt32 = [];
|
|
916
|
-
var borrowedUint8 = [];
|
|
917
|
-
var acquire = (free, borrowed, size) => {
|
|
918
|
-
for (let i = free.length - 1; i >= 0; --i) {
|
|
919
|
-
const buffer = free[i];
|
|
920
|
-
if (buffer.length >= size) {
|
|
921
|
-
free[i] = free[free.length - 1];
|
|
922
|
-
free.pop();
|
|
923
|
-
borrowed.push(buffer);
|
|
924
|
-
return buffer;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
return null;
|
|
928
|
-
};
|
|
929
|
-
var scratchInt32 = (size) => {
|
|
930
|
-
const pooled = acquire(freeInt32, borrowedInt32, size);
|
|
931
|
-
if (pooled !== null) return pooled.subarray(0, size);
|
|
932
|
-
const fresh = new Int32Array(size);
|
|
933
|
-
borrowedInt32.push(fresh);
|
|
934
|
-
return fresh;
|
|
935
|
-
};
|
|
936
|
-
var scratchUint8Zeroed = (size) => {
|
|
937
|
-
const pooled = acquire(freeUint8, borrowedUint8, size);
|
|
938
|
-
if (pooled !== null) {
|
|
939
|
-
const view = pooled.subarray(0, size);
|
|
940
|
-
view.fill(0);
|
|
941
|
-
return view;
|
|
942
|
-
}
|
|
943
|
-
const fresh = new Uint8Array(size);
|
|
944
|
-
borrowedUint8.push(fresh);
|
|
945
|
-
return fresh;
|
|
946
|
-
};
|
|
947
|
-
var releaseScratch = () => {
|
|
948
|
-
for (const buffer of borrowedInt32) freeInt32.push(buffer);
|
|
949
|
-
for (const buffer of borrowedUint8) freeUint8.push(buffer);
|
|
950
|
-
borrowedInt32.length = 0;
|
|
951
|
-
borrowedUint8.length = 0;
|
|
952
|
-
};
|
|
953
|
-
|
|
954
1032
|
// src/decoder/compression/config/CompressionShared.ts
|
|
955
1033
|
var kDracoPointCloudBitstreamVersionMajor = 2;
|
|
956
1034
|
var kDracoPointCloudBitstreamVersionMinor = 3;
|
|
@@ -1182,82 +1260,705 @@ var MetadataDecoder = class {
|
|
|
1182
1260
|
}
|
|
1183
1261
|
};
|
|
1184
1262
|
|
|
1185
|
-
// src/decoder/compression/
|
|
1186
|
-
var
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1263
|
+
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1264
|
+
var ANS_P8_PRECISION = 256;
|
|
1265
|
+
var ANS_L_BASE = 4096;
|
|
1266
|
+
var ANS_IO_BASE = 256;
|
|
1267
|
+
var COARSE_STREAM_FACTOR = 8;
|
|
1268
|
+
var COARSE_BUCKET_BITS = 8;
|
|
1269
|
+
function memGetLe16(buf, offset) {
|
|
1270
|
+
return buf[offset] | buf[offset + 1] << 8;
|
|
1271
|
+
}
|
|
1272
|
+
function memGetLe24(buf, offset) {
|
|
1273
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1274
|
+
}
|
|
1275
|
+
function memGetLe32(buf, offset) {
|
|
1276
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1277
|
+
}
|
|
1278
|
+
var AnsDecoder = class {
|
|
1279
|
+
buf;
|
|
1280
|
+
bufOffset;
|
|
1281
|
+
// First valid byte of this decoder's slice within buf: init is passed
|
|
1282
|
+
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1283
|
+
bufStart;
|
|
1284
|
+
state;
|
|
1194
1285
|
constructor() {
|
|
1195
|
-
this.
|
|
1196
|
-
this.
|
|
1197
|
-
this.
|
|
1198
|
-
this.
|
|
1199
|
-
this._options = null;
|
|
1200
|
-
this._attributesDecoders = [];
|
|
1201
|
-
this._attributeToDecoderMap = [];
|
|
1286
|
+
this.buf = null;
|
|
1287
|
+
this.bufOffset = 0;
|
|
1288
|
+
this.bufStart = 0;
|
|
1289
|
+
this.state = 0;
|
|
1202
1290
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1291
|
+
};
|
|
1292
|
+
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1293
|
+
if (offset - base < 1) {
|
|
1294
|
+
return 1;
|
|
1205
1295
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1296
|
+
ans.buf = buf;
|
|
1297
|
+
ans.bufStart = base;
|
|
1298
|
+
const x = buf[offset - 1] >> 6;
|
|
1299
|
+
if (x === 0) {
|
|
1300
|
+
ans.bufOffset = offset - 1;
|
|
1301
|
+
ans.state = buf[offset - 1] & 63;
|
|
1302
|
+
} else if (x === 1) {
|
|
1303
|
+
if (offset - base < 2) {
|
|
1304
|
+
return 1;
|
|
1212
1305
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1306
|
+
ans.bufOffset = offset - 2;
|
|
1307
|
+
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1308
|
+
} else if (x === 2) {
|
|
1309
|
+
if (offset - base < 3) {
|
|
1310
|
+
return 1;
|
|
1215
1311
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1312
|
+
ans.bufOffset = offset - 3;
|
|
1313
|
+
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1314
|
+
} else {
|
|
1315
|
+
return 1;
|
|
1316
|
+
}
|
|
1317
|
+
ans.state += ANS_L_BASE;
|
|
1318
|
+
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1319
|
+
return 1;
|
|
1320
|
+
}
|
|
1321
|
+
return 0;
|
|
1322
|
+
}
|
|
1323
|
+
function ansReadEnd(ans) {
|
|
1324
|
+
return ans.state === ANS_L_BASE;
|
|
1325
|
+
}
|
|
1326
|
+
var tablePool = [];
|
|
1327
|
+
var acquirePooled = (Ctor, size) => {
|
|
1328
|
+
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1329
|
+
const buf = tablePool[i];
|
|
1330
|
+
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1331
|
+
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1332
|
+
tablePool.pop();
|
|
1333
|
+
return buf;
|
|
1219
1334
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1335
|
+
}
|
|
1336
|
+
return new Ctor(size);
|
|
1337
|
+
};
|
|
1338
|
+
var RAnsDecoder = class {
|
|
1339
|
+
ransPrecisionBits;
|
|
1340
|
+
ransPrecision;
|
|
1341
|
+
ransPrecisionMask;
|
|
1342
|
+
lRansBase;
|
|
1343
|
+
lutTable;
|
|
1344
|
+
probTable;
|
|
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;
|
|
1353
|
+
buf;
|
|
1354
|
+
bufOffset;
|
|
1355
|
+
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1356
|
+
// see AnsDecoder.bufStart).
|
|
1357
|
+
bufStart;
|
|
1358
|
+
state;
|
|
1359
|
+
constructor(ransPrecisionBits) {
|
|
1360
|
+
this.ransPrecisionBits = ransPrecisionBits;
|
|
1361
|
+
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1362
|
+
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1363
|
+
this.lRansBase = this.ransPrecision * 4;
|
|
1364
|
+
this.lutTable = null;
|
|
1365
|
+
this.probTable = null;
|
|
1366
|
+
this.cumProbTable = null;
|
|
1367
|
+
this.coarse = false;
|
|
1368
|
+
this.bucketShift = 0;
|
|
1369
|
+
this.bucketTable = null;
|
|
1370
|
+
this.buf = null;
|
|
1371
|
+
this.bufOffset = 0;
|
|
1372
|
+
this.bufStart = 0;
|
|
1373
|
+
this.state = 0;
|
|
1374
|
+
}
|
|
1375
|
+
// offset is the absolute end of the encoded bytes within buf and base the
|
|
1376
|
+
// absolute start (offset - base = encoded length). Passing the source
|
|
1377
|
+
// buffer with absolute offsets avoids a subarray allocation per init.
|
|
1378
|
+
// Returns 0 on success, non-zero on error.
|
|
1379
|
+
readInit(buf, offset, base = 0) {
|
|
1380
|
+
if (offset - base < 1) {
|
|
1381
|
+
return 1;
|
|
1223
1382
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1383
|
+
this.buf = buf;
|
|
1384
|
+
this.bufStart = base;
|
|
1385
|
+
const x = buf[offset - 1] >> 6;
|
|
1386
|
+
if (x === 0) {
|
|
1387
|
+
this.bufOffset = offset - 1;
|
|
1388
|
+
this.state = buf[offset - 1] & 63;
|
|
1389
|
+
} else if (x === 1) {
|
|
1390
|
+
if (offset - base < 2) {
|
|
1391
|
+
return 1;
|
|
1392
|
+
}
|
|
1393
|
+
this.bufOffset = offset - 2;
|
|
1394
|
+
this.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1395
|
+
} else if (x === 2) {
|
|
1396
|
+
if (offset - base < 3) {
|
|
1397
|
+
return 1;
|
|
1398
|
+
}
|
|
1399
|
+
this.bufOffset = offset - 3;
|
|
1400
|
+
this.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1401
|
+
} else if (x === 3) {
|
|
1402
|
+
if (offset - base < 4) {
|
|
1403
|
+
return 1;
|
|
1404
|
+
}
|
|
1405
|
+
this.bufOffset = offset - 4;
|
|
1406
|
+
this.state = memGetLe32(buf, offset - 4) & 1073741823;
|
|
1407
|
+
} else {
|
|
1408
|
+
return 1;
|
|
1228
1409
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1410
|
+
this.state += this.lRansBase;
|
|
1411
|
+
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
1412
|
+
return 1;
|
|
1233
1413
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1414
|
+
return 0;
|
|
1415
|
+
}
|
|
1416
|
+
readEnd() {
|
|
1417
|
+
if (this.lutTable !== null) {
|
|
1418
|
+
tablePool.push(this.lutTable);
|
|
1419
|
+
this.lutTable = null;
|
|
1238
1420
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1421
|
+
if (this.probTable !== null) {
|
|
1422
|
+
tablePool.push(this.probTable);
|
|
1423
|
+
this.probTable = null;
|
|
1243
1424
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
// Main entry point for point cloud decoding.
|
|
1248
|
-
decode(options, inBuffer, outPointCloud) {
|
|
1249
|
-
this._options = options;
|
|
1250
|
-
this._buffer = inBuffer;
|
|
1251
|
-
this._pointCloud = outPointCloud;
|
|
1252
|
-
const header = new DracoHeader();
|
|
1253
|
-
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1254
|
-
if (!headerStatus.ok()) {
|
|
1255
|
-
return headerStatus;
|
|
1425
|
+
if (this.cumProbTable !== null) {
|
|
1426
|
+
tablePool.push(this.cumProbTable);
|
|
1427
|
+
this.cumProbTable = null;
|
|
1256
1428
|
}
|
|
1257
|
-
if (
|
|
1258
|
-
|
|
1429
|
+
if (this.bucketTable !== null) {
|
|
1430
|
+
tablePool.push(this.bucketTable);
|
|
1431
|
+
this.bucketTable = null;
|
|
1259
1432
|
}
|
|
1260
|
-
this.
|
|
1433
|
+
return this.state === this.lRansBase;
|
|
1434
|
+
}
|
|
1435
|
+
ransRead() {
|
|
1436
|
+
const buf = this.buf;
|
|
1437
|
+
const lRansBase = this.lRansBase;
|
|
1438
|
+
let state = this.state;
|
|
1439
|
+
let bufOffset = this.bufOffset;
|
|
1440
|
+
const bufStart = this.bufStart;
|
|
1441
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1442
|
+
state = state << 8 | buf[--bufOffset];
|
|
1443
|
+
}
|
|
1444
|
+
const quo = state >>> this.ransPrecisionBits;
|
|
1445
|
+
const rem = state & this.ransPrecisionMask;
|
|
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
|
+
}
|
|
1454
|
+
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
1455
|
+
this.bufOffset = bufOffset;
|
|
1456
|
+
return symbol;
|
|
1457
|
+
}
|
|
1458
|
+
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
1459
|
+
// written back once. Removes per-symbol property reads and call indirection.
|
|
1460
|
+
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
1461
|
+
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
1462
|
+
// once here so each loop body stays monomorphic on its concrete type. The
|
|
1463
|
+
// three bodies are intentionally identical copies.
|
|
1464
|
+
decodeSymbols(out, count) {
|
|
1465
|
+
if (this.coarse) {
|
|
1466
|
+
this._decodeSymbolsCoarse(out, count);
|
|
1467
|
+
return;
|
|
1468
|
+
}
|
|
1469
|
+
const lutTable = this.lutTable;
|
|
1470
|
+
if (lutTable instanceof Uint8Array) {
|
|
1471
|
+
this._decodeSymbolsU8(out, count, lutTable);
|
|
1472
|
+
} else if (lutTable instanceof Uint16Array) {
|
|
1473
|
+
this._decodeSymbolsU16(out, count, lutTable);
|
|
1474
|
+
} else {
|
|
1475
|
+
this._decodeSymbolsU32(out, count, lutTable);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
_decodeSymbolsU8(out, count, lutTable) {
|
|
1479
|
+
const buf = this.buf;
|
|
1480
|
+
const lRansBase = this.lRansBase;
|
|
1481
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1482
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1483
|
+
const probTable = this.probTable;
|
|
1484
|
+
const cumProbTable = this.cumProbTable;
|
|
1485
|
+
let state = this.state;
|
|
1486
|
+
let bufOffset = this.bufOffset;
|
|
1487
|
+
const bufStart = this.bufStart;
|
|
1488
|
+
for (let i = 0; i < count; ++i) {
|
|
1489
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1490
|
+
state = state << 8 | buf[--bufOffset];
|
|
1491
|
+
}
|
|
1492
|
+
const rem = state & ransPrecisionMask;
|
|
1493
|
+
const symbol = lutTable[rem];
|
|
1494
|
+
out[i] = symbol;
|
|
1495
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1496
|
+
}
|
|
1497
|
+
this.state = state;
|
|
1498
|
+
this.bufOffset = bufOffset;
|
|
1499
|
+
}
|
|
1500
|
+
_decodeSymbolsU16(out, count, lutTable) {
|
|
1501
|
+
const buf = this.buf;
|
|
1502
|
+
const lRansBase = this.lRansBase;
|
|
1503
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1504
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1505
|
+
const probTable = this.probTable;
|
|
1506
|
+
const cumProbTable = this.cumProbTable;
|
|
1507
|
+
let state = this.state;
|
|
1508
|
+
let bufOffset = this.bufOffset;
|
|
1509
|
+
const bufStart = this.bufStart;
|
|
1510
|
+
for (let i = 0; i < count; ++i) {
|
|
1511
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1512
|
+
state = state << 8 | buf[--bufOffset];
|
|
1513
|
+
}
|
|
1514
|
+
const rem = state & ransPrecisionMask;
|
|
1515
|
+
const symbol = lutTable[rem];
|
|
1516
|
+
out[i] = symbol;
|
|
1517
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1518
|
+
}
|
|
1519
|
+
this.state = state;
|
|
1520
|
+
this.bufOffset = bufOffset;
|
|
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
|
+
}
|
|
1549
|
+
_decodeSymbolsU32(out, count, lutTable) {
|
|
1550
|
+
const buf = this.buf;
|
|
1551
|
+
const lRansBase = this.lRansBase;
|
|
1552
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1553
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1554
|
+
const probTable = this.probTable;
|
|
1555
|
+
const cumProbTable = this.cumProbTable;
|
|
1556
|
+
let state = this.state;
|
|
1557
|
+
let bufOffset = this.bufOffset;
|
|
1558
|
+
const bufStart = this.bufStart;
|
|
1559
|
+
for (let i = 0; i < count; ++i) {
|
|
1560
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1561
|
+
state = state << 8 | buf[--bufOffset];
|
|
1562
|
+
}
|
|
1563
|
+
const rem = state & ransPrecisionMask;
|
|
1564
|
+
const symbol = lutTable[rem];
|
|
1565
|
+
out[i] = symbol;
|
|
1566
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1567
|
+
}
|
|
1568
|
+
this.state = state;
|
|
1569
|
+
this.bufOffset = bufOffset;
|
|
1570
|
+
}
|
|
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;
|
|
1585
|
+
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
1586
|
+
const cumProbTable = acquirePooled(Uint32Array, numSymbols + 1);
|
|
1587
|
+
this.probTable = probTable;
|
|
1588
|
+
this.cumProbTable = cumProbTable;
|
|
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;
|
|
1620
|
+
let actProb = 0;
|
|
1621
|
+
for (let i = 0; i < numSymbols; ++i) {
|
|
1622
|
+
const prob = tokenProbs[i];
|
|
1623
|
+
probTable[i] = prob;
|
|
1624
|
+
cumProbTable[i] = cumProb;
|
|
1625
|
+
cumProb += prob;
|
|
1626
|
+
if (cumProb > ransPrecision) {
|
|
1627
|
+
return false;
|
|
1628
|
+
}
|
|
1629
|
+
if (prob < 32) {
|
|
1630
|
+
for (let j = actProb; j < cumProb; ++j) {
|
|
1631
|
+
lutTable[j] = i;
|
|
1632
|
+
}
|
|
1633
|
+
} else {
|
|
1634
|
+
lutTable.fill(i, actProb, cumProb);
|
|
1635
|
+
}
|
|
1636
|
+
actProb = cumProb;
|
|
1637
|
+
}
|
|
1638
|
+
if (cumProb !== ransPrecision) {
|
|
1639
|
+
return false;
|
|
1640
|
+
}
|
|
1641
|
+
cumProbTable[numSymbols] = ransPrecision;
|
|
1642
|
+
return true;
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
function ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB) {
|
|
1646
|
+
const lutA = a.lutTable;
|
|
1647
|
+
const lutB = b.lutTable;
|
|
1648
|
+
const bufA = a.buf;
|
|
1649
|
+
const bufB = b.buf;
|
|
1650
|
+
const probA = a.probTable;
|
|
1651
|
+
const probB = b.probTable;
|
|
1652
|
+
const cumA = a.cumProbTable;
|
|
1653
|
+
const cumB = b.cumProbTable;
|
|
1654
|
+
const lBaseA = a.lRansBase;
|
|
1655
|
+
const lBaseB = b.lRansBase;
|
|
1656
|
+
const bitsA = a.ransPrecisionBits;
|
|
1657
|
+
const bitsB = b.ransPrecisionBits;
|
|
1658
|
+
const maskA = a.ransPrecisionMask;
|
|
1659
|
+
const maskB = b.ransPrecisionMask;
|
|
1660
|
+
const startA = a.bufStart;
|
|
1661
|
+
const startB = b.bufStart;
|
|
1662
|
+
let stateA = a.state;
|
|
1663
|
+
let stateB = b.state;
|
|
1664
|
+
let offA = a.bufOffset;
|
|
1665
|
+
let offB = b.bufOffset;
|
|
1666
|
+
const shared = countA < countB ? countA : countB;
|
|
1667
|
+
for (let i = 0; i < shared; ++i) {
|
|
1668
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1669
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1670
|
+
}
|
|
1671
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1672
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1673
|
+
}
|
|
1674
|
+
const remA = stateA & maskA;
|
|
1675
|
+
const remB = stateB & maskB;
|
|
1676
|
+
const symA = lutA[remA];
|
|
1677
|
+
const symB = lutB[remB];
|
|
1678
|
+
outA[i] = symA;
|
|
1679
|
+
outB[i] = symB;
|
|
1680
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1681
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1682
|
+
}
|
|
1683
|
+
a.state = stateA;
|
|
1684
|
+
a.bufOffset = offA;
|
|
1685
|
+
b.state = stateB;
|
|
1686
|
+
b.bufOffset = offB;
|
|
1687
|
+
if (shared < countA) {
|
|
1688
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1689
|
+
}
|
|
1690
|
+
if (shared < countB) {
|
|
1691
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
function ransDecodeSymbolsPair(a, outA, countA, b, outB, countB) {
|
|
1695
|
+
const lutA = a.lutTable;
|
|
1696
|
+
const lutB = b.lutTable;
|
|
1697
|
+
if (lutA instanceof Uint8Array && lutB instanceof Uint8Array) {
|
|
1698
|
+
ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB);
|
|
1699
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint16Array) {
|
|
1700
|
+
ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB);
|
|
1701
|
+
} else if (lutA instanceof Uint8Array && lutB instanceof Uint16Array) {
|
|
1702
|
+
ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB);
|
|
1703
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint8Array) {
|
|
1704
|
+
ransDecodeSymbolsPairU8U16(b, outB, countB, a, outA, countA);
|
|
1705
|
+
} else {
|
|
1706
|
+
a.decodeSymbols(outA, countA);
|
|
1707
|
+
b.decodeSymbols(outB, countB);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
function ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB) {
|
|
1711
|
+
const lutA = a.lutTable;
|
|
1712
|
+
const lutB = b.lutTable;
|
|
1713
|
+
const bufA = a.buf;
|
|
1714
|
+
const bufB = b.buf;
|
|
1715
|
+
const probA = a.probTable;
|
|
1716
|
+
const probB = b.probTable;
|
|
1717
|
+
const cumA = a.cumProbTable;
|
|
1718
|
+
const cumB = b.cumProbTable;
|
|
1719
|
+
const lBaseA = a.lRansBase;
|
|
1720
|
+
const lBaseB = b.lRansBase;
|
|
1721
|
+
const bitsA = a.ransPrecisionBits;
|
|
1722
|
+
const bitsB = b.ransPrecisionBits;
|
|
1723
|
+
const maskA = a.ransPrecisionMask;
|
|
1724
|
+
const maskB = b.ransPrecisionMask;
|
|
1725
|
+
const startA = a.bufStart;
|
|
1726
|
+
const startB = b.bufStart;
|
|
1727
|
+
let stateA = a.state;
|
|
1728
|
+
let stateB = b.state;
|
|
1729
|
+
let offA = a.bufOffset;
|
|
1730
|
+
let offB = b.bufOffset;
|
|
1731
|
+
const shared = countA < countB ? countA : countB;
|
|
1732
|
+
for (let i = 0; i < shared; ++i) {
|
|
1733
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1734
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1735
|
+
}
|
|
1736
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1737
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1738
|
+
}
|
|
1739
|
+
const remA = stateA & maskA;
|
|
1740
|
+
const remB = stateB & maskB;
|
|
1741
|
+
const symA = lutA[remA];
|
|
1742
|
+
const symB = lutB[remB];
|
|
1743
|
+
outA[i] = symA;
|
|
1744
|
+
outB[i] = symB;
|
|
1745
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1746
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1747
|
+
}
|
|
1748
|
+
a.state = stateA;
|
|
1749
|
+
a.bufOffset = offA;
|
|
1750
|
+
b.state = stateB;
|
|
1751
|
+
b.bufOffset = offB;
|
|
1752
|
+
if (shared < countA) {
|
|
1753
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1754
|
+
}
|
|
1755
|
+
if (shared < countB) {
|
|
1756
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
function ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB) {
|
|
1760
|
+
const lutA = a.lutTable;
|
|
1761
|
+
const lutB = b.lutTable;
|
|
1762
|
+
const bufA = a.buf;
|
|
1763
|
+
const bufB = b.buf;
|
|
1764
|
+
const probA = a.probTable;
|
|
1765
|
+
const probB = b.probTable;
|
|
1766
|
+
const cumA = a.cumProbTable;
|
|
1767
|
+
const cumB = b.cumProbTable;
|
|
1768
|
+
const lBaseA = a.lRansBase;
|
|
1769
|
+
const lBaseB = b.lRansBase;
|
|
1770
|
+
const bitsA = a.ransPrecisionBits;
|
|
1771
|
+
const bitsB = b.ransPrecisionBits;
|
|
1772
|
+
const maskA = a.ransPrecisionMask;
|
|
1773
|
+
const maskB = b.ransPrecisionMask;
|
|
1774
|
+
const startA = a.bufStart;
|
|
1775
|
+
const startB = b.bufStart;
|
|
1776
|
+
let stateA = a.state;
|
|
1777
|
+
let stateB = b.state;
|
|
1778
|
+
let offA = a.bufOffset;
|
|
1779
|
+
let offB = b.bufOffset;
|
|
1780
|
+
const shared = countA < countB ? countA : countB;
|
|
1781
|
+
for (let i = 0; i < shared; ++i) {
|
|
1782
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1783
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1784
|
+
}
|
|
1785
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1786
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1787
|
+
}
|
|
1788
|
+
const remA = stateA & maskA;
|
|
1789
|
+
const remB = stateB & maskB;
|
|
1790
|
+
const symA = lutA[remA];
|
|
1791
|
+
const symB = lutB[remB];
|
|
1792
|
+
outA[i] = symA;
|
|
1793
|
+
outB[i] = symB;
|
|
1794
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1795
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1796
|
+
}
|
|
1797
|
+
a.state = stateA;
|
|
1798
|
+
a.bufOffset = offA;
|
|
1799
|
+
b.state = stateB;
|
|
1800
|
+
b.bufOffset = offB;
|
|
1801
|
+
if (shared < countA) {
|
|
1802
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1803
|
+
}
|
|
1804
|
+
if (shared < countB) {
|
|
1805
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
function ransDecodeSymbolsTrioU8(a, outA, countA, b, outB, countB, c, outC, countC) {
|
|
1809
|
+
const lutA = a.lutTable;
|
|
1810
|
+
const lutB = b.lutTable;
|
|
1811
|
+
const lutC = c.lutTable;
|
|
1812
|
+
const bufA = a.buf;
|
|
1813
|
+
const bufB = b.buf;
|
|
1814
|
+
const bufC = c.buf;
|
|
1815
|
+
const probA = a.probTable;
|
|
1816
|
+
const probB = b.probTable;
|
|
1817
|
+
const probC = c.probTable;
|
|
1818
|
+
const cumA = a.cumProbTable;
|
|
1819
|
+
const cumB = b.cumProbTable;
|
|
1820
|
+
const cumC = c.cumProbTable;
|
|
1821
|
+
const lBaseA = a.lRansBase;
|
|
1822
|
+
const lBaseB = b.lRansBase;
|
|
1823
|
+
const lBaseC = c.lRansBase;
|
|
1824
|
+
const bitsA = a.ransPrecisionBits;
|
|
1825
|
+
const bitsB = b.ransPrecisionBits;
|
|
1826
|
+
const bitsC = c.ransPrecisionBits;
|
|
1827
|
+
const maskA = a.ransPrecisionMask;
|
|
1828
|
+
const maskB = b.ransPrecisionMask;
|
|
1829
|
+
const maskC = c.ransPrecisionMask;
|
|
1830
|
+
const startA = a.bufStart;
|
|
1831
|
+
const startB = b.bufStart;
|
|
1832
|
+
const startC = c.bufStart;
|
|
1833
|
+
let stateA = a.state;
|
|
1834
|
+
let stateB = b.state;
|
|
1835
|
+
let stateC = c.state;
|
|
1836
|
+
let offA = a.bufOffset;
|
|
1837
|
+
let offB = b.bufOffset;
|
|
1838
|
+
let offC = c.bufOffset;
|
|
1839
|
+
let shared = countA < countB ? countA : countB;
|
|
1840
|
+
if (countC < shared) shared = countC;
|
|
1841
|
+
for (let i = 0; i < shared; ++i) {
|
|
1842
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1843
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1844
|
+
}
|
|
1845
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1846
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1847
|
+
}
|
|
1848
|
+
while (stateC < lBaseC && offC > startC) {
|
|
1849
|
+
stateC = stateC << 8 | bufC[--offC];
|
|
1850
|
+
}
|
|
1851
|
+
const remA = stateA & maskA;
|
|
1852
|
+
const remB = stateB & maskB;
|
|
1853
|
+
const remC = stateC & maskC;
|
|
1854
|
+
const symA = lutA[remA];
|
|
1855
|
+
const symB = lutB[remB];
|
|
1856
|
+
const symC = lutC[remC];
|
|
1857
|
+
outA[i] = symA;
|
|
1858
|
+
outB[i] = symB;
|
|
1859
|
+
outC[i] = symC;
|
|
1860
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1861
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1862
|
+
stateC = (stateC >>> bitsC) * probC[symC] + remC - cumC[symC];
|
|
1863
|
+
}
|
|
1864
|
+
a.state = stateA;
|
|
1865
|
+
a.bufOffset = offA;
|
|
1866
|
+
b.state = stateB;
|
|
1867
|
+
b.bufOffset = offB;
|
|
1868
|
+
c.state = stateC;
|
|
1869
|
+
c.bufOffset = offC;
|
|
1870
|
+
const restA = countA - shared;
|
|
1871
|
+
const restB = countB - shared;
|
|
1872
|
+
const restC = countC - shared;
|
|
1873
|
+
const tails = [];
|
|
1874
|
+
if (restA > 0) tails.push([a, outA.subarray(shared), restA]);
|
|
1875
|
+
if (restB > 0) tails.push([b, outB.subarray(shared), restB]);
|
|
1876
|
+
if (restC > 0) tails.push([c, outC.subarray(shared), restC]);
|
|
1877
|
+
if (tails.length === 2) {
|
|
1878
|
+
ransDecodeSymbolsPairU8(tails[0][0], tails[0][1], tails[0][2], tails[1][0], tails[1][1], tails[1][2]);
|
|
1879
|
+
} else {
|
|
1880
|
+
for (const [decoder, out, count] of tails) {
|
|
1881
|
+
decoder.decodeSymbols(out, count);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
// src/decoder/compression/point_cloud/PointCloudDecoder.ts
|
|
1887
|
+
var PointCloudDecoder = class _PointCloudDecoder {
|
|
1888
|
+
_pointCloud;
|
|
1889
|
+
_buffer;
|
|
1890
|
+
_versionMajor;
|
|
1891
|
+
_versionMinor;
|
|
1892
|
+
_options;
|
|
1893
|
+
_attributesDecoders;
|
|
1894
|
+
_attributeToDecoderMap;
|
|
1895
|
+
constructor() {
|
|
1896
|
+
this._pointCloud = null;
|
|
1897
|
+
this._buffer = null;
|
|
1898
|
+
this._versionMajor = 0;
|
|
1899
|
+
this._versionMinor = 0;
|
|
1900
|
+
this._options = null;
|
|
1901
|
+
this._attributesDecoders = [];
|
|
1902
|
+
this._attributeToDecoderMap = [];
|
|
1903
|
+
}
|
|
1904
|
+
getGeometryType() {
|
|
1905
|
+
return EncodedGeometryType.POINT_CLOUD;
|
|
1906
|
+
}
|
|
1907
|
+
// Returns a Status; on success outHeader is populated.
|
|
1908
|
+
static decodeHeader(buffer, outHeader) {
|
|
1909
|
+
const kIoErrorMsg = "Failed to parse Draco header.";
|
|
1910
|
+
const bytes = buffer.decodeBytes(5);
|
|
1911
|
+
if (bytes === void 0) {
|
|
1912
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1913
|
+
}
|
|
1914
|
+
for (let i = 0; i < 5; i++) {
|
|
1915
|
+
outHeader.dracoString[i] = bytes[i];
|
|
1916
|
+
}
|
|
1917
|
+
const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
|
|
1918
|
+
if (magic !== "DRACO") {
|
|
1919
|
+
return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
|
|
1920
|
+
}
|
|
1921
|
+
const versionMajor = buffer.decodeUint8();
|
|
1922
|
+
if (versionMajor === void 0) {
|
|
1923
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1924
|
+
}
|
|
1925
|
+
outHeader.versionMajor = versionMajor;
|
|
1926
|
+
const versionMinor = buffer.decodeUint8();
|
|
1927
|
+
if (versionMinor === void 0) {
|
|
1928
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1929
|
+
}
|
|
1930
|
+
outHeader.versionMinor = versionMinor;
|
|
1931
|
+
const encoderType = buffer.decodeUint8();
|
|
1932
|
+
if (encoderType === void 0) {
|
|
1933
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1934
|
+
}
|
|
1935
|
+
outHeader.encoderType = encoderType;
|
|
1936
|
+
const encoderMethod = buffer.decodeUint8();
|
|
1937
|
+
if (encoderMethod === void 0) {
|
|
1938
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1939
|
+
}
|
|
1940
|
+
outHeader.encoderMethod = encoderMethod;
|
|
1941
|
+
const flags = buffer.decodeUint16();
|
|
1942
|
+
if (flags === void 0) {
|
|
1943
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1944
|
+
}
|
|
1945
|
+
outHeader.flags = flags;
|
|
1946
|
+
return okStatus();
|
|
1947
|
+
}
|
|
1948
|
+
// Main entry point for point cloud decoding.
|
|
1949
|
+
decode(options, inBuffer, outPointCloud) {
|
|
1950
|
+
this._options = options;
|
|
1951
|
+
this._buffer = inBuffer;
|
|
1952
|
+
this._pointCloud = outPointCloud;
|
|
1953
|
+
const header = new DracoHeader();
|
|
1954
|
+
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1955
|
+
if (!headerStatus.ok()) {
|
|
1956
|
+
return headerStatus;
|
|
1957
|
+
}
|
|
1958
|
+
if (header.encoderType !== this.getGeometryType()) {
|
|
1959
|
+
return new Status(StatusCode.DRACO_ERROR, "Using incompatible decoder for the input geometry.");
|
|
1960
|
+
}
|
|
1961
|
+
this._versionMajor = header.versionMajor;
|
|
1261
1962
|
this._versionMinor = header.versionMinor;
|
|
1262
1963
|
const maxSupportedMajorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor : kDracoMeshBitstreamVersionMajor;
|
|
1263
1964
|
const maxSupportedMinorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor;
|
|
@@ -1376,17 +2077,40 @@ var PointCloudDecoder = class _PointCloudDecoder {
|
|
|
1376
2077
|
return true;
|
|
1377
2078
|
}
|
|
1378
2079
|
decodeAllAttributes() {
|
|
1379
|
-
|
|
1380
|
-
|
|
2080
|
+
const decoders = this._attributesDecoders;
|
|
2081
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
2082
|
+
if (!decoders[i2].decodeAttributesParse(this._buffer)) {
|
|
1381
2083
|
return false;
|
|
1382
2084
|
}
|
|
1383
2085
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
2086
|
+
const pending = [];
|
|
2087
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
2088
|
+
decoders[i2].collectPendingSymbolStreams(pending);
|
|
2089
|
+
}
|
|
2090
|
+
const paired = pending.filter((stream) => !stream.ans.coarse);
|
|
2091
|
+
let i = 0;
|
|
2092
|
+
for (; i + 1 < paired.length; i += 2) {
|
|
2093
|
+
const a = paired[i];
|
|
2094
|
+
const b = paired[i + 1];
|
|
2095
|
+
ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
|
|
2096
|
+
}
|
|
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);
|
|
2102
|
+
}
|
|
2103
|
+
for (let k = 0; k < decoders.length; k++) {
|
|
2104
|
+
if (!decoders[k].decodeAttributesFinish()) {
|
|
2105
|
+
return false;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
return true;
|
|
2109
|
+
}
|
|
2110
|
+
onAttributesDecoded() {
|
|
2111
|
+
return true;
|
|
2112
|
+
}
|
|
2113
|
+
_decodeMetadata() {
|
|
1390
2114
|
const metadataDecoder = new MetadataDecoder();
|
|
1391
2115
|
if (!metadataDecoder.skipGeometryMetadata(this._buffer)) {
|
|
1392
2116
|
return new Status(StatusCode.DRACO_ERROR, "Failed to decode metadata.");
|
|
@@ -1445,46 +2169,62 @@ var MeshAttributeCornerTable = class {
|
|
|
1445
2169
|
no_interior_seams_;
|
|
1446
2170
|
corner_to_vertex_map_;
|
|
1447
2171
|
vertex_to_left_most_corner_map_;
|
|
1448
|
-
|
|
2172
|
+
// Attribute-vertex count. C++ keeps a vertex -> attribute-entry map here, but
|
|
2173
|
+
// the decoder only ever reads its size, so track the count directly instead
|
|
2174
|
+
// of allocating an Int32Array per attribute corner table.
|
|
2175
|
+
num_attribute_vertices_;
|
|
1449
2176
|
corner_table_;
|
|
1450
2177
|
// Lazily built; see oppositeCornerArray.
|
|
1451
2178
|
_effectiveOpposite;
|
|
1452
2179
|
// Every corner passed to addSeamEdge (may contain duplicates); lets
|
|
1453
2180
|
// oppositeCornerArray patch seams without scanning every corner's flag.
|
|
2181
|
+
// Preallocated to its exact upper bound (2 per seam edge) by the caller via
|
|
2182
|
+
// reserveSeamEdges -- a plain array grown by push() was measurable on
|
|
2183
|
+
// seam-heavy files.
|
|
1454
2184
|
_seamCorners;
|
|
2185
|
+
_numSeamCorners;
|
|
1455
2186
|
constructor() {
|
|
1456
2187
|
this.is_edge_on_seam_ = [];
|
|
1457
2188
|
this.is_vertex_on_seam_ = [];
|
|
1458
2189
|
this.no_interior_seams_ = true;
|
|
1459
2190
|
this.corner_to_vertex_map_ = [];
|
|
1460
2191
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1461
|
-
this.
|
|
2192
|
+
this.num_attribute_vertices_ = 0;
|
|
1462
2193
|
this.corner_table_ = null;
|
|
1463
2194
|
this._effectiveOpposite = null;
|
|
1464
2195
|
this._seamCorners = [];
|
|
2196
|
+
this._numSeamCorners = 0;
|
|
1465
2197
|
}
|
|
1466
2198
|
initEmpty(table) {
|
|
1467
2199
|
if (table === null) {
|
|
1468
2200
|
return false;
|
|
1469
2201
|
}
|
|
1470
|
-
this.is_edge_on_seam_ =
|
|
1471
|
-
this.is_vertex_on_seam_ =
|
|
1472
|
-
this.corner_to_vertex_map_ =
|
|
1473
|
-
this.
|
|
2202
|
+
this.is_edge_on_seam_ = scratchUint8Zeroed(table.numCorners());
|
|
2203
|
+
this.is_vertex_on_seam_ = scratchUint8Zeroed(table.numVertices());
|
|
2204
|
+
this.corner_to_vertex_map_ = scratchInt32Filled(table.numCorners(), kInvalidVertexIndex);
|
|
2205
|
+
this.num_attribute_vertices_ = 0;
|
|
1474
2206
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1475
2207
|
this._effectiveOpposite = null;
|
|
1476
2208
|
this._seamCorners = [];
|
|
2209
|
+
this._numSeamCorners = 0;
|
|
1477
2210
|
this.corner_table_ = table;
|
|
1478
2211
|
this.no_interior_seams_ = true;
|
|
1479
2212
|
return true;
|
|
1480
2213
|
}
|
|
2214
|
+
// Sizes the seam-corner list for numSeamEdges upcoming addSeamEdge calls
|
|
2215
|
+
// (each adds at most two corners). Decode-scoped scratch.
|
|
2216
|
+
reserveSeamEdges(numSeamEdges) {
|
|
2217
|
+
this._seamCorners = scratchInt32(numSeamEdges * 2);
|
|
2218
|
+
this._numSeamCorners = 0;
|
|
2219
|
+
}
|
|
1481
2220
|
addSeamEdge(c) {
|
|
1482
2221
|
const cornerToVertex = this.corner_table_.cornerToVertexArray();
|
|
1483
2222
|
const oppositeCorners = this.corner_table_.oppositeCornerArray();
|
|
1484
2223
|
const isEdge = this.is_edge_on_seam_;
|
|
1485
2224
|
const isVert = this.is_vertex_on_seam_;
|
|
2225
|
+
const seamCorners = this._seamCorners;
|
|
1486
2226
|
isEdge[c] = 1;
|
|
1487
|
-
this.
|
|
2227
|
+
seamCorners[this._numSeamCorners++] = c;
|
|
1488
2228
|
let rem = c - (c / 3 | 0) * 3;
|
|
1489
2229
|
isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
|
|
1490
2230
|
isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
|
|
@@ -1492,7 +2232,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1492
2232
|
if (oppCorner !== kInvalidCornerIndex) {
|
|
1493
2233
|
this.no_interior_seams_ = false;
|
|
1494
2234
|
isEdge[oppCorner] = 1;
|
|
1495
|
-
this.
|
|
2235
|
+
seamCorners[this._numSeamCorners++] = oppCorner;
|
|
1496
2236
|
rem = oppCorner - (oppCorner / 3 | 0) * 3;
|
|
1497
2237
|
isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
|
|
1498
2238
|
isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
|
|
@@ -1507,12 +2247,12 @@ var MeshAttributeCornerTable = class {
|
|
|
1507
2247
|
const ct = this.corner_table_;
|
|
1508
2248
|
const numCorners = ct.numCorners();
|
|
1509
2249
|
const numBaseVertices = ct.numVertices();
|
|
1510
|
-
const leftMostMap =
|
|
2250
|
+
const leftMostMap = scratchInt32(numCorners);
|
|
1511
2251
|
const cornerToVertex = this.corner_to_vertex_map_;
|
|
1512
2252
|
const isVertexOnSeam = this.is_vertex_on_seam_;
|
|
1513
2253
|
const isEdgeOnSeam = this.is_edge_on_seam_;
|
|
1514
2254
|
const seamOpp = this.oppositeCornerArray();
|
|
1515
|
-
const
|
|
2255
|
+
const swingRight = ct.swingRightArray();
|
|
1516
2256
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
1517
2257
|
let numNewVertices = 0;
|
|
1518
2258
|
for (let v = 0; v < numBaseVertices; ++v) {
|
|
@@ -1522,14 +2262,10 @@ var MeshAttributeCornerTable = class {
|
|
|
1522
2262
|
const firstVertId = numNewVertices++;
|
|
1523
2263
|
leftMostMap[firstVertId] = c;
|
|
1524
2264
|
cornerToVertex[c] = firstVertId;
|
|
1525
|
-
let
|
|
1526
|
-
let bopp = baseOpp[pv];
|
|
1527
|
-
let actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2265
|
+
let actC = swingRight[c];
|
|
1528
2266
|
while (actC !== kInvalidCornerIndex && actC !== c) {
|
|
1529
2267
|
cornerToVertex[actC] = firstVertId;
|
|
1530
|
-
|
|
1531
|
-
bopp = baseOpp[pv];
|
|
1532
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2268
|
+
actC = swingRight[actC];
|
|
1533
2269
|
}
|
|
1534
2270
|
} else {
|
|
1535
2271
|
let firstVertId = numNewVertices++;
|
|
@@ -1547,9 +2283,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1547
2283
|
}
|
|
1548
2284
|
cornerToVertex[firstC] = firstVertId;
|
|
1549
2285
|
leftMostMap[firstVertId] = firstC;
|
|
1550
|
-
|
|
1551
|
-
let bopp = baseOpp[pv];
|
|
1552
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2286
|
+
actC = swingRight[firstC];
|
|
1553
2287
|
while (actC !== kInvalidCornerIndex && actC !== firstC) {
|
|
1554
2288
|
const nAct = actC % 3 === 2 ? actC - 2 : actC + 1;
|
|
1555
2289
|
if (isEdgeOnSeam[nAct]) {
|
|
@@ -1557,13 +2291,11 @@ var MeshAttributeCornerTable = class {
|
|
|
1557
2291
|
leftMostMap[firstVertId] = actC;
|
|
1558
2292
|
}
|
|
1559
2293
|
cornerToVertex[actC] = firstVertId;
|
|
1560
|
-
|
|
1561
|
-
bopp = baseOpp[pv];
|
|
1562
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2294
|
+
actC = swingRight[actC];
|
|
1563
2295
|
}
|
|
1564
2296
|
}
|
|
1565
2297
|
}
|
|
1566
|
-
this.
|
|
2298
|
+
this.num_attribute_vertices_ = numNewVertices;
|
|
1567
2299
|
this.vertex_to_left_most_corner_map_ = leftMostMap.subarray(0, numNewVertices);
|
|
1568
2300
|
return true;
|
|
1569
2301
|
}
|
|
@@ -1589,7 +2321,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1589
2321
|
return this.next(this.opposite(this.next(corner)));
|
|
1590
2322
|
}
|
|
1591
2323
|
numVertices() {
|
|
1592
|
-
return this.
|
|
2324
|
+
return this.num_attribute_vertices_;
|
|
1593
2325
|
}
|
|
1594
2326
|
numFaces() {
|
|
1595
2327
|
return this.corner_table_.numFaces();
|
|
@@ -1617,12 +2349,13 @@ var MeshAttributeCornerTable = class {
|
|
|
1617
2349
|
const nc = this.corner_table_.numCorners();
|
|
1618
2350
|
const base = this.corner_table_.oppositeCornerArray();
|
|
1619
2351
|
const seamCorners = this._seamCorners;
|
|
1620
|
-
|
|
2352
|
+
const numSeamCorners = this._numSeamCorners;
|
|
2353
|
+
if (numSeamCorners === 0) {
|
|
1621
2354
|
this._effectiveOpposite = base;
|
|
1622
2355
|
} else {
|
|
1623
2356
|
const eff = scratchInt32(nc);
|
|
1624
2357
|
eff.set(base.length === nc ? base : base.subarray(0, nc));
|
|
1625
|
-
for (let i = 0
|
|
2358
|
+
for (let i = 0; i < numSeamCorners; ++i) {
|
|
1626
2359
|
eff[seamCorners[i]] = kInvalidCornerIndex;
|
|
1627
2360
|
}
|
|
1628
2361
|
this._effectiveOpposite = eff;
|
|
@@ -1637,23 +2370,20 @@ var MeshAttributeCornerTable = class {
|
|
|
1637
2370
|
vertexOnSeamArray() {
|
|
1638
2371
|
return this.is_vertex_on_seam_;
|
|
1639
2372
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1648
|
-
return true;
|
|
1649
|
-
}
|
|
1650
|
-
adoptVertexRecompute(other) {
|
|
2373
|
+
// Takes over another table's state wholesale. Only valid when both tables
|
|
2374
|
+
// were built from the same corner table and the same seam edges, in which
|
|
2375
|
+
// case every one of these is identical and read-only from here on.
|
|
2376
|
+
adoptFrom(other) {
|
|
2377
|
+
this.corner_table_ = other.corner_table_;
|
|
2378
|
+
this.is_edge_on_seam_ = other.is_edge_on_seam_;
|
|
2379
|
+
this.is_vertex_on_seam_ = other.is_vertex_on_seam_;
|
|
1651
2380
|
this.corner_to_vertex_map_ = other.corner_to_vertex_map_;
|
|
1652
|
-
this.
|
|
2381
|
+
this.num_attribute_vertices_ = other.num_attribute_vertices_;
|
|
1653
2382
|
this.vertex_to_left_most_corner_map_ = other.vertex_to_left_most_corner_map_;
|
|
1654
2383
|
this.no_interior_seams_ = other.no_interior_seams_;
|
|
1655
2384
|
this._effectiveOpposite = other._effectiveOpposite;
|
|
1656
2385
|
this._seamCorners = other._seamCorners;
|
|
2386
|
+
this._numSeamCorners = other._numSeamCorners;
|
|
1657
2387
|
}
|
|
1658
2388
|
};
|
|
1659
2389
|
|
|
@@ -1667,6 +2397,21 @@ var AttributesDecoderInterface = class {
|
|
|
1667
2397
|
decodeAttributesDecoderData(_buffer) {
|
|
1668
2398
|
return false;
|
|
1669
2399
|
}
|
|
2400
|
+
// --- Optional two-phase decode across attributes decoders ---
|
|
2401
|
+
// PointCloudDecoder parses every decoder first (all buffer reads are
|
|
2402
|
+
// size-driven, so parsing runs ahead of the deferred rANS symbol decodes),
|
|
2403
|
+
// then decodes the collected streams two at a time, then finishes each
|
|
2404
|
+
// decoder in order (so parent attributes complete before dependents).
|
|
2405
|
+
// Defaults keep the original single-phase behavior for decoders that do not
|
|
2406
|
+
// split.
|
|
2407
|
+
decodeAttributesParse(buffer) {
|
|
2408
|
+
return this.decodeAttributes(buffer);
|
|
2409
|
+
}
|
|
2410
|
+
collectPendingSymbolStreams(_out) {
|
|
2411
|
+
}
|
|
2412
|
+
decodeAttributesFinish() {
|
|
2413
|
+
return true;
|
|
2414
|
+
}
|
|
1670
2415
|
decodeAttributes(_buffer) {
|
|
1671
2416
|
return false;
|
|
1672
2417
|
}
|
|
@@ -1813,6 +2558,22 @@ var SequentialAttributeDecoder = class {
|
|
|
1813
2558
|
this._attributeId = attributeId;
|
|
1814
2559
|
return true;
|
|
1815
2560
|
}
|
|
2561
|
+
// --- Optional two-phase decode ---
|
|
2562
|
+
// The controller calls Parse for every attribute first (headers, schemes,
|
|
2563
|
+
// prediction data -- all size-driven cursor movement), collects the pending
|
|
2564
|
+
// rANS symbol streams, decodes them in pairs (see ransDecodeSymbolsPair),
|
|
2565
|
+
// then calls Finish per attribute in order. Decoders without a deferrable
|
|
2566
|
+
// stream simply do the whole decode in Parse. Defaults preserve the
|
|
2567
|
+
// original single-phase behavior.
|
|
2568
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
2569
|
+
return this.decodePortableAttribute(pointIds, buffer);
|
|
2570
|
+
}
|
|
2571
|
+
pendingSymbolStream() {
|
|
2572
|
+
return null;
|
|
2573
|
+
}
|
|
2574
|
+
decodePortableAttributeFinish() {
|
|
2575
|
+
return true;
|
|
2576
|
+
}
|
|
1816
2577
|
decodePortableAttribute(pointIds, buffer) {
|
|
1817
2578
|
if (this._attribute.numComponents <= 0) {
|
|
1818
2579
|
return false;
|
|
@@ -1833,7 +2594,7 @@ var SequentialAttributeDecoder = class {
|
|
|
1833
2594
|
getPortableAttribute() {
|
|
1834
2595
|
if (!this._attribute.isMappingIdentity && this._portableAttribute && this._portableAttribute.isMappingIdentity) {
|
|
1835
2596
|
const size = this._attribute.indicesMapSize;
|
|
1836
|
-
this._portableAttribute.
|
|
2597
|
+
this._portableAttribute.setExplicitMappingScratch(size);
|
|
1837
2598
|
const src = this._attribute.indicesMap;
|
|
1838
2599
|
const dst = this._portableAttribute.indicesMap;
|
|
1839
2600
|
if (src.length === size) {
|
|
@@ -1875,304 +2636,15 @@ var SequentialAttributeDecoder = class {
|
|
|
1875
2636
|
if (valueData === void 0) {
|
|
1876
2637
|
return false;
|
|
1877
2638
|
}
|
|
1878
|
-
this._attribute.buffer.write(0, valueData, totalSize);
|
|
1879
|
-
return true;
|
|
1880
|
-
}
|
|
1881
|
-
setPortableAttribute(att) {
|
|
1882
|
-
this._portableAttribute = att;
|
|
1883
|
-
}
|
|
1884
|
-
get portableAttribute() {
|
|
1885
|
-
return this._portableAttribute;
|
|
1886
|
-
}
|
|
1887
|
-
};
|
|
1888
|
-
|
|
1889
|
-
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1890
|
-
var ANS_P8_PRECISION = 256;
|
|
1891
|
-
var ANS_L_BASE = 4096;
|
|
1892
|
-
var ANS_IO_BASE = 256;
|
|
1893
|
-
function memGetLe16(buf, offset) {
|
|
1894
|
-
return buf[offset] | buf[offset + 1] << 8;
|
|
1895
|
-
}
|
|
1896
|
-
function memGetLe24(buf, offset) {
|
|
1897
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1898
|
-
}
|
|
1899
|
-
function memGetLe32(buf, offset) {
|
|
1900
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1901
|
-
}
|
|
1902
|
-
var AnsDecoder = class {
|
|
1903
|
-
buf;
|
|
1904
|
-
bufOffset;
|
|
1905
|
-
// First valid byte of this decoder's slice within buf: init is passed
|
|
1906
|
-
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1907
|
-
bufStart;
|
|
1908
|
-
state;
|
|
1909
|
-
constructor() {
|
|
1910
|
-
this.buf = null;
|
|
1911
|
-
this.bufOffset = 0;
|
|
1912
|
-
this.bufStart = 0;
|
|
1913
|
-
this.state = 0;
|
|
1914
|
-
}
|
|
1915
|
-
};
|
|
1916
|
-
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1917
|
-
if (offset - base < 1) {
|
|
1918
|
-
return 1;
|
|
1919
|
-
}
|
|
1920
|
-
ans.buf = buf;
|
|
1921
|
-
ans.bufStart = base;
|
|
1922
|
-
const x = buf[offset - 1] >> 6;
|
|
1923
|
-
if (x === 0) {
|
|
1924
|
-
ans.bufOffset = offset - 1;
|
|
1925
|
-
ans.state = buf[offset - 1] & 63;
|
|
1926
|
-
} else if (x === 1) {
|
|
1927
|
-
if (offset - base < 2) {
|
|
1928
|
-
return 1;
|
|
1929
|
-
}
|
|
1930
|
-
ans.bufOffset = offset - 2;
|
|
1931
|
-
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1932
|
-
} else if (x === 2) {
|
|
1933
|
-
if (offset - base < 3) {
|
|
1934
|
-
return 1;
|
|
1935
|
-
}
|
|
1936
|
-
ans.bufOffset = offset - 3;
|
|
1937
|
-
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1938
|
-
} else {
|
|
1939
|
-
return 1;
|
|
1940
|
-
}
|
|
1941
|
-
ans.state += ANS_L_BASE;
|
|
1942
|
-
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1943
|
-
return 1;
|
|
1944
|
-
}
|
|
1945
|
-
return 0;
|
|
1946
|
-
}
|
|
1947
|
-
function ansReadEnd(ans) {
|
|
1948
|
-
return ans.state === ANS_L_BASE;
|
|
1949
|
-
}
|
|
1950
|
-
var tablePool = [];
|
|
1951
|
-
var acquirePooled = (Ctor, size) => {
|
|
1952
|
-
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1953
|
-
const buf = tablePool[i];
|
|
1954
|
-
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1955
|
-
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1956
|
-
tablePool.pop();
|
|
1957
|
-
return buf;
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
return new Ctor(size);
|
|
1961
|
-
};
|
|
1962
|
-
var RAnsDecoder = class {
|
|
1963
|
-
ransPrecisionBits;
|
|
1964
|
-
ransPrecision;
|
|
1965
|
-
ransPrecisionMask;
|
|
1966
|
-
lRansBase;
|
|
1967
|
-
lutTable;
|
|
1968
|
-
probTable;
|
|
1969
|
-
cumProbTable;
|
|
1970
|
-
buf;
|
|
1971
|
-
bufOffset;
|
|
1972
|
-
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1973
|
-
// see AnsDecoder.bufStart).
|
|
1974
|
-
bufStart;
|
|
1975
|
-
state;
|
|
1976
|
-
constructor(ransPrecisionBits) {
|
|
1977
|
-
this.ransPrecisionBits = ransPrecisionBits;
|
|
1978
|
-
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1979
|
-
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1980
|
-
this.lRansBase = this.ransPrecision * 4;
|
|
1981
|
-
this.lutTable = null;
|
|
1982
|
-
this.probTable = null;
|
|
1983
|
-
this.cumProbTable = null;
|
|
1984
|
-
this.buf = null;
|
|
1985
|
-
this.bufOffset = 0;
|
|
1986
|
-
this.bufStart = 0;
|
|
1987
|
-
this.state = 0;
|
|
1988
|
-
}
|
|
1989
|
-
// offset is the absolute end of the encoded bytes within buf and base the
|
|
1990
|
-
// absolute start (offset - base = encoded length). Passing the source
|
|
1991
|
-
// buffer with absolute offsets avoids a subarray allocation per init.
|
|
1992
|
-
// Returns 0 on success, non-zero on error.
|
|
1993
|
-
readInit(buf, offset, base = 0) {
|
|
1994
|
-
if (offset - base < 1) {
|
|
1995
|
-
return 1;
|
|
1996
|
-
}
|
|
1997
|
-
this.buf = buf;
|
|
1998
|
-
this.bufStart = base;
|
|
1999
|
-
const x = buf[offset - 1] >> 6;
|
|
2000
|
-
if (x === 0) {
|
|
2001
|
-
this.bufOffset = offset - 1;
|
|
2002
|
-
this.state = buf[offset - 1] & 63;
|
|
2003
|
-
} else if (x === 1) {
|
|
2004
|
-
if (offset - base < 2) {
|
|
2005
|
-
return 1;
|
|
2006
|
-
}
|
|
2007
|
-
this.bufOffset = offset - 2;
|
|
2008
|
-
this.state = memGetLe16(buf, offset - 2) & 16383;
|
|
2009
|
-
} else if (x === 2) {
|
|
2010
|
-
if (offset - base < 3) {
|
|
2011
|
-
return 1;
|
|
2012
|
-
}
|
|
2013
|
-
this.bufOffset = offset - 3;
|
|
2014
|
-
this.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
2015
|
-
} else if (x === 3) {
|
|
2016
|
-
if (offset - base < 4) {
|
|
2017
|
-
return 1;
|
|
2018
|
-
}
|
|
2019
|
-
this.bufOffset = offset - 4;
|
|
2020
|
-
this.state = memGetLe32(buf, offset - 4) & 1073741823;
|
|
2021
|
-
} else {
|
|
2022
|
-
return 1;
|
|
2023
|
-
}
|
|
2024
|
-
this.state += this.lRansBase;
|
|
2025
|
-
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
2026
|
-
return 1;
|
|
2027
|
-
}
|
|
2028
|
-
return 0;
|
|
2029
|
-
}
|
|
2030
|
-
readEnd() {
|
|
2031
|
-
if (this.lutTable !== null) {
|
|
2032
|
-
tablePool.push(this.lutTable);
|
|
2033
|
-
this.lutTable = null;
|
|
2034
|
-
}
|
|
2035
|
-
if (this.probTable !== null) {
|
|
2036
|
-
tablePool.push(this.probTable);
|
|
2037
|
-
this.probTable = null;
|
|
2038
|
-
}
|
|
2039
|
-
if (this.cumProbTable !== null) {
|
|
2040
|
-
tablePool.push(this.cumProbTable);
|
|
2041
|
-
this.cumProbTable = null;
|
|
2042
|
-
}
|
|
2043
|
-
return this.state === this.lRansBase;
|
|
2044
|
-
}
|
|
2045
|
-
ransRead() {
|
|
2046
|
-
const buf = this.buf;
|
|
2047
|
-
const lRansBase = this.lRansBase;
|
|
2048
|
-
let state = this.state;
|
|
2049
|
-
let bufOffset = this.bufOffset;
|
|
2050
|
-
const bufStart = this.bufStart;
|
|
2051
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2052
|
-
state = state << 8 | buf[--bufOffset];
|
|
2053
|
-
}
|
|
2054
|
-
const quo = state >>> this.ransPrecisionBits;
|
|
2055
|
-
const rem = state & this.ransPrecisionMask;
|
|
2056
|
-
const symbol = this.lutTable[rem];
|
|
2057
|
-
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
2058
|
-
this.bufOffset = bufOffset;
|
|
2059
|
-
return symbol;
|
|
2060
|
-
}
|
|
2061
|
-
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
2062
|
-
// written back once. Removes per-symbol property reads and call indirection.
|
|
2063
|
-
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
2064
|
-
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
2065
|
-
// once here so each loop body stays monomorphic on its concrete type. The
|
|
2066
|
-
// three bodies are intentionally identical copies.
|
|
2067
|
-
decodeSymbols(out, count) {
|
|
2068
|
-
const lutTable = this.lutTable;
|
|
2069
|
-
if (lutTable instanceof Uint8Array) {
|
|
2070
|
-
this._decodeSymbolsU8(out, count, lutTable);
|
|
2071
|
-
} else if (lutTable instanceof Uint16Array) {
|
|
2072
|
-
this._decodeSymbolsU16(out, count, lutTable);
|
|
2073
|
-
} else {
|
|
2074
|
-
this._decodeSymbolsU32(out, count, lutTable);
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
_decodeSymbolsU8(out, count, lutTable) {
|
|
2078
|
-
const buf = this.buf;
|
|
2079
|
-
const lRansBase = this.lRansBase;
|
|
2080
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2081
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2082
|
-
const probTable = this.probTable;
|
|
2083
|
-
const cumProbTable = this.cumProbTable;
|
|
2084
|
-
let state = this.state;
|
|
2085
|
-
let bufOffset = this.bufOffset;
|
|
2086
|
-
const bufStart = this.bufStart;
|
|
2087
|
-
for (let i = 0; i < count; ++i) {
|
|
2088
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2089
|
-
state = state << 8 | buf[--bufOffset];
|
|
2090
|
-
}
|
|
2091
|
-
const rem = state & ransPrecisionMask;
|
|
2092
|
-
const symbol = lutTable[rem];
|
|
2093
|
-
out[i] = symbol;
|
|
2094
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2095
|
-
}
|
|
2096
|
-
this.state = state;
|
|
2097
|
-
this.bufOffset = bufOffset;
|
|
2098
|
-
}
|
|
2099
|
-
_decodeSymbolsU16(out, count, lutTable) {
|
|
2100
|
-
const buf = this.buf;
|
|
2101
|
-
const lRansBase = this.lRansBase;
|
|
2102
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2103
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2104
|
-
const probTable = this.probTable;
|
|
2105
|
-
const cumProbTable = this.cumProbTable;
|
|
2106
|
-
let state = this.state;
|
|
2107
|
-
let bufOffset = this.bufOffset;
|
|
2108
|
-
const bufStart = this.bufStart;
|
|
2109
|
-
for (let i = 0; i < count; ++i) {
|
|
2110
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2111
|
-
state = state << 8 | buf[--bufOffset];
|
|
2112
|
-
}
|
|
2113
|
-
const rem = state & ransPrecisionMask;
|
|
2114
|
-
const symbol = lutTable[rem];
|
|
2115
|
-
out[i] = symbol;
|
|
2116
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2117
|
-
}
|
|
2118
|
-
this.state = state;
|
|
2119
|
-
this.bufOffset = bufOffset;
|
|
2120
|
-
}
|
|
2121
|
-
_decodeSymbolsU32(out, count, lutTable) {
|
|
2122
|
-
const buf = this.buf;
|
|
2123
|
-
const lRansBase = this.lRansBase;
|
|
2124
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2125
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2126
|
-
const probTable = this.probTable;
|
|
2127
|
-
const cumProbTable = this.cumProbTable;
|
|
2128
|
-
let state = this.state;
|
|
2129
|
-
let bufOffset = this.bufOffset;
|
|
2130
|
-
const bufStart = this.bufStart;
|
|
2131
|
-
for (let i = 0; i < count; ++i) {
|
|
2132
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2133
|
-
state = state << 8 | buf[--bufOffset];
|
|
2134
|
-
}
|
|
2135
|
-
const rem = state & ransPrecisionMask;
|
|
2136
|
-
const symbol = lutTable[rem];
|
|
2137
|
-
out[i] = symbol;
|
|
2138
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2139
|
-
}
|
|
2140
|
-
this.state = state;
|
|
2141
|
-
this.bufOffset = bufOffset;
|
|
2142
|
-
}
|
|
2143
|
-
// Builds the ransPrecision-entry lookup table. Returns false on bad input data.
|
|
2144
|
-
ransBuildLookUpTable(tokenProbs, numSymbols) {
|
|
2145
|
-
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
2146
|
-
const lutTable = acquirePooled(LutArray, this.ransPrecision);
|
|
2147
|
-
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
2148
|
-
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
2149
|
-
this.lutTable = lutTable;
|
|
2150
|
-
this.probTable = probTable;
|
|
2151
|
-
this.cumProbTable = cumProbTable;
|
|
2152
|
-
let cumProb = 0;
|
|
2153
|
-
let actProb = 0;
|
|
2154
|
-
for (let i = 0; i < numSymbols; ++i) {
|
|
2155
|
-
const prob = tokenProbs[i];
|
|
2156
|
-
probTable[i] = prob;
|
|
2157
|
-
cumProbTable[i] = cumProb;
|
|
2158
|
-
cumProb += prob;
|
|
2159
|
-
if (cumProb > this.ransPrecision) {
|
|
2160
|
-
return false;
|
|
2161
|
-
}
|
|
2162
|
-
if (prob < 32) {
|
|
2163
|
-
for (let j = actProb; j < cumProb; ++j) {
|
|
2164
|
-
lutTable[j] = i;
|
|
2165
|
-
}
|
|
2166
|
-
} else {
|
|
2167
|
-
lutTable.fill(i, actProb, cumProb);
|
|
2168
|
-
}
|
|
2169
|
-
actProb = cumProb;
|
|
2170
|
-
}
|
|
2171
|
-
if (cumProb !== this.ransPrecision) {
|
|
2172
|
-
return false;
|
|
2173
|
-
}
|
|
2639
|
+
this._attribute.buffer.write(0, valueData, totalSize);
|
|
2174
2640
|
return true;
|
|
2175
2641
|
}
|
|
2642
|
+
setPortableAttribute(att) {
|
|
2643
|
+
this._portableAttribute = att;
|
|
2644
|
+
}
|
|
2645
|
+
get portableAttribute() {
|
|
2646
|
+
return this._portableAttribute;
|
|
2647
|
+
}
|
|
2176
2648
|
};
|
|
2177
2649
|
|
|
2178
2650
|
// src/decoder/compression/entropy/RAnsSymbolDecoder.ts
|
|
@@ -2196,8 +2668,10 @@ var RAnsSymbolDecoder = class {
|
|
|
2196
2668
|
get numSymbols() {
|
|
2197
2669
|
return this.numSymbols_;
|
|
2198
2670
|
}
|
|
2199
|
-
// Initialize the decoder and decode the probability table.
|
|
2200
|
-
|
|
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) {
|
|
2201
2675
|
if (buffer.bitstreamVersion === 0) {
|
|
2202
2676
|
return false;
|
|
2203
2677
|
}
|
|
@@ -2208,7 +2682,7 @@ var RAnsSymbolDecoder = class {
|
|
|
2208
2682
|
return false;
|
|
2209
2683
|
}
|
|
2210
2684
|
const numSymbols = this.numSymbols_;
|
|
2211
|
-
const probabilityTable =
|
|
2685
|
+
const probabilityTable = scratchUint32Zeroed(numSymbols);
|
|
2212
2686
|
this.probabilityTable_ = probabilityTable;
|
|
2213
2687
|
if (numSymbols === 0) {
|
|
2214
2688
|
return true;
|
|
@@ -2238,7 +2712,7 @@ var RAnsSymbolDecoder = class {
|
|
|
2238
2712
|
}
|
|
2239
2713
|
}
|
|
2240
2714
|
buffer.advance(pos - startPos);
|
|
2241
|
-
if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_)) {
|
|
2715
|
+
if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_, expectedCount)) {
|
|
2242
2716
|
return false;
|
|
2243
2717
|
}
|
|
2244
2718
|
return true;
|
|
@@ -2280,7 +2754,7 @@ function decodeSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
|
2280
2754
|
}
|
|
2281
2755
|
function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
2282
2756
|
const tagDecoder = new RAnsSymbolDecoder(5);
|
|
2283
|
-
if (!tagDecoder.create(srcBuffer)) {
|
|
2757
|
+
if (!tagDecoder.create(srcBuffer, Math.ceil(numValues / numComponents))) {
|
|
2284
2758
|
return false;
|
|
2285
2759
|
}
|
|
2286
2760
|
if (!tagDecoder.startDecoding(srcBuffer)) {
|
|
@@ -2289,27 +2763,76 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
|
2289
2763
|
if (numValues > 0 && tagDecoder.numSymbols === 0) {
|
|
2290
2764
|
return false;
|
|
2291
2765
|
}
|
|
2766
|
+
const tagAns = tagDecoder.ans_;
|
|
2292
2767
|
srcBuffer.startBitDecoding(false);
|
|
2293
2768
|
const bd = srcBuffer._bitDecoder;
|
|
2294
|
-
const
|
|
2769
|
+
const buf = bd._bitBuffer;
|
|
2770
|
+
const byteLength = bd._byteLength;
|
|
2771
|
+
let bitOffset = bd._bitOffset;
|
|
2295
2772
|
let valueId = 0;
|
|
2296
2773
|
for (let i = 0; i < numValues; i += numComponents) {
|
|
2297
2774
|
const bitLength = tagAns.ransRead();
|
|
2298
|
-
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2301
|
-
|
|
2775
|
+
if (bitLength < 32) {
|
|
2776
|
+
const mask = (1 << bitLength) - 1;
|
|
2777
|
+
let j = 0;
|
|
2778
|
+
for (; j < numComponents; ++j) {
|
|
2779
|
+
const byteOffset = bitOffset >> 3;
|
|
2780
|
+
if (byteOffset + 4 >= byteLength) break;
|
|
2781
|
+
const bitShift = bitOffset & 7;
|
|
2782
|
+
let value = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> bitShift;
|
|
2783
|
+
if (bitLength > 32 - bitShift) {
|
|
2784
|
+
value = (value | buf[byteOffset + 4] << 32 - bitShift) >>> 0;
|
|
2785
|
+
}
|
|
2786
|
+
bitOffset += bitLength;
|
|
2787
|
+
outValues[valueId++] = value & mask;
|
|
2788
|
+
}
|
|
2789
|
+
if (j === numComponents) continue;
|
|
2790
|
+
bd._bitOffset = bitOffset;
|
|
2791
|
+
for (; j < numComponents; ++j) {
|
|
2792
|
+
const val = bd.getBits(bitLength);
|
|
2793
|
+
if (val === void 0) {
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
outValues[valueId++] = val;
|
|
2797
|
+
}
|
|
2798
|
+
bitOffset = bd._bitOffset;
|
|
2799
|
+
} else {
|
|
2800
|
+
bd._bitOffset = bitOffset;
|
|
2801
|
+
for (let j = 0; j < numComponents; ++j) {
|
|
2802
|
+
const val = bd.getBits(bitLength);
|
|
2803
|
+
if (val === void 0) {
|
|
2804
|
+
return false;
|
|
2805
|
+
}
|
|
2806
|
+
outValues[valueId++] = val;
|
|
2302
2807
|
}
|
|
2303
|
-
|
|
2808
|
+
bitOffset = bd._bitOffset;
|
|
2304
2809
|
}
|
|
2305
2810
|
}
|
|
2811
|
+
bd._bitOffset = bitOffset;
|
|
2306
2812
|
tagDecoder.endDecoding();
|
|
2307
2813
|
srcBuffer.endBitDecoding();
|
|
2308
2814
|
return true;
|
|
2309
2815
|
}
|
|
2816
|
+
function parseRawSymbolStream(numValues, srcBuffer) {
|
|
2817
|
+
const maxBitLength = srcBuffer.decodeUint8();
|
|
2818
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
2819
|
+
return null;
|
|
2820
|
+
}
|
|
2821
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
2822
|
+
if (!decoder.create(srcBuffer, numValues)) {
|
|
2823
|
+
return null;
|
|
2824
|
+
}
|
|
2825
|
+
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
2826
|
+
return null;
|
|
2827
|
+
}
|
|
2828
|
+
if (!decoder.startDecoding(srcBuffer)) {
|
|
2829
|
+
return null;
|
|
2830
|
+
}
|
|
2831
|
+
return decoder;
|
|
2832
|
+
}
|
|
2310
2833
|
function decodeRawSymbolsInternal(uniqueSymbolsBitLength, numValues, srcBuffer, outValues) {
|
|
2311
2834
|
const decoder = new RAnsSymbolDecoder(uniqueSymbolsBitLength);
|
|
2312
|
-
if (!decoder.create(srcBuffer)) {
|
|
2835
|
+
if (!decoder.create(srcBuffer, numValues)) {
|
|
2313
2836
|
return false;
|
|
2314
2837
|
}
|
|
2315
2838
|
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
@@ -2409,6 +2932,16 @@ var PredictionSchemeDecoderInterface = class {
|
|
|
2409
2932
|
decodePredictionData(_buffer) {
|
|
2410
2933
|
return true;
|
|
2411
2934
|
}
|
|
2935
|
+
/**
|
|
2936
|
+
* Like computeOriginalValues, but inCorr still holds unsigned zigzag-coded
|
|
2937
|
+
* corrections; the implementation unpacks each one inline, replacing the
|
|
2938
|
+
* standalone convertSymbolsToSignedInts pass. Returns undefined when the
|
|
2939
|
+
* scheme/transform combination cannot fuse (the caller then falls back to
|
|
2940
|
+
* the two-pass path). Base implementation: never fusable.
|
|
2941
|
+
*/
|
|
2942
|
+
computeOriginalValuesZigzag(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2943
|
+
return void 0;
|
|
2944
|
+
}
|
|
2412
2945
|
/** Reverts the prediction applied during encoding, writing original values to outData. */
|
|
2413
2946
|
computeOriginalValues(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2414
2947
|
return false;
|
|
@@ -2744,7 +3277,7 @@ var OctahedronToolBox = class {
|
|
|
2744
3277
|
// src/decoder/compression/attributes/prediction_schemes/MeshPredictionSchemeGeometricNormalPredictorArea.ts
|
|
2745
3278
|
var UPPER_BOUND = 1 << 29;
|
|
2746
3279
|
function buildInt32PositionCache(att, map, numEntries, tempPos) {
|
|
2747
|
-
const cache =
|
|
3280
|
+
const cache = scratchInt32(numEntries * 3);
|
|
2748
3281
|
const bufData = att.buffer && att.buffer.data;
|
|
2749
3282
|
if (att.dataType === DataType.INT32 && att.numComponents === 3 && bufData) {
|
|
2750
3283
|
const src = new Int32Array(bufData.buffer);
|
|
@@ -2825,7 +3358,7 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
|
|
|
2825
3358
|
const cornerToVertex = this._cornerToVertex;
|
|
2826
3359
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
2827
3360
|
const nc = cornerToVertex.length;
|
|
2828
|
-
const c2o =
|
|
3361
|
+
const c2o = scratchInt32(nc);
|
|
2829
3362
|
for (let c = 0; c < nc; ++c) {
|
|
2830
3363
|
const v = cornerToVertex[c];
|
|
2831
3364
|
c2o[c] = v < 0 ? -1 : vertexToDataMap[v] * 3;
|
|
@@ -3076,10 +3609,21 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3076
3609
|
isInitialized() {
|
|
3077
3610
|
return this._meshData.isInitialized();
|
|
3078
3611
|
}
|
|
3612
|
+
// Zigzag-fused variant: decodes corrections that are still in their unsigned
|
|
3613
|
+
// zigzag form, unpacking each one inline. Only offered for the wrap
|
|
3614
|
+
// transform (whose corrections are the only zigzag-coded ones this scheme
|
|
3615
|
+
// sees); callers fall back to the standalone conversion pass otherwise.
|
|
3616
|
+
computeOriginalValuesZigzag(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
|
|
3617
|
+
this._transform.init(numComponents);
|
|
3618
|
+
if (!this._transform.getType || this._transform.getType() !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3619
|
+
return void 0;
|
|
3620
|
+
}
|
|
3621
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, true);
|
|
3622
|
+
}
|
|
3079
3623
|
computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
|
|
3080
3624
|
this._transform.init(numComponents);
|
|
3081
3625
|
if (this._transform.getType && this._transform.getType() === PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3082
|
-
return this._computeOriginalValuesWrap(inCorr, outData, numComponents);
|
|
3626
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, false);
|
|
3083
3627
|
}
|
|
3084
3628
|
const table = this._meshData.cornerTable;
|
|
3085
3629
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3120,12 +3664,18 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3120
3664
|
}
|
|
3121
3665
|
return true;
|
|
3122
3666
|
}
|
|
3123
|
-
|
|
3667
|
+
// The wrap transform's corrections are zigzag-coded; with `zigzag` set the
|
|
3668
|
+
// decode folds the (val >>> 1) ^ -(val & 1) unpacking into each correction
|
|
3669
|
+
// read, replacing the standalone convertSymbolsToSignedInts pass over the
|
|
3670
|
+
// whole array (see computeOriginalValuesZigzag). Every correction is read
|
|
3671
|
+
// exactly once before its slot is overwritten, so the in-place aliasing of
|
|
3672
|
+
// inCorr and outData is preserved.
|
|
3673
|
+
_computeOriginalValuesWrap(inCorr, outData, numComponents, zigzag) {
|
|
3124
3674
|
if (numComponents === 2) {
|
|
3125
|
-
return this._computeOriginalValuesWrap2(inCorr, outData);
|
|
3675
|
+
return this._computeOriginalValuesWrap2(inCorr, outData, zigzag);
|
|
3126
3676
|
}
|
|
3127
3677
|
if (numComponents === 3) {
|
|
3128
|
-
return this._computeOriginalValuesWrap3(inCorr, outData);
|
|
3678
|
+
return this._computeOriginalValuesWrap3(inCorr, outData, zigzag);
|
|
3129
3679
|
}
|
|
3130
3680
|
const table = this._meshData.cornerTable;
|
|
3131
3681
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3143,7 +3693,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3143
3693
|
} else if (pred < minValue) {
|
|
3144
3694
|
pred = minValue;
|
|
3145
3695
|
}
|
|
3146
|
-
|
|
3696
|
+
const raw = inCorr[c];
|
|
3697
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3147
3698
|
if (orig > maxValue) {
|
|
3148
3699
|
orig -= maxDif;
|
|
3149
3700
|
} else if (orig < minValue) {
|
|
@@ -3182,7 +3733,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3182
3733
|
} else if (pred < minValue) {
|
|
3183
3734
|
pred = minValue;
|
|
3184
3735
|
}
|
|
3185
|
-
|
|
3736
|
+
const raw = inCorr[dstOffset + c];
|
|
3737
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3186
3738
|
if (orig > maxValue) {
|
|
3187
3739
|
orig -= maxDif;
|
|
3188
3740
|
} else if (orig < minValue) {
|
|
@@ -3199,7 +3751,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3199
3751
|
} else if (pred < minValue) {
|
|
3200
3752
|
pred = minValue;
|
|
3201
3753
|
}
|
|
3202
|
-
|
|
3754
|
+
const raw = inCorr[dstOffset + c];
|
|
3755
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3203
3756
|
if (orig > maxValue) {
|
|
3204
3757
|
orig -= maxDif;
|
|
3205
3758
|
} else if (orig < minValue) {
|
|
@@ -3211,7 +3764,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3211
3764
|
}
|
|
3212
3765
|
return true;
|
|
3213
3766
|
}
|
|
3214
|
-
_computeOriginalValuesWrap2(inCorr, outData) {
|
|
3767
|
+
_computeOriginalValuesWrap2(inCorr, outData, zigzag) {
|
|
3215
3768
|
const table = this._meshData.cornerTable;
|
|
3216
3769
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3217
3770
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3233,8 +3786,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3233
3786
|
} else if (pred1 < minValue) {
|
|
3234
3787
|
pred1 = minValue;
|
|
3235
3788
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3789
|
+
const raw0 = inCorr[0];
|
|
3790
|
+
const raw1 = inCorr[1];
|
|
3791
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3792
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3238
3793
|
if (orig0 > maxValue) {
|
|
3239
3794
|
orig0 -= maxDif;
|
|
3240
3795
|
} else if (orig0 < minValue) {
|
|
@@ -3288,8 +3843,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3288
3843
|
} else if (pred1 < minValue) {
|
|
3289
3844
|
pred1 = minValue;
|
|
3290
3845
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3846
|
+
const rawA = inCorr[dstOffset];
|
|
3847
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3848
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3849
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3293
3850
|
if (orig0 > maxValue) {
|
|
3294
3851
|
orig0 -= maxDif;
|
|
3295
3852
|
} else if (orig0 < minValue) {
|
|
@@ -3305,7 +3862,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3305
3862
|
}
|
|
3306
3863
|
return true;
|
|
3307
3864
|
}
|
|
3308
|
-
_computeOriginalValuesWrap3(inCorr, outData) {
|
|
3865
|
+
_computeOriginalValuesWrap3(inCorr, outData, zigzag) {
|
|
3309
3866
|
const table = this._meshData.cornerTable;
|
|
3310
3867
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3311
3868
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3333,9 +3890,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3333
3890
|
} else if (pred2 < minValue) {
|
|
3334
3891
|
pred2 = minValue;
|
|
3335
3892
|
}
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3893
|
+
const raw0 = inCorr[0];
|
|
3894
|
+
const raw1 = inCorr[1];
|
|
3895
|
+
const raw2 = inCorr[2];
|
|
3896
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3897
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3898
|
+
let orig2 = pred2 + (zigzag ? raw2 >>> 1 ^ -(raw2 & 1) : raw2) | 0;
|
|
3339
3899
|
if (orig0 > maxValue) {
|
|
3340
3900
|
orig0 -= maxDif;
|
|
3341
3901
|
} else if (orig0 < minValue) {
|
|
@@ -3402,9 +3962,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3402
3962
|
} else if (pred2 < minValue) {
|
|
3403
3963
|
pred2 = minValue;
|
|
3404
3964
|
}
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3965
|
+
const rawA = inCorr[dstOffset];
|
|
3966
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3967
|
+
const rawC = inCorr[dstOffset + 2];
|
|
3968
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3969
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3970
|
+
orig2 = pred2 + (zigzag ? rawC >>> 1 ^ -(rawC & 1) : rawC) | 0;
|
|
3408
3971
|
if (orig0 > maxValue) {
|
|
3409
3972
|
orig0 -= maxDif;
|
|
3410
3973
|
} else if (orig0 < minValue) {
|
|
@@ -3771,11 +4334,16 @@ var PredictionSchemeDeltaDecoder = class extends PredictionSchemeDecoder {
|
|
|
3771
4334
|
return true;
|
|
3772
4335
|
}
|
|
3773
4336
|
computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
|
|
3774
|
-
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
|
+
}
|
|
3775
4343
|
const zeroVals = new Int32Array(numComponents);
|
|
3776
|
-
|
|
4344
|
+
transform.computeOriginalValue(zeroVals, 0, inCorr, 0, outData, 0);
|
|
3777
4345
|
for (let i = numComponents; i < size; i += numComponents) {
|
|
3778
|
-
|
|
4346
|
+
transform.computeOriginalValue(outData, i - numComponents, inCorr, i, outData, i);
|
|
3779
4347
|
}
|
|
3780
4348
|
return true;
|
|
3781
4349
|
}
|
|
@@ -3911,14 +4479,49 @@ var PredictionSchemeWrapDecodingTransform = class {
|
|
|
3911
4479
|
// src/decoder/compression/attributes/SequentialIntegerAttributeDecoder.ts
|
|
3912
4480
|
var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder {
|
|
3913
4481
|
_predictionScheme;
|
|
4482
|
+
// Two-phase decode state (see SequentialAttributeDecoder): the parse phase
|
|
4483
|
+
// stashes the primed raw-symbol stream here so the controller can batch and
|
|
4484
|
+
// pair several attributes' decodes; the finish phase consumes it.
|
|
4485
|
+
_pendingSymbolDecoder;
|
|
4486
|
+
_pendingNumValues;
|
|
4487
|
+
_finishPointIds;
|
|
3914
4488
|
constructor() {
|
|
3915
4489
|
super();
|
|
3916
4490
|
this._predictionScheme = null;
|
|
4491
|
+
this._pendingSymbolDecoder = null;
|
|
4492
|
+
this._pendingNumValues = 0;
|
|
4493
|
+
this._finishPointIds = null;
|
|
3917
4494
|
}
|
|
3918
|
-
|
|
3919
|
-
|
|
4495
|
+
// --- Two-phase decode (parse headers / batch symbol decode / finish) ---
|
|
4496
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
4497
|
+
if (this.attribute.numComponents <= 0) {
|
|
4498
|
+
return false;
|
|
4499
|
+
}
|
|
4500
|
+
if (!this.attribute.reset(pointIds.length)) {
|
|
4501
|
+
return false;
|
|
4502
|
+
}
|
|
4503
|
+
this._finishPointIds = pointIds;
|
|
4504
|
+
return this._decodeValuesParse(pointIds, buffer);
|
|
3920
4505
|
}
|
|
3921
|
-
|
|
4506
|
+
pendingSymbolStream() {
|
|
4507
|
+
if (this._pendingSymbolDecoder === null) {
|
|
4508
|
+
return null;
|
|
4509
|
+
}
|
|
4510
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4511
|
+
return {
|
|
4512
|
+
ans: this._pendingSymbolDecoder.ans_,
|
|
4513
|
+
out: new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, this._pendingNumValues),
|
|
4514
|
+
count: this._pendingNumValues
|
|
4515
|
+
};
|
|
4516
|
+
}
|
|
4517
|
+
decodePortableAttributeFinish() {
|
|
4518
|
+
if (this._pendingSymbolDecoder !== null) {
|
|
4519
|
+
this._pendingSymbolDecoder.endDecoding();
|
|
4520
|
+
this._pendingSymbolDecoder = null;
|
|
4521
|
+
}
|
|
4522
|
+
return this._finishIntegerValues(this._finishPointIds);
|
|
4523
|
+
}
|
|
4524
|
+
_decodeValuesParse(pointIds, buffer) {
|
|
3922
4525
|
const predictionSchemeMethod = buffer.decodeInt8();
|
|
3923
4526
|
if (predictionSchemeMethod === void 0) return false;
|
|
3924
4527
|
if (predictionSchemeMethod < PredictionSchemeMethod.PREDICTION_NONE || predictionSchemeMethod >= PredictionSchemeMethod.NUM_PREDICTION_SCHEMES) {
|
|
@@ -3937,12 +4540,6 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3937
4540
|
return false;
|
|
3938
4541
|
}
|
|
3939
4542
|
}
|
|
3940
|
-
if (!this.decodeIntegerValues(pointIds, buffer)) {
|
|
3941
|
-
return false;
|
|
3942
|
-
}
|
|
3943
|
-
return true;
|
|
3944
|
-
}
|
|
3945
|
-
decodeIntegerValues(pointIds, buffer) {
|
|
3946
4543
|
const numComponents = this.getNumValueComponents();
|
|
3947
4544
|
if (numComponents <= 0) {
|
|
3948
4545
|
return false;
|
|
@@ -3957,9 +4554,23 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3957
4554
|
const compressed = buffer.decodeUint8();
|
|
3958
4555
|
if (compressed === void 0) return false;
|
|
3959
4556
|
if (compressed > 0) {
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
4557
|
+
if (numValues > 0) {
|
|
4558
|
+
const scheme = buffer.decodeUint8();
|
|
4559
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
4560
|
+
const decoder = parseRawSymbolStream(numValues, buffer);
|
|
4561
|
+
if (decoder === null) {
|
|
4562
|
+
return false;
|
|
4563
|
+
}
|
|
4564
|
+
this._pendingSymbolDecoder = decoder;
|
|
4565
|
+
this._pendingNumValues = numValues;
|
|
4566
|
+
} else if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
4567
|
+
const outUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4568
|
+
if (!decodeTaggedSymbols(numValues, numComponents, buffer, outUint32)) {
|
|
4569
|
+
return false;
|
|
4570
|
+
}
|
|
4571
|
+
} else {
|
|
4572
|
+
return false;
|
|
4573
|
+
}
|
|
3963
4574
|
}
|
|
3964
4575
|
} else {
|
|
3965
4576
|
const numBytes = buffer.decodeUint8();
|
|
@@ -3990,15 +4601,40 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3990
4601
|
}
|
|
3991
4602
|
}
|
|
3992
4603
|
}
|
|
3993
|
-
if (numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive())) {
|
|
3994
|
-
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
3995
|
-
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
3996
|
-
}
|
|
3997
4604
|
if (this._predictionScheme) {
|
|
3998
4605
|
if (!this._predictionScheme.decodePredictionData(buffer)) {
|
|
3999
4606
|
return false;
|
|
4000
4607
|
}
|
|
4608
|
+
}
|
|
4609
|
+
return true;
|
|
4610
|
+
}
|
|
4611
|
+
// The post-symbol tail of the decode: zigzag unpacking and prediction.
|
|
4612
|
+
_finishIntegerValues(pointIds) {
|
|
4613
|
+
const numComponents = this.getNumValueComponents();
|
|
4614
|
+
const numValues = pointIds.length * numComponents;
|
|
4615
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4616
|
+
if (portableAttributeData === null) {
|
|
4617
|
+
return false;
|
|
4618
|
+
}
|
|
4619
|
+
const needsZigzag = numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive());
|
|
4620
|
+
if (this._predictionScheme) {
|
|
4001
4621
|
if (numValues > 0) {
|
|
4622
|
+
if (needsZigzag) {
|
|
4623
|
+
const fused = this._predictionScheme.computeOriginalValuesZigzag(
|
|
4624
|
+
portableAttributeData,
|
|
4625
|
+
portableAttributeData,
|
|
4626
|
+
numValues,
|
|
4627
|
+
numComponents,
|
|
4628
|
+
pointIds
|
|
4629
|
+
);
|
|
4630
|
+
if (fused !== void 0) {
|
|
4631
|
+
return fused;
|
|
4632
|
+
}
|
|
4633
|
+
}
|
|
4634
|
+
if (needsZigzag) {
|
|
4635
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4636
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4637
|
+
}
|
|
4002
4638
|
if (!this._predictionScheme.computeOriginalValues(
|
|
4003
4639
|
portableAttributeData,
|
|
4004
4640
|
portableAttributeData,
|
|
@@ -4009,9 +4645,34 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4009
4645
|
return false;
|
|
4010
4646
|
}
|
|
4011
4647
|
}
|
|
4648
|
+
} else if (needsZigzag) {
|
|
4649
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4650
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4012
4651
|
}
|
|
4013
4652
|
return true;
|
|
4014
4653
|
}
|
|
4654
|
+
transformAttributeToOriginalFormat(pointIds) {
|
|
4655
|
+
return this._storeValues(pointIds.length);
|
|
4656
|
+
}
|
|
4657
|
+
// Single-phase entry (base-class decodePortableAttribute path): parse,
|
|
4658
|
+
// decode any deferred symbol stream immediately, finish.
|
|
4659
|
+
decodeValues(pointIds, buffer) {
|
|
4660
|
+
this._finishPointIds = pointIds;
|
|
4661
|
+
if (!this._decodeValuesParse(pointIds, buffer)) {
|
|
4662
|
+
return false;
|
|
4663
|
+
}
|
|
4664
|
+
const pending = this._pendingSymbolDecoder;
|
|
4665
|
+
if (pending !== null) {
|
|
4666
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4667
|
+
const outUint32 = new Uint32Array(
|
|
4668
|
+
portableAttributeData.buffer,
|
|
4669
|
+
portableAttributeData.byteOffset,
|
|
4670
|
+
this._pendingNumValues
|
|
4671
|
+
);
|
|
4672
|
+
pending.ans_.decodeSymbols(outUint32, this._pendingNumValues);
|
|
4673
|
+
}
|
|
4674
|
+
return this.decodePortableAttributeFinish();
|
|
4675
|
+
}
|
|
4015
4676
|
// Prediction scheme for decoding integer values; subclasses override for others.
|
|
4016
4677
|
createIntPredictionScheme(method, transformType) {
|
|
4017
4678
|
if (transformType !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
@@ -4074,7 +4735,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4074
4735
|
);
|
|
4075
4736
|
const portAtt = new PointAttribute(ga);
|
|
4076
4737
|
portAtt.setIdentityMapping();
|
|
4077
|
-
portAtt.
|
|
4738
|
+
portAtt.resetScratch(numEntries);
|
|
4078
4739
|
portAtt.uniqueId = this.attribute.uniqueId;
|
|
4079
4740
|
this.setPortableAttribute(portAtt);
|
|
4080
4741
|
}
|
|
@@ -4100,12 +4761,22 @@ var AttributeTransformType = {
|
|
|
4100
4761
|
};
|
|
4101
4762
|
|
|
4102
4763
|
// src/decoder/attributes/AttributeTransformData.ts
|
|
4764
|
+
var INITIAL_CAPACITY = 32;
|
|
4103
4765
|
var AttributeTransformData = class {
|
|
4104
4766
|
_transformType;
|
|
4105
|
-
|
|
4767
|
+
// Parameter bytes, little-endian, appended in transform-defined order.
|
|
4768
|
+
// Capacity grows geometrically and the DataView is cached alongside it: the
|
|
4769
|
+
// previous DataBuffer-backed version reallocated the buffer and built a
|
|
4770
|
+
// fresh DataView on *every* appended value, which on primitive-heavy files
|
|
4771
|
+
// cost more than the dequantization it describes.
|
|
4772
|
+
_bytes;
|
|
4773
|
+
_view;
|
|
4774
|
+
_size;
|
|
4106
4775
|
constructor() {
|
|
4107
4776
|
this._transformType = AttributeTransformType.INVALID;
|
|
4108
|
-
this.
|
|
4777
|
+
this._bytes = new Uint8Array(INITIAL_CAPACITY);
|
|
4778
|
+
this._view = new DataView(this._bytes.buffer);
|
|
4779
|
+
this._size = 0;
|
|
4109
4780
|
}
|
|
4110
4781
|
get transformType() {
|
|
4111
4782
|
return this._transformType;
|
|
@@ -4113,13 +4784,29 @@ var AttributeTransformData = class {
|
|
|
4113
4784
|
set transformType(type) {
|
|
4114
4785
|
this._transformType = type;
|
|
4115
4786
|
}
|
|
4787
|
+
// Number of parameter bytes written so far (the next append offset).
|
|
4788
|
+
get dataSize() {
|
|
4789
|
+
return this._size;
|
|
4790
|
+
}
|
|
4791
|
+
get data() {
|
|
4792
|
+
return this._bytes.subarray(0, this._size);
|
|
4793
|
+
}
|
|
4794
|
+
_reserve(sizeNeeded) {
|
|
4795
|
+
if (sizeNeeded <= this._bytes.length) return;
|
|
4796
|
+
let capacity = this._bytes.length * 2;
|
|
4797
|
+
if (capacity < sizeNeeded) capacity = sizeNeeded;
|
|
4798
|
+
const grown = new Uint8Array(capacity);
|
|
4799
|
+
grown.set(this._bytes);
|
|
4800
|
+
this._bytes = grown;
|
|
4801
|
+
this._view = new DataView(grown.buffer);
|
|
4802
|
+
}
|
|
4116
4803
|
setParameterValue(byteOffset, value, type) {
|
|
4117
4804
|
const sizeNeeded = byteOffset + this._typeSize(type);
|
|
4118
|
-
|
|
4119
|
-
|
|
4805
|
+
this._reserve(sizeNeeded);
|
|
4806
|
+
if (sizeNeeded > this._size) {
|
|
4807
|
+
this._size = sizeNeeded;
|
|
4120
4808
|
}
|
|
4121
|
-
const
|
|
4122
|
-
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
4809
|
+
const view = this._view;
|
|
4123
4810
|
switch (type) {
|
|
4124
4811
|
case "int32":
|
|
4125
4812
|
view.setInt32(byteOffset, value, true);
|
|
@@ -4151,7 +4838,7 @@ var AttributeTransformData = class {
|
|
|
4151
4838
|
}
|
|
4152
4839
|
}
|
|
4153
4840
|
appendParameterValue(value, type) {
|
|
4154
|
-
this.setParameterValue(this.
|
|
4841
|
+
this.setParameterValue(this._size, value, type);
|
|
4155
4842
|
}
|
|
4156
4843
|
_typeSize(type) {
|
|
4157
4844
|
switch (type) {
|
|
@@ -4197,7 +4884,6 @@ var AttributeTransform = class {
|
|
|
4197
4884
|
// src/decoder/attributes/AttributeOctahedronTransform.ts
|
|
4198
4885
|
var AttributeOctahedronTransform = class extends AttributeTransform {
|
|
4199
4886
|
_quantizationBits;
|
|
4200
|
-
_tmpVec;
|
|
4201
4887
|
constructor() {
|
|
4202
4888
|
super();
|
|
4203
4889
|
this._quantizationBits = -1;
|
|
@@ -4229,15 +4915,30 @@ var AttributeOctahedronTransform = class extends AttributeTransform {
|
|
|
4229
4915
|
const srcI32 = new Int32Array(srcAddr.buffer, srcAddr.byteOffset, numPoints * 2);
|
|
4230
4916
|
const dstAddr = targetAttribute.getAddress(0);
|
|
4231
4917
|
const dstF32 = new Float32Array(dstAddr.buffer, dstAddr.byteOffset, numPoints * 3);
|
|
4232
|
-
const
|
|
4918
|
+
const fround = Math.fround;
|
|
4919
|
+
const scale = toolBox._dequantizationScale;
|
|
4233
4920
|
let si = 0;
|
|
4234
4921
|
let di = 0;
|
|
4235
4922
|
for (let i = 0; i < numPoints; i++) {
|
|
4236
|
-
|
|
4923
|
+
let y = fround(fround(fround(srcI32[si]) * scale) - 1);
|
|
4924
|
+
let z = fround(fround(fround(srcI32[si + 1]) * scale) - 1);
|
|
4237
4925
|
si += 2;
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
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
|
+
}
|
|
4241
4942
|
di += 3;
|
|
4242
4943
|
}
|
|
4243
4944
|
return true;
|
|
@@ -4407,6 +5108,140 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
|
|
|
4407
5108
|
outOrigVals[outOffset] = origS + center;
|
|
4408
5109
|
outOrigVals[outOffset + 1] = origT + center;
|
|
4409
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
|
+
}
|
|
4410
5245
|
};
|
|
4411
5246
|
|
|
4412
5247
|
// src/decoder/compression/attributes/prediction_schemes/PredictionSchemeNormalOctahedronDecodingTransform.ts
|
|
@@ -4721,6 +5556,12 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4721
5556
|
return true;
|
|
4722
5557
|
}
|
|
4723
5558
|
decodeAttributes(buffer) {
|
|
5559
|
+
if (!this._prepareSequence()) {
|
|
5560
|
+
return false;
|
|
5561
|
+
}
|
|
5562
|
+
return super.decodeAttributes(buffer);
|
|
5563
|
+
}
|
|
5564
|
+
_prepareSequence() {
|
|
4724
5565
|
if (!this._sequencer) {
|
|
4725
5566
|
return false;
|
|
4726
5567
|
}
|
|
@@ -4735,7 +5576,44 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4735
5576
|
return false;
|
|
4736
5577
|
}
|
|
4737
5578
|
}
|
|
4738
|
-
return
|
|
5579
|
+
return true;
|
|
5580
|
+
}
|
|
5581
|
+
// Two-phase decode (see AttributesDecoder): parse everything that reads the
|
|
5582
|
+
// buffer -- sequence, portable headers (deferring raw rANS symbol decodes),
|
|
5583
|
+
// and the transform parameters -- so the deferred streams of ALL attributes
|
|
5584
|
+
// decoders can then be paired, and finish (zigzag, prediction, inverse
|
|
5585
|
+
// transform) runs per decoder in the original order afterwards. None of the
|
|
5586
|
+
// finish work reads the buffer, and dependents only read parent portable
|
|
5587
|
+
// VALUES in finish, so ordering and output stay identical.
|
|
5588
|
+
decodeAttributesParse(buffer) {
|
|
5589
|
+
if (!this._prepareSequence()) {
|
|
5590
|
+
return false;
|
|
5591
|
+
}
|
|
5592
|
+
const numAttributes = this.getNumAttributes();
|
|
5593
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5594
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeParse(this._pointIds, buffer)) {
|
|
5595
|
+
return false;
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
return this.decodeDataNeededByPortableTransforms(buffer);
|
|
5599
|
+
}
|
|
5600
|
+
collectPendingSymbolStreams(out) {
|
|
5601
|
+
const numAttributes = this.getNumAttributes();
|
|
5602
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5603
|
+
const pending = this._sequentialDecoders[i].pendingSymbolStream();
|
|
5604
|
+
if (pending !== null) {
|
|
5605
|
+
out.push(pending);
|
|
5606
|
+
}
|
|
5607
|
+
}
|
|
5608
|
+
}
|
|
5609
|
+
decodeAttributesFinish() {
|
|
5610
|
+
const numAttributes = this.getNumAttributes();
|
|
5611
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5612
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeFinish()) {
|
|
5613
|
+
return false;
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5616
|
+
return this.transformAttributesToOriginalFormat();
|
|
4739
5617
|
}
|
|
4740
5618
|
getPortableAttribute(pointAttributeId) {
|
|
4741
5619
|
const locId = this.getLocalIdForPointAttribute(pointAttributeId);
|
|
@@ -4862,14 +5740,13 @@ var DepthFirstTraverser = class {
|
|
|
4862
5740
|
// Scratch buffers are set up here rather than in init() so a shared-traversal
|
|
4863
5741
|
// -cache hit — where generateSequence returns before any traversal — skips
|
|
4864
5742
|
// this entirely, including the visited-flag zero-fill (worth ~0.5% on the
|
|
4865
|
-
//
|
|
5743
|
+
// ~500-primitive manablade bundle, which shares attribute corner tables across
|
|
4866
5744
|
// primitives). Uint8Array (0/1) instead of Array(bool): these flags are read
|
|
4867
5745
|
// and written on every corner of the hottest decode loop (traverseFromCorner).
|
|
4868
5746
|
// Decode-scoped scratch: released in bulk at the end of the decode.
|
|
4869
5747
|
onTraversalStart() {
|
|
4870
5748
|
const cornerTable = this._cornerTable;
|
|
4871
5749
|
this._isFaceVisited = scratchUint8Zeroed(cornerTable.numFaces());
|
|
4872
|
-
this._isVertexVisited = scratchUint8Zeroed(cornerTable.numVertices());
|
|
4873
5750
|
this._cornerTraversalStack = scratchInt32(this._numCorners);
|
|
4874
5751
|
}
|
|
4875
5752
|
onTraversalEnd() {
|
|
@@ -4879,7 +5756,6 @@ var DepthFirstTraverser = class {
|
|
|
4879
5756
|
return true;
|
|
4880
5757
|
}
|
|
4881
5758
|
const isFaceVisited = this._isFaceVisited;
|
|
4882
|
-
const isVertexVisited = this._isVertexVisited;
|
|
4883
5759
|
const observer = this._observer;
|
|
4884
5760
|
const cornerToVertex = this._cornerToVertex;
|
|
4885
5761
|
const oppositeCorners = this._oppositeCorners;
|
|
@@ -4903,14 +5779,12 @@ var DepthFirstTraverser = class {
|
|
|
4903
5779
|
if (nextVert === kInvalidVertexIndex2 || prevVert === kInvalidVertexIndex2) {
|
|
4904
5780
|
return false;
|
|
4905
5781
|
}
|
|
4906
|
-
if (
|
|
4907
|
-
isVertexVisited[nextVert] = 1;
|
|
5782
|
+
if (vertexToEncodedMap[nextVert] < 0) {
|
|
4908
5783
|
outPointIds[numOutPoints++] = obsFaces[nextCorner];
|
|
4909
5784
|
encodedToCornerMap[numValues] = nextCorner;
|
|
4910
5785
|
vertexToEncodedMap[nextVert] = numValues++;
|
|
4911
5786
|
}
|
|
4912
|
-
if (
|
|
4913
|
-
isVertexVisited[prevVert] = 1;
|
|
5787
|
+
if (vertexToEncodedMap[prevVert] < 0) {
|
|
4914
5788
|
outPointIds[numOutPoints++] = obsFaces[prevCorner];
|
|
4915
5789
|
encodedToCornerMap[numValues] = prevCorner;
|
|
4916
5790
|
vertexToEncodedMap[prevVert] = numValues++;
|
|
@@ -4931,27 +5805,26 @@ var DepthFirstTraverser = class {
|
|
|
4931
5805
|
encodingData.numValues = numValues;
|
|
4932
5806
|
return false;
|
|
4933
5807
|
}
|
|
4934
|
-
|
|
5808
|
+
const faceBase = faceId * 3;
|
|
5809
|
+
const nextCornerId = cornerId === faceBase + 2 ? faceBase : cornerId + 1;
|
|
5810
|
+
if (vertexToEncodedMap[vertId] < 0) {
|
|
4935
5811
|
const lc = vertexLeftmost[vertId];
|
|
4936
5812
|
let onBoundary = true;
|
|
4937
|
-
if (lc
|
|
5813
|
+
if (lc >= 0) {
|
|
4938
5814
|
const nextLc = lc % 3 === 2 ? lc - 2 : lc + 1;
|
|
4939
5815
|
onBoundary = oppositeCorners[nextLc] < 0;
|
|
4940
5816
|
}
|
|
4941
|
-
isVertexVisited[vertId] = 1;
|
|
4942
5817
|
outPointIds[numOutPoints++] = obsFaces[cornerId];
|
|
4943
5818
|
encodedToCornerMap[numValues] = cornerId;
|
|
4944
5819
|
vertexToEncodedMap[vertId] = numValues++;
|
|
4945
5820
|
if (!onBoundary) {
|
|
4946
|
-
|
|
4947
|
-
cornerId = oppositeCorners[nextCornerId2];
|
|
5821
|
+
cornerId = oppositeCorners[nextCornerId];
|
|
4948
5822
|
faceId = cornerId / 3 | 0;
|
|
4949
5823
|
continue;
|
|
4950
5824
|
}
|
|
4951
5825
|
}
|
|
4952
|
-
const nextCornerId = cornerId % 3 === 2 ? cornerId - 2 : cornerId + 1;
|
|
4953
5826
|
const rightCornerId = oppositeCorners[nextCornerId];
|
|
4954
|
-
const prevCornerId = cornerId
|
|
5827
|
+
const prevCornerId = cornerId === faceBase ? faceBase + 2 : cornerId - 1;
|
|
4955
5828
|
const leftCornerId = oppositeCorners[prevCornerId];
|
|
4956
5829
|
const rightFaceId = rightCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : rightCornerId / 3 | 0;
|
|
4957
5830
|
const leftFaceId = leftCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : leftCornerId / 3 | 0;
|
|
@@ -5181,6 +6054,9 @@ var MeshTraversalSequencer = class {
|
|
|
5181
6054
|
_outPointIds;
|
|
5182
6055
|
_numOutPoints;
|
|
5183
6056
|
_traversalCache;
|
|
6057
|
+
// The cache entry the last generateSequence resolved to (hit or store);
|
|
6058
|
+
// carries the shared indicesMap.
|
|
6059
|
+
_cacheEntry;
|
|
5184
6060
|
constructor(mesh, encodingData, traversalCache = null) {
|
|
5185
6061
|
this._mesh = mesh;
|
|
5186
6062
|
this._encodingData = encodingData;
|
|
@@ -5188,6 +6064,7 @@ var MeshTraversalSequencer = class {
|
|
|
5188
6064
|
this._outPointIds = new Int32Array(0);
|
|
5189
6065
|
this._numOutPoints = 0;
|
|
5190
6066
|
this._traversalCache = traversalCache;
|
|
6067
|
+
this._cacheEntry = null;
|
|
5191
6068
|
}
|
|
5192
6069
|
setTraverser(traverser) {
|
|
5193
6070
|
this._traverser = traverser;
|
|
@@ -5202,6 +6079,7 @@ var MeshTraversalSequencer = class {
|
|
|
5202
6079
|
if (cached !== void 0) {
|
|
5203
6080
|
this._outPointIds = cached.pointIds;
|
|
5204
6081
|
this._encodingData.adoptTraversalResult(cached.vertexMap, cached.cornerMap, cached.numValues);
|
|
6082
|
+
this._cacheEntry = cached;
|
|
5205
6083
|
return true;
|
|
5206
6084
|
}
|
|
5207
6085
|
}
|
|
@@ -5217,12 +6095,15 @@ var MeshTraversalSequencer = class {
|
|
|
5217
6095
|
byMethod = /* @__PURE__ */ new Map();
|
|
5218
6096
|
this._traversalCache.set(cacheKey, byMethod);
|
|
5219
6097
|
}
|
|
5220
|
-
|
|
6098
|
+
const entry = {
|
|
5221
6099
|
pointIds: this._outPointIds,
|
|
5222
6100
|
vertexMap: this._encodingData.vertexToEncodedAttributeValueIndexMap,
|
|
5223
6101
|
cornerMap: this._encodingData.encodedAttributeValueIndexToCornerMap,
|
|
5224
|
-
numValues: this._encodingData.numValues
|
|
5225
|
-
|
|
6102
|
+
numValues: this._encodingData.numValues,
|
|
6103
|
+
indicesMap: null
|
|
6104
|
+
};
|
|
6105
|
+
byMethod.set(methodId, entry);
|
|
6106
|
+
this._cacheEntry = entry;
|
|
5226
6107
|
}
|
|
5227
6108
|
return true;
|
|
5228
6109
|
}
|
|
@@ -5233,6 +6114,11 @@ var MeshTraversalSequencer = class {
|
|
|
5233
6114
|
this._outPointIds[this._numOutPoints++] = pointId;
|
|
5234
6115
|
}
|
|
5235
6116
|
updatePointToAttributeIndexMapping(attribute) {
|
|
6117
|
+
const entry = this._cacheEntry;
|
|
6118
|
+
if (entry !== null && entry.indicesMap !== null) {
|
|
6119
|
+
attribute.setExplicitMappingShared(entry.indicesMap);
|
|
6120
|
+
return true;
|
|
6121
|
+
}
|
|
5236
6122
|
const cornerTable = this._traverser.cornerTable();
|
|
5237
6123
|
const numFaces = this._mesh.numFaces();
|
|
5238
6124
|
const numPoints = this._mesh.numPoints();
|
|
@@ -5254,11 +6140,14 @@ var MeshTraversalSequencer = class {
|
|
|
5254
6140
|
}
|
|
5255
6141
|
indicesMap[pointId] = attEntryId;
|
|
5256
6142
|
}
|
|
6143
|
+
if (entry !== null) {
|
|
6144
|
+
entry.indicesMap = attribute.indicesMap;
|
|
6145
|
+
}
|
|
5257
6146
|
return true;
|
|
5258
6147
|
}
|
|
5259
6148
|
_generateSequenceInternal() {
|
|
5260
6149
|
this._numOutPoints = 0;
|
|
5261
|
-
this._outPointIds =
|
|
6150
|
+
this._outPointIds = scratchInt32(this._mesh.numPoints());
|
|
5262
6151
|
this._traverser.onTraversalStart();
|
|
5263
6152
|
const numFaces = this._traverser.cornerTable().numFaces();
|
|
5264
6153
|
for (let i = 0; i < numFaces && this._traverser._numVisitedFaces < numFaces; ++i) {
|
|
@@ -5449,14 +6338,14 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5449
6338
|
this._attributeData = [];
|
|
5450
6339
|
for (let i = 0; i < numAttributeData; ++i) {
|
|
5451
6340
|
const ad = new AttributeData();
|
|
5452
|
-
ad.attributeSeamCorners =
|
|
6341
|
+
ad.attributeSeamCorners = scratchInt32(numFaces * 3);
|
|
5453
6342
|
ad.numSeamCorners = 0;
|
|
5454
6343
|
this._attributeData.push(ad);
|
|
5455
6344
|
}
|
|
5456
6345
|
if (!this._cornerTable.reset(numFaces, this._numEncodedVertices + numEncodedSplitSymbols)) {
|
|
5457
6346
|
return false;
|
|
5458
6347
|
}
|
|
5459
|
-
this._isVertHole =
|
|
6348
|
+
this._isVertHole = scratchUint8Filled(this._numEncodedVertices + numEncodedSplitSymbols, 1);
|
|
5460
6349
|
if (this._decodeHoleAndTopologySplitEvents(this._decoder.buffer()) === -1) {
|
|
5461
6350
|
return false;
|
|
5462
6351
|
}
|
|
@@ -5481,20 +6370,37 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5481
6370
|
}
|
|
5482
6371
|
this._traversalDecoder.done();
|
|
5483
6372
|
let previousConnectivityData = null;
|
|
6373
|
+
let previousSeamCorners = null;
|
|
6374
|
+
let previousSeamCount = 0;
|
|
5484
6375
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
5485
6376
|
const connectivityData = this._attributeData[i].connectivityData;
|
|
5486
|
-
connectivityData.initEmpty(this._cornerTable);
|
|
5487
6377
|
const seamCorners = this._attributeData[i].attributeSeamCorners;
|
|
5488
6378
|
const seamCount = this._attributeData[i].numSeamCorners;
|
|
5489
|
-
|
|
5490
|
-
|
|
6379
|
+
let sameAsPrevious = previousConnectivityData !== null && seamCount === previousSeamCount;
|
|
6380
|
+
if (sameAsPrevious) {
|
|
6381
|
+
const previous = previousSeamCorners;
|
|
6382
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6383
|
+
if (seamCorners[s] !== previous[s]) {
|
|
6384
|
+
sameAsPrevious = false;
|
|
6385
|
+
break;
|
|
6386
|
+
}
|
|
6387
|
+
}
|
|
5491
6388
|
}
|
|
5492
|
-
if (
|
|
5493
|
-
connectivityData.
|
|
5494
|
-
} else
|
|
5495
|
-
|
|
6389
|
+
if (sameAsPrevious) {
|
|
6390
|
+
connectivityData.adoptFrom(previousConnectivityData);
|
|
6391
|
+
} else {
|
|
6392
|
+
connectivityData.initEmpty(this._cornerTable);
|
|
6393
|
+
connectivityData.reserveSeamEdges(seamCount);
|
|
6394
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6395
|
+
connectivityData.addSeamEdge(seamCorners[s]);
|
|
6396
|
+
}
|
|
6397
|
+
if (!connectivityData.recomputeVertices(null, null)) {
|
|
6398
|
+
return false;
|
|
6399
|
+
}
|
|
5496
6400
|
}
|
|
5497
6401
|
previousConnectivityData = connectivityData;
|
|
6402
|
+
previousSeamCorners = seamCorners;
|
|
6403
|
+
previousSeamCount = seamCount;
|
|
5498
6404
|
}
|
|
5499
6405
|
this._posEncodingData.init(this._cornerTable.numVertices());
|
|
5500
6406
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
@@ -5533,39 +6439,27 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5533
6439
|
const activeCornerStack = scratchInt32(numSymbols + this._topologySplitData.length + 16);
|
|
5534
6440
|
let activeCornerStackSize = 0;
|
|
5535
6441
|
const topologySplitActiveCorners = /* @__PURE__ */ new Map();
|
|
6442
|
+
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5536
6443
|
const invalidVertices = [];
|
|
5537
6444
|
const removeInvalidVertices = this._attributeData.length === 0;
|
|
5538
6445
|
let maxNumVertices = this._isVertHole.length;
|
|
5539
6446
|
let numFacesDecoded = 0;
|
|
5540
6447
|
const cornerToVertex = this._cornerTable._cornerToVertex;
|
|
5541
6448
|
const oppositeCorners = this._cornerTable._oppositeCorners;
|
|
5542
|
-
const numCorners = this._cornerTable.numCorners();
|
|
5543
|
-
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
5544
|
-
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
5545
|
-
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
5546
|
-
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
5547
|
-
const leftMostCorner = (v) => v < 0 || v >= this._cornerTable._vertexCorners.length ? -1 : this._cornerTable._vertexCorners[v];
|
|
5548
|
-
const swingLeft = (c) => {
|
|
5549
|
-
const n = next(c);
|
|
5550
|
-
const o = opposite(n);
|
|
5551
|
-
return o < 0 ? -1 : next(o);
|
|
5552
|
-
};
|
|
5553
|
-
const swingRight = (c) => {
|
|
5554
|
-
const p = prev(c);
|
|
5555
|
-
const o = opposite(p);
|
|
5556
|
-
return o < 0 ? -1 : prev(o);
|
|
5557
|
-
};
|
|
5558
6449
|
const vc = this._cornerTable;
|
|
6450
|
+
let vertexCorners = vc._vertexCorners;
|
|
6451
|
+
const isVertHole = this._isVertHole;
|
|
6452
|
+
const traversalDecoder = this._traversalDecoder;
|
|
5559
6453
|
for (let symbolId = 0; symbolId < numSymbols; ++symbolId) {
|
|
5560
6454
|
const faceIndex = numFacesDecoded++;
|
|
5561
6455
|
let checkTopologySplit = false;
|
|
5562
|
-
const symbol =
|
|
6456
|
+
const symbol = traversalDecoder.decodeSymbol();
|
|
5563
6457
|
if (symbol === TOPOLOGY_C) {
|
|
5564
6458
|
if (activeCornerStackSize === 0) return -1;
|
|
5565
6459
|
const cornerA = activeCornerStack[activeCornerStackSize - 1];
|
|
5566
6460
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5567
6461
|
const vertexX = cornerToVertex[nA];
|
|
5568
|
-
const lmcX =
|
|
6462
|
+
const lmcX = vertexCorners[vertexX];
|
|
5569
6463
|
const cornerB = lmcX % 3 === 2 ? lmcX - 2 : lmcX + 1;
|
|
5570
6464
|
if (cornerA === cornerB) return -1;
|
|
5571
6465
|
if (oppositeCorners[cornerA] !== kInvalidCornerIndex6 || oppositeCorners[cornerB] !== kInvalidCornerIndex6) {
|
|
@@ -5584,8 +6478,8 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5584
6478
|
cornerToVertex[corner] = vertexX;
|
|
5585
6479
|
cornerToVertex[corner + 1] = vertBNext;
|
|
5586
6480
|
cornerToVertex[corner + 2] = vertAPrev;
|
|
5587
|
-
|
|
5588
|
-
|
|
6481
|
+
vertexCorners[vertAPrev] = corner + 2;
|
|
6482
|
+
isVertHole[vertexX] = 0;
|
|
5589
6483
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5590
6484
|
} else if (symbol === TOPOLOGY_R || symbol === TOPOLOGY_L) {
|
|
5591
6485
|
if (activeCornerStackSize === 0) return -1;
|
|
@@ -5606,14 +6500,20 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5606
6500
|
}
|
|
5607
6501
|
oppositeCorners[oppCorner] = cornerA;
|
|
5608
6502
|
oppositeCorners[cornerA] = oppCorner;
|
|
5609
|
-
|
|
5610
|
-
if (
|
|
6503
|
+
let newVertIndex;
|
|
6504
|
+
if (vc._numVertices < vertexCorners.length) {
|
|
6505
|
+
newVertIndex = vc._numVertices++;
|
|
6506
|
+
} else {
|
|
6507
|
+
newVertIndex = vc.addNewVertex();
|
|
6508
|
+
vertexCorners = vc._vertexCorners;
|
|
6509
|
+
}
|
|
6510
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5611
6511
|
cornerToVertex[oppCorner] = newVertIndex;
|
|
5612
|
-
|
|
6512
|
+
vertexCorners[newVertIndex] = oppCorner;
|
|
5613
6513
|
const pA = cornerA % 3 === 0 ? cornerA + 2 : cornerA - 1;
|
|
5614
6514
|
const vertexR = cornerToVertex[pA];
|
|
5615
6515
|
cornerToVertex[cornerR] = vertexR;
|
|
5616
|
-
|
|
6516
|
+
vertexCorners[vertexR] = cornerR;
|
|
5617
6517
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5618
6518
|
cornerToVertex[cornerL] = cornerToVertex[nA];
|
|
5619
6519
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
@@ -5645,11 +6545,11 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5645
6545
|
const pB = cornerB % 3 === 0 ? cornerB + 2 : cornerB - 1;
|
|
5646
6546
|
const vertBPrev = cornerToVertex[pB];
|
|
5647
6547
|
cornerToVertex[corner + 2] = vertBPrev;
|
|
5648
|
-
|
|
6548
|
+
vertexCorners[vertBPrev] = corner + 2;
|
|
5649
6549
|
let cornerN = cornerB % 3 === 2 ? cornerB - 2 : cornerB + 1;
|
|
5650
6550
|
const vertexN = cornerToVertex[cornerN];
|
|
5651
|
-
|
|
5652
|
-
|
|
6551
|
+
traversalDecoder.mergeVertices(vertexP, vertexN);
|
|
6552
|
+
vertexCorners[vertexP] = vertexCorners[vertexN];
|
|
5653
6553
|
const firstCorner = cornerN;
|
|
5654
6554
|
while (cornerN !== kInvalidCornerIndex6) {
|
|
5655
6555
|
cornerToVertex[cornerN] = vertexP;
|
|
@@ -5660,32 +6560,38 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5660
6560
|
return -1;
|
|
5661
6561
|
}
|
|
5662
6562
|
}
|
|
5663
|
-
|
|
6563
|
+
vertexCorners[vertexN] = -1;
|
|
5664
6564
|
if (removeInvalidVertices) {
|
|
5665
6565
|
invalidVertices.push(vertexN);
|
|
5666
6566
|
}
|
|
5667
6567
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5668
6568
|
} else if (symbol === TOPOLOGY_E) {
|
|
5669
6569
|
const corner = 3 * faceIndex;
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
6570
|
+
let firstVertIndex;
|
|
6571
|
+
if (vc._numVertices + 3 <= vertexCorners.length) {
|
|
6572
|
+
firstVertIndex = vc._numVertices;
|
|
6573
|
+
vc._numVertices += 3;
|
|
6574
|
+
} else {
|
|
6575
|
+
firstVertIndex = vc.addNewVertex();
|
|
6576
|
+
vc.addNewVertex();
|
|
6577
|
+
vc.addNewVertex();
|
|
6578
|
+
vertexCorners = vc._vertexCorners;
|
|
6579
|
+
}
|
|
6580
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5674
6581
|
cornerToVertex[corner] = firstVertIndex;
|
|
5675
6582
|
cornerToVertex[corner + 1] = firstVertIndex + 1;
|
|
5676
6583
|
cornerToVertex[corner + 2] = firstVertIndex + 2;
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
6584
|
+
vertexCorners[firstVertIndex] = corner;
|
|
6585
|
+
vertexCorners[firstVertIndex + 1] = corner + 1;
|
|
6586
|
+
vertexCorners[firstVertIndex + 2] = corner + 2;
|
|
5680
6587
|
activeCornerStack[activeCornerStackSize++] = corner;
|
|
5681
6588
|
checkTopologySplit = true;
|
|
5682
6589
|
} else {
|
|
5683
6590
|
return -1;
|
|
5684
6591
|
}
|
|
5685
|
-
|
|
5686
|
-
if (checkTopologySplit) {
|
|
6592
|
+
traversalDecoder.newActiveCornerReached(activeCornerStack[activeCornerStackSize - 1]);
|
|
6593
|
+
if (checkTopologySplit && this._topologySplitData.length > 0) {
|
|
5687
6594
|
const encoderSymbolId = numSymbols - symbolId - 1;
|
|
5688
|
-
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5689
6595
|
while (this._isTopologySplit(encoderSymbolId, splitResult)) {
|
|
5690
6596
|
if (splitResult.encoderSplitSymbolId < 0) return -1;
|
|
5691
6597
|
const actTopCorner = activeCornerStack[activeCornerStackSize - 1];
|
|
@@ -5700,15 +6606,39 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5700
6606
|
}
|
|
5701
6607
|
}
|
|
5702
6608
|
}
|
|
5703
|
-
if (
|
|
6609
|
+
if (vc._numVertices > maxNumVertices) {
|
|
6610
|
+
return -1;
|
|
6611
|
+
}
|
|
6612
|
+
numFacesDecoded = this._decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded);
|
|
6613
|
+
if (numFacesDecoded === -1) {
|
|
6614
|
+
return -1;
|
|
6615
|
+
}
|
|
6616
|
+
if (numFacesDecoded !== this._cornerTable.numFaces()) {
|
|
5704
6617
|
return -1;
|
|
5705
6618
|
}
|
|
6619
|
+
return this._removeInvalidVertices(invalidVertices);
|
|
6620
|
+
}
|
|
6621
|
+
// Connects the remaining active-stack corners to newly decoded start faces.
|
|
6622
|
+
// Returns the updated decoded-face count, or -1 on malformed input.
|
|
6623
|
+
_decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
|
|
6624
|
+
const ct = this._cornerTable;
|
|
6625
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6626
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6627
|
+
const vertexCorners = ct._vertexCorners;
|
|
6628
|
+
const isVertHole = this._isVertHole;
|
|
6629
|
+
const traversalDecoder = this._traversalDecoder;
|
|
6630
|
+
const numCorners = ct.numCorners();
|
|
6631
|
+
const numFaces = ct.numFaces();
|
|
6632
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6633
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6634
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6635
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
5706
6636
|
while (activeCornerStackSize > 0) {
|
|
5707
6637
|
const corner = activeCornerStack[activeCornerStackSize - 1];
|
|
5708
6638
|
activeCornerStackSize--;
|
|
5709
|
-
const interiorFace =
|
|
6639
|
+
const interiorFace = traversalDecoder.decodeStartFaceConfiguration();
|
|
5710
6640
|
if (interiorFace) {
|
|
5711
|
-
if (numFacesDecoded >=
|
|
6641
|
+
if (numFacesDecoded >= numFaces) {
|
|
5712
6642
|
return -1;
|
|
5713
6643
|
}
|
|
5714
6644
|
const cornerA = corner;
|
|
@@ -5734,9 +6664,9 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5734
6664
|
cornerToVertex[newCorner] = vertX;
|
|
5735
6665
|
cornerToVertex[newCorner + 1] = vertP;
|
|
5736
6666
|
cornerToVertex[newCorner + 2] = vertN;
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
6667
|
+
isVertHole[vertX] = 0;
|
|
6668
|
+
isVertHole[vertP] = 0;
|
|
6669
|
+
isVertHole[vertN] = 0;
|
|
5740
6670
|
this._initFaceConfigurations.push(true);
|
|
5741
6671
|
this._initCorners.push(newCorner);
|
|
5742
6672
|
} else {
|
|
@@ -5744,10 +6674,34 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5744
6674
|
this._initCorners.push(corner);
|
|
5745
6675
|
}
|
|
5746
6676
|
}
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
6677
|
+
return numFacesDecoded;
|
|
6678
|
+
}
|
|
6679
|
+
// Removes invalid (isolated) vertices by swapping them with the last valid
|
|
6680
|
+
// vertex in the table, matching C++ mesh_edgebreaker_decoder_impl.cc (the
|
|
6681
|
+
// forward iteration order matters). Returns the final vertex count, or -1.
|
|
6682
|
+
_removeInvalidVertices(invalidVertices) {
|
|
6683
|
+
const ct = this._cornerTable;
|
|
6684
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6685
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6686
|
+
const vertexCorners = ct._vertexCorners;
|
|
6687
|
+
const isVertHole = this._isVertHole;
|
|
6688
|
+
const numCorners = ct.numCorners();
|
|
6689
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6690
|
+
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
6691
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6692
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6693
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
6694
|
+
const swingLeft = (c) => {
|
|
6695
|
+
const n = next(c);
|
|
6696
|
+
const o = opposite(n);
|
|
6697
|
+
return o < 0 ? -1 : next(o);
|
|
6698
|
+
};
|
|
6699
|
+
const swingRight = (c) => {
|
|
6700
|
+
const p = prev(c);
|
|
6701
|
+
const o = opposite(p);
|
|
6702
|
+
return o < 0 ? -1 : prev(o);
|
|
6703
|
+
};
|
|
6704
|
+
let numVertices = ct.numVertices();
|
|
5751
6705
|
for (let ivIdx = 0; ivIdx < invalidVertices.length; ++ivIdx) {
|
|
5752
6706
|
const invalidVert = invalidVertices[ivIdx];
|
|
5753
6707
|
let srcVert = numVertices - 1;
|
|
@@ -5777,10 +6731,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5777
6731
|
cid = swingRight(cid);
|
|
5778
6732
|
}
|
|
5779
6733
|
}
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
6734
|
+
vertexCorners[invalidVert] = leftMostCorner(srcVert);
|
|
6735
|
+
vertexCorners[srcVert] = -1;
|
|
6736
|
+
isVertHole[invalidVert] = isVertHole[srcVert];
|
|
6737
|
+
isVertHole[srcVert] = 0;
|
|
5784
6738
|
numVertices--;
|
|
5785
6739
|
}
|
|
5786
6740
|
return numVertices;
|
|
@@ -5823,14 +6777,55 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5823
6777
|
// per-corner decodeNextBit work. Within each face the three corners are
|
|
5824
6778
|
// visited in encoder edge order [base, next, prev] = [c, c+1, c+2] (the
|
|
5825
6779
|
// caller always starts a face at its base corner, so next/prev need no wrap).
|
|
6780
|
+
//
|
|
6781
|
+
// The face comparison the C++ makes -- floor(oppCorner/3) >= floor(cc/3) for
|
|
6782
|
+
// the face's base corner -- is just `oppCorner >= faceBaseCorner`, since the
|
|
6783
|
+
// base corner is a multiple of 3. That removes the per-corner division; the
|
|
6784
|
+
// invalid-corner case (-1) is still handled by the branch above it.
|
|
5826
6785
|
_decodeAttributeConnectivities() {
|
|
5827
6786
|
const oppositeCorners = this._cornerTable.oppositeCornerArray();
|
|
5828
6787
|
const attributeData = this._attributeData;
|
|
5829
6788
|
const numAttrData = attributeData.length;
|
|
5830
6789
|
const connectivityDecoders = this._traversalDecoder._attributeConnectivityDecoders;
|
|
5831
6790
|
const numCorners = this._cornerTable.numCorners();
|
|
6791
|
+
if (numAttrData === 1) {
|
|
6792
|
+
const ad = attributeData[0];
|
|
6793
|
+
const seamCorners = ad.attributeSeamCorners;
|
|
6794
|
+
let numSeamCorners = ad.numSeamCorners;
|
|
6795
|
+
const decoder = connectivityDecoders[0];
|
|
6796
|
+
const ans = decoder.ansDecoder_;
|
|
6797
|
+
const p = decoder.p_;
|
|
6798
|
+
const buf = ans.buf;
|
|
6799
|
+
const bufStart = ans.bufStart;
|
|
6800
|
+
let state = ans.state;
|
|
6801
|
+
let bufOffset = ans.bufOffset;
|
|
6802
|
+
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
6803
|
+
for (let k = 0; k < 3; ++k) {
|
|
6804
|
+
const cc = corner + k;
|
|
6805
|
+
const oppCorner = oppositeCorners[cc];
|
|
6806
|
+
if (oppCorner === kInvalidCornerIndex6) {
|
|
6807
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6808
|
+
} else if (oppCorner >= corner) {
|
|
6809
|
+
if (state < ANS_L_BASE && bufOffset > bufStart) {
|
|
6810
|
+
state = state << 8 | buf[--bufOffset];
|
|
6811
|
+
}
|
|
6812
|
+
const rem = state & 255;
|
|
6813
|
+
const xn = (state >>> 8) * p;
|
|
6814
|
+
if (rem < p) {
|
|
6815
|
+
state = xn + rem;
|
|
6816
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6817
|
+
} else {
|
|
6818
|
+
state = state - xn - p;
|
|
6819
|
+
}
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
6823
|
+
ans.state = state;
|
|
6824
|
+
ans.bufOffset = bufOffset;
|
|
6825
|
+
ad.numSeamCorners = numSeamCorners;
|
|
6826
|
+
return;
|
|
6827
|
+
}
|
|
5832
6828
|
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
5833
|
-
const srcFaceId = corner / 3 | 0;
|
|
5834
6829
|
for (let k = 0; k < 3; ++k) {
|
|
5835
6830
|
const cc = corner + k;
|
|
5836
6831
|
const oppCorner = oppositeCorners[cc];
|
|
@@ -5839,7 +6834,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5839
6834
|
const ad = attributeData[i];
|
|
5840
6835
|
ad.attributeSeamCorners[ad.numSeamCorners++] = cc;
|
|
5841
6836
|
}
|
|
5842
|
-
} else if (
|
|
6837
|
+
} else if (oppCorner >= corner) {
|
|
5843
6838
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5844
6839
|
if (connectivityDecoders[i].decodeNextBit()) {
|
|
5845
6840
|
const ad = attributeData[i];
|
|
@@ -5870,10 +6865,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5870
6865
|
const attributeData = this._attributeData;
|
|
5871
6866
|
const numAttrData = attributeData.length;
|
|
5872
6867
|
let numPoints = 0;
|
|
5873
|
-
const cornerToPointMap =
|
|
6868
|
+
const cornerToPointMap = scratchInt32(ct.numCorners());
|
|
5874
6869
|
const numVertices = ct.numVertices();
|
|
5875
6870
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
5876
|
-
const
|
|
6871
|
+
const swingRight = ct.swingRightArray();
|
|
5877
6872
|
const _baseCornerToVertex = ct.cornerToVertexArray();
|
|
5878
6873
|
const isVertHole = this._isVertHole;
|
|
5879
6874
|
const attCornerToVertex = new Array(numAttrData);
|
|
@@ -5887,7 +6882,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5887
6882
|
if (numAttrData === 1) {
|
|
5888
6883
|
anyAttVertexOnSeam = attVertexOnSeam[0];
|
|
5889
6884
|
} else {
|
|
5890
|
-
anyAttVertexOnSeam =
|
|
6885
|
+
anyAttVertexOnSeam = scratchUint8Zeroed(numVertices);
|
|
5891
6886
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5892
6887
|
const attSeam = attVertexOnSeam[i];
|
|
5893
6888
|
for (let v = 0; v < numVertices; ++v) {
|
|
@@ -5905,37 +6900,24 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5905
6900
|
const initialC = c;
|
|
5906
6901
|
const pointId = numPoints++;
|
|
5907
6902
|
cornerToPointMap[initialC] = pointId;
|
|
5908
|
-
|
|
5909
|
-
let pv = rem === 0 ? initialC + 2 : initialC - 1;
|
|
5910
|
-
let opp = baseOpp[pv];
|
|
5911
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6903
|
+
c = swingRight[initialC];
|
|
5912
6904
|
while (c !== kInvalidCornerIndex6 && c !== initialC) {
|
|
5913
6905
|
cornerToPointMap[c] = pointId;
|
|
5914
|
-
|
|
5915
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5916
|
-
opp = baseOpp[pv];
|
|
5917
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6906
|
+
c = swingRight[c];
|
|
5918
6907
|
}
|
|
5919
6908
|
} else {
|
|
5920
6909
|
let deduplicationFirstCorner = c;
|
|
5921
|
-
let rem, pv, opp;
|
|
5922
6910
|
if (!isVertHole[v]) {
|
|
5923
6911
|
if (numAttrData === 1) {
|
|
5924
6912
|
const vertId = singleAttC2V[c];
|
|
5925
|
-
|
|
5926
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5927
|
-
opp = baseOpp[pv];
|
|
5928
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6913
|
+
let actC = swingRight[c];
|
|
5929
6914
|
while (actC !== c) {
|
|
5930
6915
|
if (actC === kInvalidCornerIndex6) return false;
|
|
5931
6916
|
if (singleAttC2V[actC] !== vertId) {
|
|
5932
6917
|
deduplicationFirstCorner = actC;
|
|
5933
6918
|
break;
|
|
5934
6919
|
}
|
|
5935
|
-
|
|
5936
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5937
|
-
opp = baseOpp[pv];
|
|
5938
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6920
|
+
actC = swingRight[actC];
|
|
5939
6921
|
}
|
|
5940
6922
|
} else {
|
|
5941
6923
|
for (let i = 0; i < numAttrData; ++i) {
|
|
@@ -5944,10 +6926,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5944
6926
|
}
|
|
5945
6927
|
const attC2V = attCornerToVertex[i];
|
|
5946
6928
|
const vertId = attC2V[c];
|
|
5947
|
-
|
|
5948
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5949
|
-
opp = baseOpp[pv];
|
|
5950
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6929
|
+
let actC = swingRight[c];
|
|
5951
6930
|
let seamFound = false;
|
|
5952
6931
|
while (actC !== c) {
|
|
5953
6932
|
if (actC === kInvalidCornerIndex6) return false;
|
|
@@ -5956,10 +6935,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5956
6935
|
seamFound = true;
|
|
5957
6936
|
break;
|
|
5958
6937
|
}
|
|
5959
|
-
|
|
5960
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5961
|
-
opp = baseOpp[pv];
|
|
5962
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6938
|
+
actC = swingRight[actC];
|
|
5963
6939
|
}
|
|
5964
6940
|
if (seamFound) break;
|
|
5965
6941
|
}
|
|
@@ -5968,10 +6944,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5968
6944
|
c = deduplicationFirstCorner;
|
|
5969
6945
|
cornerToPointMap[c] = numPoints++;
|
|
5970
6946
|
let prevC = c;
|
|
5971
|
-
|
|
5972
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5973
|
-
opp = baseOpp[pv];
|
|
5974
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6947
|
+
c = swingRight[c];
|
|
5975
6948
|
while (c !== kInvalidCornerIndex6 && c !== deduplicationFirstCorner) {
|
|
5976
6949
|
let attributeSeam;
|
|
5977
6950
|
if (numAttrData === 1) {
|
|
@@ -5992,10 +6965,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5992
6965
|
cornerToPointMap[c] = cornerToPointMap[prevC];
|
|
5993
6966
|
}
|
|
5994
6967
|
prevC = c;
|
|
5995
|
-
|
|
5996
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5997
|
-
opp = baseOpp[pv];
|
|
5998
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6968
|
+
c = swingRight[c];
|
|
5999
6969
|
}
|
|
6000
6970
|
}
|
|
6001
6971
|
}
|
|
@@ -6021,8 +6991,8 @@ var MeshAttributeIndicesEncodingData = class {
|
|
|
6021
6991
|
this._numValues = 0;
|
|
6022
6992
|
}
|
|
6023
6993
|
init(numVertices) {
|
|
6024
|
-
this._vertexToEncodedAttributeValueIndexMap =
|
|
6025
|
-
this._encodedAttributeValueIndexToCornerMap =
|
|
6994
|
+
this._vertexToEncodedAttributeValueIndexMap = scratchInt32Filled(numVertices, -1);
|
|
6995
|
+
this._encodedAttributeValueIndexToCornerMap = scratchInt32(numVertices);
|
|
6026
6996
|
this._numValues = 0;
|
|
6027
6997
|
}
|
|
6028
6998
|
// Adopts a traversal result from an identical corner table, avoiding a
|
|
@@ -6072,6 +7042,8 @@ var CornerTable = class {
|
|
|
6072
7042
|
// corner -> opposite corner
|
|
6073
7043
|
_vertexCorners;
|
|
6074
7044
|
// vertex -> left-most corner
|
|
7045
|
+
_swingRight;
|
|
7046
|
+
// corner -> next corner around its vertex, CW
|
|
6075
7047
|
constructor() {
|
|
6076
7048
|
this._numFaces = 0;
|
|
6077
7049
|
this._numCorners = 0;
|
|
@@ -6079,16 +7051,42 @@ var CornerTable = class {
|
|
|
6079
7051
|
this._cornerToVertex = null;
|
|
6080
7052
|
this._oppositeCorners = null;
|
|
6081
7053
|
this._vertexCorners = null;
|
|
7054
|
+
this._swingRight = null;
|
|
6082
7055
|
}
|
|
6083
7056
|
reset(numFaces, numVertices) {
|
|
6084
7057
|
this._numFaces = numFaces;
|
|
6085
7058
|
this._numCorners = numFaces * 3;
|
|
6086
7059
|
this._numVertices = 0;
|
|
6087
|
-
this._cornerToVertex =
|
|
6088
|
-
this._oppositeCorners =
|
|
6089
|
-
this._vertexCorners =
|
|
7060
|
+
this._cornerToVertex = scratchInt32Filled(this._numCorners, -1);
|
|
7061
|
+
this._oppositeCorners = scratchInt32Filled(this._numCorners, -1);
|
|
7062
|
+
this._vertexCorners = scratchInt32Filled(numVertices, -1);
|
|
7063
|
+
this._swingRight = null;
|
|
6090
7064
|
return true;
|
|
6091
7065
|
}
|
|
7066
|
+
// swingRight(c) = previous(opposite(previous(c))) for every corner. Walking
|
|
7067
|
+
// the corner ring of a vertex is the inner loop of both the attribute-vertex
|
|
7068
|
+
// recompute and the point assignment, and each of those passes otherwise
|
|
7069
|
+
// pays two modulus-by-3 chains per step on top of the opposite lookup. Built
|
|
7070
|
+
// lazily -- callers only reach it once connectivity is final -- from
|
|
7071
|
+
// decode-scoped scratch, and dropped by reset().
|
|
7072
|
+
swingRightArray() {
|
|
7073
|
+
let table = this._swingRight;
|
|
7074
|
+
if (table === null) {
|
|
7075
|
+
const numCorners = this._numCorners;
|
|
7076
|
+
const opposite = this._oppositeCorners;
|
|
7077
|
+
table = scratchInt32(numCorners);
|
|
7078
|
+
for (let c = 0; c < numCorners; c += 3) {
|
|
7079
|
+
let o = opposite[c + 2];
|
|
7080
|
+
table[c] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
7081
|
+
o = opposite[c];
|
|
7082
|
+
table[c + 1] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
7083
|
+
o = opposite[c + 1];
|
|
7084
|
+
table[c + 2] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
7085
|
+
}
|
|
7086
|
+
this._swingRight = table;
|
|
7087
|
+
}
|
|
7088
|
+
return table;
|
|
7089
|
+
}
|
|
6092
7090
|
numFaces() {
|
|
6093
7091
|
return this._numFaces;
|
|
6094
7092
|
}
|
|
@@ -6132,8 +7130,7 @@ var CornerTable = class {
|
|
|
6132
7130
|
this._numVertices++;
|
|
6133
7131
|
if (newVertex >= this._vertexCorners.length) {
|
|
6134
7132
|
const newCapacity = Math.max(newVertex + 1, this._vertexCorners.length * 2, 64);
|
|
6135
|
-
const newArr =
|
|
6136
|
-
newArr.fill(-1);
|
|
7133
|
+
const newArr = scratchInt32Filled(newCapacity, -1);
|
|
6137
7134
|
newArr.set(this._vertexCorners);
|
|
6138
7135
|
this._vertexCorners = newArr;
|
|
6139
7136
|
}
|
|
@@ -6164,6 +7161,10 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6164
7161
|
_attributeConnectivityDecoders;
|
|
6165
7162
|
_numAttributeData;
|
|
6166
7163
|
_decoderImpl;
|
|
7164
|
+
// _symbolBuffer's bit cursor, captured once bit decoding starts: decodeSymbol
|
|
7165
|
+
// runs per decoded face and would otherwise reach it through two property
|
|
7166
|
+
// loads and a method call per read.
|
|
7167
|
+
_symbolBits;
|
|
6167
7168
|
constructor() {
|
|
6168
7169
|
this._buffer = new DecoderBuffer();
|
|
6169
7170
|
this._symbolBuffer = new DecoderBuffer();
|
|
@@ -6171,6 +7172,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6171
7172
|
this._attributeConnectivityDecoders = null;
|
|
6172
7173
|
this._numAttributeData = 0;
|
|
6173
7174
|
this._decoderImpl = null;
|
|
7175
|
+
this._symbolBits = null;
|
|
6174
7176
|
}
|
|
6175
7177
|
init(decoder) {
|
|
6176
7178
|
this._decoderImpl = decoder;
|
|
@@ -6205,6 +7207,21 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6205
7207
|
return this._startFaceDecoder.decodeNextBit() ? true : false;
|
|
6206
7208
|
}
|
|
6207
7209
|
decodeSymbol() {
|
|
7210
|
+
const bd = this._symbolBits;
|
|
7211
|
+
if (bd !== null) {
|
|
7212
|
+
const buf = bd._bitBuffer;
|
|
7213
|
+
const off = bd._bitOffset;
|
|
7214
|
+
const byteOffset = off >> 3;
|
|
7215
|
+
if (byteOffset + 4 < bd._byteLength) {
|
|
7216
|
+
const bits = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> (off & 7) & 7;
|
|
7217
|
+
if ((bits & 1) === TOPOLOGY_C) {
|
|
7218
|
+
bd._bitOffset = off + 1;
|
|
7219
|
+
return TOPOLOGY_C;
|
|
7220
|
+
}
|
|
7221
|
+
bd._bitOffset = off + 3;
|
|
7222
|
+
return bits;
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
6208
7225
|
let symbol = this._symbolBuffer.decodeLeastSignificantBits32(1);
|
|
6209
7226
|
if (symbol === TOPOLOGY_C) {
|
|
6210
7227
|
return symbol;
|
|
@@ -6234,6 +7251,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6234
7251
|
if (traversalSize === void 0) {
|
|
6235
7252
|
return false;
|
|
6236
7253
|
}
|
|
7254
|
+
this._symbolBits = this._symbolBuffer._bitDecoder;
|
|
6237
7255
|
this._buffer.init(
|
|
6238
7256
|
this._symbolBuffer.dataHead,
|
|
6239
7257
|
this._symbolBuffer.remainingSize,
|
|
@@ -6386,7 +7404,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6386
7404
|
_maxValence;
|
|
6387
7405
|
_vertexValences;
|
|
6388
7406
|
_contextSymbols;
|
|
7407
|
+
// Int32Array, not number[]: read and written once per decoded symbol.
|
|
6389
7408
|
_contextCounters;
|
|
7409
|
+
// corner -> vertex of _cornerTable, cached at init(); the array is created
|
|
7410
|
+
// once by CornerTable.reset() before the traversal decoder is initialized and
|
|
7411
|
+
// never replaced, so the per-symbol hot path can read it without two property
|
|
7412
|
+
// loads.
|
|
7413
|
+
_cornerToVertex;
|
|
6390
7414
|
constructor() {
|
|
6391
7415
|
super();
|
|
6392
7416
|
this._cornerTable = null;
|
|
@@ -6397,11 +7421,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6397
7421
|
this._maxValence = 7;
|
|
6398
7422
|
this._vertexValences = new Int32Array(0);
|
|
6399
7423
|
this._contextSymbols = [];
|
|
6400
|
-
this._contextCounters =
|
|
7424
|
+
this._contextCounters = new Int32Array(0);
|
|
7425
|
+
this._cornerToVertex = new Int32Array(0);
|
|
6401
7426
|
}
|
|
6402
7427
|
init(decoder) {
|
|
6403
7428
|
super.init(decoder);
|
|
6404
7429
|
this._cornerTable = decoder.getCornerTable();
|
|
7430
|
+
this._cornerToVertex = this._cornerTable._cornerToVertex;
|
|
6405
7431
|
}
|
|
6406
7432
|
setNumEncodedVertices(numVertices) {
|
|
6407
7433
|
this._numVertices = numVertices;
|
|
@@ -6419,10 +7445,11 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6419
7445
|
if (this._numVertices < 0) {
|
|
6420
7446
|
return false;
|
|
6421
7447
|
}
|
|
6422
|
-
this._vertexValences =
|
|
7448
|
+
this._vertexValences = scratchInt32Filled(this._numVertices, 0);
|
|
6423
7449
|
const numUniqueValences = this._maxValence - this._minValence + 1;
|
|
6424
7450
|
this._contextSymbols = new Array(numUniqueValences);
|
|
6425
|
-
this._contextCounters = new
|
|
7451
|
+
this._contextCounters = new Int32Array(numUniqueValences);
|
|
7452
|
+
const pending = [];
|
|
6426
7453
|
for (let i = 0; i < numUniqueValences; ++i) {
|
|
6427
7454
|
const numSymbols = decodeVarint(outBuffer);
|
|
6428
7455
|
if (numSymbols === void 0) {
|
|
@@ -6432,16 +7459,73 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6432
7459
|
return false;
|
|
6433
7460
|
}
|
|
6434
7461
|
if (numSymbols > 0) {
|
|
6435
|
-
this._contextSymbols[i] =
|
|
6436
|
-
|
|
7462
|
+
this._contextSymbols[i] = scratchUint32(numSymbols);
|
|
7463
|
+
const scheme = outBuffer.decodeUint8();
|
|
7464
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
7465
|
+
if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this._contextSymbols[i])) {
|
|
7466
|
+
return false;
|
|
7467
|
+
}
|
|
7468
|
+
this._contextCounters[i] = numSymbols;
|
|
7469
|
+
continue;
|
|
7470
|
+
}
|
|
7471
|
+
if (scheme !== SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
6437
7472
|
return false;
|
|
6438
7473
|
}
|
|
7474
|
+
const maxBitLength = outBuffer.decodeUint8();
|
|
7475
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
7476
|
+
return false;
|
|
7477
|
+
}
|
|
7478
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
7479
|
+
if (!decoder.create(outBuffer, numSymbols)) {
|
|
7480
|
+
return false;
|
|
7481
|
+
}
|
|
7482
|
+
if (decoder.numSymbols === 0) {
|
|
7483
|
+
return false;
|
|
7484
|
+
}
|
|
7485
|
+
if (!decoder.startDecoding(outBuffer)) {
|
|
7486
|
+
return false;
|
|
7487
|
+
}
|
|
7488
|
+
pending.push({ decoder, out: this._contextSymbols[i], count: numSymbols });
|
|
6439
7489
|
this._contextCounters[i] = numSymbols;
|
|
6440
7490
|
} else {
|
|
6441
7491
|
this._contextSymbols[i] = new Uint32Array(0);
|
|
6442
7492
|
this._contextCounters[i] = 0;
|
|
6443
7493
|
}
|
|
6444
7494
|
}
|
|
7495
|
+
const lockstep = pending.filter((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
|
|
7496
|
+
let p = 0;
|
|
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;
|
|
7513
|
+
}
|
|
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);
|
|
7522
|
+
}
|
|
7523
|
+
for (const entry of pending) {
|
|
7524
|
+
if (!(entry.decoder.ans_.lutTable instanceof Uint8Array)) {
|
|
7525
|
+
entry.decoder.ans_.decodeSymbols(entry.out, entry.count);
|
|
7526
|
+
}
|
|
7527
|
+
entry.decoder.endDecoding();
|
|
7528
|
+
}
|
|
6445
7529
|
return true;
|
|
6446
7530
|
}
|
|
6447
7531
|
decodeSymbol() {
|
|
@@ -6461,7 +7545,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6461
7545
|
return this._lastSymbol;
|
|
6462
7546
|
}
|
|
6463
7547
|
newActiveCornerReached(corner) {
|
|
6464
|
-
const cornerToVertex = this.
|
|
7548
|
+
const cornerToVertex = this._cornerToVertex;
|
|
6465
7549
|
const valences = this._vertexValences;
|
|
6466
7550
|
const next = corner % 3 === 2 ? corner - 2 : corner + 1;
|
|
6467
7551
|
const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
|