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/index.js
CHANGED
|
@@ -259,6 +259,90 @@ var Mesh = class extends PointCloud {
|
|
|
259
259
|
}
|
|
260
260
|
};
|
|
261
261
|
|
|
262
|
+
// src/decoder/core/ScratchArena.ts
|
|
263
|
+
var MAX_CLASS = 28;
|
|
264
|
+
var freeInt32 = [];
|
|
265
|
+
var freeUint32 = [];
|
|
266
|
+
var freeUint8 = [];
|
|
267
|
+
for (let i = 0; i <= MAX_CLASS; ++i) {
|
|
268
|
+
freeInt32.push([]);
|
|
269
|
+
freeUint32.push([]);
|
|
270
|
+
freeUint8.push([]);
|
|
271
|
+
}
|
|
272
|
+
var borrowedInt32 = [];
|
|
273
|
+
var borrowedUint32 = [];
|
|
274
|
+
var borrowedUint8 = [];
|
|
275
|
+
var sizeClass = (size) => size <= 1 ? 0 : 32 - Math.clz32(size - 1);
|
|
276
|
+
var takeInt32 = (size) => {
|
|
277
|
+
const k = sizeClass(size);
|
|
278
|
+
if (k > MAX_CLASS) return new Int32Array(size);
|
|
279
|
+
const bucket = freeInt32[k];
|
|
280
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Int32Array(size);
|
|
281
|
+
if (pooled.length < size) pooled = new Int32Array(1 << k);
|
|
282
|
+
borrowedInt32.push(pooled);
|
|
283
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
284
|
+
};
|
|
285
|
+
var takeUint32 = (size) => {
|
|
286
|
+
const k = sizeClass(size);
|
|
287
|
+
if (k > MAX_CLASS) return new Uint32Array(size);
|
|
288
|
+
const bucket = freeUint32[k];
|
|
289
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint32Array(size);
|
|
290
|
+
if (pooled.length < size) pooled = new Uint32Array(1 << k);
|
|
291
|
+
borrowedUint32.push(pooled);
|
|
292
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
293
|
+
};
|
|
294
|
+
var byteCapacity = (size) => size < 8 ? 8 : size + 7 & ~7;
|
|
295
|
+
var takeUint8 = (size) => {
|
|
296
|
+
const capacity = byteCapacity(size);
|
|
297
|
+
const k = sizeClass(capacity);
|
|
298
|
+
if (k > MAX_CLASS) return new Uint8Array(capacity);
|
|
299
|
+
const bucket = freeUint8[k];
|
|
300
|
+
let pooled = bucket.length > 0 ? bucket.pop() : new Uint8Array(capacity);
|
|
301
|
+
if (pooled.length < size) pooled = new Uint8Array(1 << k);
|
|
302
|
+
borrowedUint8.push(pooled);
|
|
303
|
+
return pooled.length === size ? pooled : pooled.subarray(0, size);
|
|
304
|
+
};
|
|
305
|
+
var scratchInt32 = (size) => takeInt32(size);
|
|
306
|
+
var scratchInt32Filled = (size, value) => {
|
|
307
|
+
const view = takeInt32(size);
|
|
308
|
+
view.fill(value);
|
|
309
|
+
return view;
|
|
310
|
+
};
|
|
311
|
+
var scratchUint32 = (size) => takeUint32(size);
|
|
312
|
+
var scratchUint32Zeroed = (size) => {
|
|
313
|
+
const view = takeUint32(size);
|
|
314
|
+
view.fill(0);
|
|
315
|
+
return view;
|
|
316
|
+
};
|
|
317
|
+
var scratchUint8 = (size) => takeUint8(size);
|
|
318
|
+
var scratchUint8Zeroed = (size) => {
|
|
319
|
+
const view = takeUint8(size);
|
|
320
|
+
view.fill(0);
|
|
321
|
+
return view;
|
|
322
|
+
};
|
|
323
|
+
var scratchUint8Filled = (size, value) => {
|
|
324
|
+
const view = takeUint8(size);
|
|
325
|
+
view.fill(value);
|
|
326
|
+
return view;
|
|
327
|
+
};
|
|
328
|
+
var releaseScratch = () => {
|
|
329
|
+
for (let i = 0; i < borrowedInt32.length; ++i) {
|
|
330
|
+
const buffer = borrowedInt32[i];
|
|
331
|
+
freeInt32[sizeClass(buffer.length)].push(buffer);
|
|
332
|
+
}
|
|
333
|
+
for (let i = 0; i < borrowedUint32.length; ++i) {
|
|
334
|
+
const buffer = borrowedUint32[i];
|
|
335
|
+
freeUint32[sizeClass(buffer.length)].push(buffer);
|
|
336
|
+
}
|
|
337
|
+
for (let i = 0; i < borrowedUint8.length; ++i) {
|
|
338
|
+
const buffer = borrowedUint8[i];
|
|
339
|
+
freeUint8[sizeClass(buffer.length)].push(buffer);
|
|
340
|
+
}
|
|
341
|
+
borrowedInt32.length = 0;
|
|
342
|
+
borrowedUint32.length = 0;
|
|
343
|
+
borrowedUint8.length = 0;
|
|
344
|
+
};
|
|
345
|
+
|
|
262
346
|
// src/decoder/core/DataBuffer.ts
|
|
263
347
|
var DataBuffer = class {
|
|
264
348
|
_data;
|
|
@@ -283,6 +367,15 @@ var DataBuffer = class {
|
|
|
283
367
|
resize(newSize) {
|
|
284
368
|
this._resize(newSize);
|
|
285
369
|
}
|
|
370
|
+
// Replaces the contents with a decode-scoped scratch buffer of exactly
|
|
371
|
+
// `size` bytes; the previous contents are dropped and the new ones are
|
|
372
|
+
// arbitrary, so every byte must be written before it is read. Only for
|
|
373
|
+
// buffers that never outlive the decode (see ScratchArena) — the portable
|
|
374
|
+
// attributes the integer decoders build and discard per attribute are the
|
|
375
|
+
// one caller, and their per-primitive allocation showed up in profiles.
|
|
376
|
+
adoptScratch(size) {
|
|
377
|
+
this._data = scratchUint8(size);
|
|
378
|
+
}
|
|
286
379
|
write(bytePos, inArray, dataSize) {
|
|
287
380
|
if (inArray instanceof Uint8Array) {
|
|
288
381
|
this._data.set(inArray.length === dataSize ? inArray : inArray.subarray(0, dataSize), bytePos);
|
|
@@ -372,6 +465,19 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
372
465
|
this._numUniqueEntries = numAttributeValues;
|
|
373
466
|
return true;
|
|
374
467
|
}
|
|
468
|
+
// Like reset(), but backs the attribute with decode-scoped scratch memory.
|
|
469
|
+
// Only valid for attributes that never escape the decode and whose every
|
|
470
|
+
// byte is written before it is read (see DataBuffer.adoptScratch).
|
|
471
|
+
resetScratch(numAttributeValues) {
|
|
472
|
+
if (this._attributeBuffer === null) {
|
|
473
|
+
this._attributeBuffer = new DataBuffer();
|
|
474
|
+
}
|
|
475
|
+
const entrySize = dataTypeLength(this.dataType) * this.numComponents;
|
|
476
|
+
this._attributeBuffer.adoptScratch(numAttributeValues * entrySize);
|
|
477
|
+
this.resetBuffer(this._attributeBuffer, entrySize, 0);
|
|
478
|
+
this._numUniqueEntries = numAttributeValues;
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
375
481
|
get size() {
|
|
376
482
|
return this._numUniqueEntries;
|
|
377
483
|
}
|
|
@@ -414,6 +520,20 @@ var PointAttribute = class extends GeometryAttribute {
|
|
|
414
520
|
this._identityMapping = false;
|
|
415
521
|
this._indicesMap = new Uint32Array(numPoints);
|
|
416
522
|
}
|
|
523
|
+
// Adopts an already-computed map, shared with other attributes of the same
|
|
524
|
+
// mesh. The map must be treated as read-only from here on (reads go through
|
|
525
|
+
// mappedIndex/extractTo; copyFrom slices).
|
|
526
|
+
setExplicitMappingShared(map) {
|
|
527
|
+
this._identityMapping = false;
|
|
528
|
+
this._indicesMap = map;
|
|
529
|
+
}
|
|
530
|
+
// Like setExplicitMappingUnfilled, but from decode-scoped scratch. Only for
|
|
531
|
+
// attributes that never escape the decode (see ScratchArena) -- the portable
|
|
532
|
+
// attributes the sequential decoders build and discard.
|
|
533
|
+
setExplicitMappingScratch(numPoints) {
|
|
534
|
+
this._identityMapping = false;
|
|
535
|
+
this._indicesMap = scratchUint32(numPoints);
|
|
536
|
+
}
|
|
417
537
|
setAttributeTransformData(transformData) {
|
|
418
538
|
this._attributeTransformData = transformData;
|
|
419
539
|
}
|
|
@@ -909,48 +1029,6 @@ var DecoderBuffer = class {
|
|
|
909
1029
|
}
|
|
910
1030
|
};
|
|
911
1031
|
|
|
912
|
-
// src/decoder/core/ScratchArena.ts
|
|
913
|
-
var freeInt32 = [];
|
|
914
|
-
var freeUint8 = [];
|
|
915
|
-
var borrowedInt32 = [];
|
|
916
|
-
var borrowedUint8 = [];
|
|
917
|
-
var acquire = (free, borrowed, size) => {
|
|
918
|
-
for (let i = free.length - 1; i >= 0; --i) {
|
|
919
|
-
const buffer = free[i];
|
|
920
|
-
if (buffer.length >= size) {
|
|
921
|
-
free[i] = free[free.length - 1];
|
|
922
|
-
free.pop();
|
|
923
|
-
borrowed.push(buffer);
|
|
924
|
-
return buffer;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
return null;
|
|
928
|
-
};
|
|
929
|
-
var scratchInt32 = (size) => {
|
|
930
|
-
const pooled = acquire(freeInt32, borrowedInt32, size);
|
|
931
|
-
if (pooled !== null) return pooled.subarray(0, size);
|
|
932
|
-
const fresh = new Int32Array(size);
|
|
933
|
-
borrowedInt32.push(fresh);
|
|
934
|
-
return fresh;
|
|
935
|
-
};
|
|
936
|
-
var scratchUint8Zeroed = (size) => {
|
|
937
|
-
const pooled = acquire(freeUint8, borrowedUint8, size);
|
|
938
|
-
if (pooled !== null) {
|
|
939
|
-
const view = pooled.subarray(0, size);
|
|
940
|
-
view.fill(0);
|
|
941
|
-
return view;
|
|
942
|
-
}
|
|
943
|
-
const fresh = new Uint8Array(size);
|
|
944
|
-
borrowedUint8.push(fresh);
|
|
945
|
-
return fresh;
|
|
946
|
-
};
|
|
947
|
-
var releaseScratch = () => {
|
|
948
|
-
for (const buffer of borrowedInt32) freeInt32.push(buffer);
|
|
949
|
-
for (const buffer of borrowedUint8) freeUint8.push(buffer);
|
|
950
|
-
borrowedInt32.length = 0;
|
|
951
|
-
borrowedUint8.length = 0;
|
|
952
|
-
};
|
|
953
|
-
|
|
954
1032
|
// src/decoder/compression/config/CompressionShared.ts
|
|
955
1033
|
var kDracoPointCloudBitstreamVersionMajor = 2;
|
|
956
1034
|
var kDracoPointCloudBitstreamVersionMinor = 3;
|
|
@@ -1182,85 +1260,614 @@ var MetadataDecoder = class {
|
|
|
1182
1260
|
}
|
|
1183
1261
|
};
|
|
1184
1262
|
|
|
1185
|
-
// src/decoder/compression/
|
|
1186
|
-
var
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1263
|
+
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1264
|
+
var ANS_P8_PRECISION = 256;
|
|
1265
|
+
var ANS_L_BASE = 4096;
|
|
1266
|
+
var ANS_IO_BASE = 256;
|
|
1267
|
+
function memGetLe16(buf, offset) {
|
|
1268
|
+
return buf[offset] | buf[offset + 1] << 8;
|
|
1269
|
+
}
|
|
1270
|
+
function memGetLe24(buf, offset) {
|
|
1271
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1272
|
+
}
|
|
1273
|
+
function memGetLe32(buf, offset) {
|
|
1274
|
+
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1275
|
+
}
|
|
1276
|
+
var AnsDecoder = class {
|
|
1277
|
+
buf;
|
|
1278
|
+
bufOffset;
|
|
1279
|
+
// First valid byte of this decoder's slice within buf: init is passed
|
|
1280
|
+
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1281
|
+
bufStart;
|
|
1282
|
+
state;
|
|
1194
1283
|
constructor() {
|
|
1195
|
-
this.
|
|
1196
|
-
this.
|
|
1197
|
-
this.
|
|
1198
|
-
this.
|
|
1199
|
-
this._options = null;
|
|
1200
|
-
this._attributesDecoders = [];
|
|
1201
|
-
this._attributeToDecoderMap = [];
|
|
1284
|
+
this.buf = null;
|
|
1285
|
+
this.bufOffset = 0;
|
|
1286
|
+
this.bufStart = 0;
|
|
1287
|
+
this.state = 0;
|
|
1202
1288
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1289
|
+
};
|
|
1290
|
+
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1291
|
+
if (offset - base < 1) {
|
|
1292
|
+
return 1;
|
|
1205
1293
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
}
|
|
1216
|
-
const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
|
|
1217
|
-
if (magic !== "DRACO") {
|
|
1218
|
-
return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
|
|
1294
|
+
ans.buf = buf;
|
|
1295
|
+
ans.bufStart = base;
|
|
1296
|
+
const x = buf[offset - 1] >> 6;
|
|
1297
|
+
if (x === 0) {
|
|
1298
|
+
ans.bufOffset = offset - 1;
|
|
1299
|
+
ans.state = buf[offset - 1] & 63;
|
|
1300
|
+
} else if (x === 1) {
|
|
1301
|
+
if (offset - base < 2) {
|
|
1302
|
+
return 1;
|
|
1219
1303
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1304
|
+
ans.bufOffset = offset - 2;
|
|
1305
|
+
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1306
|
+
} else if (x === 2) {
|
|
1307
|
+
if (offset - base < 3) {
|
|
1308
|
+
return 1;
|
|
1223
1309
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1310
|
+
ans.bufOffset = offset - 3;
|
|
1311
|
+
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1312
|
+
} else {
|
|
1313
|
+
return 1;
|
|
1314
|
+
}
|
|
1315
|
+
ans.state += ANS_L_BASE;
|
|
1316
|
+
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1317
|
+
return 1;
|
|
1318
|
+
}
|
|
1319
|
+
return 0;
|
|
1320
|
+
}
|
|
1321
|
+
function ansReadEnd(ans) {
|
|
1322
|
+
return ans.state === ANS_L_BASE;
|
|
1323
|
+
}
|
|
1324
|
+
var tablePool = [];
|
|
1325
|
+
var acquirePooled = (Ctor, size) => {
|
|
1326
|
+
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1327
|
+
const buf = tablePool[i];
|
|
1328
|
+
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1329
|
+
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1330
|
+
tablePool.pop();
|
|
1331
|
+
return buf;
|
|
1228
1332
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1333
|
+
}
|
|
1334
|
+
return new Ctor(size);
|
|
1335
|
+
};
|
|
1336
|
+
var RAnsDecoder = class {
|
|
1337
|
+
ransPrecisionBits;
|
|
1338
|
+
ransPrecision;
|
|
1339
|
+
ransPrecisionMask;
|
|
1340
|
+
lRansBase;
|
|
1341
|
+
lutTable;
|
|
1342
|
+
probTable;
|
|
1343
|
+
cumProbTable;
|
|
1344
|
+
buf;
|
|
1345
|
+
bufOffset;
|
|
1346
|
+
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1347
|
+
// see AnsDecoder.bufStart).
|
|
1348
|
+
bufStart;
|
|
1349
|
+
state;
|
|
1350
|
+
constructor(ransPrecisionBits) {
|
|
1351
|
+
this.ransPrecisionBits = ransPrecisionBits;
|
|
1352
|
+
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1353
|
+
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1354
|
+
this.lRansBase = this.ransPrecision * 4;
|
|
1355
|
+
this.lutTable = null;
|
|
1356
|
+
this.probTable = null;
|
|
1357
|
+
this.cumProbTable = null;
|
|
1358
|
+
this.buf = null;
|
|
1359
|
+
this.bufOffset = 0;
|
|
1360
|
+
this.bufStart = 0;
|
|
1361
|
+
this.state = 0;
|
|
1362
|
+
}
|
|
1363
|
+
// offset is the absolute end of the encoded bytes within buf and base the
|
|
1364
|
+
// absolute start (offset - base = encoded length). Passing the source
|
|
1365
|
+
// buffer with absolute offsets avoids a subarray allocation per init.
|
|
1366
|
+
// Returns 0 on success, non-zero on error.
|
|
1367
|
+
readInit(buf, offset, base = 0) {
|
|
1368
|
+
if (offset - base < 1) {
|
|
1369
|
+
return 1;
|
|
1233
1370
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1371
|
+
this.buf = buf;
|
|
1372
|
+
this.bufStart = base;
|
|
1373
|
+
const x = buf[offset - 1] >> 6;
|
|
1374
|
+
if (x === 0) {
|
|
1375
|
+
this.bufOffset = offset - 1;
|
|
1376
|
+
this.state = buf[offset - 1] & 63;
|
|
1377
|
+
} else if (x === 1) {
|
|
1378
|
+
if (offset - base < 2) {
|
|
1379
|
+
return 1;
|
|
1380
|
+
}
|
|
1381
|
+
this.bufOffset = offset - 2;
|
|
1382
|
+
this.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1383
|
+
} else if (x === 2) {
|
|
1384
|
+
if (offset - base < 3) {
|
|
1385
|
+
return 1;
|
|
1386
|
+
}
|
|
1387
|
+
this.bufOffset = offset - 3;
|
|
1388
|
+
this.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1389
|
+
} else if (x === 3) {
|
|
1390
|
+
if (offset - base < 4) {
|
|
1391
|
+
return 1;
|
|
1392
|
+
}
|
|
1393
|
+
this.bufOffset = offset - 4;
|
|
1394
|
+
this.state = memGetLe32(buf, offset - 4) & 1073741823;
|
|
1395
|
+
} else {
|
|
1396
|
+
return 1;
|
|
1238
1397
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1398
|
+
this.state += this.lRansBase;
|
|
1399
|
+
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
1400
|
+
return 1;
|
|
1243
1401
|
}
|
|
1244
|
-
|
|
1245
|
-
return okStatus();
|
|
1402
|
+
return 0;
|
|
1246
1403
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
this._pointCloud = outPointCloud;
|
|
1252
|
-
const header = new DracoHeader();
|
|
1253
|
-
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1254
|
-
if (!headerStatus.ok()) {
|
|
1255
|
-
return headerStatus;
|
|
1404
|
+
readEnd() {
|
|
1405
|
+
if (this.lutTable !== null) {
|
|
1406
|
+
tablePool.push(this.lutTable);
|
|
1407
|
+
this.lutTable = null;
|
|
1256
1408
|
}
|
|
1257
|
-
if (
|
|
1258
|
-
|
|
1409
|
+
if (this.probTable !== null) {
|
|
1410
|
+
tablePool.push(this.probTable);
|
|
1411
|
+
this.probTable = null;
|
|
1259
1412
|
}
|
|
1260
|
-
this.
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1413
|
+
if (this.cumProbTable !== null) {
|
|
1414
|
+
tablePool.push(this.cumProbTable);
|
|
1415
|
+
this.cumProbTable = null;
|
|
1416
|
+
}
|
|
1417
|
+
return this.state === this.lRansBase;
|
|
1418
|
+
}
|
|
1419
|
+
ransRead() {
|
|
1420
|
+
const buf = this.buf;
|
|
1421
|
+
const lRansBase = this.lRansBase;
|
|
1422
|
+
let state = this.state;
|
|
1423
|
+
let bufOffset = this.bufOffset;
|
|
1424
|
+
const bufStart = this.bufStart;
|
|
1425
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1426
|
+
state = state << 8 | buf[--bufOffset];
|
|
1427
|
+
}
|
|
1428
|
+
const quo = state >>> this.ransPrecisionBits;
|
|
1429
|
+
const rem = state & this.ransPrecisionMask;
|
|
1430
|
+
const symbol = this.lutTable[rem];
|
|
1431
|
+
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
1432
|
+
this.bufOffset = bufOffset;
|
|
1433
|
+
return symbol;
|
|
1434
|
+
}
|
|
1435
|
+
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
1436
|
+
// written back once. Removes per-symbol property reads and call indirection.
|
|
1437
|
+
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
1438
|
+
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
1439
|
+
// once here so each loop body stays monomorphic on its concrete type. The
|
|
1440
|
+
// three bodies are intentionally identical copies.
|
|
1441
|
+
decodeSymbols(out, count) {
|
|
1442
|
+
const lutTable = this.lutTable;
|
|
1443
|
+
if (lutTable instanceof Uint8Array) {
|
|
1444
|
+
this._decodeSymbolsU8(out, count, lutTable);
|
|
1445
|
+
} else if (lutTable instanceof Uint16Array) {
|
|
1446
|
+
this._decodeSymbolsU16(out, count, lutTable);
|
|
1447
|
+
} else {
|
|
1448
|
+
this._decodeSymbolsU32(out, count, lutTable);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
_decodeSymbolsU8(out, count, lutTable) {
|
|
1452
|
+
const buf = this.buf;
|
|
1453
|
+
const lRansBase = this.lRansBase;
|
|
1454
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1455
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1456
|
+
const probTable = this.probTable;
|
|
1457
|
+
const cumProbTable = this.cumProbTable;
|
|
1458
|
+
let state = this.state;
|
|
1459
|
+
let bufOffset = this.bufOffset;
|
|
1460
|
+
const bufStart = this.bufStart;
|
|
1461
|
+
for (let i = 0; i < count; ++i) {
|
|
1462
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1463
|
+
state = state << 8 | buf[--bufOffset];
|
|
1464
|
+
}
|
|
1465
|
+
const rem = state & ransPrecisionMask;
|
|
1466
|
+
const symbol = lutTable[rem];
|
|
1467
|
+
out[i] = symbol;
|
|
1468
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1469
|
+
}
|
|
1470
|
+
this.state = state;
|
|
1471
|
+
this.bufOffset = bufOffset;
|
|
1472
|
+
}
|
|
1473
|
+
_decodeSymbolsU16(out, count, lutTable) {
|
|
1474
|
+
const buf = this.buf;
|
|
1475
|
+
const lRansBase = this.lRansBase;
|
|
1476
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1477
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1478
|
+
const probTable = this.probTable;
|
|
1479
|
+
const cumProbTable = this.cumProbTable;
|
|
1480
|
+
let state = this.state;
|
|
1481
|
+
let bufOffset = this.bufOffset;
|
|
1482
|
+
const bufStart = this.bufStart;
|
|
1483
|
+
for (let i = 0; i < count; ++i) {
|
|
1484
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1485
|
+
state = state << 8 | buf[--bufOffset];
|
|
1486
|
+
}
|
|
1487
|
+
const rem = state & ransPrecisionMask;
|
|
1488
|
+
const symbol = lutTable[rem];
|
|
1489
|
+
out[i] = symbol;
|
|
1490
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1491
|
+
}
|
|
1492
|
+
this.state = state;
|
|
1493
|
+
this.bufOffset = bufOffset;
|
|
1494
|
+
}
|
|
1495
|
+
_decodeSymbolsU32(out, count, lutTable) {
|
|
1496
|
+
const buf = this.buf;
|
|
1497
|
+
const lRansBase = this.lRansBase;
|
|
1498
|
+
const ransPrecisionBits = this.ransPrecisionBits;
|
|
1499
|
+
const ransPrecisionMask = this.ransPrecisionMask;
|
|
1500
|
+
const probTable = this.probTable;
|
|
1501
|
+
const cumProbTable = this.cumProbTable;
|
|
1502
|
+
let state = this.state;
|
|
1503
|
+
let bufOffset = this.bufOffset;
|
|
1504
|
+
const bufStart = this.bufStart;
|
|
1505
|
+
for (let i = 0; i < count; ++i) {
|
|
1506
|
+
while (state < lRansBase && bufOffset > bufStart) {
|
|
1507
|
+
state = state << 8 | buf[--bufOffset];
|
|
1508
|
+
}
|
|
1509
|
+
const rem = state & ransPrecisionMask;
|
|
1510
|
+
const symbol = lutTable[rem];
|
|
1511
|
+
out[i] = symbol;
|
|
1512
|
+
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
1513
|
+
}
|
|
1514
|
+
this.state = state;
|
|
1515
|
+
this.bufOffset = bufOffset;
|
|
1516
|
+
}
|
|
1517
|
+
// Builds the ransPrecision-entry lookup table. Returns false on bad input data.
|
|
1518
|
+
ransBuildLookUpTable(tokenProbs, numSymbols) {
|
|
1519
|
+
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
1520
|
+
const lutTable = acquirePooled(LutArray, this.ransPrecision);
|
|
1521
|
+
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
1522
|
+
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
1523
|
+
this.lutTable = lutTable;
|
|
1524
|
+
this.probTable = probTable;
|
|
1525
|
+
this.cumProbTable = cumProbTable;
|
|
1526
|
+
let cumProb = 0;
|
|
1527
|
+
let actProb = 0;
|
|
1528
|
+
for (let i = 0; i < numSymbols; ++i) {
|
|
1529
|
+
const prob = tokenProbs[i];
|
|
1530
|
+
probTable[i] = prob;
|
|
1531
|
+
cumProbTable[i] = cumProb;
|
|
1532
|
+
cumProb += prob;
|
|
1533
|
+
if (cumProb > this.ransPrecision) {
|
|
1534
|
+
return false;
|
|
1535
|
+
}
|
|
1536
|
+
if (prob < 32) {
|
|
1537
|
+
for (let j = actProb; j < cumProb; ++j) {
|
|
1538
|
+
lutTable[j] = i;
|
|
1539
|
+
}
|
|
1540
|
+
} else {
|
|
1541
|
+
lutTable.fill(i, actProb, cumProb);
|
|
1542
|
+
}
|
|
1543
|
+
actProb = cumProb;
|
|
1544
|
+
}
|
|
1545
|
+
if (cumProb !== this.ransPrecision) {
|
|
1546
|
+
return false;
|
|
1547
|
+
}
|
|
1548
|
+
return true;
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
function ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB) {
|
|
1552
|
+
const lutA = a.lutTable;
|
|
1553
|
+
const lutB = b.lutTable;
|
|
1554
|
+
const bufA = a.buf;
|
|
1555
|
+
const bufB = b.buf;
|
|
1556
|
+
const probA = a.probTable;
|
|
1557
|
+
const probB = b.probTable;
|
|
1558
|
+
const cumA = a.cumProbTable;
|
|
1559
|
+
const cumB = b.cumProbTable;
|
|
1560
|
+
const lBaseA = a.lRansBase;
|
|
1561
|
+
const lBaseB = b.lRansBase;
|
|
1562
|
+
const bitsA = a.ransPrecisionBits;
|
|
1563
|
+
const bitsB = b.ransPrecisionBits;
|
|
1564
|
+
const maskA = a.ransPrecisionMask;
|
|
1565
|
+
const maskB = b.ransPrecisionMask;
|
|
1566
|
+
const startA = a.bufStart;
|
|
1567
|
+
const startB = b.bufStart;
|
|
1568
|
+
let stateA = a.state;
|
|
1569
|
+
let stateB = b.state;
|
|
1570
|
+
let offA = a.bufOffset;
|
|
1571
|
+
let offB = b.bufOffset;
|
|
1572
|
+
const shared = countA < countB ? countA : countB;
|
|
1573
|
+
for (let i = 0; i < shared; ++i) {
|
|
1574
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1575
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1576
|
+
}
|
|
1577
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1578
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1579
|
+
}
|
|
1580
|
+
const remA = stateA & maskA;
|
|
1581
|
+
const remB = stateB & maskB;
|
|
1582
|
+
const symA = lutA[remA];
|
|
1583
|
+
const symB = lutB[remB];
|
|
1584
|
+
outA[i] = symA;
|
|
1585
|
+
outB[i] = symB;
|
|
1586
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1587
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1588
|
+
}
|
|
1589
|
+
a.state = stateA;
|
|
1590
|
+
a.bufOffset = offA;
|
|
1591
|
+
b.state = stateB;
|
|
1592
|
+
b.bufOffset = offB;
|
|
1593
|
+
if (shared < countA) {
|
|
1594
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1595
|
+
}
|
|
1596
|
+
if (shared < countB) {
|
|
1597
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
function ransDecodeSymbolsPair(a, outA, countA, b, outB, countB) {
|
|
1601
|
+
const lutA = a.lutTable;
|
|
1602
|
+
const lutB = b.lutTable;
|
|
1603
|
+
if (lutA instanceof Uint8Array && lutB instanceof Uint8Array) {
|
|
1604
|
+
ransDecodeSymbolsPairU8(a, outA, countA, b, outB, countB);
|
|
1605
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint16Array) {
|
|
1606
|
+
ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB);
|
|
1607
|
+
} else if (lutA instanceof Uint8Array && lutB instanceof Uint16Array) {
|
|
1608
|
+
ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB);
|
|
1609
|
+
} else if (lutA instanceof Uint16Array && lutB instanceof Uint8Array) {
|
|
1610
|
+
ransDecodeSymbolsPairU8U16(b, outB, countB, a, outA, countA);
|
|
1611
|
+
} else {
|
|
1612
|
+
a.decodeSymbols(outA, countA);
|
|
1613
|
+
b.decodeSymbols(outB, countB);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
function ransDecodeSymbolsPairU16(a, outA, countA, b, outB, countB) {
|
|
1617
|
+
const lutA = a.lutTable;
|
|
1618
|
+
const lutB = b.lutTable;
|
|
1619
|
+
const bufA = a.buf;
|
|
1620
|
+
const bufB = b.buf;
|
|
1621
|
+
const probA = a.probTable;
|
|
1622
|
+
const probB = b.probTable;
|
|
1623
|
+
const cumA = a.cumProbTable;
|
|
1624
|
+
const cumB = b.cumProbTable;
|
|
1625
|
+
const lBaseA = a.lRansBase;
|
|
1626
|
+
const lBaseB = b.lRansBase;
|
|
1627
|
+
const bitsA = a.ransPrecisionBits;
|
|
1628
|
+
const bitsB = b.ransPrecisionBits;
|
|
1629
|
+
const maskA = a.ransPrecisionMask;
|
|
1630
|
+
const maskB = b.ransPrecisionMask;
|
|
1631
|
+
const startA = a.bufStart;
|
|
1632
|
+
const startB = b.bufStart;
|
|
1633
|
+
let stateA = a.state;
|
|
1634
|
+
let stateB = b.state;
|
|
1635
|
+
let offA = a.bufOffset;
|
|
1636
|
+
let offB = b.bufOffset;
|
|
1637
|
+
const shared = countA < countB ? countA : countB;
|
|
1638
|
+
for (let i = 0; i < shared; ++i) {
|
|
1639
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1640
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1641
|
+
}
|
|
1642
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1643
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1644
|
+
}
|
|
1645
|
+
const remA = stateA & maskA;
|
|
1646
|
+
const remB = stateB & maskB;
|
|
1647
|
+
const symA = lutA[remA];
|
|
1648
|
+
const symB = lutB[remB];
|
|
1649
|
+
outA[i] = symA;
|
|
1650
|
+
outB[i] = symB;
|
|
1651
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1652
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1653
|
+
}
|
|
1654
|
+
a.state = stateA;
|
|
1655
|
+
a.bufOffset = offA;
|
|
1656
|
+
b.state = stateB;
|
|
1657
|
+
b.bufOffset = offB;
|
|
1658
|
+
if (shared < countA) {
|
|
1659
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1660
|
+
}
|
|
1661
|
+
if (shared < countB) {
|
|
1662
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
function ransDecodeSymbolsPairU8U16(a, outA, countA, b, outB, countB) {
|
|
1666
|
+
const lutA = a.lutTable;
|
|
1667
|
+
const lutB = b.lutTable;
|
|
1668
|
+
const bufA = a.buf;
|
|
1669
|
+
const bufB = b.buf;
|
|
1670
|
+
const probA = a.probTable;
|
|
1671
|
+
const probB = b.probTable;
|
|
1672
|
+
const cumA = a.cumProbTable;
|
|
1673
|
+
const cumB = b.cumProbTable;
|
|
1674
|
+
const lBaseA = a.lRansBase;
|
|
1675
|
+
const lBaseB = b.lRansBase;
|
|
1676
|
+
const bitsA = a.ransPrecisionBits;
|
|
1677
|
+
const bitsB = b.ransPrecisionBits;
|
|
1678
|
+
const maskA = a.ransPrecisionMask;
|
|
1679
|
+
const maskB = b.ransPrecisionMask;
|
|
1680
|
+
const startA = a.bufStart;
|
|
1681
|
+
const startB = b.bufStart;
|
|
1682
|
+
let stateA = a.state;
|
|
1683
|
+
let stateB = b.state;
|
|
1684
|
+
let offA = a.bufOffset;
|
|
1685
|
+
let offB = b.bufOffset;
|
|
1686
|
+
const shared = countA < countB ? countA : countB;
|
|
1687
|
+
for (let i = 0; i < shared; ++i) {
|
|
1688
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1689
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1690
|
+
}
|
|
1691
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1692
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1693
|
+
}
|
|
1694
|
+
const remA = stateA & maskA;
|
|
1695
|
+
const remB = stateB & maskB;
|
|
1696
|
+
const symA = lutA[remA];
|
|
1697
|
+
const symB = lutB[remB];
|
|
1698
|
+
outA[i] = symA;
|
|
1699
|
+
outB[i] = symB;
|
|
1700
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1701
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1702
|
+
}
|
|
1703
|
+
a.state = stateA;
|
|
1704
|
+
a.bufOffset = offA;
|
|
1705
|
+
b.state = stateB;
|
|
1706
|
+
b.bufOffset = offB;
|
|
1707
|
+
if (shared < countA) {
|
|
1708
|
+
a.decodeSymbols(outA.subarray(shared), countA - shared);
|
|
1709
|
+
}
|
|
1710
|
+
if (shared < countB) {
|
|
1711
|
+
b.decodeSymbols(outB.subarray(shared), countB - shared);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
function ransDecodeSymbolsTrioU8(a, outA, countA, b, outB, countB, c, outC, countC) {
|
|
1715
|
+
const lutA = a.lutTable;
|
|
1716
|
+
const lutB = b.lutTable;
|
|
1717
|
+
const lutC = c.lutTable;
|
|
1718
|
+
const bufA = a.buf;
|
|
1719
|
+
const bufB = b.buf;
|
|
1720
|
+
const bufC = c.buf;
|
|
1721
|
+
const probA = a.probTable;
|
|
1722
|
+
const probB = b.probTable;
|
|
1723
|
+
const probC = c.probTable;
|
|
1724
|
+
const cumA = a.cumProbTable;
|
|
1725
|
+
const cumB = b.cumProbTable;
|
|
1726
|
+
const cumC = c.cumProbTable;
|
|
1727
|
+
const lBaseA = a.lRansBase;
|
|
1728
|
+
const lBaseB = b.lRansBase;
|
|
1729
|
+
const lBaseC = c.lRansBase;
|
|
1730
|
+
const bitsA = a.ransPrecisionBits;
|
|
1731
|
+
const bitsB = b.ransPrecisionBits;
|
|
1732
|
+
const bitsC = c.ransPrecisionBits;
|
|
1733
|
+
const maskA = a.ransPrecisionMask;
|
|
1734
|
+
const maskB = b.ransPrecisionMask;
|
|
1735
|
+
const maskC = c.ransPrecisionMask;
|
|
1736
|
+
const startA = a.bufStart;
|
|
1737
|
+
const startB = b.bufStart;
|
|
1738
|
+
const startC = c.bufStart;
|
|
1739
|
+
let stateA = a.state;
|
|
1740
|
+
let stateB = b.state;
|
|
1741
|
+
let stateC = c.state;
|
|
1742
|
+
let offA = a.bufOffset;
|
|
1743
|
+
let offB = b.bufOffset;
|
|
1744
|
+
let offC = c.bufOffset;
|
|
1745
|
+
let shared = countA < countB ? countA : countB;
|
|
1746
|
+
if (countC < shared) shared = countC;
|
|
1747
|
+
for (let i = 0; i < shared; ++i) {
|
|
1748
|
+
while (stateA < lBaseA && offA > startA) {
|
|
1749
|
+
stateA = stateA << 8 | bufA[--offA];
|
|
1750
|
+
}
|
|
1751
|
+
while (stateB < lBaseB && offB > startB) {
|
|
1752
|
+
stateB = stateB << 8 | bufB[--offB];
|
|
1753
|
+
}
|
|
1754
|
+
while (stateC < lBaseC && offC > startC) {
|
|
1755
|
+
stateC = stateC << 8 | bufC[--offC];
|
|
1756
|
+
}
|
|
1757
|
+
const remA = stateA & maskA;
|
|
1758
|
+
const remB = stateB & maskB;
|
|
1759
|
+
const remC = stateC & maskC;
|
|
1760
|
+
const symA = lutA[remA];
|
|
1761
|
+
const symB = lutB[remB];
|
|
1762
|
+
const symC = lutC[remC];
|
|
1763
|
+
outA[i] = symA;
|
|
1764
|
+
outB[i] = symB;
|
|
1765
|
+
outC[i] = symC;
|
|
1766
|
+
stateA = (stateA >>> bitsA) * probA[symA] + remA - cumA[symA];
|
|
1767
|
+
stateB = (stateB >>> bitsB) * probB[symB] + remB - cumB[symB];
|
|
1768
|
+
stateC = (stateC >>> bitsC) * probC[symC] + remC - cumC[symC];
|
|
1769
|
+
}
|
|
1770
|
+
a.state = stateA;
|
|
1771
|
+
a.bufOffset = offA;
|
|
1772
|
+
b.state = stateB;
|
|
1773
|
+
b.bufOffset = offB;
|
|
1774
|
+
c.state = stateC;
|
|
1775
|
+
c.bufOffset = offC;
|
|
1776
|
+
const restA = countA - shared;
|
|
1777
|
+
const restB = countB - shared;
|
|
1778
|
+
const restC = countC - shared;
|
|
1779
|
+
const tails = [];
|
|
1780
|
+
if (restA > 0) tails.push([a, outA.subarray(shared), restA]);
|
|
1781
|
+
if (restB > 0) tails.push([b, outB.subarray(shared), restB]);
|
|
1782
|
+
if (restC > 0) tails.push([c, outC.subarray(shared), restC]);
|
|
1783
|
+
if (tails.length === 2) {
|
|
1784
|
+
ransDecodeSymbolsPairU8(tails[0][0], tails[0][1], tails[0][2], tails[1][0], tails[1][1], tails[1][2]);
|
|
1785
|
+
} else {
|
|
1786
|
+
for (const [decoder, out, count] of tails) {
|
|
1787
|
+
decoder.decodeSymbols(out, count);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
// src/decoder/compression/point_cloud/PointCloudDecoder.ts
|
|
1793
|
+
var PointCloudDecoder = class _PointCloudDecoder {
|
|
1794
|
+
_pointCloud;
|
|
1795
|
+
_buffer;
|
|
1796
|
+
_versionMajor;
|
|
1797
|
+
_versionMinor;
|
|
1798
|
+
_options;
|
|
1799
|
+
_attributesDecoders;
|
|
1800
|
+
_attributeToDecoderMap;
|
|
1801
|
+
constructor() {
|
|
1802
|
+
this._pointCloud = null;
|
|
1803
|
+
this._buffer = null;
|
|
1804
|
+
this._versionMajor = 0;
|
|
1805
|
+
this._versionMinor = 0;
|
|
1806
|
+
this._options = null;
|
|
1807
|
+
this._attributesDecoders = [];
|
|
1808
|
+
this._attributeToDecoderMap = [];
|
|
1809
|
+
}
|
|
1810
|
+
getGeometryType() {
|
|
1811
|
+
return EncodedGeometryType.POINT_CLOUD;
|
|
1812
|
+
}
|
|
1813
|
+
// Returns a Status; on success outHeader is populated.
|
|
1814
|
+
static decodeHeader(buffer, outHeader) {
|
|
1815
|
+
const kIoErrorMsg = "Failed to parse Draco header.";
|
|
1816
|
+
const bytes = buffer.decodeBytes(5);
|
|
1817
|
+
if (bytes === void 0) {
|
|
1818
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1819
|
+
}
|
|
1820
|
+
for (let i = 0; i < 5; i++) {
|
|
1821
|
+
outHeader.dracoString[i] = bytes[i];
|
|
1822
|
+
}
|
|
1823
|
+
const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
|
|
1824
|
+
if (magic !== "DRACO") {
|
|
1825
|
+
return new Status(StatusCode.DRACO_ERROR, "Not a Draco file.");
|
|
1826
|
+
}
|
|
1827
|
+
const versionMajor = buffer.decodeUint8();
|
|
1828
|
+
if (versionMajor === void 0) {
|
|
1829
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1830
|
+
}
|
|
1831
|
+
outHeader.versionMajor = versionMajor;
|
|
1832
|
+
const versionMinor = buffer.decodeUint8();
|
|
1833
|
+
if (versionMinor === void 0) {
|
|
1834
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1835
|
+
}
|
|
1836
|
+
outHeader.versionMinor = versionMinor;
|
|
1837
|
+
const encoderType = buffer.decodeUint8();
|
|
1838
|
+
if (encoderType === void 0) {
|
|
1839
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1840
|
+
}
|
|
1841
|
+
outHeader.encoderType = encoderType;
|
|
1842
|
+
const encoderMethod = buffer.decodeUint8();
|
|
1843
|
+
if (encoderMethod === void 0) {
|
|
1844
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1845
|
+
}
|
|
1846
|
+
outHeader.encoderMethod = encoderMethod;
|
|
1847
|
+
const flags = buffer.decodeUint16();
|
|
1848
|
+
if (flags === void 0) {
|
|
1849
|
+
return new Status(StatusCode.IO_ERROR, kIoErrorMsg);
|
|
1850
|
+
}
|
|
1851
|
+
outHeader.flags = flags;
|
|
1852
|
+
return okStatus();
|
|
1853
|
+
}
|
|
1854
|
+
// Main entry point for point cloud decoding.
|
|
1855
|
+
decode(options, inBuffer, outPointCloud) {
|
|
1856
|
+
this._options = options;
|
|
1857
|
+
this._buffer = inBuffer;
|
|
1858
|
+
this._pointCloud = outPointCloud;
|
|
1859
|
+
const header = new DracoHeader();
|
|
1860
|
+
const headerStatus = _PointCloudDecoder.decodeHeader(this._buffer, header);
|
|
1861
|
+
if (!headerStatus.ok()) {
|
|
1862
|
+
return headerStatus;
|
|
1863
|
+
}
|
|
1864
|
+
if (header.encoderType !== this.getGeometryType()) {
|
|
1865
|
+
return new Status(StatusCode.DRACO_ERROR, "Using incompatible decoder for the input geometry.");
|
|
1866
|
+
}
|
|
1867
|
+
this._versionMajor = header.versionMajor;
|
|
1868
|
+
this._versionMinor = header.versionMinor;
|
|
1869
|
+
const maxSupportedMajorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMajor : kDracoMeshBitstreamVersionMajor;
|
|
1870
|
+
const maxSupportedMinorVersion = header.encoderType === EncodedGeometryType.POINT_CLOUD ? kDracoPointCloudBitstreamVersionMinor : kDracoMeshBitstreamVersionMinor;
|
|
1264
1871
|
if (this._versionMajor < 1 || this._versionMajor > maxSupportedMajorVersion) {
|
|
1265
1872
|
return new Status(StatusCode.UNKNOWN_VERSION, "Unknown major version.");
|
|
1266
1873
|
}
|
|
@@ -1376,8 +1983,27 @@ var PointCloudDecoder = class _PointCloudDecoder {
|
|
|
1376
1983
|
return true;
|
|
1377
1984
|
}
|
|
1378
1985
|
decodeAllAttributes() {
|
|
1379
|
-
|
|
1380
|
-
|
|
1986
|
+
const decoders = this._attributesDecoders;
|
|
1987
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
1988
|
+
if (!decoders[i2].decodeAttributesParse(this._buffer)) {
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
const pending = [];
|
|
1993
|
+
for (let i2 = 0; i2 < decoders.length; i2++) {
|
|
1994
|
+
decoders[i2].collectPendingSymbolStreams(pending);
|
|
1995
|
+
}
|
|
1996
|
+
let i = 0;
|
|
1997
|
+
for (; i + 1 < pending.length; i += 2) {
|
|
1998
|
+
const a = pending[i];
|
|
1999
|
+
const b = pending[i + 1];
|
|
2000
|
+
ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
|
|
2001
|
+
}
|
|
2002
|
+
if (i < pending.length) {
|
|
2003
|
+
pending[i].ans.decodeSymbols(pending[i].out, pending[i].count);
|
|
2004
|
+
}
|
|
2005
|
+
for (let k = 0; k < decoders.length; k++) {
|
|
2006
|
+
if (!decoders[k].decodeAttributesFinish()) {
|
|
1381
2007
|
return false;
|
|
1382
2008
|
}
|
|
1383
2009
|
}
|
|
@@ -1445,46 +2071,62 @@ var MeshAttributeCornerTable = class {
|
|
|
1445
2071
|
no_interior_seams_;
|
|
1446
2072
|
corner_to_vertex_map_;
|
|
1447
2073
|
vertex_to_left_most_corner_map_;
|
|
1448
|
-
|
|
2074
|
+
// Attribute-vertex count. C++ keeps a vertex -> attribute-entry map here, but
|
|
2075
|
+
// the decoder only ever reads its size, so track the count directly instead
|
|
2076
|
+
// of allocating an Int32Array per attribute corner table.
|
|
2077
|
+
num_attribute_vertices_;
|
|
1449
2078
|
corner_table_;
|
|
1450
2079
|
// Lazily built; see oppositeCornerArray.
|
|
1451
2080
|
_effectiveOpposite;
|
|
1452
2081
|
// Every corner passed to addSeamEdge (may contain duplicates); lets
|
|
1453
2082
|
// oppositeCornerArray patch seams without scanning every corner's flag.
|
|
2083
|
+
// Preallocated to its exact upper bound (2 per seam edge) by the caller via
|
|
2084
|
+
// reserveSeamEdges -- a plain array grown by push() was measurable on
|
|
2085
|
+
// seam-heavy files.
|
|
1454
2086
|
_seamCorners;
|
|
2087
|
+
_numSeamCorners;
|
|
1455
2088
|
constructor() {
|
|
1456
2089
|
this.is_edge_on_seam_ = [];
|
|
1457
2090
|
this.is_vertex_on_seam_ = [];
|
|
1458
2091
|
this.no_interior_seams_ = true;
|
|
1459
2092
|
this.corner_to_vertex_map_ = [];
|
|
1460
2093
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1461
|
-
this.
|
|
2094
|
+
this.num_attribute_vertices_ = 0;
|
|
1462
2095
|
this.corner_table_ = null;
|
|
1463
2096
|
this._effectiveOpposite = null;
|
|
1464
2097
|
this._seamCorners = [];
|
|
2098
|
+
this._numSeamCorners = 0;
|
|
1465
2099
|
}
|
|
1466
2100
|
initEmpty(table) {
|
|
1467
2101
|
if (table === null) {
|
|
1468
2102
|
return false;
|
|
1469
2103
|
}
|
|
1470
|
-
this.is_edge_on_seam_ =
|
|
1471
|
-
this.is_vertex_on_seam_ =
|
|
1472
|
-
this.corner_to_vertex_map_ =
|
|
1473
|
-
this.
|
|
2104
|
+
this.is_edge_on_seam_ = scratchUint8Zeroed(table.numCorners());
|
|
2105
|
+
this.is_vertex_on_seam_ = scratchUint8Zeroed(table.numVertices());
|
|
2106
|
+
this.corner_to_vertex_map_ = scratchInt32Filled(table.numCorners(), kInvalidVertexIndex);
|
|
2107
|
+
this.num_attribute_vertices_ = 0;
|
|
1474
2108
|
this.vertex_to_left_most_corner_map_ = [];
|
|
1475
2109
|
this._effectiveOpposite = null;
|
|
1476
2110
|
this._seamCorners = [];
|
|
2111
|
+
this._numSeamCorners = 0;
|
|
1477
2112
|
this.corner_table_ = table;
|
|
1478
2113
|
this.no_interior_seams_ = true;
|
|
1479
2114
|
return true;
|
|
1480
2115
|
}
|
|
2116
|
+
// Sizes the seam-corner list for numSeamEdges upcoming addSeamEdge calls
|
|
2117
|
+
// (each adds at most two corners). Decode-scoped scratch.
|
|
2118
|
+
reserveSeamEdges(numSeamEdges) {
|
|
2119
|
+
this._seamCorners = scratchInt32(numSeamEdges * 2);
|
|
2120
|
+
this._numSeamCorners = 0;
|
|
2121
|
+
}
|
|
1481
2122
|
addSeamEdge(c) {
|
|
1482
2123
|
const cornerToVertex = this.corner_table_.cornerToVertexArray();
|
|
1483
2124
|
const oppositeCorners = this.corner_table_.oppositeCornerArray();
|
|
1484
2125
|
const isEdge = this.is_edge_on_seam_;
|
|
1485
2126
|
const isVert = this.is_vertex_on_seam_;
|
|
2127
|
+
const seamCorners = this._seamCorners;
|
|
1486
2128
|
isEdge[c] = 1;
|
|
1487
|
-
this.
|
|
2129
|
+
seamCorners[this._numSeamCorners++] = c;
|
|
1488
2130
|
let rem = c - (c / 3 | 0) * 3;
|
|
1489
2131
|
isVert[cornerToVertex[rem === 2 ? c - 2 : c + 1]] = 1;
|
|
1490
2132
|
isVert[cornerToVertex[rem === 0 ? c + 2 : c - 1]] = 1;
|
|
@@ -1492,7 +2134,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1492
2134
|
if (oppCorner !== kInvalidCornerIndex) {
|
|
1493
2135
|
this.no_interior_seams_ = false;
|
|
1494
2136
|
isEdge[oppCorner] = 1;
|
|
1495
|
-
this.
|
|
2137
|
+
seamCorners[this._numSeamCorners++] = oppCorner;
|
|
1496
2138
|
rem = oppCorner - (oppCorner / 3 | 0) * 3;
|
|
1497
2139
|
isVert[cornerToVertex[rem === 2 ? oppCorner - 2 : oppCorner + 1]] = 1;
|
|
1498
2140
|
isVert[cornerToVertex[rem === 0 ? oppCorner + 2 : oppCorner - 1]] = 1;
|
|
@@ -1507,12 +2149,12 @@ var MeshAttributeCornerTable = class {
|
|
|
1507
2149
|
const ct = this.corner_table_;
|
|
1508
2150
|
const numCorners = ct.numCorners();
|
|
1509
2151
|
const numBaseVertices = ct.numVertices();
|
|
1510
|
-
const leftMostMap =
|
|
2152
|
+
const leftMostMap = scratchInt32(numCorners);
|
|
1511
2153
|
const cornerToVertex = this.corner_to_vertex_map_;
|
|
1512
2154
|
const isVertexOnSeam = this.is_vertex_on_seam_;
|
|
1513
2155
|
const isEdgeOnSeam = this.is_edge_on_seam_;
|
|
1514
2156
|
const seamOpp = this.oppositeCornerArray();
|
|
1515
|
-
const
|
|
2157
|
+
const swingRight = ct.swingRightArray();
|
|
1516
2158
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
1517
2159
|
let numNewVertices = 0;
|
|
1518
2160
|
for (let v = 0; v < numBaseVertices; ++v) {
|
|
@@ -1522,14 +2164,10 @@ var MeshAttributeCornerTable = class {
|
|
|
1522
2164
|
const firstVertId = numNewVertices++;
|
|
1523
2165
|
leftMostMap[firstVertId] = c;
|
|
1524
2166
|
cornerToVertex[c] = firstVertId;
|
|
1525
|
-
let
|
|
1526
|
-
let bopp = baseOpp[pv];
|
|
1527
|
-
let actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2167
|
+
let actC = swingRight[c];
|
|
1528
2168
|
while (actC !== kInvalidCornerIndex && actC !== c) {
|
|
1529
2169
|
cornerToVertex[actC] = firstVertId;
|
|
1530
|
-
|
|
1531
|
-
bopp = baseOpp[pv];
|
|
1532
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2170
|
+
actC = swingRight[actC];
|
|
1533
2171
|
}
|
|
1534
2172
|
} else {
|
|
1535
2173
|
let firstVertId = numNewVertices++;
|
|
@@ -1547,9 +2185,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1547
2185
|
}
|
|
1548
2186
|
cornerToVertex[firstC] = firstVertId;
|
|
1549
2187
|
leftMostMap[firstVertId] = firstC;
|
|
1550
|
-
|
|
1551
|
-
let bopp = baseOpp[pv];
|
|
1552
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2188
|
+
actC = swingRight[firstC];
|
|
1553
2189
|
while (actC !== kInvalidCornerIndex && actC !== firstC) {
|
|
1554
2190
|
const nAct = actC % 3 === 2 ? actC - 2 : actC + 1;
|
|
1555
2191
|
if (isEdgeOnSeam[nAct]) {
|
|
@@ -1557,13 +2193,11 @@ var MeshAttributeCornerTable = class {
|
|
|
1557
2193
|
leftMostMap[firstVertId] = actC;
|
|
1558
2194
|
}
|
|
1559
2195
|
cornerToVertex[actC] = firstVertId;
|
|
1560
|
-
|
|
1561
|
-
bopp = baseOpp[pv];
|
|
1562
|
-
actC = bopp < 0 ? kInvalidCornerIndex : bopp % 3 === 0 ? bopp + 2 : bopp - 1;
|
|
2196
|
+
actC = swingRight[actC];
|
|
1563
2197
|
}
|
|
1564
2198
|
}
|
|
1565
2199
|
}
|
|
1566
|
-
this.
|
|
2200
|
+
this.num_attribute_vertices_ = numNewVertices;
|
|
1567
2201
|
this.vertex_to_left_most_corner_map_ = leftMostMap.subarray(0, numNewVertices);
|
|
1568
2202
|
return true;
|
|
1569
2203
|
}
|
|
@@ -1589,7 +2223,7 @@ var MeshAttributeCornerTable = class {
|
|
|
1589
2223
|
return this.next(this.opposite(this.next(corner)));
|
|
1590
2224
|
}
|
|
1591
2225
|
numVertices() {
|
|
1592
|
-
return this.
|
|
2226
|
+
return this.num_attribute_vertices_;
|
|
1593
2227
|
}
|
|
1594
2228
|
numFaces() {
|
|
1595
2229
|
return this.corner_table_.numFaces();
|
|
@@ -1617,12 +2251,13 @@ var MeshAttributeCornerTable = class {
|
|
|
1617
2251
|
const nc = this.corner_table_.numCorners();
|
|
1618
2252
|
const base = this.corner_table_.oppositeCornerArray();
|
|
1619
2253
|
const seamCorners = this._seamCorners;
|
|
1620
|
-
|
|
2254
|
+
const numSeamCorners = this._numSeamCorners;
|
|
2255
|
+
if (numSeamCorners === 0) {
|
|
1621
2256
|
this._effectiveOpposite = base;
|
|
1622
2257
|
} else {
|
|
1623
2258
|
const eff = scratchInt32(nc);
|
|
1624
2259
|
eff.set(base.length === nc ? base : base.subarray(0, nc));
|
|
1625
|
-
for (let i = 0
|
|
2260
|
+
for (let i = 0; i < numSeamCorners; ++i) {
|
|
1626
2261
|
eff[seamCorners[i]] = kInvalidCornerIndex;
|
|
1627
2262
|
}
|
|
1628
2263
|
this._effectiveOpposite = eff;
|
|
@@ -1637,23 +2272,20 @@ var MeshAttributeCornerTable = class {
|
|
|
1637
2272
|
vertexOnSeamArray() {
|
|
1638
2273
|
return this.is_vertex_on_seam_;
|
|
1639
2274
|
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1648
|
-
return true;
|
|
1649
|
-
}
|
|
1650
|
-
adoptVertexRecompute(other) {
|
|
2275
|
+
// Takes over another table's state wholesale. Only valid when both tables
|
|
2276
|
+
// were built from the same corner table and the same seam edges, in which
|
|
2277
|
+
// case every one of these is identical and read-only from here on.
|
|
2278
|
+
adoptFrom(other) {
|
|
2279
|
+
this.corner_table_ = other.corner_table_;
|
|
2280
|
+
this.is_edge_on_seam_ = other.is_edge_on_seam_;
|
|
2281
|
+
this.is_vertex_on_seam_ = other.is_vertex_on_seam_;
|
|
1651
2282
|
this.corner_to_vertex_map_ = other.corner_to_vertex_map_;
|
|
1652
|
-
this.
|
|
2283
|
+
this.num_attribute_vertices_ = other.num_attribute_vertices_;
|
|
1653
2284
|
this.vertex_to_left_most_corner_map_ = other.vertex_to_left_most_corner_map_;
|
|
1654
2285
|
this.no_interior_seams_ = other.no_interior_seams_;
|
|
1655
2286
|
this._effectiveOpposite = other._effectiveOpposite;
|
|
1656
2287
|
this._seamCorners = other._seamCorners;
|
|
2288
|
+
this._numSeamCorners = other._numSeamCorners;
|
|
1657
2289
|
}
|
|
1658
2290
|
};
|
|
1659
2291
|
|
|
@@ -1667,6 +2299,21 @@ var AttributesDecoderInterface = class {
|
|
|
1667
2299
|
decodeAttributesDecoderData(_buffer) {
|
|
1668
2300
|
return false;
|
|
1669
2301
|
}
|
|
2302
|
+
// --- Optional two-phase decode across attributes decoders ---
|
|
2303
|
+
// PointCloudDecoder parses every decoder first (all buffer reads are
|
|
2304
|
+
// size-driven, so parsing runs ahead of the deferred rANS symbol decodes),
|
|
2305
|
+
// then decodes the collected streams two at a time, then finishes each
|
|
2306
|
+
// decoder in order (so parent attributes complete before dependents).
|
|
2307
|
+
// Defaults keep the original single-phase behavior for decoders that do not
|
|
2308
|
+
// split.
|
|
2309
|
+
decodeAttributesParse(buffer) {
|
|
2310
|
+
return this.decodeAttributes(buffer);
|
|
2311
|
+
}
|
|
2312
|
+
collectPendingSymbolStreams(_out) {
|
|
2313
|
+
}
|
|
2314
|
+
decodeAttributesFinish() {
|
|
2315
|
+
return true;
|
|
2316
|
+
}
|
|
1670
2317
|
decodeAttributes(_buffer) {
|
|
1671
2318
|
return false;
|
|
1672
2319
|
}
|
|
@@ -1813,6 +2460,22 @@ var SequentialAttributeDecoder = class {
|
|
|
1813
2460
|
this._attributeId = attributeId;
|
|
1814
2461
|
return true;
|
|
1815
2462
|
}
|
|
2463
|
+
// --- Optional two-phase decode ---
|
|
2464
|
+
// The controller calls Parse for every attribute first (headers, schemes,
|
|
2465
|
+
// prediction data -- all size-driven cursor movement), collects the pending
|
|
2466
|
+
// rANS symbol streams, decodes them in pairs (see ransDecodeSymbolsPair),
|
|
2467
|
+
// then calls Finish per attribute in order. Decoders without a deferrable
|
|
2468
|
+
// stream simply do the whole decode in Parse. Defaults preserve the
|
|
2469
|
+
// original single-phase behavior.
|
|
2470
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
2471
|
+
return this.decodePortableAttribute(pointIds, buffer);
|
|
2472
|
+
}
|
|
2473
|
+
pendingSymbolStream() {
|
|
2474
|
+
return null;
|
|
2475
|
+
}
|
|
2476
|
+
decodePortableAttributeFinish() {
|
|
2477
|
+
return true;
|
|
2478
|
+
}
|
|
1816
2479
|
decodePortableAttribute(pointIds, buffer) {
|
|
1817
2480
|
if (this._attribute.numComponents <= 0) {
|
|
1818
2481
|
return false;
|
|
@@ -1833,7 +2496,7 @@ var SequentialAttributeDecoder = class {
|
|
|
1833
2496
|
getPortableAttribute() {
|
|
1834
2497
|
if (!this._attribute.isMappingIdentity && this._portableAttribute && this._portableAttribute.isMappingIdentity) {
|
|
1835
2498
|
const size = this._attribute.indicesMapSize;
|
|
1836
|
-
this._portableAttribute.
|
|
2499
|
+
this._portableAttribute.setExplicitMappingScratch(size);
|
|
1837
2500
|
const src = this._attribute.indicesMap;
|
|
1838
2501
|
const dst = this._portableAttribute.indicesMap;
|
|
1839
2502
|
if (src.length === size) {
|
|
@@ -1846,333 +2509,44 @@ var SequentialAttributeDecoder = class {
|
|
|
1846
2509
|
}
|
|
1847
2510
|
get attribute() {
|
|
1848
2511
|
return this._attribute;
|
|
1849
|
-
}
|
|
1850
|
-
get attributeId() {
|
|
1851
|
-
return this._attributeId;
|
|
1852
|
-
}
|
|
1853
|
-
get decoder() {
|
|
1854
|
-
return this._decoder;
|
|
1855
|
-
}
|
|
1856
|
-
initPredictionScheme(ps) {
|
|
1857
|
-
for (let i = 0; i < ps.getNumParentAttributes(); i++) {
|
|
1858
|
-
const attId = this._decoder.pointCloud().getNamedAttributeId(ps.getParentAttributeType(i));
|
|
1859
|
-
if (attId === -1) {
|
|
1860
|
-
return false;
|
|
1861
|
-
}
|
|
1862
|
-
const pa = this._decoder.getPortableAttribute(attId);
|
|
1863
|
-
if (pa === null || !ps.setParentAttribute(pa)) {
|
|
1864
|
-
return false;
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
return true;
|
|
1868
|
-
}
|
|
1869
|
-
// Decodes raw attribute values in their original format.
|
|
1870
|
-
decodeValues(pointIds, buffer) {
|
|
1871
|
-
const numValues = pointIds.length;
|
|
1872
|
-
const entrySize = this._attribute.byteStride;
|
|
1873
|
-
const totalSize = numValues * entrySize;
|
|
1874
|
-
const valueData = buffer.decodeBytesView(totalSize);
|
|
1875
|
-
if (valueData === void 0) {
|
|
1876
|
-
return false;
|
|
1877
|
-
}
|
|
1878
|
-
this._attribute.buffer.write(0, valueData, totalSize);
|
|
1879
|
-
return true;
|
|
1880
|
-
}
|
|
1881
|
-
setPortableAttribute(att) {
|
|
1882
|
-
this._portableAttribute = att;
|
|
1883
|
-
}
|
|
1884
|
-
get portableAttribute() {
|
|
1885
|
-
return this._portableAttribute;
|
|
1886
|
-
}
|
|
1887
|
-
};
|
|
1888
|
-
|
|
1889
|
-
// src/decoder/compression/entropy/ANSCoding.ts
|
|
1890
|
-
var ANS_P8_PRECISION = 256;
|
|
1891
|
-
var ANS_L_BASE = 4096;
|
|
1892
|
-
var ANS_IO_BASE = 256;
|
|
1893
|
-
function memGetLe16(buf, offset) {
|
|
1894
|
-
return buf[offset] | buf[offset + 1] << 8;
|
|
1895
|
-
}
|
|
1896
|
-
function memGetLe24(buf, offset) {
|
|
1897
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16;
|
|
1898
|
-
}
|
|
1899
|
-
function memGetLe32(buf, offset) {
|
|
1900
|
-
return buf[offset] | buf[offset + 1] << 8 | buf[offset + 2] << 16 | buf[offset + 3] << 24 >>> 0;
|
|
1901
|
-
}
|
|
1902
|
-
var AnsDecoder = class {
|
|
1903
|
-
buf;
|
|
1904
|
-
bufOffset;
|
|
1905
|
-
// First valid byte of this decoder's slice within buf: init is passed
|
|
1906
|
-
// absolute offsets into the source buffer to avoid a subarray allocation.
|
|
1907
|
-
bufStart;
|
|
1908
|
-
state;
|
|
1909
|
-
constructor() {
|
|
1910
|
-
this.buf = null;
|
|
1911
|
-
this.bufOffset = 0;
|
|
1912
|
-
this.bufStart = 0;
|
|
1913
|
-
this.state = 0;
|
|
1914
|
-
}
|
|
1915
|
-
};
|
|
1916
|
-
function ansReadInit(ans, buf, offset, base = 0) {
|
|
1917
|
-
if (offset - base < 1) {
|
|
1918
|
-
return 1;
|
|
1919
|
-
}
|
|
1920
|
-
ans.buf = buf;
|
|
1921
|
-
ans.bufStart = base;
|
|
1922
|
-
const x = buf[offset - 1] >> 6;
|
|
1923
|
-
if (x === 0) {
|
|
1924
|
-
ans.bufOffset = offset - 1;
|
|
1925
|
-
ans.state = buf[offset - 1] & 63;
|
|
1926
|
-
} else if (x === 1) {
|
|
1927
|
-
if (offset - base < 2) {
|
|
1928
|
-
return 1;
|
|
1929
|
-
}
|
|
1930
|
-
ans.bufOffset = offset - 2;
|
|
1931
|
-
ans.state = memGetLe16(buf, offset - 2) & 16383;
|
|
1932
|
-
} else if (x === 2) {
|
|
1933
|
-
if (offset - base < 3) {
|
|
1934
|
-
return 1;
|
|
1935
|
-
}
|
|
1936
|
-
ans.bufOffset = offset - 3;
|
|
1937
|
-
ans.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
1938
|
-
} else {
|
|
1939
|
-
return 1;
|
|
1940
|
-
}
|
|
1941
|
-
ans.state += ANS_L_BASE;
|
|
1942
|
-
if (ans.state >= ANS_L_BASE * ANS_IO_BASE) {
|
|
1943
|
-
return 1;
|
|
1944
|
-
}
|
|
1945
|
-
return 0;
|
|
1946
|
-
}
|
|
1947
|
-
function ansReadEnd(ans) {
|
|
1948
|
-
return ans.state === ANS_L_BASE;
|
|
1949
|
-
}
|
|
1950
|
-
var tablePool = [];
|
|
1951
|
-
var acquirePooled = (Ctor, size) => {
|
|
1952
|
-
for (let i = tablePool.length - 1; i >= 0; --i) {
|
|
1953
|
-
const buf = tablePool[i];
|
|
1954
|
-
if (buf.constructor === Ctor && buf.length >= size) {
|
|
1955
|
-
tablePool[i] = tablePool[tablePool.length - 1];
|
|
1956
|
-
tablePool.pop();
|
|
1957
|
-
return buf;
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
return new Ctor(size);
|
|
1961
|
-
};
|
|
1962
|
-
var RAnsDecoder = class {
|
|
1963
|
-
ransPrecisionBits;
|
|
1964
|
-
ransPrecision;
|
|
1965
|
-
ransPrecisionMask;
|
|
1966
|
-
lRansBase;
|
|
1967
|
-
lutTable;
|
|
1968
|
-
probTable;
|
|
1969
|
-
cumProbTable;
|
|
1970
|
-
buf;
|
|
1971
|
-
bufOffset;
|
|
1972
|
-
// First valid byte of this decoder's slice within buf (absolute offsets,
|
|
1973
|
-
// see AnsDecoder.bufStart).
|
|
1974
|
-
bufStart;
|
|
1975
|
-
state;
|
|
1976
|
-
constructor(ransPrecisionBits) {
|
|
1977
|
-
this.ransPrecisionBits = ransPrecisionBits;
|
|
1978
|
-
this.ransPrecision = 1 << ransPrecisionBits;
|
|
1979
|
-
this.ransPrecisionMask = this.ransPrecision - 1;
|
|
1980
|
-
this.lRansBase = this.ransPrecision * 4;
|
|
1981
|
-
this.lutTable = null;
|
|
1982
|
-
this.probTable = null;
|
|
1983
|
-
this.cumProbTable = null;
|
|
1984
|
-
this.buf = null;
|
|
1985
|
-
this.bufOffset = 0;
|
|
1986
|
-
this.bufStart = 0;
|
|
1987
|
-
this.state = 0;
|
|
1988
|
-
}
|
|
1989
|
-
// offset is the absolute end of the encoded bytes within buf and base the
|
|
1990
|
-
// absolute start (offset - base = encoded length). Passing the source
|
|
1991
|
-
// buffer with absolute offsets avoids a subarray allocation per init.
|
|
1992
|
-
// Returns 0 on success, non-zero on error.
|
|
1993
|
-
readInit(buf, offset, base = 0) {
|
|
1994
|
-
if (offset - base < 1) {
|
|
1995
|
-
return 1;
|
|
1996
|
-
}
|
|
1997
|
-
this.buf = buf;
|
|
1998
|
-
this.bufStart = base;
|
|
1999
|
-
const x = buf[offset - 1] >> 6;
|
|
2000
|
-
if (x === 0) {
|
|
2001
|
-
this.bufOffset = offset - 1;
|
|
2002
|
-
this.state = buf[offset - 1] & 63;
|
|
2003
|
-
} else if (x === 1) {
|
|
2004
|
-
if (offset - base < 2) {
|
|
2005
|
-
return 1;
|
|
2006
|
-
}
|
|
2007
|
-
this.bufOffset = offset - 2;
|
|
2008
|
-
this.state = memGetLe16(buf, offset - 2) & 16383;
|
|
2009
|
-
} else if (x === 2) {
|
|
2010
|
-
if (offset - base < 3) {
|
|
2011
|
-
return 1;
|
|
2012
|
-
}
|
|
2013
|
-
this.bufOffset = offset - 3;
|
|
2014
|
-
this.state = memGetLe24(buf, offset - 3) & 4194303;
|
|
2015
|
-
} else if (x === 3) {
|
|
2016
|
-
if (offset - base < 4) {
|
|
2017
|
-
return 1;
|
|
2018
|
-
}
|
|
2019
|
-
this.bufOffset = offset - 4;
|
|
2020
|
-
this.state = memGetLe32(buf, offset - 4) & 1073741823;
|
|
2021
|
-
} else {
|
|
2022
|
-
return 1;
|
|
2023
|
-
}
|
|
2024
|
-
this.state += this.lRansBase;
|
|
2025
|
-
if (this.state >= this.lRansBase * ANS_IO_BASE) {
|
|
2026
|
-
return 1;
|
|
2027
|
-
}
|
|
2028
|
-
return 0;
|
|
2029
|
-
}
|
|
2030
|
-
readEnd() {
|
|
2031
|
-
if (this.lutTable !== null) {
|
|
2032
|
-
tablePool.push(this.lutTable);
|
|
2033
|
-
this.lutTable = null;
|
|
2034
|
-
}
|
|
2035
|
-
if (this.probTable !== null) {
|
|
2036
|
-
tablePool.push(this.probTable);
|
|
2037
|
-
this.probTable = null;
|
|
2038
|
-
}
|
|
2039
|
-
if (this.cumProbTable !== null) {
|
|
2040
|
-
tablePool.push(this.cumProbTable);
|
|
2041
|
-
this.cumProbTable = null;
|
|
2042
|
-
}
|
|
2043
|
-
return this.state === this.lRansBase;
|
|
2044
|
-
}
|
|
2045
|
-
ransRead() {
|
|
2046
|
-
const buf = this.buf;
|
|
2047
|
-
const lRansBase = this.lRansBase;
|
|
2048
|
-
let state = this.state;
|
|
2049
|
-
let bufOffset = this.bufOffset;
|
|
2050
|
-
const bufStart = this.bufStart;
|
|
2051
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2052
|
-
state = state << 8 | buf[--bufOffset];
|
|
2053
|
-
}
|
|
2054
|
-
const quo = state >>> this.ransPrecisionBits;
|
|
2055
|
-
const rem = state & this.ransPrecisionMask;
|
|
2056
|
-
const symbol = this.lutTable[rem];
|
|
2057
|
-
this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
|
|
2058
|
-
this.bufOffset = bufOffset;
|
|
2059
|
-
return symbol;
|
|
2060
|
-
}
|
|
2061
|
-
// Batch ransRead() into out[0..count): all fields hoisted to locals, state
|
|
2062
|
-
// written back once. Removes per-symbol property reads and call indirection.
|
|
2063
|
-
// lutTable's element type varies per decoder (Uint8/16/32 by symbol count),
|
|
2064
|
-
// which would make the hot lutTable[rem] access site polymorphic — dispatch
|
|
2065
|
-
// once here so each loop body stays monomorphic on its concrete type. The
|
|
2066
|
-
// three bodies are intentionally identical copies.
|
|
2067
|
-
decodeSymbols(out, count) {
|
|
2068
|
-
const lutTable = this.lutTable;
|
|
2069
|
-
if (lutTable instanceof Uint8Array) {
|
|
2070
|
-
this._decodeSymbolsU8(out, count, lutTable);
|
|
2071
|
-
} else if (lutTable instanceof Uint16Array) {
|
|
2072
|
-
this._decodeSymbolsU16(out, count, lutTable);
|
|
2073
|
-
} else {
|
|
2074
|
-
this._decodeSymbolsU32(out, count, lutTable);
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
_decodeSymbolsU8(out, count, lutTable) {
|
|
2078
|
-
const buf = this.buf;
|
|
2079
|
-
const lRansBase = this.lRansBase;
|
|
2080
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2081
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2082
|
-
const probTable = this.probTable;
|
|
2083
|
-
const cumProbTable = this.cumProbTable;
|
|
2084
|
-
let state = this.state;
|
|
2085
|
-
let bufOffset = this.bufOffset;
|
|
2086
|
-
const bufStart = this.bufStart;
|
|
2087
|
-
for (let i = 0; i < count; ++i) {
|
|
2088
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2089
|
-
state = state << 8 | buf[--bufOffset];
|
|
2090
|
-
}
|
|
2091
|
-
const rem = state & ransPrecisionMask;
|
|
2092
|
-
const symbol = lutTable[rem];
|
|
2093
|
-
out[i] = symbol;
|
|
2094
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2095
|
-
}
|
|
2096
|
-
this.state = state;
|
|
2097
|
-
this.bufOffset = bufOffset;
|
|
2098
|
-
}
|
|
2099
|
-
_decodeSymbolsU16(out, count, lutTable) {
|
|
2100
|
-
const buf = this.buf;
|
|
2101
|
-
const lRansBase = this.lRansBase;
|
|
2102
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2103
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2104
|
-
const probTable = this.probTable;
|
|
2105
|
-
const cumProbTable = this.cumProbTable;
|
|
2106
|
-
let state = this.state;
|
|
2107
|
-
let bufOffset = this.bufOffset;
|
|
2108
|
-
const bufStart = this.bufStart;
|
|
2109
|
-
for (let i = 0; i < count; ++i) {
|
|
2110
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2111
|
-
state = state << 8 | buf[--bufOffset];
|
|
2112
|
-
}
|
|
2113
|
-
const rem = state & ransPrecisionMask;
|
|
2114
|
-
const symbol = lutTable[rem];
|
|
2115
|
-
out[i] = symbol;
|
|
2116
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2117
|
-
}
|
|
2118
|
-
this.state = state;
|
|
2119
|
-
this.bufOffset = bufOffset;
|
|
2120
|
-
}
|
|
2121
|
-
_decodeSymbolsU32(out, count, lutTable) {
|
|
2122
|
-
const buf = this.buf;
|
|
2123
|
-
const lRansBase = this.lRansBase;
|
|
2124
|
-
const ransPrecisionBits = this.ransPrecisionBits;
|
|
2125
|
-
const ransPrecisionMask = this.ransPrecisionMask;
|
|
2126
|
-
const probTable = this.probTable;
|
|
2127
|
-
const cumProbTable = this.cumProbTable;
|
|
2128
|
-
let state = this.state;
|
|
2129
|
-
let bufOffset = this.bufOffset;
|
|
2130
|
-
const bufStart = this.bufStart;
|
|
2131
|
-
for (let i = 0; i < count; ++i) {
|
|
2132
|
-
while (state < lRansBase && bufOffset > bufStart) {
|
|
2133
|
-
state = state << 8 | buf[--bufOffset];
|
|
2134
|
-
}
|
|
2135
|
-
const rem = state & ransPrecisionMask;
|
|
2136
|
-
const symbol = lutTable[rem];
|
|
2137
|
-
out[i] = symbol;
|
|
2138
|
-
state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
|
|
2139
|
-
}
|
|
2140
|
-
this.state = state;
|
|
2141
|
-
this.bufOffset = bufOffset;
|
|
2142
|
-
}
|
|
2143
|
-
// Builds the ransPrecision-entry lookup table. Returns false on bad input data.
|
|
2144
|
-
ransBuildLookUpTable(tokenProbs, numSymbols) {
|
|
2145
|
-
const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
|
|
2146
|
-
const lutTable = acquirePooled(LutArray, this.ransPrecision);
|
|
2147
|
-
const probTable = acquirePooled(Uint32Array, numSymbols);
|
|
2148
|
-
const cumProbTable = acquirePooled(Uint32Array, numSymbols);
|
|
2149
|
-
this.lutTable = lutTable;
|
|
2150
|
-
this.probTable = probTable;
|
|
2151
|
-
this.cumProbTable = cumProbTable;
|
|
2152
|
-
let cumProb = 0;
|
|
2153
|
-
let actProb = 0;
|
|
2154
|
-
for (let i = 0; i < numSymbols; ++i) {
|
|
2155
|
-
const prob = tokenProbs[i];
|
|
2156
|
-
probTable[i] = prob;
|
|
2157
|
-
cumProbTable[i] = cumProb;
|
|
2158
|
-
cumProb += prob;
|
|
2159
|
-
if (cumProb > this.ransPrecision) {
|
|
2512
|
+
}
|
|
2513
|
+
get attributeId() {
|
|
2514
|
+
return this._attributeId;
|
|
2515
|
+
}
|
|
2516
|
+
get decoder() {
|
|
2517
|
+
return this._decoder;
|
|
2518
|
+
}
|
|
2519
|
+
initPredictionScheme(ps) {
|
|
2520
|
+
for (let i = 0; i < ps.getNumParentAttributes(); i++) {
|
|
2521
|
+
const attId = this._decoder.pointCloud().getNamedAttributeId(ps.getParentAttributeType(i));
|
|
2522
|
+
if (attId === -1) {
|
|
2160
2523
|
return false;
|
|
2161
2524
|
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
}
|
|
2166
|
-
} else {
|
|
2167
|
-
lutTable.fill(i, actProb, cumProb);
|
|
2525
|
+
const pa = this._decoder.getPortableAttribute(attId);
|
|
2526
|
+
if (pa === null || !ps.setParentAttribute(pa)) {
|
|
2527
|
+
return false;
|
|
2168
2528
|
}
|
|
2169
|
-
actProb = cumProb;
|
|
2170
2529
|
}
|
|
2171
|
-
|
|
2530
|
+
return true;
|
|
2531
|
+
}
|
|
2532
|
+
// Decodes raw attribute values in their original format.
|
|
2533
|
+
decodeValues(pointIds, buffer) {
|
|
2534
|
+
const numValues = pointIds.length;
|
|
2535
|
+
const entrySize = this._attribute.byteStride;
|
|
2536
|
+
const totalSize = numValues * entrySize;
|
|
2537
|
+
const valueData = buffer.decodeBytesView(totalSize);
|
|
2538
|
+
if (valueData === void 0) {
|
|
2172
2539
|
return false;
|
|
2173
2540
|
}
|
|
2541
|
+
this._attribute.buffer.write(0, valueData, totalSize);
|
|
2174
2542
|
return true;
|
|
2175
2543
|
}
|
|
2544
|
+
setPortableAttribute(att) {
|
|
2545
|
+
this._portableAttribute = att;
|
|
2546
|
+
}
|
|
2547
|
+
get portableAttribute() {
|
|
2548
|
+
return this._portableAttribute;
|
|
2549
|
+
}
|
|
2176
2550
|
};
|
|
2177
2551
|
|
|
2178
2552
|
// src/decoder/compression/entropy/RAnsSymbolDecoder.ts
|
|
@@ -2208,7 +2582,7 @@ var RAnsSymbolDecoder = class {
|
|
|
2208
2582
|
return false;
|
|
2209
2583
|
}
|
|
2210
2584
|
const numSymbols = this.numSymbols_;
|
|
2211
|
-
const probabilityTable =
|
|
2585
|
+
const probabilityTable = scratchUint32Zeroed(numSymbols);
|
|
2212
2586
|
this.probabilityTable_ = probabilityTable;
|
|
2213
2587
|
if (numSymbols === 0) {
|
|
2214
2588
|
return true;
|
|
@@ -2289,24 +2663,73 @@ function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
|
|
|
2289
2663
|
if (numValues > 0 && tagDecoder.numSymbols === 0) {
|
|
2290
2664
|
return false;
|
|
2291
2665
|
}
|
|
2666
|
+
const tagAns = tagDecoder.ans_;
|
|
2292
2667
|
srcBuffer.startBitDecoding(false);
|
|
2293
2668
|
const bd = srcBuffer._bitDecoder;
|
|
2294
|
-
const
|
|
2669
|
+
const buf = bd._bitBuffer;
|
|
2670
|
+
const byteLength = bd._byteLength;
|
|
2671
|
+
let bitOffset = bd._bitOffset;
|
|
2295
2672
|
let valueId = 0;
|
|
2296
2673
|
for (let i = 0; i < numValues; i += numComponents) {
|
|
2297
2674
|
const bitLength = tagAns.ransRead();
|
|
2298
|
-
|
|
2299
|
-
const
|
|
2300
|
-
|
|
2301
|
-
|
|
2675
|
+
if (bitLength < 32) {
|
|
2676
|
+
const mask = (1 << bitLength) - 1;
|
|
2677
|
+
let j = 0;
|
|
2678
|
+
for (; j < numComponents; ++j) {
|
|
2679
|
+
const byteOffset = bitOffset >> 3;
|
|
2680
|
+
if (byteOffset + 4 >= byteLength) break;
|
|
2681
|
+
const bitShift = bitOffset & 7;
|
|
2682
|
+
let value = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> bitShift;
|
|
2683
|
+
if (bitLength > 32 - bitShift) {
|
|
2684
|
+
value = (value | buf[byteOffset + 4] << 32 - bitShift) >>> 0;
|
|
2685
|
+
}
|
|
2686
|
+
bitOffset += bitLength;
|
|
2687
|
+
outValues[valueId++] = value & mask;
|
|
2688
|
+
}
|
|
2689
|
+
if (j === numComponents) continue;
|
|
2690
|
+
bd._bitOffset = bitOffset;
|
|
2691
|
+
for (; j < numComponents; ++j) {
|
|
2692
|
+
const val = bd.getBits(bitLength);
|
|
2693
|
+
if (val === void 0) {
|
|
2694
|
+
return false;
|
|
2695
|
+
}
|
|
2696
|
+
outValues[valueId++] = val;
|
|
2697
|
+
}
|
|
2698
|
+
bitOffset = bd._bitOffset;
|
|
2699
|
+
} else {
|
|
2700
|
+
bd._bitOffset = bitOffset;
|
|
2701
|
+
for (let j = 0; j < numComponents; ++j) {
|
|
2702
|
+
const val = bd.getBits(bitLength);
|
|
2703
|
+
if (val === void 0) {
|
|
2704
|
+
return false;
|
|
2705
|
+
}
|
|
2706
|
+
outValues[valueId++] = val;
|
|
2302
2707
|
}
|
|
2303
|
-
|
|
2708
|
+
bitOffset = bd._bitOffset;
|
|
2304
2709
|
}
|
|
2305
2710
|
}
|
|
2711
|
+
bd._bitOffset = bitOffset;
|
|
2306
2712
|
tagDecoder.endDecoding();
|
|
2307
2713
|
srcBuffer.endBitDecoding();
|
|
2308
2714
|
return true;
|
|
2309
2715
|
}
|
|
2716
|
+
function parseRawSymbolStream(numValues, srcBuffer) {
|
|
2717
|
+
const maxBitLength = srcBuffer.decodeUint8();
|
|
2718
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
2719
|
+
return null;
|
|
2720
|
+
}
|
|
2721
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
2722
|
+
if (!decoder.create(srcBuffer)) {
|
|
2723
|
+
return null;
|
|
2724
|
+
}
|
|
2725
|
+
if (numValues > 0 && decoder.numSymbols === 0) {
|
|
2726
|
+
return null;
|
|
2727
|
+
}
|
|
2728
|
+
if (!decoder.startDecoding(srcBuffer)) {
|
|
2729
|
+
return null;
|
|
2730
|
+
}
|
|
2731
|
+
return decoder;
|
|
2732
|
+
}
|
|
2310
2733
|
function decodeRawSymbolsInternal(uniqueSymbolsBitLength, numValues, srcBuffer, outValues) {
|
|
2311
2734
|
const decoder = new RAnsSymbolDecoder(uniqueSymbolsBitLength);
|
|
2312
2735
|
if (!decoder.create(srcBuffer)) {
|
|
@@ -2409,6 +2832,16 @@ var PredictionSchemeDecoderInterface = class {
|
|
|
2409
2832
|
decodePredictionData(_buffer) {
|
|
2410
2833
|
return true;
|
|
2411
2834
|
}
|
|
2835
|
+
/**
|
|
2836
|
+
* Like computeOriginalValues, but inCorr still holds unsigned zigzag-coded
|
|
2837
|
+
* corrections; the implementation unpacks each one inline, replacing the
|
|
2838
|
+
* standalone convertSymbolsToSignedInts pass. Returns undefined when the
|
|
2839
|
+
* scheme/transform combination cannot fuse (the caller then falls back to
|
|
2840
|
+
* the two-pass path). Base implementation: never fusable.
|
|
2841
|
+
*/
|
|
2842
|
+
computeOriginalValuesZigzag(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2843
|
+
return void 0;
|
|
2844
|
+
}
|
|
2412
2845
|
/** Reverts the prediction applied during encoding, writing original values to outData. */
|
|
2413
2846
|
computeOriginalValues(_inCorr, _outData, _size, _numComponents, _entryToPointIdMap) {
|
|
2414
2847
|
return false;
|
|
@@ -2744,7 +3177,7 @@ var OctahedronToolBox = class {
|
|
|
2744
3177
|
// src/decoder/compression/attributes/prediction_schemes/MeshPredictionSchemeGeometricNormalPredictorArea.ts
|
|
2745
3178
|
var UPPER_BOUND = 1 << 29;
|
|
2746
3179
|
function buildInt32PositionCache(att, map, numEntries, tempPos) {
|
|
2747
|
-
const cache =
|
|
3180
|
+
const cache = scratchInt32(numEntries * 3);
|
|
2748
3181
|
const bufData = att.buffer && att.buffer.data;
|
|
2749
3182
|
if (att.dataType === DataType.INT32 && att.numComponents === 3 && bufData) {
|
|
2750
3183
|
const src = new Int32Array(bufData.buffer);
|
|
@@ -2825,7 +3258,7 @@ var MeshPredictionSchemeGeometricNormalPredictorArea = class {
|
|
|
2825
3258
|
const cornerToVertex = this._cornerToVertex;
|
|
2826
3259
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
2827
3260
|
const nc = cornerToVertex.length;
|
|
2828
|
-
const c2o =
|
|
3261
|
+
const c2o = scratchInt32(nc);
|
|
2829
3262
|
for (let c = 0; c < nc; ++c) {
|
|
2830
3263
|
const v = cornerToVertex[c];
|
|
2831
3264
|
c2o[c] = v < 0 ? -1 : vertexToDataMap[v] * 3;
|
|
@@ -3076,10 +3509,21 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3076
3509
|
isInitialized() {
|
|
3077
3510
|
return this._meshData.isInitialized();
|
|
3078
3511
|
}
|
|
3512
|
+
// Zigzag-fused variant: decodes corrections that are still in their unsigned
|
|
3513
|
+
// zigzag form, unpacking each one inline. Only offered for the wrap
|
|
3514
|
+
// transform (whose corrections are the only zigzag-coded ones this scheme
|
|
3515
|
+
// sees); callers fall back to the standalone conversion pass otherwise.
|
|
3516
|
+
computeOriginalValuesZigzag(inCorr, outData, _size, numComponents, _entryToPointIdMap) {
|
|
3517
|
+
this._transform.init(numComponents);
|
|
3518
|
+
if (!this._transform.getType || this._transform.getType() !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3519
|
+
return void 0;
|
|
3520
|
+
}
|
|
3521
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, true);
|
|
3522
|
+
}
|
|
3079
3523
|
computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
|
|
3080
3524
|
this._transform.init(numComponents);
|
|
3081
3525
|
if (this._transform.getType && this._transform.getType() === PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
3082
|
-
return this._computeOriginalValuesWrap(inCorr, outData, numComponents);
|
|
3526
|
+
return this._computeOriginalValuesWrap(inCorr, outData, numComponents, false);
|
|
3083
3527
|
}
|
|
3084
3528
|
const table = this._meshData.cornerTable;
|
|
3085
3529
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3120,12 +3564,18 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3120
3564
|
}
|
|
3121
3565
|
return true;
|
|
3122
3566
|
}
|
|
3123
|
-
|
|
3567
|
+
// The wrap transform's corrections are zigzag-coded; with `zigzag` set the
|
|
3568
|
+
// decode folds the (val >>> 1) ^ -(val & 1) unpacking into each correction
|
|
3569
|
+
// read, replacing the standalone convertSymbolsToSignedInts pass over the
|
|
3570
|
+
// whole array (see computeOriginalValuesZigzag). Every correction is read
|
|
3571
|
+
// exactly once before its slot is overwritten, so the in-place aliasing of
|
|
3572
|
+
// inCorr and outData is preserved.
|
|
3573
|
+
_computeOriginalValuesWrap(inCorr, outData, numComponents, zigzag) {
|
|
3124
3574
|
if (numComponents === 2) {
|
|
3125
|
-
return this._computeOriginalValuesWrap2(inCorr, outData);
|
|
3575
|
+
return this._computeOriginalValuesWrap2(inCorr, outData, zigzag);
|
|
3126
3576
|
}
|
|
3127
3577
|
if (numComponents === 3) {
|
|
3128
|
-
return this._computeOriginalValuesWrap3(inCorr, outData);
|
|
3578
|
+
return this._computeOriginalValuesWrap3(inCorr, outData, zigzag);
|
|
3129
3579
|
}
|
|
3130
3580
|
const table = this._meshData.cornerTable;
|
|
3131
3581
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
@@ -3143,7 +3593,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3143
3593
|
} else if (pred < minValue) {
|
|
3144
3594
|
pred = minValue;
|
|
3145
3595
|
}
|
|
3146
|
-
|
|
3596
|
+
const raw = inCorr[c];
|
|
3597
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3147
3598
|
if (orig > maxValue) {
|
|
3148
3599
|
orig -= maxDif;
|
|
3149
3600
|
} else if (orig < minValue) {
|
|
@@ -3182,7 +3633,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3182
3633
|
} else if (pred < minValue) {
|
|
3183
3634
|
pred = minValue;
|
|
3184
3635
|
}
|
|
3185
|
-
|
|
3636
|
+
const raw = inCorr[dstOffset + c];
|
|
3637
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3186
3638
|
if (orig > maxValue) {
|
|
3187
3639
|
orig -= maxDif;
|
|
3188
3640
|
} else if (orig < minValue) {
|
|
@@ -3199,7 +3651,8 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3199
3651
|
} else if (pred < minValue) {
|
|
3200
3652
|
pred = minValue;
|
|
3201
3653
|
}
|
|
3202
|
-
|
|
3654
|
+
const raw = inCorr[dstOffset + c];
|
|
3655
|
+
let orig = pred + (zigzag ? raw >>> 1 ^ -(raw & 1) : raw) | 0;
|
|
3203
3656
|
if (orig > maxValue) {
|
|
3204
3657
|
orig -= maxDif;
|
|
3205
3658
|
} else if (orig < minValue) {
|
|
@@ -3211,7 +3664,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3211
3664
|
}
|
|
3212
3665
|
return true;
|
|
3213
3666
|
}
|
|
3214
|
-
_computeOriginalValuesWrap2(inCorr, outData) {
|
|
3667
|
+
_computeOriginalValuesWrap2(inCorr, outData, zigzag) {
|
|
3215
3668
|
const table = this._meshData.cornerTable;
|
|
3216
3669
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3217
3670
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3233,8 +3686,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3233
3686
|
} else if (pred1 < minValue) {
|
|
3234
3687
|
pred1 = minValue;
|
|
3235
3688
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3689
|
+
const raw0 = inCorr[0];
|
|
3690
|
+
const raw1 = inCorr[1];
|
|
3691
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3692
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3238
3693
|
if (orig0 > maxValue) {
|
|
3239
3694
|
orig0 -= maxDif;
|
|
3240
3695
|
} else if (orig0 < minValue) {
|
|
@@ -3288,8 +3743,10 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3288
3743
|
} else if (pred1 < minValue) {
|
|
3289
3744
|
pred1 = minValue;
|
|
3290
3745
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3746
|
+
const rawA = inCorr[dstOffset];
|
|
3747
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3748
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3749
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3293
3750
|
if (orig0 > maxValue) {
|
|
3294
3751
|
orig0 -= maxDif;
|
|
3295
3752
|
} else if (orig0 < minValue) {
|
|
@@ -3305,7 +3762,7 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3305
3762
|
}
|
|
3306
3763
|
return true;
|
|
3307
3764
|
}
|
|
3308
|
-
_computeOriginalValuesWrap3(inCorr, outData) {
|
|
3765
|
+
_computeOriginalValuesWrap3(inCorr, outData, zigzag) {
|
|
3309
3766
|
const table = this._meshData.cornerTable;
|
|
3310
3767
|
const vertexToDataMap = this._meshData.vertexToDataMap;
|
|
3311
3768
|
const oppositeCorners = table.oppositeCornerArray();
|
|
@@ -3333,9 +3790,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3333
3790
|
} else if (pred2 < minValue) {
|
|
3334
3791
|
pred2 = minValue;
|
|
3335
3792
|
}
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3793
|
+
const raw0 = inCorr[0];
|
|
3794
|
+
const raw1 = inCorr[1];
|
|
3795
|
+
const raw2 = inCorr[2];
|
|
3796
|
+
let orig0 = pred0 + (zigzag ? raw0 >>> 1 ^ -(raw0 & 1) : raw0) | 0;
|
|
3797
|
+
let orig1 = pred1 + (zigzag ? raw1 >>> 1 ^ -(raw1 & 1) : raw1) | 0;
|
|
3798
|
+
let orig2 = pred2 + (zigzag ? raw2 >>> 1 ^ -(raw2 & 1) : raw2) | 0;
|
|
3339
3799
|
if (orig0 > maxValue) {
|
|
3340
3800
|
orig0 -= maxDif;
|
|
3341
3801
|
} else if (orig0 < minValue) {
|
|
@@ -3402,9 +3862,12 @@ var MeshPredictionSchemeParallelogramDecoder = class extends MeshPredictionSchem
|
|
|
3402
3862
|
} else if (pred2 < minValue) {
|
|
3403
3863
|
pred2 = minValue;
|
|
3404
3864
|
}
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3865
|
+
const rawA = inCorr[dstOffset];
|
|
3866
|
+
const rawB = inCorr[dstOffset + 1];
|
|
3867
|
+
const rawC = inCorr[dstOffset + 2];
|
|
3868
|
+
orig0 = pred0 + (zigzag ? rawA >>> 1 ^ -(rawA & 1) : rawA) | 0;
|
|
3869
|
+
orig1 = pred1 + (zigzag ? rawB >>> 1 ^ -(rawB & 1) : rawB) | 0;
|
|
3870
|
+
orig2 = pred2 + (zigzag ? rawC >>> 1 ^ -(rawC & 1) : rawC) | 0;
|
|
3408
3871
|
if (orig0 > maxValue) {
|
|
3409
3872
|
orig0 -= maxDif;
|
|
3410
3873
|
} else if (orig0 < minValue) {
|
|
@@ -3911,14 +4374,49 @@ var PredictionSchemeWrapDecodingTransform = class {
|
|
|
3911
4374
|
// src/decoder/compression/attributes/SequentialIntegerAttributeDecoder.ts
|
|
3912
4375
|
var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder {
|
|
3913
4376
|
_predictionScheme;
|
|
4377
|
+
// Two-phase decode state (see SequentialAttributeDecoder): the parse phase
|
|
4378
|
+
// stashes the primed raw-symbol stream here so the controller can batch and
|
|
4379
|
+
// pair several attributes' decodes; the finish phase consumes it.
|
|
4380
|
+
_pendingSymbolDecoder;
|
|
4381
|
+
_pendingNumValues;
|
|
4382
|
+
_finishPointIds;
|
|
3914
4383
|
constructor() {
|
|
3915
4384
|
super();
|
|
3916
4385
|
this._predictionScheme = null;
|
|
4386
|
+
this._pendingSymbolDecoder = null;
|
|
4387
|
+
this._pendingNumValues = 0;
|
|
4388
|
+
this._finishPointIds = null;
|
|
3917
4389
|
}
|
|
3918
|
-
|
|
3919
|
-
|
|
4390
|
+
// --- Two-phase decode (parse headers / batch symbol decode / finish) ---
|
|
4391
|
+
decodePortableAttributeParse(pointIds, buffer) {
|
|
4392
|
+
if (this.attribute.numComponents <= 0) {
|
|
4393
|
+
return false;
|
|
4394
|
+
}
|
|
4395
|
+
if (!this.attribute.reset(pointIds.length)) {
|
|
4396
|
+
return false;
|
|
4397
|
+
}
|
|
4398
|
+
this._finishPointIds = pointIds;
|
|
4399
|
+
return this._decodeValuesParse(pointIds, buffer);
|
|
3920
4400
|
}
|
|
3921
|
-
|
|
4401
|
+
pendingSymbolStream() {
|
|
4402
|
+
if (this._pendingSymbolDecoder === null) {
|
|
4403
|
+
return null;
|
|
4404
|
+
}
|
|
4405
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4406
|
+
return {
|
|
4407
|
+
ans: this._pendingSymbolDecoder.ans_,
|
|
4408
|
+
out: new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, this._pendingNumValues),
|
|
4409
|
+
count: this._pendingNumValues
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
decodePortableAttributeFinish() {
|
|
4413
|
+
if (this._pendingSymbolDecoder !== null) {
|
|
4414
|
+
this._pendingSymbolDecoder.endDecoding();
|
|
4415
|
+
this._pendingSymbolDecoder = null;
|
|
4416
|
+
}
|
|
4417
|
+
return this._finishIntegerValues(this._finishPointIds);
|
|
4418
|
+
}
|
|
4419
|
+
_decodeValuesParse(pointIds, buffer) {
|
|
3922
4420
|
const predictionSchemeMethod = buffer.decodeInt8();
|
|
3923
4421
|
if (predictionSchemeMethod === void 0) return false;
|
|
3924
4422
|
if (predictionSchemeMethod < PredictionSchemeMethod.PREDICTION_NONE || predictionSchemeMethod >= PredictionSchemeMethod.NUM_PREDICTION_SCHEMES) {
|
|
@@ -3937,12 +4435,6 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3937
4435
|
return false;
|
|
3938
4436
|
}
|
|
3939
4437
|
}
|
|
3940
|
-
if (!this.decodeIntegerValues(pointIds, buffer)) {
|
|
3941
|
-
return false;
|
|
3942
|
-
}
|
|
3943
|
-
return true;
|
|
3944
|
-
}
|
|
3945
|
-
decodeIntegerValues(pointIds, buffer) {
|
|
3946
4438
|
const numComponents = this.getNumValueComponents();
|
|
3947
4439
|
if (numComponents <= 0) {
|
|
3948
4440
|
return false;
|
|
@@ -3957,9 +4449,23 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3957
4449
|
const compressed = buffer.decodeUint8();
|
|
3958
4450
|
if (compressed === void 0) return false;
|
|
3959
4451
|
if (compressed > 0) {
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
4452
|
+
if (numValues > 0) {
|
|
4453
|
+
const scheme = buffer.decodeUint8();
|
|
4454
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
4455
|
+
const decoder = parseRawSymbolStream(numValues, buffer);
|
|
4456
|
+
if (decoder === null) {
|
|
4457
|
+
return false;
|
|
4458
|
+
}
|
|
4459
|
+
this._pendingSymbolDecoder = decoder;
|
|
4460
|
+
this._pendingNumValues = numValues;
|
|
4461
|
+
} else if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
4462
|
+
const outUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4463
|
+
if (!decodeTaggedSymbols(numValues, numComponents, buffer, outUint32)) {
|
|
4464
|
+
return false;
|
|
4465
|
+
}
|
|
4466
|
+
} else {
|
|
4467
|
+
return false;
|
|
4468
|
+
}
|
|
3963
4469
|
}
|
|
3964
4470
|
} else {
|
|
3965
4471
|
const numBytes = buffer.decodeUint8();
|
|
@@ -3990,15 +4496,40 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
3990
4496
|
}
|
|
3991
4497
|
}
|
|
3992
4498
|
}
|
|
3993
|
-
if (numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive())) {
|
|
3994
|
-
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
3995
|
-
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
3996
|
-
}
|
|
3997
4499
|
if (this._predictionScheme) {
|
|
3998
4500
|
if (!this._predictionScheme.decodePredictionData(buffer)) {
|
|
3999
4501
|
return false;
|
|
4000
4502
|
}
|
|
4503
|
+
}
|
|
4504
|
+
return true;
|
|
4505
|
+
}
|
|
4506
|
+
// The post-symbol tail of the decode: zigzag unpacking and prediction.
|
|
4507
|
+
_finishIntegerValues(pointIds) {
|
|
4508
|
+
const numComponents = this.getNumValueComponents();
|
|
4509
|
+
const numValues = pointIds.length * numComponents;
|
|
4510
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4511
|
+
if (portableAttributeData === null) {
|
|
4512
|
+
return false;
|
|
4513
|
+
}
|
|
4514
|
+
const needsZigzag = numValues > 0 && (this._predictionScheme === null || !this._predictionScheme.areCorrectionsPositive());
|
|
4515
|
+
if (this._predictionScheme) {
|
|
4001
4516
|
if (numValues > 0) {
|
|
4517
|
+
if (needsZigzag) {
|
|
4518
|
+
const fused = this._predictionScheme.computeOriginalValuesZigzag(
|
|
4519
|
+
portableAttributeData,
|
|
4520
|
+
portableAttributeData,
|
|
4521
|
+
numValues,
|
|
4522
|
+
numComponents,
|
|
4523
|
+
pointIds
|
|
4524
|
+
);
|
|
4525
|
+
if (fused !== void 0) {
|
|
4526
|
+
return fused;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
if (needsZigzag) {
|
|
4530
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4531
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4532
|
+
}
|
|
4002
4533
|
if (!this._predictionScheme.computeOriginalValues(
|
|
4003
4534
|
portableAttributeData,
|
|
4004
4535
|
portableAttributeData,
|
|
@@ -4009,9 +4540,34 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4009
4540
|
return false;
|
|
4010
4541
|
}
|
|
4011
4542
|
}
|
|
4543
|
+
} else if (needsZigzag) {
|
|
4544
|
+
const asUint32 = new Uint32Array(portableAttributeData.buffer, portableAttributeData.byteOffset, numValues);
|
|
4545
|
+
convertSymbolsToSignedInts(asUint32, numValues, portableAttributeData);
|
|
4012
4546
|
}
|
|
4013
4547
|
return true;
|
|
4014
4548
|
}
|
|
4549
|
+
transformAttributeToOriginalFormat(pointIds) {
|
|
4550
|
+
return this._storeValues(pointIds.length);
|
|
4551
|
+
}
|
|
4552
|
+
// Single-phase entry (base-class decodePortableAttribute path): parse,
|
|
4553
|
+
// decode any deferred symbol stream immediately, finish.
|
|
4554
|
+
decodeValues(pointIds, buffer) {
|
|
4555
|
+
this._finishPointIds = pointIds;
|
|
4556
|
+
if (!this._decodeValuesParse(pointIds, buffer)) {
|
|
4557
|
+
return false;
|
|
4558
|
+
}
|
|
4559
|
+
const pending = this._pendingSymbolDecoder;
|
|
4560
|
+
if (pending !== null) {
|
|
4561
|
+
const portableAttributeData = this.getPortableAttributeData();
|
|
4562
|
+
const outUint32 = new Uint32Array(
|
|
4563
|
+
portableAttributeData.buffer,
|
|
4564
|
+
portableAttributeData.byteOffset,
|
|
4565
|
+
this._pendingNumValues
|
|
4566
|
+
);
|
|
4567
|
+
pending.ans_.decodeSymbols(outUint32, this._pendingNumValues);
|
|
4568
|
+
}
|
|
4569
|
+
return this.decodePortableAttributeFinish();
|
|
4570
|
+
}
|
|
4015
4571
|
// Prediction scheme for decoding integer values; subclasses override for others.
|
|
4016
4572
|
createIntPredictionScheme(method, transformType) {
|
|
4017
4573
|
if (transformType !== PredictionSchemeTransformType.PREDICTION_TRANSFORM_WRAP) {
|
|
@@ -4074,7 +4630,7 @@ var SequentialIntegerAttributeDecoder = class extends SequentialAttributeDecoder
|
|
|
4074
4630
|
);
|
|
4075
4631
|
const portAtt = new PointAttribute(ga);
|
|
4076
4632
|
portAtt.setIdentityMapping();
|
|
4077
|
-
portAtt.
|
|
4633
|
+
portAtt.resetScratch(numEntries);
|
|
4078
4634
|
portAtt.uniqueId = this.attribute.uniqueId;
|
|
4079
4635
|
this.setPortableAttribute(portAtt);
|
|
4080
4636
|
}
|
|
@@ -4100,12 +4656,22 @@ var AttributeTransformType = {
|
|
|
4100
4656
|
};
|
|
4101
4657
|
|
|
4102
4658
|
// src/decoder/attributes/AttributeTransformData.ts
|
|
4659
|
+
var INITIAL_CAPACITY = 32;
|
|
4103
4660
|
var AttributeTransformData = class {
|
|
4104
4661
|
_transformType;
|
|
4105
|
-
|
|
4662
|
+
// Parameter bytes, little-endian, appended in transform-defined order.
|
|
4663
|
+
// Capacity grows geometrically and the DataView is cached alongside it: the
|
|
4664
|
+
// previous DataBuffer-backed version reallocated the buffer and built a
|
|
4665
|
+
// fresh DataView on *every* appended value, which on primitive-heavy files
|
|
4666
|
+
// cost more than the dequantization it describes.
|
|
4667
|
+
_bytes;
|
|
4668
|
+
_view;
|
|
4669
|
+
_size;
|
|
4106
4670
|
constructor() {
|
|
4107
4671
|
this._transformType = AttributeTransformType.INVALID;
|
|
4108
|
-
this.
|
|
4672
|
+
this._bytes = new Uint8Array(INITIAL_CAPACITY);
|
|
4673
|
+
this._view = new DataView(this._bytes.buffer);
|
|
4674
|
+
this._size = 0;
|
|
4109
4675
|
}
|
|
4110
4676
|
get transformType() {
|
|
4111
4677
|
return this._transformType;
|
|
@@ -4113,13 +4679,29 @@ var AttributeTransformData = class {
|
|
|
4113
4679
|
set transformType(type) {
|
|
4114
4680
|
this._transformType = type;
|
|
4115
4681
|
}
|
|
4682
|
+
// Number of parameter bytes written so far (the next append offset).
|
|
4683
|
+
get dataSize() {
|
|
4684
|
+
return this._size;
|
|
4685
|
+
}
|
|
4686
|
+
get data() {
|
|
4687
|
+
return this._bytes.subarray(0, this._size);
|
|
4688
|
+
}
|
|
4689
|
+
_reserve(sizeNeeded) {
|
|
4690
|
+
if (sizeNeeded <= this._bytes.length) return;
|
|
4691
|
+
let capacity = this._bytes.length * 2;
|
|
4692
|
+
if (capacity < sizeNeeded) capacity = sizeNeeded;
|
|
4693
|
+
const grown = new Uint8Array(capacity);
|
|
4694
|
+
grown.set(this._bytes);
|
|
4695
|
+
this._bytes = grown;
|
|
4696
|
+
this._view = new DataView(grown.buffer);
|
|
4697
|
+
}
|
|
4116
4698
|
setParameterValue(byteOffset, value, type) {
|
|
4117
4699
|
const sizeNeeded = byteOffset + this._typeSize(type);
|
|
4118
|
-
|
|
4119
|
-
|
|
4700
|
+
this._reserve(sizeNeeded);
|
|
4701
|
+
if (sizeNeeded > this._size) {
|
|
4702
|
+
this._size = sizeNeeded;
|
|
4120
4703
|
}
|
|
4121
|
-
const
|
|
4122
|
-
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
4704
|
+
const view = this._view;
|
|
4123
4705
|
switch (type) {
|
|
4124
4706
|
case "int32":
|
|
4125
4707
|
view.setInt32(byteOffset, value, true);
|
|
@@ -4151,7 +4733,7 @@ var AttributeTransformData = class {
|
|
|
4151
4733
|
}
|
|
4152
4734
|
}
|
|
4153
4735
|
appendParameterValue(value, type) {
|
|
4154
|
-
this.setParameterValue(this.
|
|
4736
|
+
this.setParameterValue(this._size, value, type);
|
|
4155
4737
|
}
|
|
4156
4738
|
_typeSize(type) {
|
|
4157
4739
|
switch (type) {
|
|
@@ -4721,6 +5303,12 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4721
5303
|
return true;
|
|
4722
5304
|
}
|
|
4723
5305
|
decodeAttributes(buffer) {
|
|
5306
|
+
if (!this._prepareSequence()) {
|
|
5307
|
+
return false;
|
|
5308
|
+
}
|
|
5309
|
+
return super.decodeAttributes(buffer);
|
|
5310
|
+
}
|
|
5311
|
+
_prepareSequence() {
|
|
4724
5312
|
if (!this._sequencer) {
|
|
4725
5313
|
return false;
|
|
4726
5314
|
}
|
|
@@ -4735,7 +5323,44 @@ var SequentialAttributeDecodersController = class extends AttributesDecoder {
|
|
|
4735
5323
|
return false;
|
|
4736
5324
|
}
|
|
4737
5325
|
}
|
|
4738
|
-
return
|
|
5326
|
+
return true;
|
|
5327
|
+
}
|
|
5328
|
+
// Two-phase decode (see AttributesDecoder): parse everything that reads the
|
|
5329
|
+
// buffer -- sequence, portable headers (deferring raw rANS symbol decodes),
|
|
5330
|
+
// and the transform parameters -- so the deferred streams of ALL attributes
|
|
5331
|
+
// decoders can then be paired, and finish (zigzag, prediction, inverse
|
|
5332
|
+
// transform) runs per decoder in the original order afterwards. None of the
|
|
5333
|
+
// finish work reads the buffer, and dependents only read parent portable
|
|
5334
|
+
// VALUES in finish, so ordering and output stay identical.
|
|
5335
|
+
decodeAttributesParse(buffer) {
|
|
5336
|
+
if (!this._prepareSequence()) {
|
|
5337
|
+
return false;
|
|
5338
|
+
}
|
|
5339
|
+
const numAttributes = this.getNumAttributes();
|
|
5340
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5341
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeParse(this._pointIds, buffer)) {
|
|
5342
|
+
return false;
|
|
5343
|
+
}
|
|
5344
|
+
}
|
|
5345
|
+
return this.decodeDataNeededByPortableTransforms(buffer);
|
|
5346
|
+
}
|
|
5347
|
+
collectPendingSymbolStreams(out) {
|
|
5348
|
+
const numAttributes = this.getNumAttributes();
|
|
5349
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5350
|
+
const pending = this._sequentialDecoders[i].pendingSymbolStream();
|
|
5351
|
+
if (pending !== null) {
|
|
5352
|
+
out.push(pending);
|
|
5353
|
+
}
|
|
5354
|
+
}
|
|
5355
|
+
}
|
|
5356
|
+
decodeAttributesFinish() {
|
|
5357
|
+
const numAttributes = this.getNumAttributes();
|
|
5358
|
+
for (let i = 0; i < numAttributes; i++) {
|
|
5359
|
+
if (!this._sequentialDecoders[i].decodePortableAttributeFinish()) {
|
|
5360
|
+
return false;
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
return this.transformAttributesToOriginalFormat();
|
|
4739
5364
|
}
|
|
4740
5365
|
getPortableAttribute(pointAttributeId) {
|
|
4741
5366
|
const locId = this.getLocalIdForPointAttribute(pointAttributeId);
|
|
@@ -4862,14 +5487,13 @@ var DepthFirstTraverser = class {
|
|
|
4862
5487
|
// Scratch buffers are set up here rather than in init() so a shared-traversal
|
|
4863
5488
|
// -cache hit — where generateSequence returns before any traversal — skips
|
|
4864
5489
|
// this entirely, including the visited-flag zero-fill (worth ~0.5% on the
|
|
4865
|
-
//
|
|
5490
|
+
// ~500-primitive manablade bundle, which shares attribute corner tables across
|
|
4866
5491
|
// primitives). Uint8Array (0/1) instead of Array(bool): these flags are read
|
|
4867
5492
|
// and written on every corner of the hottest decode loop (traverseFromCorner).
|
|
4868
5493
|
// Decode-scoped scratch: released in bulk at the end of the decode.
|
|
4869
5494
|
onTraversalStart() {
|
|
4870
5495
|
const cornerTable = this._cornerTable;
|
|
4871
5496
|
this._isFaceVisited = scratchUint8Zeroed(cornerTable.numFaces());
|
|
4872
|
-
this._isVertexVisited = scratchUint8Zeroed(cornerTable.numVertices());
|
|
4873
5497
|
this._cornerTraversalStack = scratchInt32(this._numCorners);
|
|
4874
5498
|
}
|
|
4875
5499
|
onTraversalEnd() {
|
|
@@ -4879,7 +5503,6 @@ var DepthFirstTraverser = class {
|
|
|
4879
5503
|
return true;
|
|
4880
5504
|
}
|
|
4881
5505
|
const isFaceVisited = this._isFaceVisited;
|
|
4882
|
-
const isVertexVisited = this._isVertexVisited;
|
|
4883
5506
|
const observer = this._observer;
|
|
4884
5507
|
const cornerToVertex = this._cornerToVertex;
|
|
4885
5508
|
const oppositeCorners = this._oppositeCorners;
|
|
@@ -4903,14 +5526,12 @@ var DepthFirstTraverser = class {
|
|
|
4903
5526
|
if (nextVert === kInvalidVertexIndex2 || prevVert === kInvalidVertexIndex2) {
|
|
4904
5527
|
return false;
|
|
4905
5528
|
}
|
|
4906
|
-
if (
|
|
4907
|
-
isVertexVisited[nextVert] = 1;
|
|
5529
|
+
if (vertexToEncodedMap[nextVert] < 0) {
|
|
4908
5530
|
outPointIds[numOutPoints++] = obsFaces[nextCorner];
|
|
4909
5531
|
encodedToCornerMap[numValues] = nextCorner;
|
|
4910
5532
|
vertexToEncodedMap[nextVert] = numValues++;
|
|
4911
5533
|
}
|
|
4912
|
-
if (
|
|
4913
|
-
isVertexVisited[prevVert] = 1;
|
|
5534
|
+
if (vertexToEncodedMap[prevVert] < 0) {
|
|
4914
5535
|
outPointIds[numOutPoints++] = obsFaces[prevCorner];
|
|
4915
5536
|
encodedToCornerMap[numValues] = prevCorner;
|
|
4916
5537
|
vertexToEncodedMap[prevVert] = numValues++;
|
|
@@ -4931,27 +5552,26 @@ var DepthFirstTraverser = class {
|
|
|
4931
5552
|
encodingData.numValues = numValues;
|
|
4932
5553
|
return false;
|
|
4933
5554
|
}
|
|
4934
|
-
|
|
5555
|
+
const faceBase = faceId * 3;
|
|
5556
|
+
const nextCornerId = cornerId === faceBase + 2 ? faceBase : cornerId + 1;
|
|
5557
|
+
if (vertexToEncodedMap[vertId] < 0) {
|
|
4935
5558
|
const lc = vertexLeftmost[vertId];
|
|
4936
5559
|
let onBoundary = true;
|
|
4937
|
-
if (lc
|
|
5560
|
+
if (lc >= 0) {
|
|
4938
5561
|
const nextLc = lc % 3 === 2 ? lc - 2 : lc + 1;
|
|
4939
5562
|
onBoundary = oppositeCorners[nextLc] < 0;
|
|
4940
5563
|
}
|
|
4941
|
-
isVertexVisited[vertId] = 1;
|
|
4942
5564
|
outPointIds[numOutPoints++] = obsFaces[cornerId];
|
|
4943
5565
|
encodedToCornerMap[numValues] = cornerId;
|
|
4944
5566
|
vertexToEncodedMap[vertId] = numValues++;
|
|
4945
5567
|
if (!onBoundary) {
|
|
4946
|
-
|
|
4947
|
-
cornerId = oppositeCorners[nextCornerId2];
|
|
5568
|
+
cornerId = oppositeCorners[nextCornerId];
|
|
4948
5569
|
faceId = cornerId / 3 | 0;
|
|
4949
5570
|
continue;
|
|
4950
5571
|
}
|
|
4951
5572
|
}
|
|
4952
|
-
const nextCornerId = cornerId % 3 === 2 ? cornerId - 2 : cornerId + 1;
|
|
4953
5573
|
const rightCornerId = oppositeCorners[nextCornerId];
|
|
4954
|
-
const prevCornerId = cornerId
|
|
5574
|
+
const prevCornerId = cornerId === faceBase ? faceBase + 2 : cornerId - 1;
|
|
4955
5575
|
const leftCornerId = oppositeCorners[prevCornerId];
|
|
4956
5576
|
const rightFaceId = rightCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : rightCornerId / 3 | 0;
|
|
4957
5577
|
const leftFaceId = leftCornerId === kInvalidCornerIndex4 ? kInvalidFaceIndex : leftCornerId / 3 | 0;
|
|
@@ -5181,6 +5801,9 @@ var MeshTraversalSequencer = class {
|
|
|
5181
5801
|
_outPointIds;
|
|
5182
5802
|
_numOutPoints;
|
|
5183
5803
|
_traversalCache;
|
|
5804
|
+
// The cache entry the last generateSequence resolved to (hit or store);
|
|
5805
|
+
// carries the shared indicesMap.
|
|
5806
|
+
_cacheEntry;
|
|
5184
5807
|
constructor(mesh, encodingData, traversalCache = null) {
|
|
5185
5808
|
this._mesh = mesh;
|
|
5186
5809
|
this._encodingData = encodingData;
|
|
@@ -5188,6 +5811,7 @@ var MeshTraversalSequencer = class {
|
|
|
5188
5811
|
this._outPointIds = new Int32Array(0);
|
|
5189
5812
|
this._numOutPoints = 0;
|
|
5190
5813
|
this._traversalCache = traversalCache;
|
|
5814
|
+
this._cacheEntry = null;
|
|
5191
5815
|
}
|
|
5192
5816
|
setTraverser(traverser) {
|
|
5193
5817
|
this._traverser = traverser;
|
|
@@ -5202,6 +5826,7 @@ var MeshTraversalSequencer = class {
|
|
|
5202
5826
|
if (cached !== void 0) {
|
|
5203
5827
|
this._outPointIds = cached.pointIds;
|
|
5204
5828
|
this._encodingData.adoptTraversalResult(cached.vertexMap, cached.cornerMap, cached.numValues);
|
|
5829
|
+
this._cacheEntry = cached;
|
|
5205
5830
|
return true;
|
|
5206
5831
|
}
|
|
5207
5832
|
}
|
|
@@ -5217,12 +5842,15 @@ var MeshTraversalSequencer = class {
|
|
|
5217
5842
|
byMethod = /* @__PURE__ */ new Map();
|
|
5218
5843
|
this._traversalCache.set(cacheKey, byMethod);
|
|
5219
5844
|
}
|
|
5220
|
-
|
|
5845
|
+
const entry = {
|
|
5221
5846
|
pointIds: this._outPointIds,
|
|
5222
5847
|
vertexMap: this._encodingData.vertexToEncodedAttributeValueIndexMap,
|
|
5223
5848
|
cornerMap: this._encodingData.encodedAttributeValueIndexToCornerMap,
|
|
5224
|
-
numValues: this._encodingData.numValues
|
|
5225
|
-
|
|
5849
|
+
numValues: this._encodingData.numValues,
|
|
5850
|
+
indicesMap: null
|
|
5851
|
+
};
|
|
5852
|
+
byMethod.set(methodId, entry);
|
|
5853
|
+
this._cacheEntry = entry;
|
|
5226
5854
|
}
|
|
5227
5855
|
return true;
|
|
5228
5856
|
}
|
|
@@ -5233,6 +5861,11 @@ var MeshTraversalSequencer = class {
|
|
|
5233
5861
|
this._outPointIds[this._numOutPoints++] = pointId;
|
|
5234
5862
|
}
|
|
5235
5863
|
updatePointToAttributeIndexMapping(attribute) {
|
|
5864
|
+
const entry = this._cacheEntry;
|
|
5865
|
+
if (entry !== null && entry.indicesMap !== null) {
|
|
5866
|
+
attribute.setExplicitMappingShared(entry.indicesMap);
|
|
5867
|
+
return true;
|
|
5868
|
+
}
|
|
5236
5869
|
const cornerTable = this._traverser.cornerTable();
|
|
5237
5870
|
const numFaces = this._mesh.numFaces();
|
|
5238
5871
|
const numPoints = this._mesh.numPoints();
|
|
@@ -5254,11 +5887,14 @@ var MeshTraversalSequencer = class {
|
|
|
5254
5887
|
}
|
|
5255
5888
|
indicesMap[pointId] = attEntryId;
|
|
5256
5889
|
}
|
|
5890
|
+
if (entry !== null) {
|
|
5891
|
+
entry.indicesMap = attribute.indicesMap;
|
|
5892
|
+
}
|
|
5257
5893
|
return true;
|
|
5258
5894
|
}
|
|
5259
5895
|
_generateSequenceInternal() {
|
|
5260
5896
|
this._numOutPoints = 0;
|
|
5261
|
-
this._outPointIds =
|
|
5897
|
+
this._outPointIds = scratchInt32(this._mesh.numPoints());
|
|
5262
5898
|
this._traverser.onTraversalStart();
|
|
5263
5899
|
const numFaces = this._traverser.cornerTable().numFaces();
|
|
5264
5900
|
for (let i = 0; i < numFaces && this._traverser._numVisitedFaces < numFaces; ++i) {
|
|
@@ -5449,14 +6085,14 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5449
6085
|
this._attributeData = [];
|
|
5450
6086
|
for (let i = 0; i < numAttributeData; ++i) {
|
|
5451
6087
|
const ad = new AttributeData();
|
|
5452
|
-
ad.attributeSeamCorners =
|
|
6088
|
+
ad.attributeSeamCorners = scratchInt32(numFaces * 3);
|
|
5453
6089
|
ad.numSeamCorners = 0;
|
|
5454
6090
|
this._attributeData.push(ad);
|
|
5455
6091
|
}
|
|
5456
6092
|
if (!this._cornerTable.reset(numFaces, this._numEncodedVertices + numEncodedSplitSymbols)) {
|
|
5457
6093
|
return false;
|
|
5458
6094
|
}
|
|
5459
|
-
this._isVertHole =
|
|
6095
|
+
this._isVertHole = scratchUint8Filled(this._numEncodedVertices + numEncodedSplitSymbols, 1);
|
|
5460
6096
|
if (this._decodeHoleAndTopologySplitEvents(this._decoder.buffer()) === -1) {
|
|
5461
6097
|
return false;
|
|
5462
6098
|
}
|
|
@@ -5481,20 +6117,37 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5481
6117
|
}
|
|
5482
6118
|
this._traversalDecoder.done();
|
|
5483
6119
|
let previousConnectivityData = null;
|
|
6120
|
+
let previousSeamCorners = null;
|
|
6121
|
+
let previousSeamCount = 0;
|
|
5484
6122
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
5485
6123
|
const connectivityData = this._attributeData[i].connectivityData;
|
|
5486
|
-
connectivityData.initEmpty(this._cornerTable);
|
|
5487
6124
|
const seamCorners = this._attributeData[i].attributeSeamCorners;
|
|
5488
6125
|
const seamCount = this._attributeData[i].numSeamCorners;
|
|
5489
|
-
|
|
5490
|
-
|
|
6126
|
+
let sameAsPrevious = previousConnectivityData !== null && seamCount === previousSeamCount;
|
|
6127
|
+
if (sameAsPrevious) {
|
|
6128
|
+
const previous = previousSeamCorners;
|
|
6129
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6130
|
+
if (seamCorners[s] !== previous[s]) {
|
|
6131
|
+
sameAsPrevious = false;
|
|
6132
|
+
break;
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
5491
6135
|
}
|
|
5492
|
-
if (
|
|
5493
|
-
connectivityData.
|
|
5494
|
-
} else
|
|
5495
|
-
|
|
6136
|
+
if (sameAsPrevious) {
|
|
6137
|
+
connectivityData.adoptFrom(previousConnectivityData);
|
|
6138
|
+
} else {
|
|
6139
|
+
connectivityData.initEmpty(this._cornerTable);
|
|
6140
|
+
connectivityData.reserveSeamEdges(seamCount);
|
|
6141
|
+
for (let s = 0; s < seamCount; ++s) {
|
|
6142
|
+
connectivityData.addSeamEdge(seamCorners[s]);
|
|
6143
|
+
}
|
|
6144
|
+
if (!connectivityData.recomputeVertices(null, null)) {
|
|
6145
|
+
return false;
|
|
6146
|
+
}
|
|
5496
6147
|
}
|
|
5497
6148
|
previousConnectivityData = connectivityData;
|
|
6149
|
+
previousSeamCorners = seamCorners;
|
|
6150
|
+
previousSeamCount = seamCount;
|
|
5498
6151
|
}
|
|
5499
6152
|
this._posEncodingData.init(this._cornerTable.numVertices());
|
|
5500
6153
|
for (let i = 0; i < this._attributeData.length; ++i) {
|
|
@@ -5533,39 +6186,27 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5533
6186
|
const activeCornerStack = scratchInt32(numSymbols + this._topologySplitData.length + 16);
|
|
5534
6187
|
let activeCornerStackSize = 0;
|
|
5535
6188
|
const topologySplitActiveCorners = /* @__PURE__ */ new Map();
|
|
6189
|
+
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5536
6190
|
const invalidVertices = [];
|
|
5537
6191
|
const removeInvalidVertices = this._attributeData.length === 0;
|
|
5538
6192
|
let maxNumVertices = this._isVertHole.length;
|
|
5539
6193
|
let numFacesDecoded = 0;
|
|
5540
6194
|
const cornerToVertex = this._cornerTable._cornerToVertex;
|
|
5541
6195
|
const oppositeCorners = this._cornerTable._oppositeCorners;
|
|
5542
|
-
const numCorners = this._cornerTable.numCorners();
|
|
5543
|
-
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
5544
|
-
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
5545
|
-
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
5546
|
-
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
5547
|
-
const leftMostCorner = (v) => v < 0 || v >= this._cornerTable._vertexCorners.length ? -1 : this._cornerTable._vertexCorners[v];
|
|
5548
|
-
const swingLeft = (c) => {
|
|
5549
|
-
const n = next(c);
|
|
5550
|
-
const o = opposite(n);
|
|
5551
|
-
return o < 0 ? -1 : next(o);
|
|
5552
|
-
};
|
|
5553
|
-
const swingRight = (c) => {
|
|
5554
|
-
const p = prev(c);
|
|
5555
|
-
const o = opposite(p);
|
|
5556
|
-
return o < 0 ? -1 : prev(o);
|
|
5557
|
-
};
|
|
5558
6196
|
const vc = this._cornerTable;
|
|
6197
|
+
let vertexCorners = vc._vertexCorners;
|
|
6198
|
+
const isVertHole = this._isVertHole;
|
|
6199
|
+
const traversalDecoder = this._traversalDecoder;
|
|
5559
6200
|
for (let symbolId = 0; symbolId < numSymbols; ++symbolId) {
|
|
5560
6201
|
const faceIndex = numFacesDecoded++;
|
|
5561
6202
|
let checkTopologySplit = false;
|
|
5562
|
-
const symbol =
|
|
6203
|
+
const symbol = traversalDecoder.decodeSymbol();
|
|
5563
6204
|
if (symbol === TOPOLOGY_C) {
|
|
5564
6205
|
if (activeCornerStackSize === 0) return -1;
|
|
5565
6206
|
const cornerA = activeCornerStack[activeCornerStackSize - 1];
|
|
5566
6207
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5567
6208
|
const vertexX = cornerToVertex[nA];
|
|
5568
|
-
const lmcX =
|
|
6209
|
+
const lmcX = vertexCorners[vertexX];
|
|
5569
6210
|
const cornerB = lmcX % 3 === 2 ? lmcX - 2 : lmcX + 1;
|
|
5570
6211
|
if (cornerA === cornerB) return -1;
|
|
5571
6212
|
if (oppositeCorners[cornerA] !== kInvalidCornerIndex6 || oppositeCorners[cornerB] !== kInvalidCornerIndex6) {
|
|
@@ -5584,8 +6225,8 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5584
6225
|
cornerToVertex[corner] = vertexX;
|
|
5585
6226
|
cornerToVertex[corner + 1] = vertBNext;
|
|
5586
6227
|
cornerToVertex[corner + 2] = vertAPrev;
|
|
5587
|
-
|
|
5588
|
-
|
|
6228
|
+
vertexCorners[vertAPrev] = corner + 2;
|
|
6229
|
+
isVertHole[vertexX] = 0;
|
|
5589
6230
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5590
6231
|
} else if (symbol === TOPOLOGY_R || symbol === TOPOLOGY_L) {
|
|
5591
6232
|
if (activeCornerStackSize === 0) return -1;
|
|
@@ -5606,14 +6247,20 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5606
6247
|
}
|
|
5607
6248
|
oppositeCorners[oppCorner] = cornerA;
|
|
5608
6249
|
oppositeCorners[cornerA] = oppCorner;
|
|
5609
|
-
|
|
5610
|
-
if (
|
|
6250
|
+
let newVertIndex;
|
|
6251
|
+
if (vc._numVertices < vertexCorners.length) {
|
|
6252
|
+
newVertIndex = vc._numVertices++;
|
|
6253
|
+
} else {
|
|
6254
|
+
newVertIndex = vc.addNewVertex();
|
|
6255
|
+
vertexCorners = vc._vertexCorners;
|
|
6256
|
+
}
|
|
6257
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5611
6258
|
cornerToVertex[oppCorner] = newVertIndex;
|
|
5612
|
-
|
|
6259
|
+
vertexCorners[newVertIndex] = oppCorner;
|
|
5613
6260
|
const pA = cornerA % 3 === 0 ? cornerA + 2 : cornerA - 1;
|
|
5614
6261
|
const vertexR = cornerToVertex[pA];
|
|
5615
6262
|
cornerToVertex[cornerR] = vertexR;
|
|
5616
|
-
|
|
6263
|
+
vertexCorners[vertexR] = cornerR;
|
|
5617
6264
|
const nA = cornerA % 3 === 2 ? cornerA - 2 : cornerA + 1;
|
|
5618
6265
|
cornerToVertex[cornerL] = cornerToVertex[nA];
|
|
5619
6266
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
@@ -5645,11 +6292,11 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5645
6292
|
const pB = cornerB % 3 === 0 ? cornerB + 2 : cornerB - 1;
|
|
5646
6293
|
const vertBPrev = cornerToVertex[pB];
|
|
5647
6294
|
cornerToVertex[corner + 2] = vertBPrev;
|
|
5648
|
-
|
|
6295
|
+
vertexCorners[vertBPrev] = corner + 2;
|
|
5649
6296
|
let cornerN = cornerB % 3 === 2 ? cornerB - 2 : cornerB + 1;
|
|
5650
6297
|
const vertexN = cornerToVertex[cornerN];
|
|
5651
|
-
|
|
5652
|
-
|
|
6298
|
+
traversalDecoder.mergeVertices(vertexP, vertexN);
|
|
6299
|
+
vertexCorners[vertexP] = vertexCorners[vertexN];
|
|
5653
6300
|
const firstCorner = cornerN;
|
|
5654
6301
|
while (cornerN !== kInvalidCornerIndex6) {
|
|
5655
6302
|
cornerToVertex[cornerN] = vertexP;
|
|
@@ -5660,32 +6307,38 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5660
6307
|
return -1;
|
|
5661
6308
|
}
|
|
5662
6309
|
}
|
|
5663
|
-
|
|
6310
|
+
vertexCorners[vertexN] = -1;
|
|
5664
6311
|
if (removeInvalidVertices) {
|
|
5665
6312
|
invalidVertices.push(vertexN);
|
|
5666
6313
|
}
|
|
5667
6314
|
activeCornerStack[activeCornerStackSize - 1] = corner;
|
|
5668
6315
|
} else if (symbol === TOPOLOGY_E) {
|
|
5669
6316
|
const corner = 3 * faceIndex;
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
6317
|
+
let firstVertIndex;
|
|
6318
|
+
if (vc._numVertices + 3 <= vertexCorners.length) {
|
|
6319
|
+
firstVertIndex = vc._numVertices;
|
|
6320
|
+
vc._numVertices += 3;
|
|
6321
|
+
} else {
|
|
6322
|
+
firstVertIndex = vc.addNewVertex();
|
|
6323
|
+
vc.addNewVertex();
|
|
6324
|
+
vc.addNewVertex();
|
|
6325
|
+
vertexCorners = vc._vertexCorners;
|
|
6326
|
+
}
|
|
6327
|
+
if (vc._numVertices > maxNumVertices) return -1;
|
|
5674
6328
|
cornerToVertex[corner] = firstVertIndex;
|
|
5675
6329
|
cornerToVertex[corner + 1] = firstVertIndex + 1;
|
|
5676
6330
|
cornerToVertex[corner + 2] = firstVertIndex + 2;
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
6331
|
+
vertexCorners[firstVertIndex] = corner;
|
|
6332
|
+
vertexCorners[firstVertIndex + 1] = corner + 1;
|
|
6333
|
+
vertexCorners[firstVertIndex + 2] = corner + 2;
|
|
5680
6334
|
activeCornerStack[activeCornerStackSize++] = corner;
|
|
5681
6335
|
checkTopologySplit = true;
|
|
5682
6336
|
} else {
|
|
5683
6337
|
return -1;
|
|
5684
6338
|
}
|
|
5685
|
-
|
|
5686
|
-
if (checkTopologySplit) {
|
|
6339
|
+
traversalDecoder.newActiveCornerReached(activeCornerStack[activeCornerStackSize - 1]);
|
|
6340
|
+
if (checkTopologySplit && this._topologySplitData.length > 0) {
|
|
5687
6341
|
const encoderSymbolId = numSymbols - symbolId - 1;
|
|
5688
|
-
const splitResult = { faceEdge: 0, encoderSplitSymbolId: 0 };
|
|
5689
6342
|
while (this._isTopologySplit(encoderSymbolId, splitResult)) {
|
|
5690
6343
|
if (splitResult.encoderSplitSymbolId < 0) return -1;
|
|
5691
6344
|
const actTopCorner = activeCornerStack[activeCornerStackSize - 1];
|
|
@@ -5700,15 +6353,39 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5700
6353
|
}
|
|
5701
6354
|
}
|
|
5702
6355
|
}
|
|
5703
|
-
if (
|
|
6356
|
+
if (vc._numVertices > maxNumVertices) {
|
|
6357
|
+
return -1;
|
|
6358
|
+
}
|
|
6359
|
+
numFacesDecoded = this._decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded);
|
|
6360
|
+
if (numFacesDecoded === -1) {
|
|
6361
|
+
return -1;
|
|
6362
|
+
}
|
|
6363
|
+
if (numFacesDecoded !== this._cornerTable.numFaces()) {
|
|
5704
6364
|
return -1;
|
|
5705
6365
|
}
|
|
6366
|
+
return this._removeInvalidVertices(invalidVertices);
|
|
6367
|
+
}
|
|
6368
|
+
// Connects the remaining active-stack corners to newly decoded start faces.
|
|
6369
|
+
// Returns the updated decoded-face count, or -1 on malformed input.
|
|
6370
|
+
_decodeStartFaces(activeCornerStack, activeCornerStackSize, numFacesDecoded) {
|
|
6371
|
+
const ct = this._cornerTable;
|
|
6372
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6373
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6374
|
+
const vertexCorners = ct._vertexCorners;
|
|
6375
|
+
const isVertHole = this._isVertHole;
|
|
6376
|
+
const traversalDecoder = this._traversalDecoder;
|
|
6377
|
+
const numCorners = ct.numCorners();
|
|
6378
|
+
const numFaces = ct.numFaces();
|
|
6379
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6380
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6381
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6382
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
5706
6383
|
while (activeCornerStackSize > 0) {
|
|
5707
6384
|
const corner = activeCornerStack[activeCornerStackSize - 1];
|
|
5708
6385
|
activeCornerStackSize--;
|
|
5709
|
-
const interiorFace =
|
|
6386
|
+
const interiorFace = traversalDecoder.decodeStartFaceConfiguration();
|
|
5710
6387
|
if (interiorFace) {
|
|
5711
|
-
if (numFacesDecoded >=
|
|
6388
|
+
if (numFacesDecoded >= numFaces) {
|
|
5712
6389
|
return -1;
|
|
5713
6390
|
}
|
|
5714
6391
|
const cornerA = corner;
|
|
@@ -5734,9 +6411,9 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5734
6411
|
cornerToVertex[newCorner] = vertX;
|
|
5735
6412
|
cornerToVertex[newCorner + 1] = vertP;
|
|
5736
6413
|
cornerToVertex[newCorner + 2] = vertN;
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
6414
|
+
isVertHole[vertX] = 0;
|
|
6415
|
+
isVertHole[vertP] = 0;
|
|
6416
|
+
isVertHole[vertN] = 0;
|
|
5740
6417
|
this._initFaceConfigurations.push(true);
|
|
5741
6418
|
this._initCorners.push(newCorner);
|
|
5742
6419
|
} else {
|
|
@@ -5744,10 +6421,34 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5744
6421
|
this._initCorners.push(corner);
|
|
5745
6422
|
}
|
|
5746
6423
|
}
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
6424
|
+
return numFacesDecoded;
|
|
6425
|
+
}
|
|
6426
|
+
// Removes invalid (isolated) vertices by swapping them with the last valid
|
|
6427
|
+
// vertex in the table, matching C++ mesh_edgebreaker_decoder_impl.cc (the
|
|
6428
|
+
// forward iteration order matters). Returns the final vertex count, or -1.
|
|
6429
|
+
_removeInvalidVertices(invalidVertices) {
|
|
6430
|
+
const ct = this._cornerTable;
|
|
6431
|
+
const cornerToVertex = ct._cornerToVertex;
|
|
6432
|
+
const oppositeCorners = ct._oppositeCorners;
|
|
6433
|
+
const vertexCorners = ct._vertexCorners;
|
|
6434
|
+
const isVertHole = this._isVertHole;
|
|
6435
|
+
const numCorners = ct.numCorners();
|
|
6436
|
+
const next = (c) => c < 0 ? -1 : c % 3 === 2 ? c - 2 : c + 1;
|
|
6437
|
+
const prev = (c) => c < 0 ? -1 : c % 3 === 0 ? c + 2 : c - 1;
|
|
6438
|
+
const vertex = (c) => c < 0 || c >= numCorners ? -1 : cornerToVertex[c];
|
|
6439
|
+
const opposite = (c) => c < 0 || c >= numCorners ? -1 : oppositeCorners[c];
|
|
6440
|
+
const leftMostCorner = (v) => v < 0 || v >= vertexCorners.length ? -1 : vertexCorners[v];
|
|
6441
|
+
const swingLeft = (c) => {
|
|
6442
|
+
const n = next(c);
|
|
6443
|
+
const o = opposite(n);
|
|
6444
|
+
return o < 0 ? -1 : next(o);
|
|
6445
|
+
};
|
|
6446
|
+
const swingRight = (c) => {
|
|
6447
|
+
const p = prev(c);
|
|
6448
|
+
const o = opposite(p);
|
|
6449
|
+
return o < 0 ? -1 : prev(o);
|
|
6450
|
+
};
|
|
6451
|
+
let numVertices = ct.numVertices();
|
|
5751
6452
|
for (let ivIdx = 0; ivIdx < invalidVertices.length; ++ivIdx) {
|
|
5752
6453
|
const invalidVert = invalidVertices[ivIdx];
|
|
5753
6454
|
let srcVert = numVertices - 1;
|
|
@@ -5777,10 +6478,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5777
6478
|
cid = swingRight(cid);
|
|
5778
6479
|
}
|
|
5779
6480
|
}
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
6481
|
+
vertexCorners[invalidVert] = leftMostCorner(srcVert);
|
|
6482
|
+
vertexCorners[srcVert] = -1;
|
|
6483
|
+
isVertHole[invalidVert] = isVertHole[srcVert];
|
|
6484
|
+
isVertHole[srcVert] = 0;
|
|
5784
6485
|
numVertices--;
|
|
5785
6486
|
}
|
|
5786
6487
|
return numVertices;
|
|
@@ -5823,14 +6524,55 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5823
6524
|
// per-corner decodeNextBit work. Within each face the three corners are
|
|
5824
6525
|
// visited in encoder edge order [base, next, prev] = [c, c+1, c+2] (the
|
|
5825
6526
|
// caller always starts a face at its base corner, so next/prev need no wrap).
|
|
6527
|
+
//
|
|
6528
|
+
// The face comparison the C++ makes -- floor(oppCorner/3) >= floor(cc/3) for
|
|
6529
|
+
// the face's base corner -- is just `oppCorner >= faceBaseCorner`, since the
|
|
6530
|
+
// base corner is a multiple of 3. That removes the per-corner division; the
|
|
6531
|
+
// invalid-corner case (-1) is still handled by the branch above it.
|
|
5826
6532
|
_decodeAttributeConnectivities() {
|
|
5827
6533
|
const oppositeCorners = this._cornerTable.oppositeCornerArray();
|
|
5828
6534
|
const attributeData = this._attributeData;
|
|
5829
6535
|
const numAttrData = attributeData.length;
|
|
5830
6536
|
const connectivityDecoders = this._traversalDecoder._attributeConnectivityDecoders;
|
|
5831
6537
|
const numCorners = this._cornerTable.numCorners();
|
|
6538
|
+
if (numAttrData === 1) {
|
|
6539
|
+
const ad = attributeData[0];
|
|
6540
|
+
const seamCorners = ad.attributeSeamCorners;
|
|
6541
|
+
let numSeamCorners = ad.numSeamCorners;
|
|
6542
|
+
const decoder = connectivityDecoders[0];
|
|
6543
|
+
const ans = decoder.ansDecoder_;
|
|
6544
|
+
const p = decoder.p_;
|
|
6545
|
+
const buf = ans.buf;
|
|
6546
|
+
const bufStart = ans.bufStart;
|
|
6547
|
+
let state = ans.state;
|
|
6548
|
+
let bufOffset = ans.bufOffset;
|
|
6549
|
+
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
6550
|
+
for (let k = 0; k < 3; ++k) {
|
|
6551
|
+
const cc = corner + k;
|
|
6552
|
+
const oppCorner = oppositeCorners[cc];
|
|
6553
|
+
if (oppCorner === kInvalidCornerIndex6) {
|
|
6554
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6555
|
+
} else if (oppCorner >= corner) {
|
|
6556
|
+
if (state < ANS_L_BASE && bufOffset > bufStart) {
|
|
6557
|
+
state = state << 8 | buf[--bufOffset];
|
|
6558
|
+
}
|
|
6559
|
+
const rem = state & 255;
|
|
6560
|
+
const xn = (state >>> 8) * p;
|
|
6561
|
+
if (rem < p) {
|
|
6562
|
+
state = xn + rem;
|
|
6563
|
+
seamCorners[numSeamCorners++] = cc;
|
|
6564
|
+
} else {
|
|
6565
|
+
state = state - xn - p;
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
}
|
|
6570
|
+
ans.state = state;
|
|
6571
|
+
ans.bufOffset = bufOffset;
|
|
6572
|
+
ad.numSeamCorners = numSeamCorners;
|
|
6573
|
+
return;
|
|
6574
|
+
}
|
|
5832
6575
|
for (let corner = 0; corner < numCorners; corner += 3) {
|
|
5833
|
-
const srcFaceId = corner / 3 | 0;
|
|
5834
6576
|
for (let k = 0; k < 3; ++k) {
|
|
5835
6577
|
const cc = corner + k;
|
|
5836
6578
|
const oppCorner = oppositeCorners[cc];
|
|
@@ -5839,7 +6581,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5839
6581
|
const ad = attributeData[i];
|
|
5840
6582
|
ad.attributeSeamCorners[ad.numSeamCorners++] = cc;
|
|
5841
6583
|
}
|
|
5842
|
-
} else if (
|
|
6584
|
+
} else if (oppCorner >= corner) {
|
|
5843
6585
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5844
6586
|
if (connectivityDecoders[i].decodeNextBit()) {
|
|
5845
6587
|
const ad = attributeData[i];
|
|
@@ -5870,10 +6612,10 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5870
6612
|
const attributeData = this._attributeData;
|
|
5871
6613
|
const numAttrData = attributeData.length;
|
|
5872
6614
|
let numPoints = 0;
|
|
5873
|
-
const cornerToPointMap =
|
|
6615
|
+
const cornerToPointMap = scratchInt32(ct.numCorners());
|
|
5874
6616
|
const numVertices = ct.numVertices();
|
|
5875
6617
|
const vertexLeftmost = ct.vertexLeftmostCornerArray();
|
|
5876
|
-
const
|
|
6618
|
+
const swingRight = ct.swingRightArray();
|
|
5877
6619
|
const _baseCornerToVertex = ct.cornerToVertexArray();
|
|
5878
6620
|
const isVertHole = this._isVertHole;
|
|
5879
6621
|
const attCornerToVertex = new Array(numAttrData);
|
|
@@ -5887,7 +6629,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5887
6629
|
if (numAttrData === 1) {
|
|
5888
6630
|
anyAttVertexOnSeam = attVertexOnSeam[0];
|
|
5889
6631
|
} else {
|
|
5890
|
-
anyAttVertexOnSeam =
|
|
6632
|
+
anyAttVertexOnSeam = scratchUint8Zeroed(numVertices);
|
|
5891
6633
|
for (let i = 0; i < numAttrData; ++i) {
|
|
5892
6634
|
const attSeam = attVertexOnSeam[i];
|
|
5893
6635
|
for (let v = 0; v < numVertices; ++v) {
|
|
@@ -5905,37 +6647,24 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5905
6647
|
const initialC = c;
|
|
5906
6648
|
const pointId = numPoints++;
|
|
5907
6649
|
cornerToPointMap[initialC] = pointId;
|
|
5908
|
-
|
|
5909
|
-
let pv = rem === 0 ? initialC + 2 : initialC - 1;
|
|
5910
|
-
let opp = baseOpp[pv];
|
|
5911
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6650
|
+
c = swingRight[initialC];
|
|
5912
6651
|
while (c !== kInvalidCornerIndex6 && c !== initialC) {
|
|
5913
6652
|
cornerToPointMap[c] = pointId;
|
|
5914
|
-
|
|
5915
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5916
|
-
opp = baseOpp[pv];
|
|
5917
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6653
|
+
c = swingRight[c];
|
|
5918
6654
|
}
|
|
5919
6655
|
} else {
|
|
5920
6656
|
let deduplicationFirstCorner = c;
|
|
5921
|
-
let rem, pv, opp;
|
|
5922
6657
|
if (!isVertHole[v]) {
|
|
5923
6658
|
if (numAttrData === 1) {
|
|
5924
6659
|
const vertId = singleAttC2V[c];
|
|
5925
|
-
|
|
5926
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5927
|
-
opp = baseOpp[pv];
|
|
5928
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6660
|
+
let actC = swingRight[c];
|
|
5929
6661
|
while (actC !== c) {
|
|
5930
6662
|
if (actC === kInvalidCornerIndex6) return false;
|
|
5931
6663
|
if (singleAttC2V[actC] !== vertId) {
|
|
5932
6664
|
deduplicationFirstCorner = actC;
|
|
5933
6665
|
break;
|
|
5934
6666
|
}
|
|
5935
|
-
|
|
5936
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5937
|
-
opp = baseOpp[pv];
|
|
5938
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6667
|
+
actC = swingRight[actC];
|
|
5939
6668
|
}
|
|
5940
6669
|
} else {
|
|
5941
6670
|
for (let i = 0; i < numAttrData; ++i) {
|
|
@@ -5944,10 +6673,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5944
6673
|
}
|
|
5945
6674
|
const attC2V = attCornerToVertex[i];
|
|
5946
6675
|
const vertId = attC2V[c];
|
|
5947
|
-
|
|
5948
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5949
|
-
opp = baseOpp[pv];
|
|
5950
|
-
let actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6676
|
+
let actC = swingRight[c];
|
|
5951
6677
|
let seamFound = false;
|
|
5952
6678
|
while (actC !== c) {
|
|
5953
6679
|
if (actC === kInvalidCornerIndex6) return false;
|
|
@@ -5956,10 +6682,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5956
6682
|
seamFound = true;
|
|
5957
6683
|
break;
|
|
5958
6684
|
}
|
|
5959
|
-
|
|
5960
|
-
pv = rem === 0 ? actC + 2 : actC - 1;
|
|
5961
|
-
opp = baseOpp[pv];
|
|
5962
|
-
actC = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6685
|
+
actC = swingRight[actC];
|
|
5963
6686
|
}
|
|
5964
6687
|
if (seamFound) break;
|
|
5965
6688
|
}
|
|
@@ -5968,10 +6691,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5968
6691
|
c = deduplicationFirstCorner;
|
|
5969
6692
|
cornerToPointMap[c] = numPoints++;
|
|
5970
6693
|
let prevC = c;
|
|
5971
|
-
|
|
5972
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5973
|
-
opp = baseOpp[pv];
|
|
5974
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6694
|
+
c = swingRight[c];
|
|
5975
6695
|
while (c !== kInvalidCornerIndex6 && c !== deduplicationFirstCorner) {
|
|
5976
6696
|
let attributeSeam;
|
|
5977
6697
|
if (numAttrData === 1) {
|
|
@@ -5992,10 +6712,7 @@ var MeshEdgebreakerDecoderImpl = class {
|
|
|
5992
6712
|
cornerToPointMap[c] = cornerToPointMap[prevC];
|
|
5993
6713
|
}
|
|
5994
6714
|
prevC = c;
|
|
5995
|
-
|
|
5996
|
-
pv = rem === 0 ? c + 2 : c - 1;
|
|
5997
|
-
opp = baseOpp[pv];
|
|
5998
|
-
c = opp < 0 ? kInvalidCornerIndex6 : opp % 3 === 0 ? opp + 2 : opp - 1;
|
|
6715
|
+
c = swingRight[c];
|
|
5999
6716
|
}
|
|
6000
6717
|
}
|
|
6001
6718
|
}
|
|
@@ -6021,8 +6738,8 @@ var MeshAttributeIndicesEncodingData = class {
|
|
|
6021
6738
|
this._numValues = 0;
|
|
6022
6739
|
}
|
|
6023
6740
|
init(numVertices) {
|
|
6024
|
-
this._vertexToEncodedAttributeValueIndexMap =
|
|
6025
|
-
this._encodedAttributeValueIndexToCornerMap =
|
|
6741
|
+
this._vertexToEncodedAttributeValueIndexMap = scratchInt32Filled(numVertices, -1);
|
|
6742
|
+
this._encodedAttributeValueIndexToCornerMap = scratchInt32(numVertices);
|
|
6026
6743
|
this._numValues = 0;
|
|
6027
6744
|
}
|
|
6028
6745
|
// Adopts a traversal result from an identical corner table, avoiding a
|
|
@@ -6072,6 +6789,8 @@ var CornerTable = class {
|
|
|
6072
6789
|
// corner -> opposite corner
|
|
6073
6790
|
_vertexCorners;
|
|
6074
6791
|
// vertex -> left-most corner
|
|
6792
|
+
_swingRight;
|
|
6793
|
+
// corner -> next corner around its vertex, CW
|
|
6075
6794
|
constructor() {
|
|
6076
6795
|
this._numFaces = 0;
|
|
6077
6796
|
this._numCorners = 0;
|
|
@@ -6079,16 +6798,42 @@ var CornerTable = class {
|
|
|
6079
6798
|
this._cornerToVertex = null;
|
|
6080
6799
|
this._oppositeCorners = null;
|
|
6081
6800
|
this._vertexCorners = null;
|
|
6801
|
+
this._swingRight = null;
|
|
6082
6802
|
}
|
|
6083
6803
|
reset(numFaces, numVertices) {
|
|
6084
6804
|
this._numFaces = numFaces;
|
|
6085
6805
|
this._numCorners = numFaces * 3;
|
|
6086
6806
|
this._numVertices = 0;
|
|
6087
|
-
this._cornerToVertex =
|
|
6088
|
-
this._oppositeCorners =
|
|
6089
|
-
this._vertexCorners =
|
|
6807
|
+
this._cornerToVertex = scratchInt32Filled(this._numCorners, -1);
|
|
6808
|
+
this._oppositeCorners = scratchInt32Filled(this._numCorners, -1);
|
|
6809
|
+
this._vertexCorners = scratchInt32Filled(numVertices, -1);
|
|
6810
|
+
this._swingRight = null;
|
|
6090
6811
|
return true;
|
|
6091
6812
|
}
|
|
6813
|
+
// swingRight(c) = previous(opposite(previous(c))) for every corner. Walking
|
|
6814
|
+
// the corner ring of a vertex is the inner loop of both the attribute-vertex
|
|
6815
|
+
// recompute and the point assignment, and each of those passes otherwise
|
|
6816
|
+
// pays two modulus-by-3 chains per step on top of the opposite lookup. Built
|
|
6817
|
+
// lazily -- callers only reach it once connectivity is final -- from
|
|
6818
|
+
// decode-scoped scratch, and dropped by reset().
|
|
6819
|
+
swingRightArray() {
|
|
6820
|
+
let table = this._swingRight;
|
|
6821
|
+
if (table === null) {
|
|
6822
|
+
const numCorners = this._numCorners;
|
|
6823
|
+
const opposite = this._oppositeCorners;
|
|
6824
|
+
table = scratchInt32(numCorners);
|
|
6825
|
+
for (let c = 0; c < numCorners; c += 3) {
|
|
6826
|
+
let o = opposite[c + 2];
|
|
6827
|
+
table[c] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6828
|
+
o = opposite[c];
|
|
6829
|
+
table[c + 1] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6830
|
+
o = opposite[c + 1];
|
|
6831
|
+
table[c + 2] = o < 0 ? kInvalidCornerIndex6 : o % 3 === 0 ? o + 2 : o - 1;
|
|
6832
|
+
}
|
|
6833
|
+
this._swingRight = table;
|
|
6834
|
+
}
|
|
6835
|
+
return table;
|
|
6836
|
+
}
|
|
6092
6837
|
numFaces() {
|
|
6093
6838
|
return this._numFaces;
|
|
6094
6839
|
}
|
|
@@ -6132,8 +6877,7 @@ var CornerTable = class {
|
|
|
6132
6877
|
this._numVertices++;
|
|
6133
6878
|
if (newVertex >= this._vertexCorners.length) {
|
|
6134
6879
|
const newCapacity = Math.max(newVertex + 1, this._vertexCorners.length * 2, 64);
|
|
6135
|
-
const newArr =
|
|
6136
|
-
newArr.fill(-1);
|
|
6880
|
+
const newArr = scratchInt32Filled(newCapacity, -1);
|
|
6137
6881
|
newArr.set(this._vertexCorners);
|
|
6138
6882
|
this._vertexCorners = newArr;
|
|
6139
6883
|
}
|
|
@@ -6164,6 +6908,10 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6164
6908
|
_attributeConnectivityDecoders;
|
|
6165
6909
|
_numAttributeData;
|
|
6166
6910
|
_decoderImpl;
|
|
6911
|
+
// _symbolBuffer's bit cursor, captured once bit decoding starts: decodeSymbol
|
|
6912
|
+
// runs per decoded face and would otherwise reach it through two property
|
|
6913
|
+
// loads and a method call per read.
|
|
6914
|
+
_symbolBits;
|
|
6167
6915
|
constructor() {
|
|
6168
6916
|
this._buffer = new DecoderBuffer();
|
|
6169
6917
|
this._symbolBuffer = new DecoderBuffer();
|
|
@@ -6171,6 +6919,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6171
6919
|
this._attributeConnectivityDecoders = null;
|
|
6172
6920
|
this._numAttributeData = 0;
|
|
6173
6921
|
this._decoderImpl = null;
|
|
6922
|
+
this._symbolBits = null;
|
|
6174
6923
|
}
|
|
6175
6924
|
init(decoder) {
|
|
6176
6925
|
this._decoderImpl = decoder;
|
|
@@ -6205,6 +6954,21 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6205
6954
|
return this._startFaceDecoder.decodeNextBit() ? true : false;
|
|
6206
6955
|
}
|
|
6207
6956
|
decodeSymbol() {
|
|
6957
|
+
const bd = this._symbolBits;
|
|
6958
|
+
if (bd !== null) {
|
|
6959
|
+
const buf = bd._bitBuffer;
|
|
6960
|
+
const off = bd._bitOffset;
|
|
6961
|
+
const byteOffset = off >> 3;
|
|
6962
|
+
if (byteOffset + 4 < bd._byteLength) {
|
|
6963
|
+
const bits = (buf[byteOffset] | buf[byteOffset + 1] << 8 | buf[byteOffset + 2] << 16 | buf[byteOffset + 3] << 24) >>> (off & 7) & 7;
|
|
6964
|
+
if ((bits & 1) === TOPOLOGY_C) {
|
|
6965
|
+
bd._bitOffset = off + 1;
|
|
6966
|
+
return TOPOLOGY_C;
|
|
6967
|
+
}
|
|
6968
|
+
bd._bitOffset = off + 3;
|
|
6969
|
+
return bits;
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6208
6972
|
let symbol = this._symbolBuffer.decodeLeastSignificantBits32(1);
|
|
6209
6973
|
if (symbol === TOPOLOGY_C) {
|
|
6210
6974
|
return symbol;
|
|
@@ -6234,6 +6998,7 @@ var MeshEdgebreakerTraversalDecoder = class {
|
|
|
6234
6998
|
if (traversalSize === void 0) {
|
|
6235
6999
|
return false;
|
|
6236
7000
|
}
|
|
7001
|
+
this._symbolBits = this._symbolBuffer._bitDecoder;
|
|
6237
7002
|
this._buffer.init(
|
|
6238
7003
|
this._symbolBuffer.dataHead,
|
|
6239
7004
|
this._symbolBuffer.remainingSize,
|
|
@@ -6386,7 +7151,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6386
7151
|
_maxValence;
|
|
6387
7152
|
_vertexValences;
|
|
6388
7153
|
_contextSymbols;
|
|
7154
|
+
// Int32Array, not number[]: read and written once per decoded symbol.
|
|
6389
7155
|
_contextCounters;
|
|
7156
|
+
// corner -> vertex of _cornerTable, cached at init(); the array is created
|
|
7157
|
+
// once by CornerTable.reset() before the traversal decoder is initialized and
|
|
7158
|
+
// never replaced, so the per-symbol hot path can read it without two property
|
|
7159
|
+
// loads.
|
|
7160
|
+
_cornerToVertex;
|
|
6390
7161
|
constructor() {
|
|
6391
7162
|
super();
|
|
6392
7163
|
this._cornerTable = null;
|
|
@@ -6397,11 +7168,13 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6397
7168
|
this._maxValence = 7;
|
|
6398
7169
|
this._vertexValences = new Int32Array(0);
|
|
6399
7170
|
this._contextSymbols = [];
|
|
6400
|
-
this._contextCounters =
|
|
7171
|
+
this._contextCounters = new Int32Array(0);
|
|
7172
|
+
this._cornerToVertex = new Int32Array(0);
|
|
6401
7173
|
}
|
|
6402
7174
|
init(decoder) {
|
|
6403
7175
|
super.init(decoder);
|
|
6404
7176
|
this._cornerTable = decoder.getCornerTable();
|
|
7177
|
+
this._cornerToVertex = this._cornerTable._cornerToVertex;
|
|
6405
7178
|
}
|
|
6406
7179
|
setNumEncodedVertices(numVertices) {
|
|
6407
7180
|
this._numVertices = numVertices;
|
|
@@ -6419,10 +7192,11 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6419
7192
|
if (this._numVertices < 0) {
|
|
6420
7193
|
return false;
|
|
6421
7194
|
}
|
|
6422
|
-
this._vertexValences =
|
|
7195
|
+
this._vertexValences = scratchInt32Filled(this._numVertices, 0);
|
|
6423
7196
|
const numUniqueValences = this._maxValence - this._minValence + 1;
|
|
6424
7197
|
this._contextSymbols = new Array(numUniqueValences);
|
|
6425
|
-
this._contextCounters = new
|
|
7198
|
+
this._contextCounters = new Int32Array(numUniqueValences);
|
|
7199
|
+
const pending = [];
|
|
6426
7200
|
for (let i = 0; i < numUniqueValences; ++i) {
|
|
6427
7201
|
const numSymbols = decodeVarint(outBuffer);
|
|
6428
7202
|
if (numSymbols === void 0) {
|
|
@@ -6432,16 +7206,72 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6432
7206
|
return false;
|
|
6433
7207
|
}
|
|
6434
7208
|
if (numSymbols > 0) {
|
|
6435
|
-
this._contextSymbols[i] =
|
|
6436
|
-
|
|
7209
|
+
this._contextSymbols[i] = scratchUint32(numSymbols);
|
|
7210
|
+
const scheme = outBuffer.decodeUint8();
|
|
7211
|
+
if (scheme === SymbolCodingMethod.SYMBOL_CODING_TAGGED) {
|
|
7212
|
+
if (!decodeTaggedSymbols(numSymbols, 1, outBuffer, this._contextSymbols[i])) {
|
|
7213
|
+
return false;
|
|
7214
|
+
}
|
|
7215
|
+
this._contextCounters[i] = numSymbols;
|
|
7216
|
+
continue;
|
|
7217
|
+
}
|
|
7218
|
+
if (scheme !== SymbolCodingMethod.SYMBOL_CODING_RAW) {
|
|
6437
7219
|
return false;
|
|
6438
7220
|
}
|
|
7221
|
+
const maxBitLength = outBuffer.decodeUint8();
|
|
7222
|
+
if (maxBitLength === void 0 || maxBitLength < 1 || maxBitLength > 18) {
|
|
7223
|
+
return false;
|
|
7224
|
+
}
|
|
7225
|
+
const decoder = new RAnsSymbolDecoder(maxBitLength);
|
|
7226
|
+
if (!decoder.create(outBuffer)) {
|
|
7227
|
+
return false;
|
|
7228
|
+
}
|
|
7229
|
+
if (decoder.numSymbols === 0) {
|
|
7230
|
+
return false;
|
|
7231
|
+
}
|
|
7232
|
+
if (!decoder.startDecoding(outBuffer)) {
|
|
7233
|
+
return false;
|
|
7234
|
+
}
|
|
7235
|
+
pending.push({ decoder, out: this._contextSymbols[i], count: numSymbols });
|
|
6439
7236
|
this._contextCounters[i] = numSymbols;
|
|
6440
7237
|
} else {
|
|
6441
7238
|
this._contextSymbols[i] = new Uint32Array(0);
|
|
6442
7239
|
this._contextCounters[i] = 0;
|
|
6443
7240
|
}
|
|
6444
7241
|
}
|
|
7242
|
+
const allU8 = pending.every((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
|
|
7243
|
+
let p = 0;
|
|
7244
|
+
if (allU8) {
|
|
7245
|
+
while (pending.length - p >= 3) {
|
|
7246
|
+
const a = pending[p];
|
|
7247
|
+
const b = pending[p + 1];
|
|
7248
|
+
const c = pending[p + 2];
|
|
7249
|
+
ransDecodeSymbolsTrioU8(
|
|
7250
|
+
a.decoder.ans_,
|
|
7251
|
+
a.out,
|
|
7252
|
+
a.count,
|
|
7253
|
+
b.decoder.ans_,
|
|
7254
|
+
b.out,
|
|
7255
|
+
b.count,
|
|
7256
|
+
c.decoder.ans_,
|
|
7257
|
+
c.out,
|
|
7258
|
+
c.count
|
|
7259
|
+
);
|
|
7260
|
+
p += 3;
|
|
7261
|
+
}
|
|
7262
|
+
if (pending.length - p === 2) {
|
|
7263
|
+
const a = pending[p];
|
|
7264
|
+
const b = pending[p + 1];
|
|
7265
|
+
ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
|
|
7266
|
+
p += 2;
|
|
7267
|
+
}
|
|
7268
|
+
}
|
|
7269
|
+
for (; p < pending.length; ++p) {
|
|
7270
|
+
pending[p].decoder.ans_.decodeSymbols(pending[p].out, pending[p].count);
|
|
7271
|
+
}
|
|
7272
|
+
for (const entry of pending) {
|
|
7273
|
+
entry.decoder.endDecoding();
|
|
7274
|
+
}
|
|
6445
7275
|
return true;
|
|
6446
7276
|
}
|
|
6447
7277
|
decodeSymbol() {
|
|
@@ -6461,7 +7291,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
|
|
|
6461
7291
|
return this._lastSymbol;
|
|
6462
7292
|
}
|
|
6463
7293
|
newActiveCornerReached(corner) {
|
|
6464
|
-
const cornerToVertex = this.
|
|
7294
|
+
const cornerToVertex = this._cornerToVertex;
|
|
6465
7295
|
const valences = this._vertexValences;
|
|
6466
7296
|
const next = corner % 3 === 2 ? corner - 2 : corner + 1;
|
|
6467
7297
|
const prev = corner % 3 === 0 ? corner + 2 : corner - 1;
|