minidraco 0.3.0 → 0.4.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 +7 -8
- package/dist/index.d.ts +10 -1
- package/dist/index.js +1482 -652
- package/dist/three.d.ts +10 -1
- package/dist/three.js +1480 -650
- package/dist/worker.js +1482 -652
- package/package.json +1 -1
package/dist/three.js
CHANGED
|
@@ -271,6 +271,90 @@ var Mesh = class extends PointCloud {
|
|
|
271
271
|
}
|
|
272
272
|
};
|
|
273
273
|
|
|
274
|
+
// src/decoder/core/ScratchArena.ts
|
|
275
|
+
var MAX_CLASS = 28;
|
|
276
|
+
var freeInt32 = [];
|
|
277
|
+
var freeUint32 = [];
|
|
278
|
+
var freeUint8 = [];
|
|
279
|
+
for (let i = 0; i <= MAX_CLASS; ++i) {
|
|
280
|
+
freeInt32.push([]);
|
|
281
|
+
freeUint32.push([]);
|
|
282
|
+
freeUint8.push([]);
|
|
283
|
+
}
|
|
284
|
+
var borrowedInt32 = [];
|
|
285
|
+
var borrowedUint32 = [];
|
|
286
|
+
var borrowedUint8 = [];
|
|
287
|
+
var sizeClass = (size) => size <= 1 ? 0 : 32 - Math.clz32(size - 1);
|
|
288
|
+
var takeInt32 = (size) => {
|
|
289
|
+
const k = sizeClass(size);
|
|
290
|
+
if (k > MAX_CLASS) return new Int32Array(size);
|
|
291
|
+
const bucket = freeInt32[k];
|
|
292
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Int32Array(size);
|
|
293
|
+
if (pooled.length < size) pooled = new Int32Array(1 << k);
|
|
294
|
+
borrowedInt32.push(pooled);
|
|
295
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
296
|
+
};
|
|
297
|
+
var takeUint32 = (size) => {
|
|
298
|
+
const k = sizeClass(size);
|
|
299
|
+
if (k > MAX_CLASS) return new Uint32Array(size);
|
|
300
|
+
const bucket = freeUint32[k];
|
|
301
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint32Array(size);
|
|
302
|
+
if (pooled.length < size) pooled = new Uint32Array(1 << k);
|
|
303
|
+
borrowedUint32.push(pooled);
|
|
304
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
305
|
+
};
|
|
306
|
+
var byteCapacity = (size) => size < 8 ? 8 : size + 7 & ~7;
|
|
307
|
+
var takeUint8 = (size) => {
|
|
308
|
+
const capacity = byteCapacity(size);
|
|
309
|
+
const k = sizeClass(capacity);
|
|
310
|
+
if (k > MAX_CLASS) return new Uint8Array(capacity);
|
|
311
|
+
const bucket = freeUint8[k];
|
|
312
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint8Array(capacity);
|
|
313
|
+
if (pooled.length < size) pooled = new Uint8Array(1 << k);
|
|
314
|
+
borrowedUint8.push(pooled);
|
|
315
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
316
|
+
};
|
|
317
|
+
var scratchInt32 = (size) => takeInt32(size);
|
|
318
|
+
var scratchInt32Filled = (size, value) => {
|
|
319
|
+
const view = takeInt32(size);
|
|
320
|
+
view.fill(value);
|
|
321
|
+
return view;
|
|
322
|
+
};
|
|
323
|
+
var scratchUint32 = (size) => takeUint32(size);
|
|
324
|
+
var scratchUint32Zeroed = (size) => {
|
|
325
|
+
const view = takeUint32(size);
|
|
326
|
+
view.fill(0);
|
|
327
|
+
return view;
|
|
328
|
+
};
|
|
329
|
+
var scratchUint8 = (size) => takeUint8(size);
|
|
330
|
+
var scratchUint8Zeroed = (size) => {
|
|
331
|
+
const view = takeUint8(size);
|
|
332
|
+
view.fill(0);
|
|
333
|
+
return view;
|
|
334
|
+
};
|
|
335
|
+
var scratchUint8Filled = (size, value) => {
|
|
336
|
+
const view = takeUint8(size);
|
|
337
|
+
view.fill(value);
|
|
338
|
+
return view;
|
|
339
|
+
};
|
|
340
|
+
var releaseScratch = () => {
|
|
341
|
+
for (let i = 0; i < borrowedInt32.length; ++i) {
|
|
342
|
+
const buffer = borrowedInt32[i];
|
|
343
|
+
freeInt32[sizeClass(buffer.length)].push(buffer);
|
|
344
|
+
}
|
|
345
|
+
for (let i = 0; i < borrowedUint32.length; ++i) {
|
|
346
|
+
const buffer = borrowedUint32[i];
|
|
347
|
+
freeUint32[sizeClass(buffer.length)].push(buffer);
|
|
348
|
+
}
|
|
349
|
+
for (let i = 0; i < borrowedUint8.length; ++i) {
|
|
350
|
+
const buffer = borrowedUint8[i];
|
|
351
|
+
freeUint8[sizeClass(buffer.length)].push(buffer);
|
|
352
|
+
}
|
|
353
|
+
borrowedInt32.length = 0;
|
|
354
|
+
borrowedUint32.length = 0;
|
|
355
|
+
borrowedUint8.length = 0;
|
|
356
|
+
};
|
|
357
|
+
|
|
274
358
|
// src/decoder/core/DataBuffer.ts
|
|
275
359
|
var DataBuffer = class {
|
|
276
360
|
_data;
|
|
@@ -295,6 +379,15 @@ var DataBuffer = class {
|
|
|
295
379
|
resize(newSize) {
|
|
296
380
|
this._resize(newSize);
|
|
297
381
|
}
|
|
382
|
+
// Replaces the contents with a decode-scoped scratch buffer of exactly
|
|
383
|
+
// `size` bytes; the previous contents are dropped and the new ones are
|
|
384
|
+
// arbitrary, so every byte must be written before it is read. Only for
|
|
385
|
+
// buffers that never outlive the decode (see ScratchArena) — the portable
|
|
386
|
+
// attributes the integer decoders build and discard per attribute are the
|
|
387
|
+
// one caller, and their per-primitive allocation showed up in profiles.
|
|
388
|
+
adoptScratch(size) {
|
|
389
|
+
this._data = scratchUint8(size);
|
|
390
|
+
}
|
|
298
391
|
write(bytePos, inArray, dataSize) {
|
|
299
392
|
if (inArray instanceof Uint8Array) {
|
|
300
393
|
this._data.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
|
|
@@ -384,6 +477,19 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
384
477
|
this._numUniqueEntries = numAttributeValues;
|
|
385
478
|
return true;
|
|
386
479
|
}
|
|
480
|
+
// Like reset(), but backs the attribute with decode-scoped scratch memory.
|
|
481
|
+
// Only valid for attributes that never escape the decode and whose every
|
|
482
|
+
// byte is written before it is read (see DataBuffer.adoptScratch).
|
|
483
|
+
resetScratch(numAttributeValues) {
|
|
484
|
+
if (this._attributeBuffer === null) {
|
|
485
|
+
this._attributeBuffer = new DataBuffer();
|
|
486
|
+
}
|
|
487
|
+
const entrySize = dataTypeLength(this.dataType) * this.numComponents;
|
|
488
|
+
this._attributeBuffer.adoptScratch(numAttributeValues * entrySize);
|
|
489
|
+
this.resetBuffer(this._attributeBuffer, entrySize, 0);
|
|
490
|
+
this._numUniqueEntries = numAttributeValues;
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
387
493
|
get size() {
|
|
388
494
|
return this._numUniqueEntries;
|
|
389
495
|
}
|
|
@@ -426,6 +532,20 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
426
532
|
this._identityMapping = false;
|
|
427
533
|
this._indicesMap = new Uint32Array(numPoints);
|
|
428
534
|
}
|
|
535
|
+
// Adopts an already-computed map, shared with other attributes of the same
|
|
536
|
+
// mesh. The map must be treated as read-only from here on (reads go through
|
|
537
|
+
// mappedIndex/extractTo; copyFrom slices).
|
|
538
|
+
setExplicitMappingShared(map) {
|
|
539
|
+
this._identityMapping = false;
|
|
540
|
+
this._indicesMap = map;
|
|
541
|
+
}
|
|
542
|
+
// Like setExplicitMappingUnfilled, but from decode-scoped scratch. Only for
|
|
543
|
+
// attributes that never escape the decode (see ScratchArena) -- the portable
|
|
544
|
+
// attributes the sequential decoders build and discard.
|
|
545
|
+
setExplicitMappingScratch(numPoints) {
|
|
546
|
+
this._identityMapping = false;
|
|
547
|
+
this._indicesMap = scratchUint32(numPoints);
|
|
548
|
+
}
|
|
429
549
|
setAttributeTransformData(transformData) {
|
|
430
550
|
this._attributeTransformData = transformData;
|
|
431
551
|
}
|
|
@@ -921,48 +1041,6 @@ var DecoderBuffer = class {
|
|
|
921
1041
|
}
|
|
922
1042
|
};
|
|
923
1043
|
|
|
924
|
-
// src/decoder/core/ScratchArena.ts
|
|
925
|
-
var freeInt32 = [];
|
|
926
|
-
var freeUint8 = [];
|
|
927
|
-
var borrowedInt32 = [];
|
|
928
|
-
var borrowedUint8 = [];
|
|
929
|
-
var acquire = (free, borrowed, size) => {
|
|
930
|
-
for (let i = free.length - 1; i >= 0; --i) {
|
|
931
|
-
const buffer = free[i];
|
|
932
|
-
if (buffer.length >= size) {
|
|
933
|
-
free[i] = free[free.length - 1];
|
|
934
|
-
free.pop();
|
|
935
|
-
borrowed.push(buffer);
|
|
936
|
-
return buffer;
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
return null;
|
|
940
|
-
};
|
|
941
|
-
var scratchInt32 = (size) => {
|
|
942
|
-
const pooled = acquire(freeInt32, borrowedInt32, size);
|
|
943
|
-
if (pooled !== null) return pooled.subarray(0, size);
|
|
944
|
-
const fresh = new Int32Array(size);
|
|
945
|
-
borrowedInt32.push(fresh);
|
|
946
|
-
return fresh;
|
|
947
|
-
};
|
|
948
|
-
var scratchUint8Zeroed = (size) => {
|
|
949
|
-
const pooled = acquire(freeUint8, borrowedUint8, size);
|
|
950
|
-
if (pooled !== null) {
|
|
951
|
-
const view = pooled.subarray(0, size);
|
|
952
|
-
view.fill(0);
|
|
953
|
-
return view;
|
|
954
|
-
}
|
|
955
|
-
const fresh = new Uint8Array(size);
|
|
956
|
-
borrowedUint8.push(fresh);
|
|
957
|
-
return fresh;
|
|
958
|
-
};
|
|
959
|
-
var releaseScratch = () => {
|
|
960
|
-
for (const buffer of borrowedInt32) freeInt32.push(buffer);
|
|
961
|
-
for (const buffer of borrowedUint8) freeUint8.push(buffer);
|
|
962
|
-
borrowedInt32.length = 0;
|
|
963
|
-
borrowedUint8.length = 0;
|
|
964
|
-
};
|
|
965
|
-
|
|
966
1044
|
// src/decoder/compression/config/CompressionShared.ts
|
|
967
1045
|
var kDracoPointCloudBitstreamVersionMajor = 2;
|
|
968
1046
|
var kDracoPointCloudBitstreamVersionMinor = 3;
|
|
@@ -1194,85 +1272,614 @@ var MetadataDecoder = class {
|
|
|
1194
1272
|
}
|
|
1195
1273
|
};
|
|
1196
1274
|
|
|
1197
|
-
// src/decoder/compression/
|
|
1198
|
-
var
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1275
|
+
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1276
|
+
var ANS_P8_PRECISION = 256;
|
|
1277
|
+
var ANS_L_BASE = 4096;
|
|
1278
|
+
var ANS_IO_BASE = 256;
|
|
1279
|
+
function memGetLe16(buf, offset) {
|
|
1280
|
+
return buf[offset] | buf[offset + 1] << 8;
|
|
1281
|
+
}
|
|
1282
|
+
function memGetLe24(buf, offset) {
|
|
1283
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1284
|
+
}
|
|
1285
|
+
function memGetLe32(buf, offset) {
|
|
1286
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1287
|
+
}
|
|
1288
|
+
var AnsDecoder = class {
|
|
1289
|
+
buf;
|
|
1290
|
+
bufOffset;
|
|
1291
|
+
// First valid byte of this decoder's slice within buf: init is passed
|
|
1292
|
+
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1293
|
+
bufStart;
|
|
1294
|
+
state;
|
|
1206
1295
|
constructor() {
|
|
1207
|
-
this.
|
|
1208
|
-
this.
|
|
1209
|
-
this.
|
|
1210
|
-
this.
|
|
1211
|
-
this._options = null;
|
|
1212
|
-
this._attributesDecoders = [];
|
|
1213
|
-
this._attributeToDecoderMap = [];
|
|
1296
|
+
this.buf = null;
|
|
1297
|
+
this.bufOffset = 0;
|
|
1298
|
+
this.bufStart = 0;
|
|
1299
|
+
this.state = 0;
|
|
1214
1300
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1301
|
+
};
|
|
1302
|
+
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1303
|
+
if (offset - base < 1) {
|
|
1304
|
+
return 1;
|
|
1217
1305
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
}
|
|
1228
|
-
const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
|
|
1229
|
-
if (magic !== "DRACO") {
|
|
1230
|
-
return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
|
|
1306
|
+
ans.buf = buf;
|
|
1307
|
+
ans.bufStart = base;
|
|
1308
|
+
const x = buf[offset - 1] >> 6;
|
|
1309
|
+
if (x === 0) {
|
|
1310
|
+
ans.bufOffset = offset - 1;
|
|
1311
|
+
ans.state = buf[offset - 1] & 63;
|
|
1312
|
+
} else if (x === 1) {
|
|
1313
|
+
if (offset - base < 2) {
|
|
1314
|
+
return 1;
|
|
1231
1315
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1316
|
+
ans.bufOffset = offset - 2;
|
|
1317
|
+
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1318
|
+
} else if (x === 2) {
|
|
1319
|
+
if (offset - base < 3) {
|
|
1320
|
+
return 1;
|
|
1235
1321
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1322
|
+
ans.bufOffset = offset - 3;
|
|
1323
|
+
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1324
|
+
} else {
|
|
1325
|
+
return 1;
|
|
1326
|
+
}
|
|
1327
|
+
ans.state += ANS_L_BASE;
|
|
1328
|
+
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1329
|
+
return 1;
|
|
1330
|
+
}
|
|
1331
|
+
return 0;
|
|
1332
|
+
}
|
|
1333
|
+
function ansReadEnd(ans) {
|
|
1334
|
+
return ans.state === ANS_L_BASE;
|
|
1335
|
+
}
|
|
1336
|
+
var tablePool = [];
|
|
1337
|
+
var acquirePooled = (Ctor, size) => {
|
|
1338
|
+
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1339
|
+
const buf = tablePool[i];
|
|
1340
|
+
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1341
|
+
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1342
|
+
tablePool.pop();
|
|
1343
|
+
return buf;
|
|
1240
1344
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1345
|
+
}
|
|
1346
|
+
return new Ctor(size);
|
|
1347
|
+
};
|
|
1348
|
+
var RAnsDecoder = class {
|
|
1349
|
+
ransPrecisionBits;
|
|
1350
|
+
ransPrecision;
|
|
1351
|
+
ransPrecisionMask;
|
|
1352
|
+
lRansBase;
|
|
1353
|
+
lutTable;
|
|
1354
|
+
probTable;
|
|
1355
|
+
cumProbTable;
|
|
1356
|
+
buf;
|
|
1357
|
+
bufOffset;
|
|
1358
|
+
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1359
|
+
// see AnsDecoder.bufStart).
|
|
1360
|
+
bufStart;
|
|
1361
|
+
state;
|
|
1362
|
+
constructor(ransPrecisionBits) {
|
|
1363
|
+
this.ransPrecisionBits = ransPrecisionBits;
|
|
1364
|
+
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1365
|
+
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1366
|
+
this.lRansBase = this.ransPrecision * 4;
|
|
1367
|
+
this.lutTable = null;
|
|
1368
|
+
this.probTable = null;
|
|
1369
|
+
this.cumProbTable = 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;
|
|
1245
1382
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
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;
|
|
1250
1409
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1410
|
+
this.state += this.lRansBase;
|
|
1411
|
+
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
1412
|
+
return 1;
|
|
1255
1413
|
}
|
|
1256
|
-
|
|
1257
|
-
return okStatus();
|
|
1414
|
+
return 0;
|
|
1258
1415
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
this._pointCloud = outPointCloud;
|
|
1264
|
-
const header = new DracoHeader();
|
|
1265
|
-
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1266
|
-
if (!headerStatus.ok()) {
|
|
1267
|
-
return headerStatus;
|
|
1416
|
+
readEnd() {
|
|
1417
|
+
if (this.lutTable !== null) {
|
|
1418
|
+
tablePool.push(this.lutTable);
|
|
1419
|
+
this.lutTable = null;
|
|
1268
1420
|
}
|
|
1269
|
-
if (
|
|
1270
|
-
|
|
1421
|
+
if (this.probTable !== null) {
|
|
1422
|
+
tablePool.push(this.probTable);
|
|
1423
|
+
this.probTable = null;
|
|
1271
1424
|
}
|
|
1272
|
-
this.
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1425
|
+
if (this.cumProbTable !== null) {
|
|
1426
|
+
tablePool.push(this.cumProbTable);
|
|
1427
|
+
this.cumProbTable = null;
|
|
1428
|
+
}
|
|
1429
|
+
return this.state === this.lRansBase;
|
|
1430
|
+
}
|
|
1431
|
+
ransRead() {
|
|
1432
|
+
const buf = this.buf;
|
|
1433
|
+
const lRansBase = this.lRansBase;
|
|
1434
|
+
let state = this.state;
|
|
1435
|
+
let bufOffset = this.bufOffset;
|
|
1436
|
+
const bufStart = this.bufStart;
|
|
1437
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1438
|
+
state = state << 8 | buf[--bufOffset];
|
|
1439
|
+
}
|
|
1440
|
+
const quo = state >>> this.ransPrecisionBits;
|
|
1441
|
+
const rem = state & this.ransPrecisionMask;
|
|
1442
|
+
const symbol = this.lutTable[rem];
|
|
1443
|
+
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
1444
|
+
this.bufOffset = bufOffset;
|
|
1445
|
+
return symbol;
|
|
1446
|
+
}
|
|
1447
|
+
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
1448
|
+
// written back once. Removes per-symbol property reads and call indirection.
|
|
1449
|
+
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
1450
|
+
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
1451
|
+
// once here so each loop body stays monomorphic on its concrete type. The
|
|
1452
|
+
// three bodies are intentionally identical copies.
|
|
1453
|
+
decodeSymbols(out, count) {
|
|
1454
|
+
const lutTable = this.lutTable;
|
|
1455
|
+
if (lutTable instanceof Uint8Array) {
|
|
1456
|
+
this._decodeSymbolsU8(out, count, lutTable);
|
|
1457
|
+
} else if (lutTable instanceof Uint16Array) {
|
|
1458
|
+
this._decodeSymbolsU16(out, count, lutTable);
|
|
1459
|
+
} else {
|
|
1460
|
+
this._decodeSymbolsU32(out, count, lutTable);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
_decodeSymbolsU8(out, count, lutTable) {
|
|
1464
|
+
const buf = this.buf;
|
|
1465
|
+
const lRansBase = this.lRansBase;
|
|
1466
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1467
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1468
|
+
const probTable = this.probTable;
|
|
1469
|
+
const cumProbTable = this.cumProbTable;
|
|
1470
|
+
let state = this.state;
|
|
1471
|
+
let bufOffset = this.bufOffset;
|
|
1472
|
+
const bufStart = this.bufStart;
|
|
1473
|
+
for (let i = 0; i < count; ++i) {
|
|
1474
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1475
|
+
state = state << 8 | buf[--bufOffset];
|
|
1476
|
+
}
|
|
1477
|
+
const rem = state & ransPrecisionMask;
|
|
1478
|
+
const symbol = lutTable[rem];
|
|
1479
|
+
out[i] = symbol;
|
|
1480
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1481
|
+
}
|
|
1482
|
+
this.state = state;
|
|
1483
|
+
this.bufOffset = bufOffset;
|
|
1484
|
+
}
|
|
1485
|
+
_decodeSymbolsU16(out, count, lutTable) {
|
|
1486
|
+
const buf = this.buf;
|
|
1487
|
+
const lRansBase = this.lRansBase;
|
|
1488
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1489
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1490
|
+
const probTable = this.probTable;
|
|
1491
|
+
const cumProbTable = this.cumProbTable;
|
|
1492
|
+
let state = this.state;
|
|
1493
|
+
let bufOffset = this.bufOffset;
|
|
1494
|
+
const bufStart = this.bufStart;
|
|
1495
|
+
for (let i = 0; i < count; ++i) {
|
|
1496
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1497
|
+
state = state << 8 | buf[--bufOffset];
|
|
1498
|
+
}
|
|
1499
|
+
const rem = state & ransPrecisionMask;
|
|
1500
|
+
const symbol = lutTable[rem];
|
|
1501
|
+
out[i] = symbol;
|
|
1502
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1503
|
+
}
|
|
1504
|
+
this.state = state;
|
|
1505
|
+
this.bufOffset = bufOffset;
|
|
1506
|
+
}
|
|
1507
|
+
_decodeSymbolsU32(out, count, lutTable) {
|
|
1508
|
+
const buf = this.buf;
|
|
1509
|
+
const lRansBase = this.lRansBase;
|
|
1510
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1511
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1512
|
+
const probTable = this.probTable;
|
|
1513
|
+
const cumProbTable = this.cumProbTable;
|
|
1514
|
+
let state = this.state;
|
|
1515
|
+
let bufOffset = this.bufOffset;
|
|
1516
|
+
const bufStart = this.bufStart;
|
|
1517
|
+
for (let i = 0; i < count; ++i) {
|
|
1518
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1519
|
+
state = state << 8 | buf[--bufOffset];
|
|
1520
|
+
}
|
|
1521
|
+
const rem = state & ransPrecisionMask;
|
|
1522
|
+
const symbol = lutTable[rem];
|
|
1523
|
+
out[i] = symbol;
|
|
1524
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1525
|
+
}
|
|
1526
|
+
this.state = state;
|
|
1527
|
+
this.bufOffset = bufOffset;
|
|
1528
|
+
}
|
|
1529
|
+
// Builds the ransPrecision-entry lookup table. Returns false on bad input data.
|
|
1530
|
+
ransBuildLookUpTable(tokenProbs, numSymbols) {
|
|
1531
|
+
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
1532
|
+
const lutTable = acquirePooled(LutArray, this.ransPrecision);
|
|
1533
|
+
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
1534
|
+
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
1535
|
+
this.lutTable = lutTable;
|
|
1536
|
+
this.probTable = probTable;
|
|
1537
|
+
this.cumProbTable = cumProbTable;
|
|
1538
|
+
let cumProb = 0;
|
|
1539
|
+
let actProb = 0;
|
|
1540
|
+
for (let i = 0; i < numSymbols; ++i) {
|
|
1541
|
+
const prob = tokenProbs[i];
|
|
1542
|
+
probTable[i] = prob;
|
|
1543
|
+
cumProbTable[i] = cumProb;
|
|
1544
|
+
cumProb += prob;
|
|
1545
|
+
if (cumProb > this.ransPrecision) {
|
|
1546
|
+
return false;
|
|
1547
|
+
}
|
|
1548
|
+
if (prob < 32) {
|
|
1549
|
+
for (let j = actProb; j < cumProb; ++j) {
|
|
1550
|
+
lutTable[j] = i;
|
|
1551
|
+
}
|
|
1552
|
+
} else {
|
|
1553
|
+
lutTable.fill(i, actProb, cumProb);
|
|
1554
|
+
}
|
|
1555
|
+
actProb = cumProb;
|
|
1556
|
+
}
|
|
1557
|
+
if (cumProb !== this.ransPrecision) {
|
|
1558
|
+
return false;
|
|
1559
|
+
}
|
|
1560
|
+
return true;
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
function ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB) {
|
|
1564
|
+
const lutA = a.lutTable;
|
|
1565
|
+
const lutB = b.lutTable;
|
|
1566
|
+
const bufA = a.buf;
|
|
1567
|
+
const bufB = b.buf;
|
|
1568
|
+
const probA = a.probTable;
|
|
1569
|
+
const probB = b.probTable;
|
|
1570
|
+
const cumA = a.cumProbTable;
|
|
1571
|
+
const cumB = b.cumProbTable;
|
|
1572
|
+
const lBaseA = a.lRansBase;
|
|
1573
|
+
const lBaseB = b.lRansBase;
|
|
1574
|
+
const bitsA = a.ransPrecisionBits;
|
|
1575
|
+
const bitsB = b.ransPrecisionBits;
|
|
1576
|
+
const maskA = a.ransPrecisionMask;
|
|
1577
|
+
const maskB = b.ransPrecisionMask;
|
|
1578
|
+
const startA = a.bufStart;
|
|
1579
|
+
const startB = b.bufStart;
|
|
1580
|
+
let stateA = a.state;
|
|
1581
|
+
let stateB = b.state;
|
|
1582
|
+
let offA = a.bufOffset;
|
|
1583
|
+
let offB = b.bufOffset;
|
|
1584
|
+
const shared = countA < countB ? countA : countB;
|
|
1585
|
+
for (let i = 0; i < shared; ++i) {
|
|
1586
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1587
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1588
|
+
}
|
|
1589
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1590
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1591
|
+
}
|
|
1592
|
+
const remA = stateA & maskA;
|
|
1593
|
+
const remB = stateB & maskB;
|
|
1594
|
+
const symA = lutA[remA];
|
|
1595
|
+
const symB = lutB[remB];
|
|
1596
|
+
outA[i] = symA;
|
|
1597
|
+
outB[i] = symB;
|
|
1598
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1599
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1600
|
+
}
|
|
1601
|
+
a.state = stateA;
|
|
1602
|
+
a.bufOffset = offA;
|
|
1603
|
+
b.state = stateB;
|
|
1604
|
+
b.bufOffset = offB;
|
|
1605
|
+
if (shared < countA) {
|
|
1606
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1607
|
+
}
|
|
1608
|
+
if (shared < countB) {
|
|
1609
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
function ransDecodeSymbolsPair(a, outA, countA, b, outB, countB) {
|
|
1613
|
+
const lutA = a.lutTable;
|
|
1614
|
+
const lutB = b.lutTable;
|
|
1615
|
+
if (lutA instanceof Uint8Array && lutB instanceof Uint8Array) {
|
|
1616
|
+
ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB);
|
|
1617
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint16Array) {
|
|
1618
|
+
ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB);
|
|
1619
|
+
} else if (lutA instanceof Uint8Array && lutB instanceof Uint16Array) {
|
|
1620
|
+
ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB);
|
|
1621
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint8Array) {
|
|
1622
|
+
ransDecodeSymbolsPairU8U16(b, outB, countB, a, outA, countA);
|
|
1623
|
+
} else {
|
|
1624
|
+
a.decodeSymbols(outA, countA);
|
|
1625
|
+
b.decodeSymbols(outB, countB);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
function ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB) {
|
|
1629
|
+
const lutA = a.lutTable;
|
|
1630
|
+
const lutB = b.lutTable;
|
|
1631
|
+
const bufA = a.buf;
|
|
1632
|
+
const bufB = b.buf;
|
|
1633
|
+
const probA = a.probTable;
|
|
1634
|
+
const probB = b.probTable;
|
|
1635
|
+
const cumA = a.cumProbTable;
|
|
1636
|
+
const cumB = b.cumProbTable;
|
|
1637
|
+
const lBaseA = a.lRansBase;
|
|
1638
|
+
const lBaseB = b.lRansBase;
|
|
1639
|
+
const bitsA = a.ransPrecisionBits;
|
|
1640
|
+
const bitsB = b.ransPrecisionBits;
|
|
1641
|
+
const maskA = a.ransPrecisionMask;
|
|
1642
|
+
const maskB = b.ransPrecisionMask;
|
|
1643
|
+
const startA = a.bufStart;
|
|
1644
|
+
const startB = b.bufStart;
|
|
1645
|
+
let stateA = a.state;
|
|
1646
|
+
let stateB = b.state;
|
|
1647
|
+
let offA = a.bufOffset;
|
|
1648
|
+
let offB = b.bufOffset;
|
|
1649
|
+
const shared = countA < countB ? countA : countB;
|
|
1650
|
+
for (let i = 0; i < shared; ++i) {
|
|
1651
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1652
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1653
|
+
}
|
|
1654
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1655
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1656
|
+
}
|
|
1657
|
+
const remA = stateA & maskA;
|
|
1658
|
+
const remB = stateB & maskB;
|
|
1659
|
+
const symA = lutA[remA];
|
|
1660
|
+
const symB = lutB[remB];
|
|
1661
|
+
outA[i] = symA;
|
|
1662
|
+
outB[i] = symB;
|
|
1663
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1664
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1665
|
+
}
|
|
1666
|
+
a.state = stateA;
|
|
1667
|
+
a.bufOffset = offA;
|
|
1668
|
+
b.state = stateB;
|
|
1669
|
+
b.bufOffset = offB;
|
|
1670
|
+
if (shared < countA) {
|
|
1671
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1672
|
+
}
|
|
1673
|
+
if (shared < countB) {
|
|
1674
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
function ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB) {
|
|
1678
|
+
const lutA = a.lutTable;
|
|
1679
|
+
const lutB = b.lutTable;
|
|
1680
|
+
const bufA = a.buf;
|
|
1681
|
+
const bufB = b.buf;
|
|
1682
|
+
const probA = a.probTable;
|
|
1683
|
+
const probB = b.probTable;
|
|
1684
|
+
const cumA = a.cumProbTable;
|
|
1685
|
+
const cumB = b.cumProbTable;
|
|
1686
|
+
const lBaseA = a.lRansBase;
|
|
1687
|
+
const lBaseB = b.lRansBase;
|
|
1688
|
+
const bitsA = a.ransPrecisionBits;
|
|
1689
|
+
const bitsB = b.ransPrecisionBits;
|
|
1690
|
+
const maskA = a.ransPrecisionMask;
|
|
1691
|
+
const maskB = b.ransPrecisionMask;
|
|
1692
|
+
const startA = a.bufStart;
|
|
1693
|
+
const startB = b.bufStart;
|
|
1694
|
+
let stateA = a.state;
|
|
1695
|
+
let stateB = b.state;
|
|
1696
|
+
let offA = a.bufOffset;
|
|
1697
|
+
let offB = b.bufOffset;
|
|
1698
|
+
const shared = countA < countB ? countA : countB;
|
|
1699
|
+
for (let i = 0; i < shared; ++i) {
|
|
1700
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1701
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1702
|
+
}
|
|
1703
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1704
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1705
|
+
}
|
|
1706
|
+
const remA = stateA & maskA;
|
|
1707
|
+
const remB = stateB & maskB;
|
|
1708
|
+
const symA = lutA[remA];
|
|
1709
|
+
const symB = lutB[remB];
|
|
1710
|
+
outA[i] = symA;
|
|
1711
|
+
outB[i] = symB;
|
|
1712
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1713
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1714
|
+
}
|
|
1715
|
+
a.state = stateA;
|
|
1716
|
+
a.bufOffset = offA;
|
|
1717
|
+
b.state = stateB;
|
|
1718
|
+
b.bufOffset = offB;
|
|
1719
|
+
if (shared < countA) {
|
|
1720
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1721
|
+
}
|
|
1722
|
+
if (shared < countB) {
|
|
1723
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
function ransDecodeSymbolsTrioU8(a, outA, countA, b, outB, countB, c, outC, countC) {
|
|
1727
|
+
const lutA = a.lutTable;
|
|
1728
|
+
const lutB = b.lutTable;
|
|
1729
|
+
const lutC = c.lutTable;
|
|
1730
|
+
const bufA = a.buf;
|
|
1731
|
+
const bufB = b.buf;
|
|
1732
|
+
const bufC = c.buf;
|
|
1733
|
+
const probA = a.probTable;
|
|
1734
|
+
const probB = b.probTable;
|
|
1735
|
+
const probC = c.probTable;
|
|
1736
|
+
const cumA = a.cumProbTable;
|
|
1737
|
+
const cumB = b.cumProbTable;
|
|
1738
|
+
const cumC = c.cumProbTable;
|
|
1739
|
+
const lBaseA = a.lRansBase;
|
|
1740
|
+
const lBaseB = b.lRansBase;
|
|
1741
|
+
const lBaseC = c.lRansBase;
|
|
1742
|
+
const bitsA = a.ransPrecisionBits;
|
|
1743
|
+
const bitsB = b.ransPrecisionBits;
|
|
1744
|
+
const bitsC = c.ransPrecisionBits;
|
|
1745
|
+
const maskA = a.ransPrecisionMask;
|
|
1746
|
+
const maskB = b.ransPrecisionMask;
|
|
1747
|
+
const maskC = c.ransPrecisionMask;
|
|
1748
|
+
const startA = a.bufStart;
|
|
1749
|
+
const startB = b.bufStart;
|
|
1750
|
+
const startC = c.bufStart;
|
|
1751
|
+
let stateA = a.state;
|
|
1752
|
+
let stateB = b.state;
|
|
1753
|
+
let stateC = c.state;
|
|
1754
|
+
let offA = a.bufOffset;
|
|
1755
|
+
let offB = b.bufOffset;
|
|
1756
|
+
let offC = c.bufOffset;
|
|
1757
|
+
let shared = countA < countB ? countA : countB;
|
|
1758
|
+
if (countC < shared) shared = countC;
|
|
1759
|
+
for (let i = 0; i < shared; ++i) {
|
|
1760
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1761
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1762
|
+
}
|
|
1763
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1764
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1765
|
+
}
|
|
1766
|
+
while (stateC < lBaseC && offC > startC) {
|
|
1767
|
+
stateC = stateC << 8 | bufC[--offC];
|
|
1768
|
+
}
|
|
1769
|
+
const remA = stateA & maskA;
|
|
1770
|
+
const remB = stateB & maskB;
|
|
1771
|
+
const remC = stateC & maskC;
|
|
1772
|
+
const symA = lutA[remA];
|
|
1773
|
+
const symB = lutB[remB];
|
|
1774
|
+
const symC = lutC[remC];
|
|
1775
|
+
outA[i] = symA;
|
|
1776
|
+
outB[i] = symB;
|
|
1777
|
+
outC[i] = symC;
|
|
1778
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1779
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1780
|
+
stateC = (stateC >>> bitsC) * probC[symC] + remC - cumC[symC];
|
|
1781
|
+
}
|
|
1782
|
+
a.state = stateA;
|
|
1783
|
+
a.bufOffset = offA;
|
|
1784
|
+
b.state = stateB;
|
|
1785
|
+
b.bufOffset = offB;
|
|
1786
|
+
c.state = stateC;
|
|
1787
|
+
c.bufOffset = offC;
|
|
1788
|
+
const restA = countA - shared;
|
|
1789
|
+
const restB = countB - shared;
|
|
1790
|
+
const restC = countC - shared;
|
|
1791
|
+
const tails = [];
|
|
1792
|
+
if (restA > 0) tails.push([a, outA.subarray(shared), restA]);
|
|
1793
|
+
if (restB > 0) tails.push([b, outB.subarray(shared), restB]);
|
|
1794
|
+
if (restC > 0) tails.push([c, outC.subarray(shared), restC]);
|
|
1795
|
+
if (tails.length === 2) {
|
|
1796
|
+
ransDecodeSymbolsPairU8(tails[0][0], tails[0][1], tails[0][2], tails[1][0], tails[1][1], tails[1][2]);
|
|
1797
|
+
} else {
|
|
1798
|
+
for (const [decoder, out, count] of tails) {
|
|
1799
|
+
decoder.decodeSymbols(out, count);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
// src/decoder/compression/point_cloud/PointCloudDecoder.ts
|
|
1805
|
+
var PointCloudDecoder = class _PointCloudDecoder {
|
|
1806
|
+
_pointCloud;
|
|
1807
|
+
_buffer;
|
|
1808
|
+
_versionMajor;
|
|
1809
|
+
_versionMinor;
|
|
1810
|
+
_options;
|
|
1811
|
+
_attributesDecoders;
|
|
1812
|
+
_attributeToDecoderMap;
|
|
1813
|
+
constructor() {
|
|
1814
|
+
this._pointCloud = null;
|
|
1815
|
+
this._buffer = null;
|
|
1816
|
+
this._versionMajor = 0;
|
|
1817
|
+
this._versionMinor = 0;
|
|
1818
|
+
this._options = null;
|
|
1819
|
+
this._attributesDecoders = [];
|
|
1820
|
+
this._attributeToDecoderMap = [];
|
|
1821
|
+
}
|
|
1822
|
+
getGeometryType() {
|
|
1823
|
+
return EncodedGeometryType.POINT_CLOUD;
|
|
1824
|
+
}
|
|
1825
|
+
// Returns a Status; on success outHeader is populated.
|
|
1826
|
+
static decodeHeader(buffer, outHeader) {
|
|
1827
|
+
const kIoErrorMsg = "Failed to parse Draco header.";
|
|
1828
|
+
const bytes = buffer.decodeBytes(5);
|
|
1829
|
+
if (bytes === void 0) {
|
|
1830
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1831
|
+
}
|
|
1832
|
+
for (let i = 0; i < 5; i++) {
|
|
1833
|
+
outHeader.dracoString[i] = bytes[i];
|
|
1834
|
+
}
|
|
1835
|
+
const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
|
|
1836
|
+
if (magic !== "DRACO") {
|
|
1837
|
+
return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
|
|
1838
|
+
}
|
|
1839
|
+
const versionMajor = buffer.decodeUint8();
|
|
1840
|
+
if (versionMajor === void 0) {
|
|
1841
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1842
|
+
}
|
|
1843
|
+
outHeader.versionMajor = versionMajor;
|
|
1844
|
+
const versionMinor = buffer.decodeUint8();
|
|
1845
|
+
if (versionMinor === void 0) {
|
|
1846
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1847
|
+
}
|
|
1848
|
+
outHeader.versionMinor = versionMinor;
|
|
1849
|
+
const encoderType = buffer.decodeUint8();
|
|
1850
|
+
if (encoderType === void 0) {
|
|
1851
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1852
|
+
}
|
|
1853
|
+
outHeader.encoderType = encoderType;
|
|
1854
|
+
const encoderMethod = buffer.decodeUint8();
|
|
1855
|
+
if (encoderMethod === void 0) {
|
|
1856
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1857
|
+
}
|
|
1858
|
+
outHeader.encoderMethod = encoderMethod;
|
|
1859
|
+
const flags = buffer.decodeUint16();
|
|
1860
|
+
if (flags === void 0) {
|
|
1861
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1862
|
+
}
|
|
1863
|
+
outHeader.flags = flags;
|
|
1864
|
+
return okStatus();
|
|
1865
|
+
}
|
|
1866
|
+
// Main entry point for point cloud decoding.
|
|
1867
|
+
decode(options, inBuffer, outPointCloud) {
|
|
1868
|
+
this._options = options;
|
|
1869
|
+
this._buffer = inBuffer;
|
|
1870
|
+
this._pointCloud = outPointCloud;
|
|
1871
|
+
const header = new DracoHeader();
|
|
1872
|
+
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1873
|
+
if (!headerStatus.ok()) {
|
|
1874
|
+
return headerStatus;
|
|
1875
|
+
}
|
|
1876
|
+
if (header.encoderType !== this.getGeometryType()) {
|
|
1877
|
+
return new Status(StatusCode.DRACO_ERROR, "Using incompatible decoder for the input geometry.");
|
|
1878
|
+
}
|
|
1879
|
+
this._versionMajor = header.versionMajor;
|
|
1880
|
+
this._versionMinor = header.versionMinor;
|
|
1881
|
+
const maxSupportedMajorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor : kDracoMeshBitstreamVersionMajor;
|
|
1882
|
+
const maxSupportedMinorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor;
|
|
1276
1883
|
if (this._versionMajor < 1 || this._versionMajor > maxSupportedMajorVersion) {
|
|
1277
1884
|
return new Status(StatusCode.UNKNOWN_VERSION, "Unknown major version.");
|
|
1278
1885
|
}
|
|
@@ -1388,8 +1995,27 @@ var PointCloudDecoder = class _PointCloudDecoder {
|
|
|
1388
1995
|
return true;
|
|
1389
1996
|
}
|
|
1390
1997
|
decodeAllAttributes() {
|
|
1391
|
-
|
|
1392
|
-
|
|
1998
|
+
const decoders = this._attributesDecoders;
|
|
1999
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
2000
|
+
if (!decoders[i2].decodeAttributesParse(this._buffer)) {
|
|
2001
|
+
return false;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
const pending = [];
|
|
2005
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
2006
|
+
decoders[i2].collectPendingSymbolStreams(pending);
|
|
2007
|
+
}
|
|
2008
|
+
let i = 0;
|
|
2009
|
+
for (; i + 1 < pending.length; i += 2) {
|
|
2010
|
+
const a = pending[i];
|
|
2011
|
+
const b = pending[i + 1];
|
|
2012
|
+
ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
|
|
2013
|
+
}
|
|
2014
|
+
if (i < pending.length) {
|
|
2015
|
+
pending[i].ans.decodeSymbols(pending[i].out, pending[i].count);
|
|
2016
|
+
}
|
|
2017
|
+
for (let k = 0; k < decoders.length; k++) {
|
|
2018
|
+
if (!decoders[k].decodeAttributesFinish()) {
|
|
1393
2019
|
return false;
|
|
1394
2020
|
}
|
|
1395
2021
|
}
|
|
@@ -1457,46 +2083,62 @@ var MeshAttributeCornerTable = class {
|
|
|
1457
2083
|
no_interior_seams_;
|
|
1458
2084
|
corner_to_vertex_map_;
|
|
1459
2085
|
vertex_to_left_most_corner_map_;
|
|
1460
|
-
|
|
2086
|
+
// Attribute-vertex count. C++ keeps a vertex -> attribute-entry map here, but
|
|
2087
|
+
// the decoder only ever reads its size, so track the count directly instead
|
|
2088
|
+
// of allocating an Int32Array per attribute corner table.
|
|
2089
|
+
num_attribute_vertices_;
|
|
1461
2090
|
corner_table_;
|
|
1462
2091
|
// Lazily built; see oppositeCornerArray.
|
|
1463
2092
|
_effectiveOpposite;
|
|
1464
2093
|
// Every corner passed to addSeamEdge (may contain duplicates); lets
|
|
1465
2094
|
// oppositeCornerArray patch seams without scanning every corner's flag.
|
|
2095
|
+
// Preallocated to its exact upper bound (2 per seam edge) by the caller via
|
|
2096
|
+
// reserveSeamEdges -- a plain array grown by push() was measurable on
|
|
2097
|
+
// seam-heavy files.
|
|
1466
2098
|
_seamCorners;
|
|
2099
|
+
_numSeamCorners;
|
|
1467
2100
|
constructor() {
|
|
1468
2101
|
this.is_edge_on_seam_ = [];
|
|
1469
2102
|
this.is_vertex_on_seam_ = [];
|
|
1470
2103
|
this.no_interior_seams_ = true;
|
|
1471
2104
|
this.corner_to_vertex_map_ = [];
|
|
1472
2105
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1473
|
-
this.
|
|
2106
|
+
this.num_attribute_vertices_ = 0;
|
|
1474
2107
|
this.corner_table_ = null;
|
|
1475
2108
|
this._effectiveOpposite = null;
|
|
1476
2109
|
this._seamCorners = [];
|
|
2110
|
+
this._numSeamCorners = 0;
|
|
1477
2111
|
}
|
|
1478
2112
|
initEmpty(table) {
|
|
1479
2113
|
if (table === null) {
|
|
1480
2114
|
return false;
|
|
1481
2115
|
}
|
|
1482
|
-
this.is_edge_on_seam_ =
|
|
1483
|
-
this.is_vertex_on_seam_ =
|
|
1484
|
-
this.corner_to_vertex_map_ =
|
|
1485
|
-
this.
|
|
2116
|
+
this.is_edge_on_seam_ = scratchUint8Zeroed(table.numCorners());
|
|
2117
|
+
this.is_vertex_on_seam_ = scratchUint8Zeroed(table.numVertices());
|
|
2118
|
+
this.corner_to_vertex_map_ = scratchInt32Filled(table.numCorners(), kInvalidVertexIndex);
|
|
2119
|
+
this.num_attribute_vertices_ = 0;
|
|
1486
2120
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1487
2121
|
this._effectiveOpposite = null;
|
|
1488
2122
|
this._seamCorners = [];
|
|
2123
|
+
this._numSeamCorners = 0;
|
|
1489
2124
|
this.corner_table_ = table;
|
|
1490
2125
|
this.no_interior_seams_ = true;
|
|
1491
2126
|
return true;
|
|
1492
2127
|
}
|
|
2128
|
+
// Sizes the seam-corner list for numSeamEdges upcoming addSeamEdge calls
|
|
2129
|
+
// (each adds at most two corners). Decode-scoped scratch.
|
|
2130
|
+
reserveSeamEdges(numSeamEdges) {
|
|
2131
|
+
this._seamCorners = scratchInt32(numSeamEdges * 2);
|
|
2132
|
+
this._numSeamCorners = 0;
|
|
2133
|
+
}
|
|
1493
2134
|
addSeamEdge(c) {
|
|
1494
2135
|
const cornerToVertex = this.corner_table_.cornerToVertexArray();
|
|
1495
2136
|
const oppositeCorners = this.corner_table_.oppositeCornerArray();
|
|
1496
2137
|
const isEdge = this.is_edge_on_seam_;
|
|
1497
2138
|
const isVert = this.is_vertex_on_seam_;
|
|
2139
|
+
const seamCorners = this._seamCorners;
|
|
1498
2140
|
isEdge[c] = 1;
|
|
1499
|
-
this.
|
|
2141
|
+
seamCorners[this._numSeamCorners++] = c;
|
|
1500
2142
|
let rem = c - (c / 3 | 0) * 3;
|
|
1501
2143
|
isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
|
|
1502
2144
|
isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
|
|
@@ -1504,7 +2146,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1504
2146
|
if (oppCorner !== kInvalidCornerIndex) {
|
|
1505
2147
|
this.no_interior_seams_ = false;
|
|
1506
2148
|
isEdge[oppCorner] = 1;
|
|
1507
|
-
this.
|
|
2149
|
+
seamCorners[this._numSeamCorners++] = oppCorner;
|
|
1508
2150
|
rem = oppCorner - (oppCorner / 3 | 0) * 3;
|
|
1509
2151
|
isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
|
|
1510
2152
|
isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
|
|
@@ -1519,12 +2161,12 @@ var MeshAttributeCornerTable = class {
|
|
|
1519
2161
|
const ct = this.corner_table_;
|
|
1520
2162
|
const numCorners = ct.numCorners();
|
|
1521
2163
|
const numBaseVertices = ct.numVertices();
|
|
1522
|
-
const leftMostMap =
|
|
2164
|
+
const leftMostMap = scratchInt32(numCorners);
|
|
1523
2165
|
const cornerToVertex = this.corner_to_vertex_map_;
|
|
1524
2166
|
const isVertexOnSeam = this.is_vertex_on_seam_;
|
|
1525
2167
|
const isEdgeOnSeam = this.is_edge_on_seam_;
|
|
1526
2168
|
const seamOpp = this.oppositeCornerArray();
|
|
1527
|
-
const
|
|
2169
|
+
const swingRight = ct.swingRightArray();
|
|
1528
2170
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
1529
2171
|
let numNewVertices = 0;
|
|
1530
2172
|
for (let v = 0; v < numBaseVertices; ++v) {
|
|
@@ -1534,14 +2176,10 @@ var MeshAttributeCornerTable = class {
|
|
|
1534
2176
|
const firstVertId = numNewVertices++;
|
|
1535
2177
|
leftMostMap[firstVertId] = c;
|
|
1536
2178
|
cornerToVertex[c] = firstVertId;
|
|
1537
|
-
let
|
|
1538
|
-
let bopp = baseOpp[pv];
|
|
1539
|
-
let actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2179
|
+
let actC = swingRight[c];
|
|
1540
2180
|
while (actC !== kInvalidCornerIndex && actC !== c) {
|
|
1541
2181
|
cornerToVertex[actC] = firstVertId;
|
|
1542
|
-
|
|
1543
|
-
bopp = baseOpp[pv];
|
|
1544
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2182
|
+
actC = swingRight[actC];
|
|
1545
2183
|
}
|
|
1546
2184
|
} else {
|
|
1547
2185
|
let firstVertId = numNewVertices++;
|
|
@@ -1559,9 +2197,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1559
2197
|
}
|
|
1560
2198
|
cornerToVertex[firstC] = firstVertId;
|
|
1561
2199
|
leftMostMap[firstVertId] = firstC;
|
|
1562
|
-
|
|
1563
|
-
let bopp = baseOpp[pv];
|
|
1564
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2200
|
+
actC = swingRight[firstC];
|
|
1565
2201
|
while (actC !== kInvalidCornerIndex && actC !== firstC) {
|
|
1566
2202
|
const nAct = actC % 3 === 2 ? actC - 2 : actC + 1;
|
|
1567
2203
|
if (isEdgeOnSeam[nAct]) {
|
|
@@ -1569,13 +2205,11 @@ var MeshAttributeCornerTable = class {
|
|
|
1569
2205
|
leftMostMap[firstVertId] = actC;
|
|
1570
2206
|
}
|
|
1571
2207
|
cornerToVertex[actC] = firstVertId;
|
|
1572
|
-
|
|
1573
|
-
bopp = baseOpp[pv];
|
|
1574
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2208
|
+
actC = swingRight[actC];
|
|
1575
2209
|
}
|
|
1576
2210
|
}
|
|
1577
2211
|
}
|
|
1578
|
-
this.
|
|
2212
|
+
this.num_attribute_vertices_ = numNewVertices;
|
|
1579
2213
|
this.vertex_to_left_most_corner_map_ = leftMostMap.subarray(0, numNewVertices);
|
|
1580
2214
|
return true;
|
|
1581
2215
|
}
|
|
@@ -1601,7 +2235,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1601
2235
|
return this.next(this.opposite(this.next(corner)));
|
|
1602
2236
|
}
|
|
1603
2237
|
numVertices() {
|
|
1604
|
-
return this.
|
|
2238
|
+
return this.num_attribute_vertices_;
|
|
1605
2239
|
}
|
|
1606
2240
|
numFaces() {
|
|
1607
2241
|
return this.corner_table_.numFaces();
|
|
@@ -1629,12 +2263,13 @@ var MeshAttributeCornerTable = class {
|
|
|
1629
2263
|
const nc = this.corner_table_.numCorners();
|
|
1630
2264
|
const base = this.corner_table_.oppositeCornerArray();
|
|
1631
2265
|
const seamCorners = this._seamCorners;
|
|
1632
|
-
|
|
2266
|
+
const numSeamCorners = this._numSeamCorners;
|
|
2267
|
+
if (numSeamCorners === 0) {
|
|
1633
2268
|
this._effectiveOpposite = base;
|
|
1634
2269
|
} else {
|
|
1635
2270
|
const eff = scratchInt32(nc);
|
|
1636
2271
|
eff.set(base.length === nc ? base : base.subarray(0, nc));
|
|
1637
|
-
for (let i = 0
|
|
2272
|
+
for (let i = 0; i < numSeamCorners; ++i) {
|
|
1638
2273
|
eff[seamCorners[i]] = kInvalidCornerIndex;
|
|
1639
2274
|
}
|
|
1640
2275
|
this._effectiveOpposite = eff;
|
|
@@ -1649,23 +2284,20 @@ var MeshAttributeCornerTable = class {
|
|
|
1649
2284
|
vertexOnSeamArray() {
|
|
1650
2285
|
return this.is_vertex_on_seam_;
|
|
1651
2286
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
}
|
|
1660
|
-
return true;
|
|
1661
|
-
}
|
|
1662
|
-
adoptVertexRecompute(other) {
|
|
2287
|
+
// Takes over another table's state wholesale. Only valid when both tables
|
|
2288
|
+
// were built from the same corner table and the same seam edges, in which
|
|
2289
|
+
// case every one of these is identical and read-only from here on.
|
|
2290
|
+
adoptFrom(other) {
|
|
2291
|
+
this.corner_table_ = other.corner_table_;
|
|
2292
|
+
this.is_edge_on_seam_ = other.is_edge_on_seam_;
|
|
2293
|
+
this.is_vertex_on_seam_ = other.is_vertex_on_seam_;
|
|
1663
2294
|
this.corner_to_vertex_map_ = other.corner_to_vertex_map_;
|
|
1664
|
-
this.
|
|
2295
|
+
this.num_attribute_vertices_ = other.num_attribute_vertices_;
|
|
1665
2296
|
this.vertex_to_left_most_corner_map_ = other.vertex_to_left_most_corner_map_;
|
|
1666
2297
|
this.no_interior_seams_ = other.no_interior_seams_;
|
|
1667
2298
|
this._effectiveOpposite = other._effectiveOpposite;
|
|
1668
2299
|
this._seamCorners = other._seamCorners;
|
|
2300
|
+
this._numSeamCorners = other._numSeamCorners;
|
|
1669
2301
|
}
|
|
1670
2302
|
};
|
|
1671
2303
|
|
|
@@ -1679,6 +2311,21 @@ var AttributesDecoderInterface = class {
|
|
|
1679
2311
|
decodeAttributesDecoderData(_buffer) {
|
|
1680
2312
|
return false;
|
|
1681
2313
|
}
|
|
2314
|
+
// --- Optional two-phase decode across attributes decoders ---
|
|
2315
|
+
// PointCloudDecoder parses every decoder first (all buffer reads are
|
|
2316
|
+
// size-driven, so parsing runs ahead of the deferred rANS symbol decodes),
|
|
2317
|
+
// then decodes the collected streams two at a time, then finishes each
|
|
2318
|
+
// decoder in order (so parent attributes complete before dependents).
|
|
2319
|
+
// Defaults keep the original single-phase behavior for decoders that do not
|
|
2320
|
+
// split.
|
|
2321
|
+
decodeAttributesParse(buffer) {
|
|
2322
|
+
return this.decodeAttributes(buffer);
|
|
2323
|
+
}
|
|
2324
|
+
collectPendingSymbolStreams(_out) {
|
|
2325
|
+
}
|
|
2326
|
+
decodeAttributesFinish() {
|
|
2327
|
+
return true;
|
|
2328
|
+
}
|
|
1682
2329
|
decodeAttributes(_buffer) {
|
|
1683
2330
|
return false;
|
|
1684
2331
|
}
|
|
@@ -1825,6 +2472,22 @@ var SequentialAttributeDecoder = class {
|
|
|
1825
2472
|
this._attributeId = attributeId;
|
|
1826
2473
|
return true;
|
|
1827
2474
|
}
|
|
2475
|
+
// --- Optional two-phase decode ---
|
|
2476
|
+
// The controller calls Parse for every attribute first (headers, schemes,
|
|
2477
|
+
// prediction data -- all size-driven cursor movement), collects the pending
|
|
2478
|
+
// rANS symbol streams, decodes them in pairs (see ransDecodeSymbolsPair),
|
|
2479
|
+
// then calls Finish per attribute in order. Decoders without a deferrable
|
|
2480
|
+
// stream simply do the whole decode in Parse. Defaults preserve the
|
|
2481
|
+
// original single-phase behavior.
|
|
2482
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
2483
|
+
return this.decodePortableAttribute(pointIds, buffer);
|
|
2484
|
+
}
|
|
2485
|
+
pendingSymbolStream() {
|
|
2486
|
+
return null;
|
|
2487
|
+
}
|
|
2488
|
+
decodePortableAttributeFinish() {
|
|
2489
|
+
return true;
|
|
2490
|
+
}
|
|
1828
2491
|
decodePortableAttribute(pointIds, buffer) {
|
|
1829
2492
|
if (this._attribute.numComponents <= 0) {
|
|
1830
2493
|
return false;
|
|
@@ -1845,7 +2508,7 @@ var SequentialAttributeDecoder = class {
|
|
|
1845
2508
|
getPortableAttribute() {
|
|
1846
2509
|
if (!this._attribute.isMappingIdentity && this._portableAttribute && this._portableAttribute.isMappingIdentity) {
|
|
1847
2510
|
const size = this._attribute.indicesMapSize;
|
|
1848
|
-
this._portableAttribute.
|
|
2511
|
+
this._portableAttribute.setExplicitMappingScratch(size);
|
|
1849
2512
|
const src = this._attribute.indicesMap;
|
|
1850
2513
|
const dst = this._portableAttribute.indicesMap;
|
|
1851
2514
|
if (src.length === size) {
|
|
@@ -1860,331 +2523,42 @@ var SequentialAttributeDecoder = class {
|
|
|
1860
2523
|
return this._attribute;
|
|
1861
2524
|
}
|
|
1862
2525
|
get attributeId() {
|
|
1863
|
-
return this._attributeId;
|
|
1864
|
-
}
|
|
1865
|
-
get decoder() {
|
|
1866
|
-
return this._decoder;
|
|
1867
|
-
}
|
|
1868
|
-
initPredictionScheme(ps) {
|
|
1869
|
-
for (let i = 0; i < ps.getNumParentAttributes(); i++) {
|
|
1870
|
-
const attId = this._decoder.pointCloud().getNamedAttributeId(ps.getParentAttributeType(i));
|
|
1871
|
-
if (attId === -1) {
|
|
1872
|
-
return false;
|
|
1873
|
-
}
|
|
1874
|
-
const pa = this._decoder.getPortableAttribute(attId);
|
|
1875
|
-
if (pa === null || !ps.setParentAttribute(pa)) {
|
|
1876
|
-
return false;
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
return true;
|
|
1880
|
-
}
|
|
1881
|
-
// Decodes raw attribute values in their original format.
|
|
1882
|
-
decodeValues(pointIds, buffer) {
|
|
1883
|
-
const numValues = pointIds.length;
|
|
1884
|
-
const entrySize = this._attribute.byteStride;
|
|
1885
|
-
const totalSize = numValues * entrySize;
|
|
1886
|
-
const valueData = buffer.decodeBytesView(totalSize);
|
|
1887
|
-
if (valueData === void 0) {
|
|
1888
|
-
return false;
|
|
1889
|
-
}
|
|
1890
|
-
this._attribute.buffer.write(0, valueData, totalSize);
|
|
1891
|
-
return true;
|
|
1892
|
-
}
|
|
1893
|
-
setPortableAttribute(att) {
|
|
1894
|
-
this._portableAttribute = att;
|
|
1895
|
-
}
|
|
1896
|
-
get portableAttribute() {
|
|
1897
|
-
return this._portableAttribute;
|
|
1898
|
-
}
|
|
1899
|
-
};
|
|
1900
|
-
|
|
1901
|
-
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1902
|
-
var ANS_P8_PRECISION = 256;
|
|
1903
|
-
var ANS_L_BASE = 4096;
|
|
1904
|
-
var ANS_IO_BASE = 256;
|
|
1905
|
-
function memGetLe16(buf, offset) {
|
|
1906
|
-
return buf[offset] | buf[offset + 1] << 8;
|
|
1907
|
-
}
|
|
1908
|
-
function memGetLe24(buf, offset) {
|
|
1909
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1910
|
-
}
|
|
1911
|
-
function memGetLe32(buf, offset) {
|
|
1912
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1913
|
-
}
|
|
1914
|
-
var AnsDecoder = class {
|
|
1915
|
-
buf;
|
|
1916
|
-
bufOffset;
|
|
1917
|
-
// First valid byte of this decoder's slice within buf: init is passed
|
|
1918
|
-
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1919
|
-
bufStart;
|
|
1920
|
-
state;
|
|
1921
|
-
constructor() {
|
|
1922
|
-
this.buf = null;
|
|
1923
|
-
this.bufOffset = 0;
|
|
1924
|
-
this.bufStart = 0;
|
|
1925
|
-
this.state = 0;
|
|
1926
|
-
}
|
|
1927
|
-
};
|
|
1928
|
-
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1929
|
-
if (offset - base < 1) {
|
|
1930
|
-
return 1;
|
|
1931
|
-
}
|
|
1932
|
-
ans.buf = buf;
|
|
1933
|
-
ans.bufStart = base;
|
|
1934
|
-
const x = buf[offset - 1] >> 6;
|
|
1935
|
-
if (x === 0) {
|
|
1936
|
-
ans.bufOffset = offset - 1;
|
|
1937
|
-
ans.state = buf[offset - 1] & 63;
|
|
1938
|
-
} else if (x === 1) {
|
|
1939
|
-
if (offset - base < 2) {
|
|
1940
|
-
return 1;
|
|
1941
|
-
}
|
|
1942
|
-
ans.bufOffset = offset - 2;
|
|
1943
|
-
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1944
|
-
} else if (x === 2) {
|
|
1945
|
-
if (offset - base < 3) {
|
|
1946
|
-
return 1;
|
|
1947
|
-
}
|
|
1948
|
-
ans.bufOffset = offset - 3;
|
|
1949
|
-
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1950
|
-
} else {
|
|
1951
|
-
return 1;
|
|
1952
|
-
}
|
|
1953
|
-
ans.state += ANS_L_BASE;
|
|
1954
|
-
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1955
|
-
return 1;
|
|
1956
|
-
}
|
|
1957
|
-
return 0;
|
|
1958
|
-
}
|
|
1959
|
-
function ansReadEnd(ans) {
|
|
1960
|
-
return ans.state === ANS_L_BASE;
|
|
1961
|
-
}
|
|
1962
|
-
var tablePool = [];
|
|
1963
|
-
var acquirePooled = (Ctor, size) => {
|
|
1964
|
-
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1965
|
-
const buf = tablePool[i];
|
|
1966
|
-
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1967
|
-
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1968
|
-
tablePool.pop();
|
|
1969
|
-
return buf;
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
return new Ctor(size);
|
|
1973
|
-
};
|
|
1974
|
-
var RAnsDecoder = class {
|
|
1975
|
-
ransPrecisionBits;
|
|
1976
|
-
ransPrecision;
|
|
1977
|
-
ransPrecisionMask;
|
|
1978
|
-
lRansBase;
|
|
1979
|
-
lutTable;
|
|
1980
|
-
probTable;
|
|
1981
|
-
cumProbTable;
|
|
1982
|
-
buf;
|
|
1983
|
-
bufOffset;
|
|
1984
|
-
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1985
|
-
// see AnsDecoder.bufStart).
|
|
1986
|
-
bufStart;
|
|
1987
|
-
state;
|
|
1988
|
-
constructor(ransPrecisionBits) {
|
|
1989
|
-
this.ransPrecisionBits = ransPrecisionBits;
|
|
1990
|
-
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1991
|
-
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1992
|
-
this.lRansBase = this.ransPrecision * 4;
|
|
1993
|
-
this.lutTable = null;
|
|
1994
|
-
this.probTable = null;
|
|
1995
|
-
this.cumProbTable = null;
|
|
1996
|
-
this.buf = null;
|
|
1997
|
-
this.bufOffset = 0;
|
|
1998
|
-
this.bufStart = 0;
|
|
1999
|
-
this.state = 0;
|
|
2000
|
-
}
|
|
2001
|
-
// offset is the absolute end of the encoded bytes within buf and base the
|
|
2002
|
-
// absolute start (offset - base = encoded length). Passing the source
|
|
2003
|
-
// buffer with absolute offsets avoids a subarray allocation per init.
|
|
2004
|
-
// Returns 0 on success, non-zero on error.
|
|
2005
|
-
readInit(buf, offset, base = 0) {
|
|
2006
|
-
if (offset - base < 1) {
|
|
2007
|
-
return 1;
|
|
2008
|
-
}
|
|
2009
|
-
this.buf = buf;
|
|
2010
|
-
this.bufStart = base;
|
|
2011
|
-
const x = buf[offset - 1] >> 6;
|
|
2012
|
-
if (x === 0) {
|
|
2013
|
-
this.bufOffset = offset - 1;
|
|
2014
|
-
this.state = buf[offset - 1] & 63;
|
|
2015
|
-
} else if (x === 1) {
|
|
2016
|
-
if (offset - base < 2) {
|
|
2017
|
-
return 1;
|
|
2018
|
-
}
|
|
2019
|
-
this.bufOffset = offset - 2;
|
|
2020
|
-
this.state = memGetLe16(buf, offset - 2) & 16383;
|
|
2021
|
-
} else if (x === 2) {
|
|
2022
|
-
if (offset - base < 3) {
|
|
2023
|
-
return 1;
|
|
2024
|
-
}
|
|
2025
|
-
this.bufOffset = offset - 3;
|
|
2026
|
-
this.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
2027
|
-
} else if (x === 3) {
|
|
2028
|
-
if (offset - base < 4) {
|
|
2029
|
-
return 1;
|
|
2030
|
-
}
|
|
2031
|
-
this.bufOffset = offset - 4;
|
|
2032
|
-
this.state = memGetLe32(buf, offset - 4) & 1073741823;
|
|
2033
|
-
} else {
|
|
2034
|
-
return 1;
|
|
2035
|
-
}
|
|
2036
|
-
this.state += this.lRansBase;
|
|
2037
|
-
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
2038
|
-
return 1;
|
|
2039
|
-
}
|
|
2040
|
-
return 0;
|
|
2041
|
-
}
|
|
2042
|
-
readEnd() {
|
|
2043
|
-
if (this.lutTable !== null) {
|
|
2044
|
-
tablePool.push(this.lutTable);
|
|
2045
|
-
this.lutTable = null;
|
|
2046
|
-
}
|
|
2047
|
-
if (this.probTable !== null) {
|
|
2048
|
-
tablePool.push(this.probTable);
|
|
2049
|
-
this.probTable = null;
|
|
2050
|
-
}
|
|
2051
|
-
if (this.cumProbTable !== null) {
|
|
2052
|
-
tablePool.push(this.cumProbTable);
|
|
2053
|
-
this.cumProbTable = null;
|
|
2054
|
-
}
|
|
2055
|
-
return this.state === this.lRansBase;
|
|
2056
|
-
}
|
|
2057
|
-
ransRead() {
|
|
2058
|
-
const buf = this.buf;
|
|
2059
|
-
const lRansBase = this.lRansBase;
|
|
2060
|
-
let state = this.state;
|
|
2061
|
-
let bufOffset = this.bufOffset;
|
|
2062
|
-
const bufStart = this.bufStart;
|
|
2063
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2064
|
-
state = state << 8 | buf[--bufOffset];
|
|
2065
|
-
}
|
|
2066
|
-
const quo = state >>> this.ransPrecisionBits;
|
|
2067
|
-
const rem = state & this.ransPrecisionMask;
|
|
2068
|
-
const symbol = this.lutTable[rem];
|
|
2069
|
-
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
2070
|
-
this.bufOffset = bufOffset;
|
|
2071
|
-
return symbol;
|
|
2072
|
-
}
|
|
2073
|
-
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
2074
|
-
// written back once. Removes per-symbol property reads and call indirection.
|
|
2075
|
-
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
2076
|
-
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
2077
|
-
// once here so each loop body stays monomorphic on its concrete type. The
|
|
2078
|
-
// three bodies are intentionally identical copies.
|
|
2079
|
-
decodeSymbols(out, count) {
|
|
2080
|
-
const lutTable = this.lutTable;
|
|
2081
|
-
if (lutTable instanceof Uint8Array) {
|
|
2082
|
-
this._decodeSymbolsU8(out, count, lutTable);
|
|
2083
|
-
} else if (lutTable instanceof Uint16Array) {
|
|
2084
|
-
this._decodeSymbolsU16(out, count, lutTable);
|
|
2085
|
-
} else {
|
|
2086
|
-
this._decodeSymbolsU32(out, count, lutTable);
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
_decodeSymbolsU8(out, count, lutTable) {
|
|
2090
|
-
const buf = this.buf;
|
|
2091
|
-
const lRansBase = this.lRansBase;
|
|
2092
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2093
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2094
|
-
const probTable = this.probTable;
|
|
2095
|
-
const cumProbTable = this.cumProbTable;
|
|
2096
|
-
let state = this.state;
|
|
2097
|
-
let bufOffset = this.bufOffset;
|
|
2098
|
-
const bufStart = this.bufStart;
|
|
2099
|
-
for (let i = 0; i < count; ++i) {
|
|
2100
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2101
|
-
state = state << 8 | buf[--bufOffset];
|
|
2102
|
-
}
|
|
2103
|
-
const rem = state & ransPrecisionMask;
|
|
2104
|
-
const symbol = lutTable[rem];
|
|
2105
|
-
out[i] = symbol;
|
|
2106
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2107
|
-
}
|
|
2108
|
-
this.state = state;
|
|
2109
|
-
this.bufOffset = bufOffset;
|
|
2110
|
-
}
|
|
2111
|
-
_decodeSymbolsU16(out, count, lutTable) {
|
|
2112
|
-
const buf = this.buf;
|
|
2113
|
-
const lRansBase = this.lRansBase;
|
|
2114
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2115
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2116
|
-
const probTable = this.probTable;
|
|
2117
|
-
const cumProbTable = this.cumProbTable;
|
|
2118
|
-
let state = this.state;
|
|
2119
|
-
let bufOffset = this.bufOffset;
|
|
2120
|
-
const bufStart = this.bufStart;
|
|
2121
|
-
for (let i = 0; i < count; ++i) {
|
|
2122
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2123
|
-
state = state << 8 | buf[--bufOffset];
|
|
2124
|
-
}
|
|
2125
|
-
const rem = state & ransPrecisionMask;
|
|
2126
|
-
const symbol = lutTable[rem];
|
|
2127
|
-
out[i] = symbol;
|
|
2128
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2129
|
-
}
|
|
2130
|
-
this.state = state;
|
|
2131
|
-
this.bufOffset = bufOffset;
|
|
2132
|
-
}
|
|
2133
|
-
_decodeSymbolsU32(out, count, lutTable) {
|
|
2134
|
-
const buf = this.buf;
|
|
2135
|
-
const lRansBase = this.lRansBase;
|
|
2136
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2137
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2138
|
-
const probTable = this.probTable;
|
|
2139
|
-
const cumProbTable = this.cumProbTable;
|
|
2140
|
-
let state = this.state;
|
|
2141
|
-
let bufOffset = this.bufOffset;
|
|
2142
|
-
const bufStart = this.bufStart;
|
|
2143
|
-
for (let i = 0; i < count; ++i) {
|
|
2144
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2145
|
-
state = state << 8 | buf[--bufOffset];
|
|
2146
|
-
}
|
|
2147
|
-
const rem = state & ransPrecisionMask;
|
|
2148
|
-
const symbol = lutTable[rem];
|
|
2149
|
-
out[i] = symbol;
|
|
2150
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2151
|
-
}
|
|
2152
|
-
this.state = state;
|
|
2153
|
-
this.bufOffset = bufOffset;
|
|
2154
|
-
}
|
|
2155
|
-
// Builds the ransPrecision-entry lookup table. Returns false on bad input data.
|
|
2156
|
-
ransBuildLookUpTable(tokenProbs, numSymbols) {
|
|
2157
|
-
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
2158
|
-
const lutTable = acquirePooled(LutArray, this.ransPrecision);
|
|
2159
|
-
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
2160
|
-
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
2161
|
-
this.lutTable = lutTable;
|
|
2162
|
-
this.probTable = probTable;
|
|
2163
|
-
this.cumProbTable = cumProbTable;
|
|
2164
|
-
let cumProb = 0;
|
|
2165
|
-
let actProb = 0;
|
|
2166
|
-
for (let i = 0; i < numSymbols; ++i) {
|
|
2167
|
-
const prob = tokenProbs[i];
|
|
2168
|
-
probTable[i] = prob;
|
|
2169
|
-
cumProbTable[i] = cumProb;
|
|
2170
|
-
cumProb += prob;
|
|
2171
|
-
if (cumProb > this.ransPrecision) {
|
|
2526
|
+
return this._attributeId;
|
|
2527
|
+
}
|
|
2528
|
+
get decoder() {
|
|
2529
|
+
return this._decoder;
|
|
2530
|
+
}
|
|
2531
|
+
initPredictionScheme(ps) {
|
|
2532
|
+
for (let i = 0; i < ps.getNumParentAttributes(); i++) {
|
|
2533
|
+
const attId = this._decoder.pointCloud().getNamedAttributeId(ps.getParentAttributeType(i));
|
|
2534
|
+
if (attId === -1) {
|
|
2172
2535
|
return false;
|
|
2173
2536
|
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
}
|
|
2178
|
-
} else {
|
|
2179
|
-
lutTable.fill(i, actProb, cumProb);
|
|
2537
|
+
const pa = this._decoder.getPortableAttribute(attId);
|
|
2538
|
+
if (pa === null || !ps.setParentAttribute(pa)) {
|
|
2539
|
+
return false;
|
|
2180
2540
|
}
|
|
2181
|
-
actProb = cumProb;
|
|
2182
2541
|
}
|
|
2183
|
-
|
|
2542
|
+
return true;
|
|
2543
|
+
}
|
|
2544
|
+
// Decodes raw attribute values in their original format.
|
|
2545
|
+
decodeValues(pointIds, buffer) {
|
|
2546
|
+
const numValues = pointIds.length;
|
|
2547
|
+
const entrySize = this._attribute.byteStride;
|
|
2548
|
+
const totalSize = numValues * entrySize;
|
|
2549
|
+
const valueData = buffer.decodeBytesView(totalSize);
|
|
2550
|
+
if (valueData === void 0) {
|
|
2184
2551
|
return false;
|
|
2185
2552
|
}
|
|
2553
|
+
this._attribute.buffer.write(0, valueData, totalSize);
|
|
2186
2554
|
return true;
|
|
2187
2555
|
}
|
|
2556
|
+
setPortableAttribute(att) {
|
|
2557
|
+
this._portableAttribute = att;
|
|
2558
|
+
}
|
|
2559
|
+
get portableAttribute() {
|
|
2560
|
+
return this._portableAttribute;
|
|
2561
|
+
}
|
|
2188
2562
|
};
|
|
2189
2563
|
|
|
2190
2564
|
// src/decoder/compression/entropy/RAnsSymbolDecoder.ts
|
|
@@ -2220,7 +2594,7 @@ var RAnsSymbolDecoder = class {
|
|
|
2220
2594
|
return false;
|
|
2221
2595
|
}
|
|
2222
2596
|
const numSymbols = this.numSymbols_;
|
|
2223
|
-
const probabilityTable =
|
|
2597
|
+
const probabilityTable = scratchUint32Zeroed(numSymbols);
|
|
2224
2598
|
this.probabilityTable_ = probabilityTable;
|
|
2225
2599
|
if (numSymbols === 0) {
|
|
2226
2600
|
return true;
|
|
@@ -2301,24 +2675,73 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
|
2301
2675
|
if (numValues > 0 && tagDecoder.numSymbols === 0) {
|
|
2302
2676
|
return false;
|
|
2303
2677
|
}
|
|
2678
|
+
const tagAns = tagDecoder.ans_;
|
|
2304
2679
|
srcBuffer.startBitDecoding(false);
|
|
2305
2680
|
const bd = srcBuffer._bitDecoder;
|
|
2306
|
-
const
|
|
2681
|
+
const buf = bd._bitBuffer;
|
|
2682
|
+
const byteLength = bd._byteLength;
|
|
2683
|
+
let bitOffset = bd._bitOffset;
|
|
2307
2684
|
let valueId = 0;
|
|
2308
2685
|
for (let i = 0; i < numValues; i += numComponents) {
|
|
2309
2686
|
const bitLength = tagAns.ransRead();
|
|
2310
|
-
|
|
2311
|
-
const
|
|
2312
|
-
|
|
2313
|
-
|
|
2687
|
+
if (bitLength < 32) {
|
|
2688
|
+
const mask = (1 << bitLength) - 1;
|
|
2689
|
+
let j = 0;
|
|
2690
|
+
for (; j < numComponents; ++j) {
|
|
2691
|
+
const byteOffset = bitOffset >> 3;
|
|
2692
|
+
if (byteOffset + 4 >= byteLength) break;
|
|
2693
|
+
const bitShift = bitOffset & 7;
|
|
2694
|
+
let value = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> bitShift;
|
|
2695
|
+
if (bitLength > 32 - bitShift) {
|
|
2696
|
+
value = (value | buf[byteOffset + 4] << 32 - bitShift) >>> 0;
|
|
2697
|
+
}
|
|
2698
|
+
bitOffset += bitLength;
|
|
2699
|
+
outValues[valueId++] = value & mask;
|
|
2700
|
+
}
|
|
2701
|
+
if (j === numComponents) continue;
|
|
2702
|
+
bd._bitOffset = bitOffset;
|
|
2703
|
+
for (; j < numComponents; ++j) {
|
|
2704
|
+
const val = bd.getBits(bitLength);
|
|
2705
|
+
if (val === void 0) {
|
|
2706
|
+
return false;
|
|
2707
|
+
}
|
|
2708
|
+
outValues[valueId++] = val;
|
|
2709
|
+
}
|
|
2710
|
+
bitOffset = bd._bitOffset;
|
|
2711
|
+
} else {
|
|
2712
|
+
bd._bitOffset = bitOffset;
|
|
2713
|
+
for (let j = 0; j < numComponents; ++j) {
|
|
2714
|
+
const val = bd.getBits(bitLength);
|
|
2715
|
+
if (val === void 0) {
|
|
2716
|
+
return false;
|
|
2717
|
+
}
|
|
2718
|
+
outValues[valueId++] = val;
|
|
2314
2719
|
}
|
|
2315
|
-
|
|
2720
|
+
bitOffset = bd._bitOffset;
|
|
2316
2721
|
}
|
|
2317
2722
|
}
|
|
2723
|
+
bd._bitOffset = bitOffset;
|
|
2318
2724
|
tagDecoder.endDecoding();
|
|
2319
2725
|
srcBuffer.endBitDecoding();
|
|
2320
2726
|
return true;
|
|
2321
2727
|
}
|
|
2728
|
+
function parseRawSymbolStream(numValues, srcBuffer) {
|
|
2729
|
+
const maxBitLength = srcBuffer.decodeUint8();
|
|
2730
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
2731
|
+
return null;
|
|
2732
|
+
}
|
|
2733
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
2734
|
+
if (!decoder.create(srcBuffer)) {
|
|
2735
|
+
return null;
|
|
2736
|
+
}
|
|
2737
|
+
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
2738
|
+
return null;
|
|
2739
|
+
}
|
|
2740
|
+
if (!decoder.startDecoding(srcBuffer)) {
|
|
2741
|
+
return null;
|
|
2742
|
+
}
|
|
2743
|
+
return decoder;
|
|
2744
|
+
}
|
|
2322
2745
|
function decodeRawSymbolsInternal(uniqueSymbolsBitLength, numValues, srcBuffer, outValues) {
|
|
2323
2746
|
const decoder = new RAnsSymbolDecoder(uniqueSymbolsBitLength);
|
|
2324
2747
|
if (!decoder.create(srcBuffer)) {
|
|
@@ -2421,6 +2844,16 @@ var PredictionSchemeDecoderInterface = class {
|
|
|
2421
2844
|
decodePredictionData(_buffer) {
|
|
2422
2845
|
return true;
|
|
2423
2846
|
}
|
|
2847
|
+
/**
|
|
2848
|
+
* Like computeOriginalValues, but inCorr still holds unsigned zigzag-coded
|
|
2849
|
+
* corrections; the implementation unpacks each one inline, replacing the
|
|
2850
|
+
* standalone convertSymbolsToSignedInts pass. Returns undefined when the
|
|
2851
|
+
* scheme/transform combination cannot fuse (the caller then falls back to
|
|
2852
|
+
* the two-pass path). Base implementation: never fusable.
|
|
2853
|
+
*/
|
|
2854
|
+
computeOriginalValuesZigzag(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2855
|
+
return void 0;
|
|
2856
|
+
}
|
|
2424
2857
|
/** Reverts the prediction applied during encoding, writing original values to outData. */
|
|
2425
2858
|
computeOriginalValues(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2426
2859
|
return false;
|
|
@@ -2756,7 +3189,7 @@ var OctahedronToolBox = class {
|
|
|
2756
3189
|
// src/decoder/compression/attributes/prediction_schemes/MeshPredictionSchemeGeometricNormalPredictorArea.ts
|
|
2757
3190
|
var UPPER_BOUND = 1 << 29;
|
|
2758
3191
|
function buildInt32PositionCache(att, map, numEntries, tempPos) {
|
|
2759
|
-
const cache =
|
|
3192
|
+
const cache = scratchInt32(numEntries * 3);
|
|
2760
3193
|
const bufData = att.buffer && att.buffer.data;
|
|
2761
3194
|
if (att.dataType === DataType.INT32 && att.numComponents === 3 && bufData) {
|
|
2762
3195
|
const src = new Int32Array(bufData.buffer);
|
|
@@ -2837,7 +3270,7 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
|
|
|
2837
3270
|
const cornerToVertex = this._cornerToVertex;
|
|
2838
3271
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
2839
3272
|
const nc = cornerToVertex.length;
|
|
2840
|
-
const c2o =
|
|
3273
|
+
const c2o = scratchInt32(nc);
|
|
2841
3274
|
for (let c = 0; c < nc; ++c) {
|
|
2842
3275
|
const v = cornerToVertex[c];
|
|
2843
3276
|
c2o[c] = v < 0 ? -1 : vertexToDataMap[v] * 3;
|
|
@@ -3088,10 +3521,21 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3088
3521
|
isInitialized() {
|
|
3089
3522
|
return this._meshData.isInitialized();
|
|
3090
3523
|
}
|
|
3524
|
+
// Zigzag-fused variant: decodes corrections that are still in their unsigned
|
|
3525
|
+
// zigzag form, unpacking each one inline. Only offered for the wrap
|
|
3526
|
+
// transform (whose corrections are the only zigzag-coded ones this scheme
|
|
3527
|
+
// sees); callers fall back to the standalone conversion pass otherwise.
|
|
3528
|
+
computeOriginalValuesZigzag(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
|
|
3529
|
+
this._transform.init(numComponents);
|
|
3530
|
+
if (!this._transform.getType || this._transform.getType() !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3531
|
+
return void 0;
|
|
3532
|
+
}
|
|
3533
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, true);
|
|
3534
|
+
}
|
|
3091
3535
|
computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
|
|
3092
3536
|
this._transform.init(numComponents);
|
|
3093
3537
|
if (this._transform.getType && this._transform.getType() === PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3094
|
-
return this._computeOriginalValuesWrap(inCorr, outData, numComponents);
|
|
3538
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, false);
|
|
3095
3539
|
}
|
|
3096
3540
|
const table = this._meshData.cornerTable;
|
|
3097
3541
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3132,12 +3576,18 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3132
3576
|
}
|
|
3133
3577
|
return true;
|
|
3134
3578
|
}
|
|
3135
|
-
|
|
3579
|
+
// The wrap transform's corrections are zigzag-coded; with `zigzag` set the
|
|
3580
|
+
// decode folds the (val >>> 1) ^ -(val & 1) unpacking into each correction
|
|
3581
|
+
// read, replacing the standalone convertSymbolsToSignedInts pass over the
|
|
3582
|
+
// whole array (see computeOriginalValuesZigzag). Every correction is read
|
|
3583
|
+
// exactly once before its slot is overwritten, so the in-place aliasing of
|
|
3584
|
+
// inCorr and outData is preserved.
|
|
3585
|
+
_computeOriginalValuesWrap(inCorr, outData, numComponents, zigzag) {
|
|
3136
3586
|
if (numComponents === 2) {
|
|
3137
|
-
return this._computeOriginalValuesWrap2(inCorr, outData);
|
|
3587
|
+
return this._computeOriginalValuesWrap2(inCorr, outData, zigzag);
|
|
3138
3588
|
}
|
|
3139
3589
|
if (numComponents === 3) {
|
|
3140
|
-
return this._computeOriginalValuesWrap3(inCorr, outData);
|
|
3590
|
+
return this._computeOriginalValuesWrap3(inCorr, outData, zigzag);
|
|
3141
3591
|
}
|
|
3142
3592
|
const table = this._meshData.cornerTable;
|
|
3143
3593
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3155,7 +3605,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3155
3605
|
} else if (pred < minValue) {
|
|
3156
3606
|
pred = minValue;
|
|
3157
3607
|
}
|
|
3158
|
-
|
|
3608
|
+
const raw = inCorr[c];
|
|
3609
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3159
3610
|
if (orig > maxValue) {
|
|
3160
3611
|
orig -= maxDif;
|
|
3161
3612
|
} else if (orig < minValue) {
|
|
@@ -3194,7 +3645,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3194
3645
|
} else if (pred < minValue) {
|
|
3195
3646
|
pred = minValue;
|
|
3196
3647
|
}
|
|
3197
|
-
|
|
3648
|
+
const raw = inCorr[dstOffset + c];
|
|
3649
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3198
3650
|
if (orig > maxValue) {
|
|
3199
3651
|
orig -= maxDif;
|
|
3200
3652
|
} else if (orig < minValue) {
|
|
@@ -3211,7 +3663,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3211
3663
|
} else if (pred < minValue) {
|
|
3212
3664
|
pred = minValue;
|
|
3213
3665
|
}
|
|
3214
|
-
|
|
3666
|
+
const raw = inCorr[dstOffset + c];
|
|
3667
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3215
3668
|
if (orig > maxValue) {
|
|
3216
3669
|
orig -= maxDif;
|
|
3217
3670
|
} else if (orig < minValue) {
|
|
@@ -3223,7 +3676,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3223
3676
|
}
|
|
3224
3677
|
return true;
|
|
3225
3678
|
}
|
|
3226
|
-
_computeOriginalValuesWrap2(inCorr, outData) {
|
|
3679
|
+
_computeOriginalValuesWrap2(inCorr, outData, zigzag) {
|
|
3227
3680
|
const table = this._meshData.cornerTable;
|
|
3228
3681
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3229
3682
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3245,8 +3698,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3245
3698
|
} else if (pred1 < minValue) {
|
|
3246
3699
|
pred1 = minValue;
|
|
3247
3700
|
}
|
|
3248
|
-
|
|
3249
|
-
|
|
3701
|
+
const raw0 = inCorr[0];
|
|
3702
|
+
const raw1 = inCorr[1];
|
|
3703
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3704
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3250
3705
|
if (orig0 > maxValue) {
|
|
3251
3706
|
orig0 -= maxDif;
|
|
3252
3707
|
} else if (orig0 < minValue) {
|
|
@@ -3300,8 +3755,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3300
3755
|
} else if (pred1 < minValue) {
|
|
3301
3756
|
pred1 = minValue;
|
|
3302
3757
|
}
|
|
3303
|
-
|
|
3304
|
-
|
|
3758
|
+
const rawA = inCorr[dstOffset];
|
|
3759
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3760
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3761
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3305
3762
|
if (orig0 > maxValue) {
|
|
3306
3763
|
orig0 -= maxDif;
|
|
3307
3764
|
} else if (orig0 < minValue) {
|
|
@@ -3317,7 +3774,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3317
3774
|
}
|
|
3318
3775
|
return true;
|
|
3319
3776
|
}
|
|
3320
|
-
_computeOriginalValuesWrap3(inCorr, outData) {
|
|
3777
|
+
_computeOriginalValuesWrap3(inCorr, outData, zigzag) {
|
|
3321
3778
|
const table = this._meshData.cornerTable;
|
|
3322
3779
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3323
3780
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3345,9 +3802,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3345
3802
|
} else if (pred2 < minValue) {
|
|
3346
3803
|
pred2 = minValue;
|
|
3347
3804
|
}
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3805
|
+
const raw0 = inCorr[0];
|
|
3806
|
+
const raw1 = inCorr[1];
|
|
3807
|
+
const raw2 = inCorr[2];
|
|
3808
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3809
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3810
|
+
let orig2 = pred2 + (zigzag ? raw2 >>> 1 ^ -(raw2 & 1) : raw2) | 0;
|
|
3351
3811
|
if (orig0 > maxValue) {
|
|
3352
3812
|
orig0 -= maxDif;
|
|
3353
3813
|
} else if (orig0 < minValue) {
|
|
@@ -3414,9 +3874,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3414
3874
|
} else if (pred2 < minValue) {
|
|
3415
3875
|
pred2 = minValue;
|
|
3416
3876
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3877
|
+
const rawA = inCorr[dstOffset];
|
|
3878
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3879
|
+
const rawC = inCorr[dstOffset + 2];
|
|
3880
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3881
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3882
|
+
orig2 = pred2 + (zigzag ? rawC >>> 1 ^ -(rawC & 1) : rawC) | 0;
|
|
3420
3883
|
if (orig0 > maxValue) {
|
|
3421
3884
|
orig0 -= maxDif;
|
|
3422
3885
|
} else if (orig0 < minValue) {
|
|
@@ -3923,14 +4386,49 @@ var PredictionSchemeWrapDecodingTransform = class {
|
|
|
3923
4386
|
// src/decoder/compression/attributes/SequentialIntegerAttributeDecoder.ts
|
|
3924
4387
|
var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder {
|
|
3925
4388
|
_predictionScheme;
|
|
4389
|
+
// Two-phase decode state (see SequentialAttributeDecoder): the parse phase
|
|
4390
|
+
// stashes the primed raw-symbol stream here so the controller can batch and
|
|
4391
|
+
// pair several attributes' decodes; the finish phase consumes it.
|
|
4392
|
+
_pendingSymbolDecoder;
|
|
4393
|
+
_pendingNumValues;
|
|
4394
|
+
_finishPointIds;
|
|
3926
4395
|
constructor() {
|
|
3927
4396
|
super();
|
|
3928
4397
|
this._predictionScheme = null;
|
|
4398
|
+
this._pendingSymbolDecoder = null;
|
|
4399
|
+
this._pendingNumValues = 0;
|
|
4400
|
+
this._finishPointIds = null;
|
|
3929
4401
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
4402
|
+
// --- Two-phase decode (parse headers / batch symbol decode / finish) ---
|
|
4403
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
4404
|
+
if (this.attribute.numComponents <= 0) {
|
|
4405
|
+
return false;
|
|
4406
|
+
}
|
|
4407
|
+
if (!this.attribute.reset(pointIds.length)) {
|
|
4408
|
+
return false;
|
|
4409
|
+
}
|
|
4410
|
+
this._finishPointIds = pointIds;
|
|
4411
|
+
return this._decodeValuesParse(pointIds, buffer);
|
|
3932
4412
|
}
|
|
3933
|
-
|
|
4413
|
+
pendingSymbolStream() {
|
|
4414
|
+
if (this._pendingSymbolDecoder === null) {
|
|
4415
|
+
return null;
|
|
4416
|
+
}
|
|
4417
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4418
|
+
return {
|
|
4419
|
+
ans: this._pendingSymbolDecoder.ans_,
|
|
4420
|
+
out: new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, this._pendingNumValues),
|
|
4421
|
+
count: this._pendingNumValues
|
|
4422
|
+
};
|
|
4423
|
+
}
|
|
4424
|
+
decodePortableAttributeFinish() {
|
|
4425
|
+
if (this._pendingSymbolDecoder !== null) {
|
|
4426
|
+
this._pendingSymbolDecoder.endDecoding();
|
|
4427
|
+
this._pendingSymbolDecoder = null;
|
|
4428
|
+
}
|
|
4429
|
+
return this._finishIntegerValues(this._finishPointIds);
|
|
4430
|
+
}
|
|
4431
|
+
_decodeValuesParse(pointIds, buffer) {
|
|
3934
4432
|
const predictionSchemeMethod = buffer.decodeInt8();
|
|
3935
4433
|
if (predictionSchemeMethod === void 0) return false;
|
|
3936
4434
|
if (predictionSchemeMethod < PredictionSchemeMethod.PREDICTION_NONE || predictionSchemeMethod >= PredictionSchemeMethod.NUM_PREDICTION_SCHEMES) {
|
|
@@ -3949,12 +4447,6 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3949
4447
|
return false;
|
|
3950
4448
|
}
|
|
3951
4449
|
}
|
|
3952
|
-
if (!this.decodeIntegerValues(pointIds, buffer)) {
|
|
3953
|
-
return false;
|
|
3954
|
-
}
|
|
3955
|
-
return true;
|
|
3956
|
-
}
|
|
3957
|
-
decodeIntegerValues(pointIds, buffer) {
|
|
3958
4450
|
const numComponents = this.getNumValueComponents();
|
|
3959
4451
|
if (numComponents <= 0) {
|
|
3960
4452
|
return false;
|
|
@@ -3969,9 +4461,23 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3969
4461
|
const compressed = buffer.decodeUint8();
|
|
3970
4462
|
if (compressed === void 0) return false;
|
|
3971
4463
|
if (compressed > 0) {
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
4464
|
+
if (numValues > 0) {
|
|
4465
|
+
const scheme = buffer.decodeUint8();
|
|
4466
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
4467
|
+
const decoder = parseRawSymbolStream(numValues, buffer);
|
|
4468
|
+
if (decoder === null) {
|
|
4469
|
+
return false;
|
|
4470
|
+
}
|
|
4471
|
+
this._pendingSymbolDecoder = decoder;
|
|
4472
|
+
this._pendingNumValues = numValues;
|
|
4473
|
+
} else if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
4474
|
+
const outUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4475
|
+
if (!decodeTaggedSymbols(numValues, numComponents, buffer, outUint32)) {
|
|
4476
|
+
return false;
|
|
4477
|
+
}
|
|
4478
|
+
} else {
|
|
4479
|
+
return false;
|
|
4480
|
+
}
|
|
3975
4481
|
}
|
|
3976
4482
|
} else {
|
|
3977
4483
|
const numBytes = buffer.decodeUint8();
|
|
@@ -4002,15 +4508,40 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4002
4508
|
}
|
|
4003
4509
|
}
|
|
4004
4510
|
}
|
|
4005
|
-
if (numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive())) {
|
|
4006
|
-
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4007
|
-
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4008
|
-
}
|
|
4009
4511
|
if (this._predictionScheme) {
|
|
4010
4512
|
if (!this._predictionScheme.decodePredictionData(buffer)) {
|
|
4011
4513
|
return false;
|
|
4012
4514
|
}
|
|
4515
|
+
}
|
|
4516
|
+
return true;
|
|
4517
|
+
}
|
|
4518
|
+
// The post-symbol tail of the decode: zigzag unpacking and prediction.
|
|
4519
|
+
_finishIntegerValues(pointIds) {
|
|
4520
|
+
const numComponents = this.getNumValueComponents();
|
|
4521
|
+
const numValues = pointIds.length * numComponents;
|
|
4522
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4523
|
+
if (portableAttributeData === null) {
|
|
4524
|
+
return false;
|
|
4525
|
+
}
|
|
4526
|
+
const needsZigzag = numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive());
|
|
4527
|
+
if (this._predictionScheme) {
|
|
4013
4528
|
if (numValues > 0) {
|
|
4529
|
+
if (needsZigzag) {
|
|
4530
|
+
const fused = this._predictionScheme.computeOriginalValuesZigzag(
|
|
4531
|
+
portableAttributeData,
|
|
4532
|
+
portableAttributeData,
|
|
4533
|
+
numValues,
|
|
4534
|
+
numComponents,
|
|
4535
|
+
pointIds
|
|
4536
|
+
);
|
|
4537
|
+
if (fused !== void 0) {
|
|
4538
|
+
return fused;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
if (needsZigzag) {
|
|
4542
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4543
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4544
|
+
}
|
|
4014
4545
|
if (!this._predictionScheme.computeOriginalValues(
|
|
4015
4546
|
portableAttributeData,
|
|
4016
4547
|
portableAttributeData,
|
|
@@ -4021,9 +4552,34 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4021
4552
|
return false;
|
|
4022
4553
|
}
|
|
4023
4554
|
}
|
|
4555
|
+
} else if (needsZigzag) {
|
|
4556
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4557
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4024
4558
|
}
|
|
4025
4559
|
return true;
|
|
4026
4560
|
}
|
|
4561
|
+
transformAttributeToOriginalFormat(pointIds) {
|
|
4562
|
+
return this._storeValues(pointIds.length);
|
|
4563
|
+
}
|
|
4564
|
+
// Single-phase entry (base-class decodePortableAttribute path): parse,
|
|
4565
|
+
// decode any deferred symbol stream immediately, finish.
|
|
4566
|
+
decodeValues(pointIds, buffer) {
|
|
4567
|
+
this._finishPointIds = pointIds;
|
|
4568
|
+
if (!this._decodeValuesParse(pointIds, buffer)) {
|
|
4569
|
+
return false;
|
|
4570
|
+
}
|
|
4571
|
+
const pending = this._pendingSymbolDecoder;
|
|
4572
|
+
if (pending !== null) {
|
|
4573
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4574
|
+
const outUint32 = new Uint32Array(
|
|
4575
|
+
portableAttributeData.buffer,
|
|
4576
|
+
portableAttributeData.byteOffset,
|
|
4577
|
+
this._pendingNumValues
|
|
4578
|
+
);
|
|
4579
|
+
pending.ans_.decodeSymbols(outUint32, this._pendingNumValues);
|
|
4580
|
+
}
|
|
4581
|
+
return this.decodePortableAttributeFinish();
|
|
4582
|
+
}
|
|
4027
4583
|
// Prediction scheme for decoding integer values; subclasses override for others.
|
|
4028
4584
|
createIntPredictionScheme(method, transformType) {
|
|
4029
4585
|
if (transformType !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
@@ -4086,7 +4642,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4086
4642
|
);
|
|
4087
4643
|
const portAtt = new PointAttribute(ga);
|
|
4088
4644
|
portAtt.setIdentityMapping();
|
|
4089
|
-
portAtt.
|
|
4645
|
+
portAtt.resetScratch(numEntries);
|
|
4090
4646
|
portAtt.uniqueId = this.attribute.uniqueId;
|
|
4091
4647
|
this.setPortableAttribute(portAtt);
|
|
4092
4648
|
}
|
|
@@ -4112,12 +4668,22 @@ var AttributeTransformType = {
|
|
|
4112
4668
|
};
|
|
4113
4669
|
|
|
4114
4670
|
// src/decoder/attributes/AttributeTransformData.ts
|
|
4671
|
+
var INITIAL_CAPACITY = 32;
|
|
4115
4672
|
var AttributeTransformData = class {
|
|
4116
4673
|
_transformType;
|
|
4117
|
-
|
|
4674
|
+
// Parameter bytes, little-endian, appended in transform-defined order.
|
|
4675
|
+
// Capacity grows geometrically and the DataView is cached alongside it: the
|
|
4676
|
+
// previous DataBuffer-backed version reallocated the buffer and built a
|
|
4677
|
+
// fresh DataView on *every* appended value, which on primitive-heavy files
|
|
4678
|
+
// cost more than the dequantization it describes.
|
|
4679
|
+
_bytes;
|
|
4680
|
+
_view;
|
|
4681
|
+
_size;
|
|
4118
4682
|
constructor() {
|
|
4119
4683
|
this._transformType = AttributeTransformType.INVALID;
|
|
4120
|
-
this.
|
|
4684
|
+
this._bytes = new Uint8Array(INITIAL_CAPACITY);
|
|
4685
|
+
this._view = new DataView(this._bytes.buffer);
|
|
4686
|
+
this._size = 0;
|
|
4121
4687
|
}
|
|
4122
4688
|
get transformType() {
|
|
4123
4689
|
return this._transformType;
|
|
@@ -4125,13 +4691,29 @@ var AttributeTransformData = class {
|
|
|
4125
4691
|
set transformType(type) {
|
|
4126
4692
|
this._transformType = type;
|
|
4127
4693
|
}
|
|
4694
|
+
// Number of parameter bytes written so far (the next append offset).
|
|
4695
|
+
get dataSize() {
|
|
4696
|
+
return this._size;
|
|
4697
|
+
}
|
|
4698
|
+
get data() {
|
|
4699
|
+
return this._bytes.subarray(0, this._size);
|
|
4700
|
+
}
|
|
4701
|
+
_reserve(sizeNeeded) {
|
|
4702
|
+
if (sizeNeeded <= this._bytes.length) return;
|
|
4703
|
+
let capacity = this._bytes.length * 2;
|
|
4704
|
+
if (capacity < sizeNeeded) capacity = sizeNeeded;
|
|
4705
|
+
const grown = new Uint8Array(capacity);
|
|
4706
|
+
grown.set(this._bytes);
|
|
4707
|
+
this._bytes = grown;
|
|
4708
|
+
this._view = new DataView(grown.buffer);
|
|
4709
|
+
}
|
|
4128
4710
|
setParameterValue(byteOffset, value, type) {
|
|
4129
4711
|
const sizeNeeded = byteOffset + this._typeSize(type);
|
|
4130
|
-
|
|
4131
|
-
|
|
4712
|
+
this._reserve(sizeNeeded);
|
|
4713
|
+
if (sizeNeeded > this._size) {
|
|
4714
|
+
this._size = sizeNeeded;
|
|
4132
4715
|
}
|
|
4133
|
-
const
|
|
4134
|
-
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
4716
|
+
const view = this._view;
|
|
4135
4717
|
switch (type) {
|
|
4136
4718
|
case "int32":
|
|
4137
4719
|
view.setInt32(byteOffset, value, true);
|
|
@@ -4163,7 +4745,7 @@ var AttributeTransformData = class {
|
|
|
4163
4745
|
}
|
|
4164
4746
|
}
|
|
4165
4747
|
appendParameterValue(value, type) {
|
|
4166
|
-
this.setParameterValue(this.
|
|
4748
|
+
this.setParameterValue(this._size, value, type);
|
|
4167
4749
|
}
|
|
4168
4750
|
_typeSize(type) {
|
|
4169
4751
|
switch (type) {
|
|
@@ -4733,6 +5315,12 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4733
5315
|
return true;
|
|
4734
5316
|
}
|
|
4735
5317
|
decodeAttributes(buffer) {
|
|
5318
|
+
if (!this._prepareSequence()) {
|
|
5319
|
+
return false;
|
|
5320
|
+
}
|
|
5321
|
+
return super.decodeAttributes(buffer);
|
|
5322
|
+
}
|
|
5323
|
+
_prepareSequence() {
|
|
4736
5324
|
if (!this._sequencer) {
|
|
4737
5325
|
return false;
|
|
4738
5326
|
}
|
|
@@ -4747,7 +5335,44 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4747
5335
|
return false;
|
|
4748
5336
|
}
|
|
4749
5337
|
}
|
|
4750
|
-
return
|
|
5338
|
+
return true;
|
|
5339
|
+
}
|
|
5340
|
+
// Two-phase decode (see AttributesDecoder): parse everything that reads the
|
|
5341
|
+
// buffer -- sequence, portable headers (deferring raw rANS symbol decodes),
|
|
5342
|
+
// and the transform parameters -- so the deferred streams of ALL attributes
|
|
5343
|
+
// decoders can then be paired, and finish (zigzag, prediction, inverse
|
|
5344
|
+
// transform) runs per decoder in the original order afterwards. None of the
|
|
5345
|
+
// finish work reads the buffer, and dependents only read parent portable
|
|
5346
|
+
// VALUES in finish, so ordering and output stay identical.
|
|
5347
|
+
decodeAttributesParse(buffer) {
|
|
5348
|
+
if (!this._prepareSequence()) {
|
|
5349
|
+
return false;
|
|
5350
|
+
}
|
|
5351
|
+
const numAttributes = this.getNumAttributes();
|
|
5352
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5353
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeParse(this._pointIds, buffer)) {
|
|
5354
|
+
return false;
|
|
5355
|
+
}
|
|
5356
|
+
}
|
|
5357
|
+
return this.decodeDataNeededByPortableTransforms(buffer);
|
|
5358
|
+
}
|
|
5359
|
+
collectPendingSymbolStreams(out) {
|
|
5360
|
+
const numAttributes = this.getNumAttributes();
|
|
5361
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5362
|
+
const pending = this._sequentialDecoders[i].pendingSymbolStream();
|
|
5363
|
+
if (pending !== null) {
|
|
5364
|
+
out.push(pending);
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
decodeAttributesFinish() {
|
|
5369
|
+
const numAttributes = this.getNumAttributes();
|
|
5370
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5371
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeFinish()) {
|
|
5372
|
+
return false;
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
return this.transformAttributesToOriginalFormat();
|
|
4751
5376
|
}
|
|
4752
5377
|
getPortableAttribute(pointAttributeId) {
|
|
4753
5378
|
const locId = this.getLocalIdForPointAttribute(pointAttributeId);
|
|
@@ -4874,14 +5499,13 @@ var DepthFirstTraverser = class {
|
|
|
4874
5499
|
// Scratch buffers are set up here rather than in init() so a shared-traversal
|
|
4875
5500
|
// -cache hit — where generateSequence returns before any traversal — skips
|
|
4876
5501
|
// this entirely, including the visited-flag zero-fill (worth ~0.5% on the
|
|
4877
|
-
//
|
|
5502
|
+
// ~500-primitive manablade bundle, which shares attribute corner tables across
|
|
4878
5503
|
// primitives). Uint8Array (0/1) instead of Array(bool): these flags are read
|
|
4879
5504
|
// and written on every corner of the hottest decode loop (traverseFromCorner).
|
|
4880
5505
|
// Decode-scoped scratch: released in bulk at the end of the decode.
|
|
4881
5506
|
onTraversalStart() {
|
|
4882
5507
|
const cornerTable = this._cornerTable;
|
|
4883
5508
|
this._isFaceVisited = scratchUint8Zeroed(cornerTable.numFaces());
|
|
4884
|
-
this._isVertexVisited = scratchUint8Zeroed(cornerTable.numVertices());
|
|
4885
5509
|
this._cornerTraversalStack = scratchInt32(this._numCorners);
|
|
4886
5510
|
}
|
|
4887
5511
|
onTraversalEnd() {
|
|
@@ -4891,7 +5515,6 @@ var DepthFirstTraverser = class {
|
|
|
4891
5515
|
return true;
|
|
4892
5516
|
}
|
|
4893
5517
|
const isFaceVisited = this._isFaceVisited;
|
|
4894
|
-
const isVertexVisited = this._isVertexVisited;
|
|
4895
5518
|
const observer = this._observer;
|
|
4896
5519
|
const cornerToVertex = this._cornerToVertex;
|
|
4897
5520
|
const oppositeCorners = this._oppositeCorners;
|
|
@@ -4915,14 +5538,12 @@ var DepthFirstTraverser = class {
|
|
|
4915
5538
|
if (nextVert === kInvalidVertexIndex2 || prevVert === kInvalidVertexIndex2) {
|
|
4916
5539
|
return false;
|
|
4917
5540
|
}
|
|
4918
|
-
if (
|
|
4919
|
-
isVertexVisited[nextVert] = 1;
|
|
5541
|
+
if (vertexToEncodedMap[nextVert] < 0) {
|
|
4920
5542
|
outPointIds[numOutPoints++] = obsFaces[nextCorner];
|
|
4921
5543
|
encodedToCornerMap[numValues] = nextCorner;
|
|
4922
5544
|
vertexToEncodedMap[nextVert] = numValues++;
|
|
4923
5545
|
}
|
|
4924
|
-
if (
|
|
4925
|
-
isVertexVisited[prevVert] = 1;
|
|
5546
|
+
if (vertexToEncodedMap[prevVert] < 0) {
|
|
4926
5547
|
outPointIds[numOutPoints++] = obsFaces[prevCorner];
|
|
4927
5548
|
encodedToCornerMap[numValues] = prevCorner;
|
|
4928
5549
|
vertexToEncodedMap[prevVert] = numValues++;
|
|
@@ -4943,27 +5564,26 @@ var DepthFirstTraverser = class {
|
|
|
4943
5564
|
encodingData.numValues = numValues;
|
|
4944
5565
|
return false;
|
|
4945
5566
|
}
|
|
4946
|
-
|
|
5567
|
+
const faceBase = faceId * 3;
|
|
5568
|
+
const nextCornerId = cornerId === faceBase + 2 ? faceBase : cornerId + 1;
|
|
5569
|
+
if (vertexToEncodedMap[vertId] < 0) {
|
|
4947
5570
|
const lc = vertexLeftmost[vertId];
|
|
4948
5571
|
let onBoundary = true;
|
|
4949
|
-
if (lc
|
|
5572
|
+
if (lc >= 0) {
|
|
4950
5573
|
const nextLc = lc % 3 === 2 ? lc - 2 : lc + 1;
|
|
4951
5574
|
onBoundary = oppositeCorners[nextLc] < 0;
|
|
4952
5575
|
}
|
|
4953
|
-
isVertexVisited[vertId] = 1;
|
|
4954
5576
|
outPointIds[numOutPoints++] = obsFaces[cornerId];
|
|
4955
5577
|
encodedToCornerMap[numValues] = cornerId;
|
|
4956
5578
|
vertexToEncodedMap[vertId] = numValues++;
|
|
4957
5579
|
if (!onBoundary) {
|
|
4958
|
-
|
|
4959
|
-
cornerId = oppositeCorners[nextCornerId2];
|
|
5580
|
+
cornerId = oppositeCorners[nextCornerId];
|
|
4960
5581
|
faceId = cornerId / 3 | 0;
|
|
4961
5582
|
continue;
|
|
4962
5583
|
}
|
|
4963
5584
|
}
|
|
4964
|
-
const nextCornerId = cornerId % 3 === 2 ? cornerId - 2 : cornerId + 1;
|
|
4965
5585
|
const rightCornerId = oppositeCorners[nextCornerId];
|
|
4966
|
-
const prevCornerId = cornerId
|
|
5586
|
+
const prevCornerId = cornerId === faceBase ? faceBase + 2 : cornerId - 1;
|
|
4967
5587
|
const leftCornerId = oppositeCorners[prevCornerId];
|
|
4968
5588
|
const rightFaceId = rightCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : rightCornerId / 3 | 0;
|
|
4969
5589
|
const leftFaceId = leftCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : leftCornerId / 3 | 0;
|
|
@@ -5193,6 +5813,9 @@ var MeshTraversalSequencer = class {
|
|
|
5193
5813
|
_outPointIds;
|
|
5194
5814
|
_numOutPoints;
|
|
5195
5815
|
_traversalCache;
|
|
5816
|
+
// The cache entry the last generateSequence resolved to (hit or store);
|
|
5817
|
+
// carries the shared indicesMap.
|
|
5818
|
+
_cacheEntry;
|
|
5196
5819
|
constructor(mesh, encodingData, traversalCache = null) {
|
|
5197
5820
|
this._mesh = mesh;
|
|
5198
5821
|
this._encodingData = encodingData;
|
|
@@ -5200,6 +5823,7 @@ var MeshTraversalSequencer = class {
|
|
|
5200
5823
|
this._outPointIds = new Int32Array(0);
|
|
5201
5824
|
this._numOutPoints = 0;
|
|
5202
5825
|
this._traversalCache = traversalCache;
|
|
5826
|
+
this._cacheEntry = null;
|
|
5203
5827
|
}
|
|
5204
5828
|
setTraverser(traverser) {
|
|
5205
5829
|
this._traverser = traverser;
|
|
@@ -5214,6 +5838,7 @@ var MeshTraversalSequencer = class {
|
|
|
5214
5838
|
if (cached !== void 0) {
|
|
5215
5839
|
this._outPointIds = cached.pointIds;
|
|
5216
5840
|
this._encodingData.adoptTraversalResult(cached.vertexMap, cached.cornerMap, cached.numValues);
|
|
5841
|
+
this._cacheEntry = cached;
|
|
5217
5842
|
return true;
|
|
5218
5843
|
}
|
|
5219
5844
|
}
|
|
@@ -5229,12 +5854,15 @@ var MeshTraversalSequencer = class {
|
|
|
5229
5854
|
byMethod = /* @__PURE__ */ new Map();
|
|
5230
5855
|
this._traversalCache.set(cacheKey, byMethod);
|
|
5231
5856
|
}
|
|
5232
|
-
|
|
5857
|
+
const entry = {
|
|
5233
5858
|
pointIds: this._outPointIds,
|
|
5234
5859
|
vertexMap: this._encodingData.vertexToEncodedAttributeValueIndexMap,
|
|
5235
5860
|
cornerMap: this._encodingData.encodedAttributeValueIndexToCornerMap,
|
|
5236
|
-
numValues: this._encodingData.numValues
|
|
5237
|
-
|
|
5861
|
+
numValues: this._encodingData.numValues,
|
|
5862
|
+
indicesMap: null
|
|
5863
|
+
};
|
|
5864
|
+
byMethod.set(methodId, entry);
|
|
5865
|
+
this._cacheEntry = entry;
|
|
5238
5866
|
}
|
|
5239
5867
|
return true;
|
|
5240
5868
|
}
|
|
@@ -5245,6 +5873,11 @@ var MeshTraversalSequencer = class {
|
|
|
5245
5873
|
this._outPointIds[this._numOutPoints++] = pointId;
|
|
5246
5874
|
}
|
|
5247
5875
|
updatePointToAttributeIndexMapping(attribute) {
|
|
5876
|
+
const entry = this._cacheEntry;
|
|
5877
|
+
if (entry !== null && entry.indicesMap !== null) {
|
|
5878
|
+
attribute.setExplicitMappingShared(entry.indicesMap);
|
|
5879
|
+
return true;
|
|
5880
|
+
}
|
|
5248
5881
|
const cornerTable = this._traverser.cornerTable();
|
|
5249
5882
|
const numFaces = this._mesh.numFaces();
|
|
5250
5883
|
const numPoints = this._mesh.numPoints();
|
|
@@ -5266,11 +5899,14 @@ var MeshTraversalSequencer = class {
|
|
|
5266
5899
|
}
|
|
5267
5900
|
indicesMap[pointId] = attEntryId;
|
|
5268
5901
|
}
|
|
5902
|
+
if (entry !== null) {
|
|
5903
|
+
entry.indicesMap = attribute.indicesMap;
|
|
5904
|
+
}
|
|
5269
5905
|
return true;
|
|
5270
5906
|
}
|
|
5271
5907
|
_generateSequenceInternal() {
|
|
5272
5908
|
this._numOutPoints = 0;
|
|
5273
|
-
this._outPointIds =
|
|
5909
|
+
this._outPointIds = scratchInt32(this._mesh.numPoints());
|
|
5274
5910
|
this._traverser.onTraversalStart();
|
|
5275
5911
|
const numFaces = this._traverser.cornerTable().numFaces();
|
|
5276
5912
|
for (let i = 0; i < numFaces && this._traverser._numVisitedFaces < numFaces; ++i) {
|
|
@@ -5461,14 +6097,14 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5461
6097
|
this._attributeData = [];
|
|
5462
6098
|
for (let i = 0; i < numAttributeData; ++i) {
|
|
5463
6099
|
const ad = new AttributeData();
|
|
5464
|
-
ad.attributeSeamCorners =
|
|
6100
|
+
ad.attributeSeamCorners = scratchInt32(numFaces * 3);
|
|
5465
6101
|
ad.numSeamCorners = 0;
|
|
5466
6102
|
this._attributeData.push(ad);
|
|
5467
6103
|
}
|
|
5468
6104
|
if (!this._cornerTable.reset(numFaces, this._numEncodedVertices + numEncodedSplitSymbols)) {
|
|
5469
6105
|
return false;
|
|
5470
6106
|
}
|
|
5471
|
-
this._isVertHole =
|
|
6107
|
+
this._isVertHole = scratchUint8Filled(this._numEncodedVertices + numEncodedSplitSymbols, 1);
|
|
5472
6108
|
if (this._decodeHoleAndTopologySplitEvents(this._decoder.buffer()) === -1) {
|
|
5473
6109
|
return false;
|
|
5474
6110
|
}
|
|
@@ -5493,20 +6129,37 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5493
6129
|
}
|
|
5494
6130
|
this._traversalDecoder.done();
|
|
5495
6131
|
let previousConnectivityData = null;
|
|
6132
|
+
let previousSeamCorners = null;
|
|
6133
|
+
let previousSeamCount = 0;
|
|
5496
6134
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
5497
6135
|
const connectivityData = this._attributeData[i].connectivityData;
|
|
5498
|
-
connectivityData.initEmpty(this._cornerTable);
|
|
5499
6136
|
const seamCorners = this._attributeData[i].attributeSeamCorners;
|
|
5500
6137
|
const seamCount = this._attributeData[i].numSeamCorners;
|
|
5501
|
-
|
|
5502
|
-
|
|
6138
|
+
let sameAsPrevious = previousConnectivityData !== null && seamCount === previousSeamCount;
|
|
6139
|
+
if (sameAsPrevious) {
|
|
6140
|
+
const previous = previousSeamCorners;
|
|
6141
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6142
|
+
if (seamCorners[s] !== previous[s]) {
|
|
6143
|
+
sameAsPrevious = false;
|
|
6144
|
+
break;
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
5503
6147
|
}
|
|
5504
|
-
if (
|
|
5505
|
-
connectivityData.
|
|
5506
|
-
} else
|
|
5507
|
-
|
|
6148
|
+
if (sameAsPrevious) {
|
|
6149
|
+
connectivityData.adoptFrom(previousConnectivityData);
|
|
6150
|
+
} else {
|
|
6151
|
+
connectivityData.initEmpty(this._cornerTable);
|
|
6152
|
+
connectivityData.reserveSeamEdges(seamCount);
|
|
6153
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6154
|
+
connectivityData.addSeamEdge(seamCorners[s]);
|
|
6155
|
+
}
|
|
6156
|
+
if (!connectivityData.recomputeVertices(null, null)) {
|
|
6157
|
+
return false;
|
|
6158
|
+
}
|
|
5508
6159
|
}
|
|
5509
6160
|
previousConnectivityData = connectivityData;
|
|
6161
|
+
previousSeamCorners = seamCorners;
|
|
6162
|
+
previousSeamCount = seamCount;
|
|
5510
6163
|
}
|
|
5511
6164
|
this._posEncodingData.init(this._cornerTable.numVertices());
|
|
5512
6165
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
@@ -5545,39 +6198,27 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5545
6198
|
const activeCornerStack = scratchInt32(numSymbols + this._topologySplitData.length + 16);
|
|
5546
6199
|
let activeCornerStackSize = 0;
|
|
5547
6200
|
const topologySplitActiveCorners = /* @__PURE__ */ new Map();
|
|
6201
|
+
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5548
6202
|
const invalidVertices = [];
|
|
5549
6203
|
const removeInvalidVertices = this._attributeData.length === 0;
|
|
5550
6204
|
let maxNumVertices = this._isVertHole.length;
|
|
5551
6205
|
let numFacesDecoded = 0;
|
|
5552
6206
|
const cornerToVertex = this._cornerTable._cornerToVertex;
|
|
5553
6207
|
const oppositeCorners = this._cornerTable._oppositeCorners;
|
|
5554
|
-
const numCorners = this._cornerTable.numCorners();
|
|
5555
|
-
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
5556
|
-
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
5557
|
-
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
5558
|
-
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
5559
|
-
const leftMostCorner = (v) => v < 0 || v >= this._cornerTable._vertexCorners.length ? -1 : this._cornerTable._vertexCorners[v];
|
|
5560
|
-
const swingLeft = (c) => {
|
|
5561
|
-
const n = next(c);
|
|
5562
|
-
const o = opposite(n);
|
|
5563
|
-
return o < 0 ? -1 : next(o);
|
|
5564
|
-
};
|
|
5565
|
-
const swingRight = (c) => {
|
|
5566
|
-
const p = prev(c);
|
|
5567
|
-
const o = opposite(p);
|
|
5568
|
-
return o < 0 ? -1 : prev(o);
|
|
5569
|
-
};
|
|
5570
6208
|
const vc = this._cornerTable;
|
|
6209
|
+
let vertexCorners = vc._vertexCorners;
|
|
6210
|
+
const isVertHole = this._isVertHole;
|
|
6211
|
+
const traversalDecoder = this._traversalDecoder;
|
|
5571
6212
|
for (let symbolId = 0; symbolId < numSymbols; ++symbolId) {
|
|
5572
6213
|
const faceIndex = numFacesDecoded++;
|
|
5573
6214
|
let checkTopologySplit = false;
|
|
5574
|
-
const symbol =
|
|
6215
|
+
const symbol = traversalDecoder.decodeSymbol();
|
|
5575
6216
|
if (symbol === TOPOLOGY_C) {
|
|
5576
6217
|
if (activeCornerStackSize === 0) return -1;
|
|
5577
6218
|
const cornerA = activeCornerStack[activeCornerStackSize - 1];
|
|
5578
6219
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5579
6220
|
const vertexX = cornerToVertex[nA];
|
|
5580
|
-
const lmcX =
|
|
6221
|
+
const lmcX = vertexCorners[vertexX];
|
|
5581
6222
|
const cornerB = lmcX % 3 === 2 ? lmcX - 2 : lmcX + 1;
|
|
5582
6223
|
if (cornerA === cornerB) return -1;
|
|
5583
6224
|
if (oppositeCorners[cornerA] !== kInvalidCornerIndex6 || oppositeCorners[cornerB] !== kInvalidCornerIndex6) {
|
|
@@ -5596,8 +6237,8 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5596
6237
|
cornerToVertex[corner] = vertexX;
|
|
5597
6238
|
cornerToVertex[corner + 1] = vertBNext;
|
|
5598
6239
|
cornerToVertex[corner + 2] = vertAPrev;
|
|
5599
|
-
|
|
5600
|
-
|
|
6240
|
+
vertexCorners[vertAPrev] = corner + 2;
|
|
6241
|
+
isVertHole[vertexX] = 0;
|
|
5601
6242
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5602
6243
|
} else if (symbol === TOPOLOGY_R || symbol === TOPOLOGY_L) {
|
|
5603
6244
|
if (activeCornerStackSize === 0) return -1;
|
|
@@ -5618,14 +6259,20 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5618
6259
|
}
|
|
5619
6260
|
oppositeCorners[oppCorner] = cornerA;
|
|
5620
6261
|
oppositeCorners[cornerA] = oppCorner;
|
|
5621
|
-
|
|
5622
|
-
if (
|
|
6262
|
+
let newVertIndex;
|
|
6263
|
+
if (vc._numVertices < vertexCorners.length) {
|
|
6264
|
+
newVertIndex = vc._numVertices++;
|
|
6265
|
+
} else {
|
|
6266
|
+
newVertIndex = vc.addNewVertex();
|
|
6267
|
+
vertexCorners = vc._vertexCorners;
|
|
6268
|
+
}
|
|
6269
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5623
6270
|
cornerToVertex[oppCorner] = newVertIndex;
|
|
5624
|
-
|
|
6271
|
+
vertexCorners[newVertIndex] = oppCorner;
|
|
5625
6272
|
const pA = cornerA % 3 === 0 ? cornerA + 2 : cornerA - 1;
|
|
5626
6273
|
const vertexR = cornerToVertex[pA];
|
|
5627
6274
|
cornerToVertex[cornerR] = vertexR;
|
|
5628
|
-
|
|
6275
|
+
vertexCorners[vertexR] = cornerR;
|
|
5629
6276
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5630
6277
|
cornerToVertex[cornerL] = cornerToVertex[nA];
|
|
5631
6278
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
@@ -5657,11 +6304,11 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5657
6304
|
const pB = cornerB % 3 === 0 ? cornerB + 2 : cornerB - 1;
|
|
5658
6305
|
const vertBPrev = cornerToVertex[pB];
|
|
5659
6306
|
cornerToVertex[corner + 2] = vertBPrev;
|
|
5660
|
-
|
|
6307
|
+
vertexCorners[vertBPrev] = corner + 2;
|
|
5661
6308
|
let cornerN = cornerB % 3 === 2 ? cornerB - 2 : cornerB + 1;
|
|
5662
6309
|
const vertexN = cornerToVertex[cornerN];
|
|
5663
|
-
|
|
5664
|
-
|
|
6310
|
+
traversalDecoder.mergeVertices(vertexP, vertexN);
|
|
6311
|
+
vertexCorners[vertexP] = vertexCorners[vertexN];
|
|
5665
6312
|
const firstCorner = cornerN;
|
|
5666
6313
|
while (cornerN !== kInvalidCornerIndex6) {
|
|
5667
6314
|
cornerToVertex[cornerN] = vertexP;
|
|
@@ -5672,32 +6319,38 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5672
6319
|
return -1;
|
|
5673
6320
|
}
|
|
5674
6321
|
}
|
|
5675
|
-
|
|
6322
|
+
vertexCorners[vertexN] = -1;
|
|
5676
6323
|
if (removeInvalidVertices) {
|
|
5677
6324
|
invalidVertices.push(vertexN);
|
|
5678
6325
|
}
|
|
5679
6326
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5680
6327
|
} else if (symbol === TOPOLOGY_E) {
|
|
5681
6328
|
const corner = 3 * faceIndex;
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
6329
|
+
let firstVertIndex;
|
|
6330
|
+
if (vc._numVertices + 3 <= vertexCorners.length) {
|
|
6331
|
+
firstVertIndex = vc._numVertices;
|
|
6332
|
+
vc._numVertices += 3;
|
|
6333
|
+
} else {
|
|
6334
|
+
firstVertIndex = vc.addNewVertex();
|
|
6335
|
+
vc.addNewVertex();
|
|
6336
|
+
vc.addNewVertex();
|
|
6337
|
+
vertexCorners = vc._vertexCorners;
|
|
6338
|
+
}
|
|
6339
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5686
6340
|
cornerToVertex[corner] = firstVertIndex;
|
|
5687
6341
|
cornerToVertex[corner + 1] = firstVertIndex + 1;
|
|
5688
6342
|
cornerToVertex[corner + 2] = firstVertIndex + 2;
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
6343
|
+
vertexCorners[firstVertIndex] = corner;
|
|
6344
|
+
vertexCorners[firstVertIndex + 1] = corner + 1;
|
|
6345
|
+
vertexCorners[firstVertIndex + 2] = corner + 2;
|
|
5692
6346
|
activeCornerStack[activeCornerStackSize++] = corner;
|
|
5693
6347
|
checkTopologySplit = true;
|
|
5694
6348
|
} else {
|
|
5695
6349
|
return -1;
|
|
5696
6350
|
}
|
|
5697
|
-
|
|
5698
|
-
if (checkTopologySplit) {
|
|
6351
|
+
traversalDecoder.newActiveCornerReached(activeCornerStack[activeCornerStackSize - 1]);
|
|
6352
|
+
if (checkTopologySplit && this._topologySplitData.length > 0) {
|
|
5699
6353
|
const encoderSymbolId = numSymbols - symbolId - 1;
|
|
5700
|
-
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5701
6354
|
while (this._isTopologySplit(encoderSymbolId, splitResult)) {
|
|
5702
6355
|
if (splitResult.encoderSplitSymbolId < 0) return -1;
|
|
5703
6356
|
const actTopCorner = activeCornerStack[activeCornerStackSize - 1];
|
|
@@ -5712,15 +6365,39 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5712
6365
|
}
|
|
5713
6366
|
}
|
|
5714
6367
|
}
|
|
5715
|
-
if (
|
|
6368
|
+
if (vc._numVertices > maxNumVertices) {
|
|
6369
|
+
return -1;
|
|
6370
|
+
}
|
|
6371
|
+
numFacesDecoded = this._decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded);
|
|
6372
|
+
if (numFacesDecoded === -1) {
|
|
6373
|
+
return -1;
|
|
6374
|
+
}
|
|
6375
|
+
if (numFacesDecoded !== this._cornerTable.numFaces()) {
|
|
5716
6376
|
return -1;
|
|
5717
6377
|
}
|
|
6378
|
+
return this._removeInvalidVertices(invalidVertices);
|
|
6379
|
+
}
|
|
6380
|
+
// Connects the remaining active-stack corners to newly decoded start faces.
|
|
6381
|
+
// Returns the updated decoded-face count, or -1 on malformed input.
|
|
6382
|
+
_decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
|
|
6383
|
+
const ct = this._cornerTable;
|
|
6384
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6385
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6386
|
+
const vertexCorners = ct._vertexCorners;
|
|
6387
|
+
const isVertHole = this._isVertHole;
|
|
6388
|
+
const traversalDecoder = this._traversalDecoder;
|
|
6389
|
+
const numCorners = ct.numCorners();
|
|
6390
|
+
const numFaces = ct.numFaces();
|
|
6391
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6392
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6393
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6394
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
5718
6395
|
while (activeCornerStackSize > 0) {
|
|
5719
6396
|
const corner = activeCornerStack[activeCornerStackSize - 1];
|
|
5720
6397
|
activeCornerStackSize--;
|
|
5721
|
-
const interiorFace =
|
|
6398
|
+
const interiorFace = traversalDecoder.decodeStartFaceConfiguration();
|
|
5722
6399
|
if (interiorFace) {
|
|
5723
|
-
if (numFacesDecoded >=
|
|
6400
|
+
if (numFacesDecoded >= numFaces) {
|
|
5724
6401
|
return -1;
|
|
5725
6402
|
}
|
|
5726
6403
|
const cornerA = corner;
|
|
@@ -5746,9 +6423,9 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5746
6423
|
cornerToVertex[newCorner] = vertX;
|
|
5747
6424
|
cornerToVertex[newCorner + 1] = vertP;
|
|
5748
6425
|
cornerToVertex[newCorner + 2] = vertN;
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
6426
|
+
isVertHole[vertX] = 0;
|
|
6427
|
+
isVertHole[vertP] = 0;
|
|
6428
|
+
isVertHole[vertN] = 0;
|
|
5752
6429
|
this._initFaceConfigurations.push(true);
|
|
5753
6430
|
this._initCorners.push(newCorner);
|
|
5754
6431
|
} else {
|
|
@@ -5756,10 +6433,34 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5756
6433
|
this._initCorners.push(corner);
|
|
5757
6434
|
}
|
|
5758
6435
|
}
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
6436
|
+
return numFacesDecoded;
|
|
6437
|
+
}
|
|
6438
|
+
// Removes invalid (isolated) vertices by swapping them with the last valid
|
|
6439
|
+
// vertex in the table, matching C++ mesh_edgebreaker_decoder_impl.cc (the
|
|
6440
|
+
// forward iteration order matters). Returns the final vertex count, or -1.
|
|
6441
|
+
_removeInvalidVertices(invalidVertices) {
|
|
6442
|
+
const ct = this._cornerTable;
|
|
6443
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6444
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6445
|
+
const vertexCorners = ct._vertexCorners;
|
|
6446
|
+
const isVertHole = this._isVertHole;
|
|
6447
|
+
const numCorners = ct.numCorners();
|
|
6448
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6449
|
+
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
6450
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6451
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6452
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
6453
|
+
const swingLeft = (c) => {
|
|
6454
|
+
const n = next(c);
|
|
6455
|
+
const o = opposite(n);
|
|
6456
|
+
return o < 0 ? -1 : next(o);
|
|
6457
|
+
};
|
|
6458
|
+
const swingRight = (c) => {
|
|
6459
|
+
const p = prev(c);
|
|
6460
|
+
const o = opposite(p);
|
|
6461
|
+
return o < 0 ? -1 : prev(o);
|
|
6462
|
+
};
|
|
6463
|
+
let numVertices = ct.numVertices();
|
|
5763
6464
|
for (let ivIdx = 0; ivIdx < invalidVertices.length; ++ivIdx) {
|
|
5764
6465
|
const invalidVert = invalidVertices[ivIdx];
|
|
5765
6466
|
let srcVert = numVertices - 1;
|
|
@@ -5789,10 +6490,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5789
6490
|
cid = swingRight(cid);
|
|
5790
6491
|
}
|
|
5791
6492
|
}
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
6493
|
+
vertexCorners[invalidVert] = leftMostCorner(srcVert);
|
|
6494
|
+
vertexCorners[srcVert] = -1;
|
|
6495
|
+
isVertHole[invalidVert] = isVertHole[srcVert];
|
|
6496
|
+
isVertHole[srcVert] = 0;
|
|
5796
6497
|
numVertices--;
|
|
5797
6498
|
}
|
|
5798
6499
|
return numVertices;
|
|
@@ -5835,14 +6536,55 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5835
6536
|
// per-corner decodeNextBit work. Within each face the three corners are
|
|
5836
6537
|
// visited in encoder edge order [base, next, prev] = [c, c+1, c+2] (the
|
|
5837
6538
|
// caller always starts a face at its base corner, so next/prev need no wrap).
|
|
6539
|
+
//
|
|
6540
|
+
// The face comparison the C++ makes -- floor(oppCorner/3) >= floor(cc/3) for
|
|
6541
|
+
// the face's base corner -- is just `oppCorner >= faceBaseCorner`, since the
|
|
6542
|
+
// base corner is a multiple of 3. That removes the per-corner division; the
|
|
6543
|
+
// invalid-corner case (-1) is still handled by the branch above it.
|
|
5838
6544
|
_decodeAttributeConnectivities() {
|
|
5839
6545
|
const oppositeCorners = this._cornerTable.oppositeCornerArray();
|
|
5840
6546
|
const attributeData = this._attributeData;
|
|
5841
6547
|
const numAttrData = attributeData.length;
|
|
5842
6548
|
const connectivityDecoders = this._traversalDecoder._attributeConnectivityDecoders;
|
|
5843
6549
|
const numCorners = this._cornerTable.numCorners();
|
|
6550
|
+
if (numAttrData === 1) {
|
|
6551
|
+
const ad = attributeData[0];
|
|
6552
|
+
const seamCorners = ad.attributeSeamCorners;
|
|
6553
|
+
let numSeamCorners = ad.numSeamCorners;
|
|
6554
|
+
const decoder = connectivityDecoders[0];
|
|
6555
|
+
const ans = decoder.ansDecoder_;
|
|
6556
|
+
const p = decoder.p_;
|
|
6557
|
+
const buf = ans.buf;
|
|
6558
|
+
const bufStart = ans.bufStart;
|
|
6559
|
+
let state = ans.state;
|
|
6560
|
+
let bufOffset = ans.bufOffset;
|
|
6561
|
+
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
6562
|
+
for (let k = 0; k < 3; ++k) {
|
|
6563
|
+
const cc = corner + k;
|
|
6564
|
+
const oppCorner = oppositeCorners[cc];
|
|
6565
|
+
if (oppCorner === kInvalidCornerIndex6) {
|
|
6566
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6567
|
+
} else if (oppCorner >= corner) {
|
|
6568
|
+
if (state < ANS_L_BASE && bufOffset > bufStart) {
|
|
6569
|
+
state = state << 8 | buf[--bufOffset];
|
|
6570
|
+
}
|
|
6571
|
+
const rem = state & 255;
|
|
6572
|
+
const xn = (state >>> 8) * p;
|
|
6573
|
+
if (rem < p) {
|
|
6574
|
+
state = xn + rem;
|
|
6575
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6576
|
+
} else {
|
|
6577
|
+
state = state - xn - p;
|
|
6578
|
+
}
|
|
6579
|
+
}
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
ans.state = state;
|
|
6583
|
+
ans.bufOffset = bufOffset;
|
|
6584
|
+
ad.numSeamCorners = numSeamCorners;
|
|
6585
|
+
return;
|
|
6586
|
+
}
|
|
5844
6587
|
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
5845
|
-
const srcFaceId = corner / 3 | 0;
|
|
5846
6588
|
for (let k = 0; k < 3; ++k) {
|
|
5847
6589
|
const cc = corner + k;
|
|
5848
6590
|
const oppCorner = oppositeCorners[cc];
|
|
@@ -5851,7 +6593,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5851
6593
|
const ad = attributeData[i];
|
|
5852
6594
|
ad.attributeSeamCorners[ad.numSeamCorners++] = cc;
|
|
5853
6595
|
}
|
|
5854
|
-
} else if (
|
|
6596
|
+
} else if (oppCorner >= corner) {
|
|
5855
6597
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5856
6598
|
if (connectivityDecoders[i].decodeNextBit()) {
|
|
5857
6599
|
const ad = attributeData[i];
|
|
@@ -5882,10 +6624,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5882
6624
|
const attributeData = this._attributeData;
|
|
5883
6625
|
const numAttrData = attributeData.length;
|
|
5884
6626
|
let numPoints = 0;
|
|
5885
|
-
const cornerToPointMap =
|
|
6627
|
+
const cornerToPointMap = scratchInt32(ct.numCorners());
|
|
5886
6628
|
const numVertices = ct.numVertices();
|
|
5887
6629
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
5888
|
-
const
|
|
6630
|
+
const swingRight = ct.swingRightArray();
|
|
5889
6631
|
const _baseCornerToVertex = ct.cornerToVertexArray();
|
|
5890
6632
|
const isVertHole = this._isVertHole;
|
|
5891
6633
|
const attCornerToVertex = new Array(numAttrData);
|
|
@@ -5899,7 +6641,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5899
6641
|
if (numAttrData === 1) {
|
|
5900
6642
|
anyAttVertexOnSeam = attVertexOnSeam[0];
|
|
5901
6643
|
} else {
|
|
5902
|
-
anyAttVertexOnSeam =
|
|
6644
|
+
anyAttVertexOnSeam = scratchUint8Zeroed(numVertices);
|
|
5903
6645
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5904
6646
|
const attSeam = attVertexOnSeam[i];
|
|
5905
6647
|
for (let v = 0; v < numVertices; ++v) {
|
|
@@ -5917,37 +6659,24 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5917
6659
|
const initialC = c;
|
|
5918
6660
|
const pointId = numPoints++;
|
|
5919
6661
|
cornerToPointMap[initialC] = pointId;
|
|
5920
|
-
|
|
5921
|
-
let pv = rem === 0 ? initialC + 2 : initialC - 1;
|
|
5922
|
-
let opp = baseOpp[pv];
|
|
5923
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6662
|
+
c = swingRight[initialC];
|
|
5924
6663
|
while (c !== kInvalidCornerIndex6 && c !== initialC) {
|
|
5925
6664
|
cornerToPointMap[c] = pointId;
|
|
5926
|
-
|
|
5927
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5928
|
-
opp = baseOpp[pv];
|
|
5929
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6665
|
+
c = swingRight[c];
|
|
5930
6666
|
}
|
|
5931
6667
|
} else {
|
|
5932
6668
|
let deduplicationFirstCorner = c;
|
|
5933
|
-
let rem, pv, opp;
|
|
5934
6669
|
if (!isVertHole[v]) {
|
|
5935
6670
|
if (numAttrData === 1) {
|
|
5936
6671
|
const vertId = singleAttC2V[c];
|
|
5937
|
-
|
|
5938
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5939
|
-
opp = baseOpp[pv];
|
|
5940
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6672
|
+
let actC = swingRight[c];
|
|
5941
6673
|
while (actC !== c) {
|
|
5942
6674
|
if (actC === kInvalidCornerIndex6) return false;
|
|
5943
6675
|
if (singleAttC2V[actC] !== vertId) {
|
|
5944
6676
|
deduplicationFirstCorner = actC;
|
|
5945
6677
|
break;
|
|
5946
6678
|
}
|
|
5947
|
-
|
|
5948
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5949
|
-
opp = baseOpp[pv];
|
|
5950
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6679
|
+
actC = swingRight[actC];
|
|
5951
6680
|
}
|
|
5952
6681
|
} else {
|
|
5953
6682
|
for (let i = 0; i < numAttrData; ++i) {
|
|
@@ -5956,10 +6685,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5956
6685
|
}
|
|
5957
6686
|
const attC2V = attCornerToVertex[i];
|
|
5958
6687
|
const vertId = attC2V[c];
|
|
5959
|
-
|
|
5960
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5961
|
-
opp = baseOpp[pv];
|
|
5962
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6688
|
+
let actC = swingRight[c];
|
|
5963
6689
|
let seamFound = false;
|
|
5964
6690
|
while (actC !== c) {
|
|
5965
6691
|
if (actC === kInvalidCornerIndex6) return false;
|
|
@@ -5968,10 +6694,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5968
6694
|
seamFound = true;
|
|
5969
6695
|
break;
|
|
5970
6696
|
}
|
|
5971
|
-
|
|
5972
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5973
|
-
opp = baseOpp[pv];
|
|
5974
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6697
|
+
actC = swingRight[actC];
|
|
5975
6698
|
}
|
|
5976
6699
|
if (seamFound) break;
|
|
5977
6700
|
}
|
|
@@ -5980,10 +6703,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5980
6703
|
c = deduplicationFirstCorner;
|
|
5981
6704
|
cornerToPointMap[c] = numPoints++;
|
|
5982
6705
|
let prevC = c;
|
|
5983
|
-
|
|
5984
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5985
|
-
opp = baseOpp[pv];
|
|
5986
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6706
|
+
c = swingRight[c];
|
|
5987
6707
|
while (c !== kInvalidCornerIndex6 && c !== deduplicationFirstCorner) {
|
|
5988
6708
|
let attributeSeam;
|
|
5989
6709
|
if (numAttrData === 1) {
|
|
@@ -6004,10 +6724,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
6004
6724
|
cornerToPointMap[c] = cornerToPointMap[prevC];
|
|
6005
6725
|
}
|
|
6006
6726
|
prevC = c;
|
|
6007
|
-
|
|
6008
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
6009
|
-
opp = baseOpp[pv];
|
|
6010
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6727
|
+
c = swingRight[c];
|
|
6011
6728
|
}
|
|
6012
6729
|
}
|
|
6013
6730
|
}
|
|
@@ -6033,8 +6750,8 @@ var MeshAttributeIndicesEncodingData = class {
|
|
|
6033
6750
|
this._numValues = 0;
|
|
6034
6751
|
}
|
|
6035
6752
|
init(numVertices) {
|
|
6036
|
-
this._vertexToEncodedAttributeValueIndexMap =
|
|
6037
|
-
this._encodedAttributeValueIndexToCornerMap =
|
|
6753
|
+
this._vertexToEncodedAttributeValueIndexMap = scratchInt32Filled(numVertices, -1);
|
|
6754
|
+
this._encodedAttributeValueIndexToCornerMap = scratchInt32(numVertices);
|
|
6038
6755
|
this._numValues = 0;
|
|
6039
6756
|
}
|
|
6040
6757
|
// Adopts a traversal result from an identical corner table, avoiding a
|
|
@@ -6084,6 +6801,8 @@ var CornerTable = class {
|
|
|
6084
6801
|
// corner -> opposite corner
|
|
6085
6802
|
_vertexCorners;
|
|
6086
6803
|
// vertex -> left-most corner
|
|
6804
|
+
_swingRight;
|
|
6805
|
+
// corner -> next corner around its vertex, CW
|
|
6087
6806
|
constructor() {
|
|
6088
6807
|
this._numFaces = 0;
|
|
6089
6808
|
this._numCorners = 0;
|
|
@@ -6091,16 +6810,42 @@ var CornerTable = class {
|
|
|
6091
6810
|
this._cornerToVertex = null;
|
|
6092
6811
|
this._oppositeCorners = null;
|
|
6093
6812
|
this._vertexCorners = null;
|
|
6813
|
+
this._swingRight = null;
|
|
6094
6814
|
}
|
|
6095
6815
|
reset(numFaces, numVertices) {
|
|
6096
6816
|
this._numFaces = numFaces;
|
|
6097
6817
|
this._numCorners = numFaces * 3;
|
|
6098
6818
|
this._numVertices = 0;
|
|
6099
|
-
this._cornerToVertex =
|
|
6100
|
-
this._oppositeCorners =
|
|
6101
|
-
this._vertexCorners =
|
|
6819
|
+
this._cornerToVertex = scratchInt32Filled(this._numCorners, -1);
|
|
6820
|
+
this._oppositeCorners = scratchInt32Filled(this._numCorners, -1);
|
|
6821
|
+
this._vertexCorners = scratchInt32Filled(numVertices, -1);
|
|
6822
|
+
this._swingRight = null;
|
|
6102
6823
|
return true;
|
|
6103
6824
|
}
|
|
6825
|
+
// swingRight(c) = previous(opposite(previous(c))) for every corner. Walking
|
|
6826
|
+
// the corner ring of a vertex is the inner loop of both the attribute-vertex
|
|
6827
|
+
// recompute and the point assignment, and each of those passes otherwise
|
|
6828
|
+
// pays two modulus-by-3 chains per step on top of the opposite lookup. Built
|
|
6829
|
+
// lazily -- callers only reach it once connectivity is final -- from
|
|
6830
|
+
// decode-scoped scratch, and dropped by reset().
|
|
6831
|
+
swingRightArray() {
|
|
6832
|
+
let table = this._swingRight;
|
|
6833
|
+
if (table === null) {
|
|
6834
|
+
const numCorners = this._numCorners;
|
|
6835
|
+
const opposite = this._oppositeCorners;
|
|
6836
|
+
table = scratchInt32(numCorners);
|
|
6837
|
+
for (let c = 0; c < numCorners; c += 3) {
|
|
6838
|
+
let o = opposite[c + 2];
|
|
6839
|
+
table[c] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6840
|
+
o = opposite[c];
|
|
6841
|
+
table[c + 1] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6842
|
+
o = opposite[c + 1];
|
|
6843
|
+
table[c + 2] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6844
|
+
}
|
|
6845
|
+
this._swingRight = table;
|
|
6846
|
+
}
|
|
6847
|
+
return table;
|
|
6848
|
+
}
|
|
6104
6849
|
numFaces() {
|
|
6105
6850
|
return this._numFaces;
|
|
6106
6851
|
}
|
|
@@ -6144,8 +6889,7 @@ var CornerTable = class {
|
|
|
6144
6889
|
this._numVertices++;
|
|
6145
6890
|
if (newVertex >= this._vertexCorners.length) {
|
|
6146
6891
|
const newCapacity = Math.max(newVertex + 1, this._vertexCorners.length * 2, 64);
|
|
6147
|
-
const newArr =
|
|
6148
|
-
newArr.fill(-1);
|
|
6892
|
+
const newArr = scratchInt32Filled(newCapacity, -1);
|
|
6149
6893
|
newArr.set(this._vertexCorners);
|
|
6150
6894
|
this._vertexCorners = newArr;
|
|
6151
6895
|
}
|
|
@@ -6176,6 +6920,10 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6176
6920
|
_attributeConnectivityDecoders;
|
|
6177
6921
|
_numAttributeData;
|
|
6178
6922
|
_decoderImpl;
|
|
6923
|
+
// _symbolBuffer's bit cursor, captured once bit decoding starts: decodeSymbol
|
|
6924
|
+
// runs per decoded face and would otherwise reach it through two property
|
|
6925
|
+
// loads and a method call per read.
|
|
6926
|
+
_symbolBits;
|
|
6179
6927
|
constructor() {
|
|
6180
6928
|
this._buffer = new DecoderBuffer();
|
|
6181
6929
|
this._symbolBuffer = new DecoderBuffer();
|
|
@@ -6183,6 +6931,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6183
6931
|
this._attributeConnectivityDecoders = null;
|
|
6184
6932
|
this._numAttributeData = 0;
|
|
6185
6933
|
this._decoderImpl = null;
|
|
6934
|
+
this._symbolBits = null;
|
|
6186
6935
|
}
|
|
6187
6936
|
init(decoder) {
|
|
6188
6937
|
this._decoderImpl = decoder;
|
|
@@ -6217,6 +6966,21 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6217
6966
|
return this._startFaceDecoder.decodeNextBit() ? true : false;
|
|
6218
6967
|
}
|
|
6219
6968
|
decodeSymbol() {
|
|
6969
|
+
const bd = this._symbolBits;
|
|
6970
|
+
if (bd !== null) {
|
|
6971
|
+
const buf = bd._bitBuffer;
|
|
6972
|
+
const off = bd._bitOffset;
|
|
6973
|
+
const byteOffset = off >> 3;
|
|
6974
|
+
if (byteOffset + 4 < bd._byteLength) {
|
|
6975
|
+
const bits = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> (off & 7) & 7;
|
|
6976
|
+
if ((bits & 1) === TOPOLOGY_C) {
|
|
6977
|
+
bd._bitOffset = off + 1;
|
|
6978
|
+
return TOPOLOGY_C;
|
|
6979
|
+
}
|
|
6980
|
+
bd._bitOffset = off + 3;
|
|
6981
|
+
return bits;
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6220
6984
|
let symbol = this._symbolBuffer.decodeLeastSignificantBits32(1);
|
|
6221
6985
|
if (symbol === TOPOLOGY_C) {
|
|
6222
6986
|
return symbol;
|
|
@@ -6246,6 +7010,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6246
7010
|
if (traversalSize === void 0) {
|
|
6247
7011
|
return false;
|
|
6248
7012
|
}
|
|
7013
|
+
this._symbolBits = this._symbolBuffer._bitDecoder;
|
|
6249
7014
|
this._buffer.init(
|
|
6250
7015
|
this._symbolBuffer.dataHead,
|
|
6251
7016
|
this._symbolBuffer.remainingSize,
|
|
@@ -6398,7 +7163,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6398
7163
|
_maxValence;
|
|
6399
7164
|
_vertexValences;
|
|
6400
7165
|
_contextSymbols;
|
|
7166
|
+
// Int32Array, not number[]: read and written once per decoded symbol.
|
|
6401
7167
|
_contextCounters;
|
|
7168
|
+
// corner -> vertex of _cornerTable, cached at init(); the array is created
|
|
7169
|
+
// once by CornerTable.reset() before the traversal decoder is initialized and
|
|
7170
|
+
// never replaced, so the per-symbol hot path can read it without two property
|
|
7171
|
+
// loads.
|
|
7172
|
+
_cornerToVertex;
|
|
6402
7173
|
constructor() {
|
|
6403
7174
|
super();
|
|
6404
7175
|
this._cornerTable = null;
|
|
@@ -6409,11 +7180,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6409
7180
|
this._maxValence = 7;
|
|
6410
7181
|
this._vertexValences = new Int32Array(0);
|
|
6411
7182
|
this._contextSymbols = [];
|
|
6412
|
-
this._contextCounters =
|
|
7183
|
+
this._contextCounters = new Int32Array(0);
|
|
7184
|
+
this._cornerToVertex = new Int32Array(0);
|
|
6413
7185
|
}
|
|
6414
7186
|
init(decoder) {
|
|
6415
7187
|
super.init(decoder);
|
|
6416
7188
|
this._cornerTable = decoder.getCornerTable();
|
|
7189
|
+
this._cornerToVertex = this._cornerTable._cornerToVertex;
|
|
6417
7190
|
}
|
|
6418
7191
|
setNumEncodedVertices(numVertices) {
|
|
6419
7192
|
this._numVertices = numVertices;
|
|
@@ -6431,10 +7204,11 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6431
7204
|
if (this._numVertices < 0) {
|
|
6432
7205
|
return false;
|
|
6433
7206
|
}
|
|
6434
|
-
this._vertexValences =
|
|
7207
|
+
this._vertexValences = scratchInt32Filled(this._numVertices, 0);
|
|
6435
7208
|
const numUniqueValences = this._maxValence - this._minValence + 1;
|
|
6436
7209
|
this._contextSymbols = new Array(numUniqueValences);
|
|
6437
|
-
this._contextCounters = new
|
|
7210
|
+
this._contextCounters = new Int32Array(numUniqueValences);
|
|
7211
|
+
const pending = [];
|
|
6438
7212
|
for (let i = 0; i < numUniqueValences; ++i) {
|
|
6439
7213
|
const numSymbols = decodeVarint(outBuffer);
|
|
6440
7214
|
if (numSymbols === void 0) {
|
|
@@ -6444,16 +7218,72 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6444
7218
|
return false;
|
|
6445
7219
|
}
|
|
6446
7220
|
if (numSymbols > 0) {
|
|
6447
|
-
this._contextSymbols[i] =
|
|
6448
|
-
|
|
7221
|
+
this._contextSymbols[i] = scratchUint32(numSymbols);
|
|
7222
|
+
const scheme = outBuffer.decodeUint8();
|
|
7223
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
7224
|
+
if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this._contextSymbols[i])) {
|
|
7225
|
+
return false;
|
|
7226
|
+
}
|
|
7227
|
+
this._contextCounters[i] = numSymbols;
|
|
7228
|
+
continue;
|
|
7229
|
+
}
|
|
7230
|
+
if (scheme !== SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
6449
7231
|
return false;
|
|
6450
7232
|
}
|
|
7233
|
+
const maxBitLength = outBuffer.decodeUint8();
|
|
7234
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
7235
|
+
return false;
|
|
7236
|
+
}
|
|
7237
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
7238
|
+
if (!decoder.create(outBuffer)) {
|
|
7239
|
+
return false;
|
|
7240
|
+
}
|
|
7241
|
+
if (decoder.numSymbols === 0) {
|
|
7242
|
+
return false;
|
|
7243
|
+
}
|
|
7244
|
+
if (!decoder.startDecoding(outBuffer)) {
|
|
7245
|
+
return false;
|
|
7246
|
+
}
|
|
7247
|
+
pending.push({ decoder, out: this._contextSymbols[i], count: numSymbols });
|
|
6451
7248
|
this._contextCounters[i] = numSymbols;
|
|
6452
7249
|
} else {
|
|
6453
7250
|
this._contextSymbols[i] = new Uint32Array(0);
|
|
6454
7251
|
this._contextCounters[i] = 0;
|
|
6455
7252
|
}
|
|
6456
7253
|
}
|
|
7254
|
+
const allU8 = pending.every((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
|
|
7255
|
+
let p = 0;
|
|
7256
|
+
if (allU8) {
|
|
7257
|
+
while (pending.length - p >= 3) {
|
|
7258
|
+
const a = pending[p];
|
|
7259
|
+
const b = pending[p + 1];
|
|
7260
|
+
const c = pending[p + 2];
|
|
7261
|
+
ransDecodeSymbolsTrioU8(
|
|
7262
|
+
a.decoder.ans_,
|
|
7263
|
+
a.out,
|
|
7264
|
+
a.count,
|
|
7265
|
+
b.decoder.ans_,
|
|
7266
|
+
b.out,
|
|
7267
|
+
b.count,
|
|
7268
|
+
c.decoder.ans_,
|
|
7269
|
+
c.out,
|
|
7270
|
+
c.count
|
|
7271
|
+
);
|
|
7272
|
+
p += 3;
|
|
7273
|
+
}
|
|
7274
|
+
if (pending.length - p === 2) {
|
|
7275
|
+
const a = pending[p];
|
|
7276
|
+
const b = pending[p + 1];
|
|
7277
|
+
ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
|
|
7278
|
+
p += 2;
|
|
7279
|
+
}
|
|
7280
|
+
}
|
|
7281
|
+
for (; p < pending.length; ++p) {
|
|
7282
|
+
pending[p].decoder.ans_.decodeSymbols(pending[p].out, pending[p].count);
|
|
7283
|
+
}
|
|
7284
|
+
for (const entry of pending) {
|
|
7285
|
+
entry.decoder.endDecoding();
|
|
7286
|
+
}
|
|
6457
7287
|
return true;
|
|
6458
7288
|
}
|
|
6459
7289
|
decodeSymbol() {
|
|
@@ -6473,7 +7303,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6473
7303
|
return this._lastSymbol;
|
|
6474
7304
|
}
|
|
6475
7305
|
newActiveCornerReached(corner) {
|
|
6476
|
-
const cornerToVertex = this.
|
|
7306
|
+
const cornerToVertex = this._cornerToVertex;
|
|
6477
7307
|
const valences = this._vertexValences;
|
|
6478
7308
|
const next = corner % 3 === 2 ? corner - 2 : corner + 1;
|
|
6479
7309
|
const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
|