@playcanvas/splat-transform 1.9.0 → 1.9.2
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 +1 -1
- package/dist/cli.mjs +1547 -110
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +1523 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1523 -100
- package/dist/index.mjs.map +1 -1
- package/dist/lib/index.d.cts +2 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/spatial/kd-tree.d.ts +1 -0
- package/dist/lib/types.d.ts +4 -0
- package/dist/lib/utils/logger.d.ts +6 -0
- package/dist/lib/voxel/collision-glb.d.ts +12 -0
- package/dist/lib/voxel/index.d.ts +2 -0
- package/dist/lib/voxel/marching-cubes.d.ts +25 -0
- package/dist/lib/writers/write-voxel.d.ts +7 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -742,6 +742,16 @@ class Progress {
|
|
|
742
742
|
if (!quiet)
|
|
743
743
|
impl.onProgress(this.currentNode);
|
|
744
744
|
}
|
|
745
|
+
/**
|
|
746
|
+
* Cancel the current progress node, popping it from the stack without
|
|
747
|
+
* completing remaining steps. Use this before early exits (e.g. break)
|
|
748
|
+
* to keep the progress stack balanced.
|
|
749
|
+
*/
|
|
750
|
+
cancel() {
|
|
751
|
+
if (!this.currentNode)
|
|
752
|
+
return;
|
|
753
|
+
this.currentNode = this.currentNode.parent;
|
|
754
|
+
}
|
|
745
755
|
/**
|
|
746
756
|
* Advance to the next step. Auto-increments the step counter.
|
|
747
757
|
* Auto-ends when all steps are complete.
|
|
@@ -929,33 +939,74 @@ const sortMortonOrder = (dataTable, indices) => {
|
|
|
929
939
|
generate(indices);
|
|
930
940
|
};
|
|
931
941
|
|
|
942
|
+
const nthElement = (arr, lo, hi, k, values) => {
|
|
943
|
+
while (lo < hi) {
|
|
944
|
+
const mid = (lo + hi) >> 1;
|
|
945
|
+
const va = values[arr[lo]], vb = values[arr[mid]], vc = values[arr[hi]];
|
|
946
|
+
let pivotIdx;
|
|
947
|
+
if ((vb - va) * (vc - vb) >= 0)
|
|
948
|
+
pivotIdx = mid;
|
|
949
|
+
else if ((va - vb) * (vc - va) >= 0)
|
|
950
|
+
pivotIdx = lo;
|
|
951
|
+
else
|
|
952
|
+
pivotIdx = hi;
|
|
953
|
+
const pivotVal = values[arr[pivotIdx]];
|
|
954
|
+
let tmp = arr[pivotIdx];
|
|
955
|
+
arr[pivotIdx] = arr[hi];
|
|
956
|
+
arr[hi] = tmp;
|
|
957
|
+
let store = lo;
|
|
958
|
+
for (let i = lo; i < hi; i++) {
|
|
959
|
+
if (values[arr[i]] < pivotVal) {
|
|
960
|
+
tmp = arr[i];
|
|
961
|
+
arr[i] = arr[store];
|
|
962
|
+
arr[store] = tmp;
|
|
963
|
+
store++;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
tmp = arr[store];
|
|
967
|
+
arr[store] = arr[hi];
|
|
968
|
+
arr[hi] = tmp;
|
|
969
|
+
if (store === k)
|
|
970
|
+
return;
|
|
971
|
+
else if (store < k)
|
|
972
|
+
lo = store + 1;
|
|
973
|
+
else
|
|
974
|
+
hi = store - 1;
|
|
975
|
+
}
|
|
976
|
+
};
|
|
932
977
|
class KdTree {
|
|
933
978
|
centroids;
|
|
934
979
|
root;
|
|
980
|
+
colData;
|
|
935
981
|
constructor(centroids) {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
982
|
+
const numCols = centroids.numColumns;
|
|
983
|
+
const colData = centroids.columns.map(c => c.data);
|
|
984
|
+
const indices = new Uint32Array(centroids.numRows);
|
|
985
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
986
|
+
indices[i] = i;
|
|
987
|
+
}
|
|
988
|
+
const build = (lo, hi, depth) => {
|
|
989
|
+
const count = hi - lo + 1;
|
|
990
|
+
if (count === 1) {
|
|
991
|
+
return { index: indices[lo], count: 1 };
|
|
992
|
+
}
|
|
993
|
+
const values = colData[depth % numCols];
|
|
994
|
+
if (count === 2) {
|
|
995
|
+
if (values[indices[lo]] > values[indices[hi]]) {
|
|
996
|
+
const tmp = indices[lo];
|
|
997
|
+
indices[lo] = indices[hi];
|
|
998
|
+
indices[hi] = tmp;
|
|
999
|
+
}
|
|
947
1000
|
return {
|
|
948
|
-
index: indices[
|
|
1001
|
+
index: indices[lo],
|
|
949
1002
|
count: 2,
|
|
950
|
-
right: {
|
|
951
|
-
index: indices[1],
|
|
952
|
-
count: 1
|
|
953
|
-
}
|
|
1003
|
+
right: { index: indices[hi], count: 1 }
|
|
954
1004
|
};
|
|
955
1005
|
}
|
|
956
|
-
const mid =
|
|
957
|
-
|
|
958
|
-
const
|
|
1006
|
+
const mid = lo + (count >> 1);
|
|
1007
|
+
nthElement(indices, lo, hi, mid, values);
|
|
1008
|
+
const left = build(lo, mid - 1, depth + 1);
|
|
1009
|
+
const right = build(mid + 1, hi, depth + 1);
|
|
959
1010
|
return {
|
|
960
1011
|
index: indices[mid],
|
|
961
1012
|
count: 1 + left.count + right.count,
|
|
@@ -963,48 +1014,39 @@ class KdTree {
|
|
|
963
1014
|
right
|
|
964
1015
|
};
|
|
965
1016
|
};
|
|
966
|
-
const indices = new Uint32Array(centroids.numRows);
|
|
967
|
-
for (let i = 0; i < indices.length; ++i) {
|
|
968
|
-
indices[i] = i;
|
|
969
|
-
}
|
|
970
1017
|
this.centroids = centroids;
|
|
971
|
-
this.
|
|
1018
|
+
this.colData = colData;
|
|
1019
|
+
this.root = build(0, indices.length - 1, 0);
|
|
972
1020
|
}
|
|
973
1021
|
findNearest(point, filterFunc) {
|
|
974
|
-
const
|
|
975
|
-
const
|
|
976
|
-
const calcDistance = (index) => {
|
|
977
|
-
let l = 0;
|
|
978
|
-
for (let i = 0; i < numColumns; ++i) {
|
|
979
|
-
const v = centroids.columns[i].data[index] - point[i];
|
|
980
|
-
l += v * v;
|
|
981
|
-
}
|
|
982
|
-
return l;
|
|
983
|
-
};
|
|
1022
|
+
const colData = this.colData;
|
|
1023
|
+
const numCols = colData.length;
|
|
984
1024
|
let mind = Infinity;
|
|
985
1025
|
let mini = -1;
|
|
986
1026
|
let cnt = 0;
|
|
987
|
-
const recurse = (node,
|
|
988
|
-
const
|
|
989
|
-
const distance = point[axis] - centroids.columns[axis].data[node.index];
|
|
1027
|
+
const recurse = (node, axis) => {
|
|
1028
|
+
const distance = point[axis] - colData[axis][node.index];
|
|
990
1029
|
const next = (distance > 0) ? node.right : node.left;
|
|
1030
|
+
const nextAxis = axis + 1 < numCols ? axis + 1 : 0;
|
|
991
1031
|
cnt++;
|
|
992
1032
|
if (next) {
|
|
993
|
-
recurse(next,
|
|
1033
|
+
recurse(next, nextAxis);
|
|
994
1034
|
}
|
|
995
|
-
// check index
|
|
996
1035
|
if (!filterFunc || filterFunc(node.index)) {
|
|
997
|
-
|
|
1036
|
+
let thisd = 0;
|
|
1037
|
+
for (let c = 0; c < numCols; c++) {
|
|
1038
|
+
const v = colData[c][node.index] - point[c];
|
|
1039
|
+
thisd += v * v;
|
|
1040
|
+
}
|
|
998
1041
|
if (thisd < mind) {
|
|
999
1042
|
mind = thisd;
|
|
1000
1043
|
mini = node.index;
|
|
1001
1044
|
}
|
|
1002
1045
|
}
|
|
1003
|
-
// check the other side
|
|
1004
1046
|
if (distance * distance < mind) {
|
|
1005
1047
|
const other = next === node.right ? node.left : node.right;
|
|
1006
1048
|
if (other) {
|
|
1007
|
-
recurse(other,
|
|
1049
|
+
recurse(other, nextAxis);
|
|
1008
1050
|
}
|
|
1009
1051
|
}
|
|
1010
1052
|
};
|
|
@@ -1016,16 +1058,8 @@ class KdTree {
|
|
|
1016
1058
|
return { indices: new Int32Array(0), distances: new Float32Array(0) };
|
|
1017
1059
|
}
|
|
1018
1060
|
k = Math.min(k, this.centroids.numRows);
|
|
1019
|
-
const
|
|
1020
|
-
const
|
|
1021
|
-
const calcDistance = (index) => {
|
|
1022
|
-
let l = 0;
|
|
1023
|
-
for (let i = 0; i < numColumns; ++i) {
|
|
1024
|
-
const v = centroids.columns[i].data[index] - point[i];
|
|
1025
|
-
l += v * v;
|
|
1026
|
-
}
|
|
1027
|
-
return l;
|
|
1028
|
-
};
|
|
1061
|
+
const colData = this.colData;
|
|
1062
|
+
const numCols = colData.length;
|
|
1029
1063
|
// Bounded max-heap: stores (distance, index) pairs sorted so the
|
|
1030
1064
|
// farthest element is at position 0, enabling O(1) pruning bound.
|
|
1031
1065
|
const heapDist = new Float32Array(k).fill(Infinity);
|
|
@@ -1033,14 +1067,12 @@ class KdTree {
|
|
|
1033
1067
|
let heapSize = 0;
|
|
1034
1068
|
const heapPush = (dist, idx) => {
|
|
1035
1069
|
if (heapSize < k) {
|
|
1036
|
-
// Heap not full yet -- insert via sift-up
|
|
1037
1070
|
let pos = heapSize++;
|
|
1038
1071
|
heapDist[pos] = dist;
|
|
1039
1072
|
heapIdx[pos] = idx;
|
|
1040
1073
|
while (pos > 0) {
|
|
1041
1074
|
const parent = (pos - 1) >> 1;
|
|
1042
1075
|
if (heapDist[parent] < heapDist[pos]) {
|
|
1043
|
-
// swap
|
|
1044
1076
|
const td = heapDist[parent];
|
|
1045
1077
|
heapDist[parent] = heapDist[pos];
|
|
1046
1078
|
heapDist[pos] = td;
|
|
@@ -1055,7 +1087,6 @@ class KdTree {
|
|
|
1055
1087
|
}
|
|
1056
1088
|
}
|
|
1057
1089
|
else if (dist < heapDist[0]) {
|
|
1058
|
-
// Replace root (farthest) and sift-down
|
|
1059
1090
|
heapDist[0] = dist;
|
|
1060
1091
|
heapIdx[0] = idx;
|
|
1061
1092
|
let pos = 0;
|
|
@@ -1079,22 +1110,26 @@ class KdTree {
|
|
|
1079
1110
|
}
|
|
1080
1111
|
}
|
|
1081
1112
|
};
|
|
1082
|
-
const recurse = (node,
|
|
1083
|
-
const
|
|
1084
|
-
const distance = point[axis] - centroids.columns[axis].data[node.index];
|
|
1113
|
+
const recurse = (node, axis) => {
|
|
1114
|
+
const distance = point[axis] - colData[axis][node.index];
|
|
1085
1115
|
const next = (distance > 0) ? node.right : node.left;
|
|
1116
|
+
const nextAxis = axis + 1 < numCols ? axis + 1 : 0;
|
|
1086
1117
|
if (next) {
|
|
1087
|
-
recurse(next,
|
|
1118
|
+
recurse(next, nextAxis);
|
|
1088
1119
|
}
|
|
1089
1120
|
if (!filterFunc || filterFunc(node.index)) {
|
|
1090
|
-
|
|
1121
|
+
let thisd = 0;
|
|
1122
|
+
for (let c = 0; c < numCols; c++) {
|
|
1123
|
+
const v = colData[c][node.index] - point[c];
|
|
1124
|
+
thisd += v * v;
|
|
1125
|
+
}
|
|
1091
1126
|
heapPush(thisd, node.index);
|
|
1092
1127
|
}
|
|
1093
1128
|
const bound = heapSize < k ? Infinity : heapDist[0];
|
|
1094
1129
|
if (distance * distance < bound) {
|
|
1095
1130
|
const other = next === node.right ? node.left : node.right;
|
|
1096
1131
|
if (other) {
|
|
1097
|
-
recurse(other,
|
|
1132
|
+
recurse(other, nextAxis);
|
|
1098
1133
|
}
|
|
1099
1134
|
}
|
|
1100
1135
|
};
|
|
@@ -1129,6 +1164,54 @@ const OPACITY_PRUNE_THRESHOLD = 0.1;
|
|
|
1129
1164
|
const KNN_K = 16;
|
|
1130
1165
|
const MC_SAMPLES = 1;
|
|
1131
1166
|
const EPS_COV = 1e-8;
|
|
1167
|
+
const PROGRESS_TICKS = 100;
|
|
1168
|
+
// Radix sort edge indices by their Float32 costs.
|
|
1169
|
+
// Converts floats to sortable uint32 keys (preserving order), then does
|
|
1170
|
+
// 4-pass LSD radix sort with 8-bit radix. Returns the number of valid
|
|
1171
|
+
// (finite-cost) edges written to `out`.
|
|
1172
|
+
const radixSortIndicesByFloat = (out, count, keys) => {
|
|
1173
|
+
const keyBits = new Uint32Array(keys.buffer, keys.byteOffset, keys.length);
|
|
1174
|
+
const sortKeys = new Uint32Array(count);
|
|
1175
|
+
let validCount = 0;
|
|
1176
|
+
for (let i = 0; i < count; i++) {
|
|
1177
|
+
const bits = keyBits[i];
|
|
1178
|
+
if ((bits & 0x7F800000) === 0x7F800000)
|
|
1179
|
+
continue;
|
|
1180
|
+
sortKeys[validCount] = (bits & 0x80000000) ? ~bits >>> 0 : (bits | 0x80000000) >>> 0;
|
|
1181
|
+
out[validCount] = i;
|
|
1182
|
+
validCount++;
|
|
1183
|
+
}
|
|
1184
|
+
if (validCount <= 1)
|
|
1185
|
+
return validCount;
|
|
1186
|
+
const n = validCount;
|
|
1187
|
+
const temp = new Uint32Array(n);
|
|
1188
|
+
const tempKeys = new Uint32Array(n);
|
|
1189
|
+
const counts = new Uint32Array(256);
|
|
1190
|
+
for (let pass = 0; pass < 4; pass++) {
|
|
1191
|
+
const shift = pass << 3;
|
|
1192
|
+
const srcIdx = (pass & 1) ? temp : out;
|
|
1193
|
+
const dstIdx = (pass & 1) ? out : temp;
|
|
1194
|
+
const srcK = (pass & 1) ? tempKeys : sortKeys;
|
|
1195
|
+
const dstK = (pass & 1) ? sortKeys : tempKeys;
|
|
1196
|
+
counts.fill(0);
|
|
1197
|
+
for (let i = 0; i < n; i++) {
|
|
1198
|
+
counts[(srcK[i] >>> shift) & 0xFF]++;
|
|
1199
|
+
}
|
|
1200
|
+
let sum = 0;
|
|
1201
|
+
for (let b = 0; b < 256; b++) {
|
|
1202
|
+
const c = counts[b];
|
|
1203
|
+
counts[b] = sum;
|
|
1204
|
+
sum += c;
|
|
1205
|
+
}
|
|
1206
|
+
for (let i = 0; i < n; i++) {
|
|
1207
|
+
const bucket = (srcK[i] >>> shift) & 0xFF;
|
|
1208
|
+
const pos = counts[bucket]++;
|
|
1209
|
+
dstIdx[pos] = srcIdx[i];
|
|
1210
|
+
dstK[pos] = srcK[i];
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
return validCount;
|
|
1214
|
+
};
|
|
1132
1215
|
// ---------- sigmoid / logit ----------
|
|
1133
1216
|
const sigmoid$1 = (x) => 1 / (1 + Math.exp(-x));
|
|
1134
1217
|
const logit = (p) => {
|
|
@@ -1616,7 +1699,6 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1616
1699
|
let current;
|
|
1617
1700
|
if (keptIndices.length < N && keptIndices.length > targetCount) {
|
|
1618
1701
|
current = dataTable.permuteRows(keptIndices);
|
|
1619
|
-
logger.debug(`opacity pruning: ${N} -> ${current.numRows} splats (threshold=${pruneThreshold.toFixed(4)})`);
|
|
1620
1702
|
}
|
|
1621
1703
|
else {
|
|
1622
1704
|
current = dataTable;
|
|
@@ -1627,7 +1709,8 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1627
1709
|
while (current.numRows > targetCount) {
|
|
1628
1710
|
const n = current.numRows;
|
|
1629
1711
|
const kEff = Math.min(Math.max(1, KNN_K), Math.max(1, n - 1));
|
|
1630
|
-
logger.
|
|
1712
|
+
logger.progress.begin(5);
|
|
1713
|
+
logger.progress.step('Building KD-tree');
|
|
1631
1714
|
const cx = current.getColumnByName('x').data;
|
|
1632
1715
|
const cy = current.getColumnByName('y').data;
|
|
1633
1716
|
const cz = current.getColumnByName('z').data;
|
|
@@ -1640,16 +1723,21 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1640
1723
|
const cr2 = current.getColumnByName('rot_2').data;
|
|
1641
1724
|
const cr3 = current.getColumnByName('rot_3').data;
|
|
1642
1725
|
const cache = buildPerSplatCache(n, cx, cy, cz, cop, cs0, cs1, cs2, cr0, cr1, cr2, cr3);
|
|
1643
|
-
// Build KNN graph
|
|
1644
1726
|
const posTable = new DataTable([
|
|
1645
1727
|
new Column('x', cx instanceof Float32Array ? cx : new Float32Array(cx)),
|
|
1646
1728
|
new Column('y', cy instanceof Float32Array ? cy : new Float32Array(cy)),
|
|
1647
1729
|
new Column('z', cz instanceof Float32Array ? cz : new Float32Array(cz))
|
|
1648
1730
|
]);
|
|
1649
1731
|
const kdTree = new KdTree(posTable);
|
|
1650
|
-
|
|
1651
|
-
|
|
1732
|
+
logger.progress.step('Finding nearest neighbors');
|
|
1733
|
+
let edgeCapacity = Math.ceil(n * kEff / 2);
|
|
1734
|
+
let edgeU = new Uint32Array(edgeCapacity);
|
|
1735
|
+
let edgeV = new Uint32Array(edgeCapacity);
|
|
1736
|
+
let edgeCount = 0;
|
|
1652
1737
|
const queryPoint = new Float32Array(3);
|
|
1738
|
+
const knnInterval = Math.max(1, Math.ceil(n / PROGRESS_TICKS));
|
|
1739
|
+
const knnTicks = Math.ceil(n / knnInterval);
|
|
1740
|
+
logger.progress.begin(knnTicks);
|
|
1653
1741
|
for (let i = 0; i < n; i++) {
|
|
1654
1742
|
queryPoint[0] = cx[i];
|
|
1655
1743
|
queryPoint[1] = cy[i];
|
|
@@ -1657,46 +1745,58 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1657
1745
|
const knn = kdTree.findKNearest(queryPoint, kEff + 1);
|
|
1658
1746
|
for (let ki = 0; ki < knn.indices.length; ki++) {
|
|
1659
1747
|
const j = knn.indices[ki];
|
|
1660
|
-
if (j
|
|
1748
|
+
if (j <= i)
|
|
1661
1749
|
continue;
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1750
|
+
if (edgeCount === edgeCapacity) {
|
|
1751
|
+
edgeCapacity *= 2;
|
|
1752
|
+
const newU = new Uint32Array(edgeCapacity);
|
|
1753
|
+
const newV = new Uint32Array(edgeCapacity);
|
|
1754
|
+
newU.set(edgeU);
|
|
1755
|
+
newV.set(edgeV);
|
|
1756
|
+
edgeU = newU;
|
|
1757
|
+
edgeV = newV;
|
|
1668
1758
|
}
|
|
1759
|
+
edgeU[edgeCount] = i;
|
|
1760
|
+
edgeV[edgeCount] = j;
|
|
1761
|
+
edgeCount++;
|
|
1669
1762
|
}
|
|
1763
|
+
if ((i + 1) % knnInterval === 0)
|
|
1764
|
+
logger.progress.step();
|
|
1670
1765
|
}
|
|
1671
|
-
if (
|
|
1766
|
+
if (n % knnInterval !== 0)
|
|
1767
|
+
logger.progress.step();
|
|
1768
|
+
if (edgeCount === 0) {
|
|
1769
|
+
logger.progress.cancel();
|
|
1672
1770
|
break;
|
|
1673
|
-
|
|
1771
|
+
}
|
|
1772
|
+
logger.progress.step('Computing edge costs');
|
|
1674
1773
|
const appData = [];
|
|
1675
1774
|
for (let ai = 0; ai < allAppearanceCols.length; ai++) {
|
|
1676
1775
|
const col = current.getColumnByName(allAppearanceCols[ai]);
|
|
1677
1776
|
if (col)
|
|
1678
1777
|
appData.push(col.data);
|
|
1679
1778
|
}
|
|
1680
|
-
const costs = new Float32Array(edges.length);
|
|
1681
|
-
for (let e = 0; e < edges.length; e++) {
|
|
1682
|
-
costs[e] = computeEdgeCost(edges[e][0], edges[e][1], cx, cy, cz, cache, Z, appData, appData.length);
|
|
1683
|
-
}
|
|
1684
|
-
// Greedy disjoint pair selection
|
|
1685
|
-
const valid = [];
|
|
1686
|
-
for (let i = 0; i < edges.length; i++) {
|
|
1687
|
-
if (Number.isFinite(costs[i]))
|
|
1688
|
-
valid.push(i);
|
|
1689
|
-
}
|
|
1690
|
-
valid.sort((a, b) => {
|
|
1691
|
-
const d = costs[a] - costs[b];
|
|
1692
|
-
return d !== 0 ? d : a - b;
|
|
1693
|
-
});
|
|
1694
1779
|
const mergesNeeded = n - targetCount;
|
|
1780
|
+
const costs = new Float32Array(edgeCount);
|
|
1781
|
+
const costInterval = Math.max(1, Math.ceil(edgeCount / PROGRESS_TICKS));
|
|
1782
|
+
const costTicks = Math.ceil(edgeCount / costInterval);
|
|
1783
|
+
logger.progress.begin(costTicks);
|
|
1784
|
+
for (let e = 0; e < edgeCount; e++) {
|
|
1785
|
+
costs[e] = computeEdgeCost(edgeU[e], edgeV[e], cx, cy, cz, cache, Z, appData, appData.length);
|
|
1786
|
+
if ((e + 1) % costInterval === 0)
|
|
1787
|
+
logger.progress.step();
|
|
1788
|
+
}
|
|
1789
|
+
if (edgeCount % costInterval !== 0)
|
|
1790
|
+
logger.progress.step();
|
|
1791
|
+
logger.progress.step('Merging splats');
|
|
1792
|
+
// Sort and greedy disjoint pair selection
|
|
1793
|
+
const sorted = new Uint32Array(edgeCount);
|
|
1794
|
+
const validCount = radixSortIndicesByFloat(sorted, edgeCount, costs);
|
|
1695
1795
|
const used = new Uint8Array(n);
|
|
1696
1796
|
const pairs = [];
|
|
1697
|
-
for (let t = 0; t <
|
|
1698
|
-
const e =
|
|
1699
|
-
const u =
|
|
1797
|
+
for (let t = 0; t < validCount; t++) {
|
|
1798
|
+
const e = sorted[t];
|
|
1799
|
+
const u = edgeU[e], v = edgeV[e];
|
|
1700
1800
|
if (used[u] || used[v])
|
|
1701
1801
|
continue;
|
|
1702
1802
|
used[u] = 1;
|
|
@@ -1705,9 +1805,10 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1705
1805
|
if (pairs.length >= mergesNeeded)
|
|
1706
1806
|
break;
|
|
1707
1807
|
}
|
|
1708
|
-
if (pairs.length === 0)
|
|
1808
|
+
if (pairs.length === 0) {
|
|
1809
|
+
logger.progress.cancel();
|
|
1709
1810
|
break;
|
|
1710
|
-
|
|
1811
|
+
}
|
|
1711
1812
|
// Mark which indices are consumed by merging
|
|
1712
1813
|
const usedSet = new Uint8Array(n);
|
|
1713
1814
|
for (let p = 0; p < pairs.length; p++) {
|
|
@@ -1735,7 +1836,7 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1735
1836
|
newTable.columns[c].data[dst] = cols[c].data[src];
|
|
1736
1837
|
}
|
|
1737
1838
|
}
|
|
1738
|
-
// Merge pairs
|
|
1839
|
+
// Merge pairs
|
|
1739
1840
|
const mergeOut = {
|
|
1740
1841
|
mu: new Float64Array(3),
|
|
1741
1842
|
sc: new Float64Array(3),
|
|
@@ -1763,6 +1864,9 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1763
1864
|
.filter(col => !handledCols.has(col.name))
|
|
1764
1865
|
.map(col => ({ src: col, dst: newTable.getColumnByName(col.name) }))
|
|
1765
1866
|
.filter(pair => pair.dst);
|
|
1867
|
+
const mergeInterval = Math.max(1, Math.ceil(pairs.length / PROGRESS_TICKS));
|
|
1868
|
+
const mergeTicks = Math.ceil(pairs.length / mergeInterval);
|
|
1869
|
+
logger.progress.begin(mergeTicks);
|
|
1766
1870
|
for (let p = 0; p < pairs.length; p++, dst++) {
|
|
1767
1871
|
const pi = pairs[p][0], pj = pairs[p][1];
|
|
1768
1872
|
momentMatch(pi, pj, cx, cy, cz, cop, cs0, cs1, cs2, cr0, cr1, cr2, cr3, mergeOut, appData, appData.length);
|
|
@@ -1785,7 +1889,12 @@ const simplifyGaussians = (dataTable, targetCount) => {
|
|
|
1785
1889
|
for (let u = 0; u < unhandledColPairs.length; u++) {
|
|
1786
1890
|
unhandledColPairs[u].dst.data[dst] = unhandledColPairs[u].src.data[dominant];
|
|
1787
1891
|
}
|
|
1892
|
+
if ((p + 1) % mergeInterval === 0)
|
|
1893
|
+
logger.progress.step();
|
|
1788
1894
|
}
|
|
1895
|
+
if (pairs.length % mergeInterval !== 0)
|
|
1896
|
+
logger.progress.step();
|
|
1897
|
+
logger.progress.step('Finalizing');
|
|
1789
1898
|
current = newTable;
|
|
1790
1899
|
}
|
|
1791
1900
|
return current;
|
|
@@ -5613,7 +5722,7 @@ class CompressedChunk {
|
|
|
5613
5722
|
}
|
|
5614
5723
|
}
|
|
5615
5724
|
|
|
5616
|
-
var version = "1.9.
|
|
5725
|
+
var version = "1.9.2";
|
|
5617
5726
|
|
|
5618
5727
|
const generatedByString = `Generated by splat-transform ${version}`;
|
|
5619
5728
|
const chunkProps = [
|
|
@@ -7660,6 +7769,746 @@ const writePly = async (options, fs) => {
|
|
|
7660
7769
|
await writer.close();
|
|
7661
7770
|
};
|
|
7662
7771
|
|
|
7772
|
+
// This file is part of meshoptimizer library and is distributed under the terms of MIT License.
|
|
7773
|
+
// Copyright (C) 2016-2025, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
|
7774
|
+
var MeshoptSimplifier = (function () {
|
|
7775
|
+
// Built with clang version 19.1.5-wasi-sdk
|
|
7776
|
+
// Built from meshoptimizer 1.0
|
|
7777
|
+
var wasm =
|
|
7778
|
+
'b9H79Tebbbe:6eO9Geueu9Geub9Gbb9Gsuuuuuuuuuuuu99uueu9Gvuuuuub9Gruuuuuuub9Gouuuuuue999Gvuuuuueu9Gzuuuuuuuuuuu99uuuub9Gquuuuuuu99uueu9GPuuuuuuuuuuu99uueu9Gquuuuuuuu99ueu9Gruuuuuu99eu9Gwuuuuuu99ueu9Giuuue999Gluuuueu9Gluuuub9GiuuueuiLQdilvorlwDiqkxmPszbHHbelve9Weiiviebeoweuec:G:Pdkr:Bdxo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bbz9TW79O9V9Wt9F79P9T9W29P9M95bw8E9TW79O9V9Wt9F79P9T9W29P9M959x9Pt9OcttV9P9I91tW7bD8A9TW79O9V9Wt9F79P9T9W29P9M959x9Pt9O9v9W9K9HtWbqQ9TW79O9V9Wt9F79P9T9W29P9M959t29V9W9W95bkX9TW79O9V9Wt9F79P9T9W29P9M959qV919UWbxQ9TW79O9V9Wt9F79P9T9W29P9M959q9V9P9Ut7bmX9TW79O9V9Wt9F79P9T9W29P9M959t9J9H2WbPa9TW79O9V9Wt9F9V9Wt9P9T9P96W9wWVtW94SWt9J9O9sW9T9H9Wbs59TW79O9V9Wt9F9NW9UWV9HtW9q9V79Pt9P9V9U9sW9T9H9Wbzl79IV9RbHDwebcekdCXqM;YeQdbk;A1er3ue99euE99Que9:r998Jjjjjbcj;sb9Rgs8Kjjjjbcbhzasc:Cefcbc;Kbz:tjjjb8AdnabaeSmbabaeadcdtzMjjjb8AkdnamcdGTmbalcrfci4cbyd1:jjjbHjjjjbbhHasc:Cefasyd;8egecdtfaHBdbasaecefBd;8ecbhlcbhednadTmbabheadhOinaHaeydbci4fcb86bbaeclfheaOcufgOmbkcbhlabheadhOinaHaeydbgAci4fgCaCRbbgCceaAcrGgAtV86bbaCcu7aA4ceGalfhlaeclfheaOcufgOmbkcualcdtalcFFFFi0Ehekaecbyd1:jjjbHjjjjbbhzasc:Cefasyd;8egecdtfazBdbasaecefBd;8ealcd4alfhOcehHinaHgecethHaeaO6mbkcbhXcuaecdtgOaecFFFFi0Ecbyd1:jjjbHjjjjbbhHasc:Cefasyd;8egAcdtfaHBdbasaAcefBd;8eaHcFeaOz:tjjjbhQdnadTmbaecufhLcbhKindndnaQabaXcdtfgYydbgAc:v;t;h;Ev2aLGgOcdtfgCydbgHcuSmbceheinazaHcdtfydbaASmdaOaefhHaecefheaQaHaLGgOcdtfgCydbgHcu9hmbkkazaKcdtfaABdbaCaKBdbaKhHaKcefhKkaYaHBdbaXcefgXad9hmbkkaQcbyd:m:jjjbH:bjjjbbasasyd;8ecufBd;8ekcbh8AcualcefgecdtaecFFFFi0Ecbyd1:jjjbHjjjjbbhXasc:Cefasyd;8egecdtfaXBdbasaXBdNeasaecefBd;8ecuadcitadcFFFFe0Ecbyd1:jjjbHjjjjbbhEasc:Cefasyd;8egecdtfaEBdbasaEBd:yeasaecefBd;8eascNefabadalcbz:cjjjbcualcdtgealcFFFFi0Eg3cbyd1:jjjbHjjjjbbhAasc:Cefasyd;8egHcdtfaABdbasaHcefBd;8ea3cbyd1:jjjbHjjjjbbhKasc:Cefasyd;8egHcdtfaKBdbasaHcefBd;8eaAaKaialavazasc:Cefz:djjjbalcbyd1:jjjbHjjjjbbh5asc:Cefasyd;8egHcdtfa5BdbasaHcefBd;8ea3cbyd1:jjjbHjjjjbbhHasc:Cefasyd;8egOcdtfaHBdbasaOcefBd;8ea3cbyd1:jjjbHjjjjbbhOasc:Cefasyd;8egCcdtfaOBdbasaCcefBd;8eaHcFeaez:tjjjbh8EaOcFeaez:tjjjbh8FdnalTmbaEcwfhaindnaXa8AgOcefg8AcdtfydbgCaXaOcdtgefydbgHSmbaCaH9RhhaEaHcitfhga8Faefh8Ja8Eaefh8KcbhQindndnagaQcitfydbgLaO9hmba8KaOBdba8JaOBdbxekdnaXaLcdtg8LfgeclfydbgHaeydbgeSmbaEaecitgCfydbaOSmeaHae9Rh8Maecu7aHfhYaaaCfhHcbheinaYaeSmeaecefheaHydbhCaHcwfhHaCaO9hmbkaea8M6meka8Fa8LfgeaOaLaeydbcuSEBdba8KaLaOa8KydbcuSEBdbkaQcefgQah9hmbkka8Aal9hmbkaAhHaKhOa8FhCa8EhQcbheindndnaeaHydbgL9hmbdnaeaOydbgL9hmbaQydbhLdnaCydbgYcu9hmbaLcu9hmba5aefcb86bbxikdnaYcuSmbaLcuSmbaeaYSmbaAaYcdtfydbaAaLcdtfydb9hmba5aefcd86bbxika5aefh8KdnaeaYSmbaeaLSmba8Kce86bbxika8Kcl86bbxdkdnaeaKaLcdtgYfydb9hmbdnaCydbg8KcuSmbaea8KSmbaQydbghcuSmbaeahSmba8FaYfydbggcuSmbagaLSmba8EaYfydbgYcuSmbaYaLSmbdnaAa8KcdtfydbgLaAaYcdtfydb9hmbaLaAahcdtfydbgYSmbaYaAagcdtfydb9hmba5aefcd86bbxlka5aefcl86bbxika5aefcl86bbxdka5aefcl86bbxeka5aefa5aLfRbb86bbkaHclfhHaOclfhOaCclfhCaQclfhQalaecefge9hmbkdnamcaGTmbaEcwfh8Jcbh8Nindndna5a8NfgyRbbg8Pc9:fPibebekdndndnaAa8Ncdtfydbgea8N9hmbdnaqmbcbhgxdkdnazTmbcbhga8NheinagaqazaecdtgefydbfRbbcdGce4VhgaKaefydbgea8N9hmbxikkcbhga8NheinagaqaefRbbcdGce4VhgaKaecdtfydbgea8N9hmbxdkka5aefRbbhexeka8NheindnaXaecdtgafgeclfydbgHaeydbgeSmbaHae9Rh8AaEaecitfh8MaAaafh8Lcbh8Kina8Ma8KcitfydbgYhednindnaXaecdtgLfgeclfydbgHaeydbgeSmbdnaAaEaecitgOfydbcdtfydba8LydbgQ9hmbcehexikaHae9Rhhaecu7aHfhCa8JaOfhHcbheinaCaeSmeaecefheaHydbhOaHcwfhHaAaOcdtfydbaQ9hmbkaeah6hexdkaKaLfydbgeaY9hmbkcbhekagaece7Vhga8Kcefg8Ka8A9hmbkkaKaafydbgea8N9hmbka8PciagceGEhekayae86bbka8Ncefg8Nal9hmbkkdnaqTmbdndnazTmbazheaAhHalhOindnaqaeydbfRbbceGTmba5aHydbfcl86bbkaeclfheaHclfhHaOcufgOmbxdkkaqheaAhHalhOindnaeRbbceGTmba5aHydbfcl86bbkaecefheaHclfhHaOcufgOmbkkaAhealhOa5hHindna5aeydbfRbbcl9hmbaHcl86bbkaeclfheaHcefhHaOcufgOmbkkamceGTmba5healhHindnaeRbbce9hmbaecl86bbkaecefheaHcufgHmbkkcbhIcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbhaasc:Cefasyd;8egecdtfaaBdbasaecefBd;8easc:qefcbBdbas9cb83i1eaaaialavazasc1efz:ejjjbh8RdndnaDmbcbhycbhCxekcbhCawhecbhHindnaeIdbJbbbb9ETmbasaCcdtfaHBdbaCcefhCkaeclfheaDaHcefgH9hmbkcuaCal2gecdtaecFFFFi0Ecbyd1:jjjbHjjjjbbhyasc:Cefasyd;8egecdtfayBdbasaecefBd;8ealTmbdnaCmbcbhCxekarcd4h8KdnazTmbaCcdthhcbhXayhYinaoazaXcdtfydba8K2cdtfhLasheaYhHaChOinaHaLaeydbcdtgQfIdbawaQfIdbNUdbaeclfheaHclfhHaOcufgOmbkaYahfhYaXcefgXal9hmbxdkkaCcdthhcbhXayhYinaoaXa8K2cdtfhLasheaYhHaChOinaHaLaeydbcdtgQfIdbawaQfIdbNUdbaeclfheaHclfhHaOcufgOmbkaYahfhYaXcefgXal9hmbkkcualc8S2gHalc;D;O;f8U0EgQcbyd1:jjjbHjjjjbbheasc:Cefasyd;8egOcdtfaeBdbasaOcefBd;8eaecbaHz:tjjjbh8ScbhDcbh8KdnaCTmbcbhIaQcbyd1:jjjbHjjjjbbh8Kasc:Cefasyd;8egecdtfa8KBdbasaecefBd;8ea8KcbaHz:tjjjb8AcuaCal2gecltgHaecFFFFb0Ecbyd1:jjjbHjjjjbbhDasc:Cefasyd;8egecdtfaDBdbasaecefBd;8eaDcbaHz:tjjjb8AamcjjjjdGTmbcualcltgealcFFFFb0Ecbyd1:jjjbHjjjjbbhIasc:Cefasyd;8egHcdtfaIBdbasaHcefBd;8eaIcbaez:tjjjb8AkdnadTmbcbhLabhHinaaaHclfydbgXcx2fgeIdbaaaHydbgYcx2fgOIdbgR:tg8UaaaHcwfydbghcx2fgQIdlaOIdlg8V:tg8WNaQIdbaR:tg8XaeIdla8V:tg8YN:tg8Zh80aeIdwaOIdwg81:tgBa8XNaQIdwa81:tg83a8UN:tgUh8Xa8Ya83Na8WaBN:tg8Yh8Udna8Za8ZNa8Ya8YNaUaUNMM:rgBJbbbb9EgOTmba8ZaB:vh80aUaB:vh8Xa8YaB:vh8Uka8SaAaYcdtfydbgQc8S2fgea8UaB:rg8Wa8UNNg85aeIdbMUdbaea8Xa8Wa8XNg86Ng87aeIdlMUdlaea80a8Wa80Ng83Ng88aeIdwMUdwaea86a8UNg86aeIdxMUdxaea83a8UNg89aeIdzMUdzaea83a8XNg8:aeIdCMUdCaea8Ua8Wa80a81Na8UaRNa8Va8XNMM:mgZNg83Ng8UaeIdKMUdKaea8Xa83Ng8XaeId3MUd3aea80a83Ng80aeIdaMUdaaea83aZNg83aeId8KMUd8Kaea8WaeIdyMUdya8SaAaXcdtfydbgXc8S2fgea85aeIdbMUdbaea87aeIdlMUdlaea88aeIdwMUdwaea86aeIdxMUdxaea89aeIdzMUdzaea8:aeIdCMUdCaea8UaeIdKMUdKaea8XaeId3MUd3aea80aeIdaMUdaaea83aeId8KMUd8Kaea8WaeIdyMUdya8SaAahcdtfydbgYc8S2fgea85aeIdbMUdbaea87aeIdlMUdlaea88aeIdwMUdwaea86aeIdxMUdxaea89aeIdzMUdzaea8:aeIdCMUdCaea8UaeIdKMUdKaea8XaeId3MUd3aea80aeIdaMUdaaea83aeId8KMUd8Kaea8WaeIdyMUdydnaITmbdnaOTmba8ZaB:vh8ZaUaB:vhUa8YaB:vh8YkaIaQcltfgeaBJbbbZNg8UaUNg8WaeIdlMUdlaea8Ua8ZNg8XaeIdwMUdwaea8Ua8YNg80aeIdbMUdbaea8UaR:ma8YNaUa8VN:ta81a8ZN:tNg8UaeIdxMUdxaIaXcltfgea8WaeIdlMUdlaea8XaeIdwMUdwaea80aeIdbMUdbaea8UaeIdxMUdxaIaYcltfgea8WaeIdlMUdlaea8XaeIdwMUdwaea80aeIdbMUdbaea8UaeIdxMUdxkaHcxfhHaLcifgLad6mbkkdnalTmbJ;n;m;m89J:v:;;w8ZamczGEh8YcbhOaAhQaahHa8SheindnaOaQydb9hmbaecxfgLaLIdbJbbbbMUdbaeczfgLaLIdbJbbbbMUdbaecCfgLaLIdbJbbbbMUdbaea8YaecyfgLIdbg8ZNg8UaeIdbMUdbaeclfgXa8UaXIdbMUdbaecwfgXa8UaXIdbMUdbaecKfgXaXIdbaHIdbg8Xa8UN:tUdbaHcwfIdbh8Waec3fgXaXIdba8UaHclfIdbg80N:tUdbaecafgXaXIdba8Ua8WN:tUdbaec8KfgXIdbhUaLa8Za8UMUdbaXaUa8Ua8Wa8WNa8Xa8XNa80a80NMMNMUdbkaQclfhQaHcxfhHaec8SfhealaOcefgO9hmbkkdnadTmbcbhhabhYinabahcdtfhXcbhHina5aXaHc:G1jjbfydbcdtfydbgOfRbbhedndna5aYaHfydbgQfRbbgLc99fcFeGcpe0mbaec99fcFeGc;:e6mekdnaLcufcFeGce0mba8EaQcdtfydbaO9hmekdnaecufcFeGce0mba8FaOcdtfydbaQ9hmekJbbacJbbacJbbbZaecFeGceSEaLcFeGceSEh88aaaOcx2fgeIdwaaaQcx2fgLIdwgB:tg80:mh86aeIdlaLIdlg83:tg8Z:mh89aeIdbaLIdbgR:tgU:mh8:dnaaaXaHc:K1jjbfydbcdtfydbcx2fgeIdwaB:tg8Va80a80NaUaUNa8Za8ZNMMg8YNa8Va80NaeIdbaR:tg81aUNa8ZaeIdla83:tg85NMMg8Wa80N:tg8Xa8XNa81a8YNa8WaUN:tg8Ua8UNa85a8YNa8Wa8ZN:tg8Wa8WNMM:rg87Jbbbb9ETmba8Xa87:vh8Xa8Wa87:vh8Wa8Ua87:vh8Uka88a8Y:rNg8Ya8XaBNa8UaRNa83a8WNMM:mgZNg87aZNhZa8Xa87Nhna8Wa87Nhca8Ua87Nh9ca8Ya8XNg87a8WNhJa87a8UNh9ea8Ya8WNgTa8UNhSa8Xa87Nh87a8WaTNhTa8Ua8Ya8UNNh9hdnaUa85Na81a89NMg8Xa8XNa8Za8VNa85a86NMg8Ua8UNa80a81Na8Va8:NMg8Wa8WNMM:rg80Jbbbb9ETmba8Xa80:vh8Xa8Wa80:vh8Wa8Ua80:vh8Uka8SaAaQcdtfydbc8S2fgeaeIdba9ha8Ua88a80:rNg80a8UNNMgUMUdbaeaTa8Wa80a8WNg8VNMg81aeIdlMUdlaea87a8Xa80a8XNg8ZNMg85aeIdwMUdwaeaSa8Va8UNMg8VaeIdxMUdxaea9ea8Za8UNMg87aeIdzMUdzaeaJa8Za8WNMg8ZaeIdCMUdCaea9ca8Ua80a8XaBNa8UaRNa83a8WNMMgB:mNg80NMg8UaeIdKMUdKaeaca8Wa80NMg8WaeId3MUd3aeana8Xa80NMg8XaeIdaMUdaaeaZaBa80N:tg80aeId8KMUd8Kaea8YJbbbbMg8YaeIdyMUdya8SaAaOcdtfydbc8S2fgeaUaeIdbMUdbaea81aeIdlMUdlaea85aeIdwMUdwaea8VaeIdxMUdxaea87aeIdzMUdzaea8ZaeIdCMUdCaea8UaeIdKMUdKaea8WaeId3MUd3aea8XaeIdaMUdaaea80aeId8KMUd8Kaea8YaeIdyMUdykaHclfgHcx9hmbkaYcxfhYahcifghad6mbkaCTmbcbhYinJbbbbh8YaaabaYcdtfgeclfydbghcx2fgHIdwaaaeydbggcx2fgOIdwg81:tg8Wa8WNaHIdbaOIdbg85:tg8Xa8XNaHIdlaOIdlg87:tg80a80NMMgRaaaecwfydbgEcx2fgeIdwa81:tg8ZNa8Wa8Wa8ZNa8XaeIdba85:tgUNa80aeIdla87:tgBNMMg8UN:tJbbbbJbbjZaRa8Za8ZNaUaUNaBaBNMMg8VNa8Ua8UN:tg83:va83Jbbbb9BEg83Nh89a8Va8WNa8Za8UN:ta83Nh8:aRaBNa80a8UN:ta83NhZa8Va80NaBa8UN:ta83NhnaRaUNa8Xa8UN:ta83Nhca8Va8XNaUa8UN:ta83Nh9ca8XaBNaUa80N:tg8Ua8UNa80a8ZNaBa8WN:tg8Ua8UNa8WaUNa8Za8XN:tg8Ua8UNMM:rJbbbZNh8UayagaC2g8LcdtfhHayaEaC2g8JcdtfhOayahaC2g8AcdtfhQa81:mhJa87:mh9ea85:mhTcbhLaChXJbbbbhBJbbbbh83JbbbbhRJbbbbh8VJbbbbh81Jbbbbh85Jbbbbh87Jbbbbh88Jbbbbh86inascjdfaLfgecwfa8Ua8:aQIdbaHIdbg8Z:tg80Na89aOIdba8Z:tgUNMg8WNUdbaeclfa8Uana80NaZaUNMg8XNUdbaea8Ua9ca80NacaUNMg80NUdbaecxfa8UaJa8WNa9ea8XNa8ZaTa80NMMMg8ZNUdba8Ua8Wa8XNNa8VMh8Va8Ua8Wa80NNa81Mh81a8Ua8Xa80NNa85Mh85a8Ua8Za8ZNNa8YMh8Ya8Ua8Wa8ZNNaBMhBa8Ua8Xa8ZNNa83Mh83a8Ua80a8ZNNaRMhRa8Ua8Wa8WNNa87Mh87a8Ua8Xa8XNNa88Mh88a8Ua80a80NNa86Mh86aHclfhHaQclfhQaOclfhOaLczfhLaXcufgXmbka8Kagc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdya8Kahc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdya8KaEc8S2fgea86aeIdbMUdbaea88aeIdlMUdlaea87aeIdwMUdwaea85aeIdxMUdxaea81aeIdzMUdzaea8VaeIdCMUdCaeaRaeIdKMUdKaea83aeId3MUd3aeaBaeIdaMUdaaea8YaeId8KMUd8Kaea8UaeIdyMUdyaDa8LcltfhXcbhHaChQinaXaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgLaOclfIdbaLIdbMUdbaecwfgLaOcwfIdbaLIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaQcufgQmbkaDa8AcltfhXcbhHaChQinaXaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgLaOclfIdbaLIdbMUdbaecwfgLaOcwfIdbaLIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaQcufgQmbkaDa8JcltfhXcbhHaChQinaXaHfgeascjdfaHfgOIdbaeIdbMUdbaeclfgLaOclfIdbaLIdbMUdbaecwfgLaOcwfIdbaLIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaQcufgQmbkaYcifgYad6mbkkcbhOdndnamcwGg9imbJbbbbhRcbh6cbh9kcbh0xekcbh6a3cbyd1:jjjbHjjjjbbh0asc:Cefasyd;8egecdtfa0BdbasaecefBd;8ecua0alabadaAz:fjjjbgQcltaQcjjjjiGEcbyd1:jjjbHjjjjbbh9kasc:Cefasyd;8egecdtfa9kBdbasaecefBd;8ea9kaQa0aaalz:gjjjbJFFuuhRaQTmba9kheaQhHinaeIdbg8UaRaRa8U9EEhRaeclfheaHcufgHmbkaQh6kasydNeh9mdnalTmba9mclfhea9mydbhQa5hHalhLcbhOincbaeydbgXaQ9RaHRbbcpeGEaOfhOaHcefhHaeclfheaXhQaLcufgLmbkaOce4hOkcuadaO9Rcifg9ncx2a9nc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbh9oasc:Cefasyd;8egecdtfa9oBdbasaecefBd;8ecua9ncdta9ncFFFFi0Ecbyd1:jjjbHjjjjbbh9pasc:Cefasyd;8egecdtfa9pBdbasaecefBd;8ea3cbyd1:jjjbHjjjjbbh8Pasc:Cefasyd;8egecdtfa8PBdbasaecefBd;8ealcbyd1:jjjbHjjjjbbh9qasc:Cefasyd;8egecdtfa9qBdbasaecefBd;8eaxaxNa8RJbbjZamclGEgnanN:vh88Jbbbbh86dnadak9nmbdna9nci6mbasyd:yeh9raCclth9sa9ocwfh9tJbbbbh87Jbbbbh86inascNefabadalaAz:cjjjbabhgcbh8Ncbh3inaba3cdtfh8LcbheindnaAagaefydbgOcdtghfydbgQaAa8Laec:W1jjbfydbcdtfydbgHcdtgEfydbgLSmba5aHfRbbgYcv2a5aOfRbbgXfc;a1jjbfRbbg8AaXcv2aYfg8Jc;a1jjbfRbbg8MVcFeGTmbdnaLaQ9nmba8Jc;G1jjbfRbbcFeGmekdnaXcufcFeGce0mbaYTmba8EahfydbaH9hmekdnaXTmbaYcufcFeGce0mba8FaEfydbaO9hmeka9oa8Ncx2fgQaHaOa8McFeGgLEBdlaQaOaHaLEBdbaQaLa8AGcb9hBdwa8Ncefh8Nkaeclfgecx9hmbkdna3cifg3ad9pmbagcxfhga8Ncifa9n9nmekka8NTmdcbh8Jina8SaAa9oa8Jcx2fghydbgLcdtgQfydbggc8S2fgeIdwaaahydlgXcx2fgHIdwg8XNaeIdzaHIdbg80NaeIdaMg8Ua8UMMa8XNaeIdlaHIdlg8ZNaeIdCa8XNaeId3Mg8Ua8UMMa8ZNaeIdba80NaeIdxa8ZNaeIdKMg8Ua8UMMa80NaeId8KMMM:lh8UJbbbbJbbjZaeIdyg8W:va8WJbbbb9BEh8Wdndnahydwg8LmbJFFuuh83xekJbbbbJbbjZa8SaAaXcdtfydbc8S2fgeIdygU:vaUJbbbb9BEaeIdwaaaLcx2fgHIdwgUNaeIdzaHIdbg8YNaeIdaMgBaBMMaUNaeIdlaHIdlgBNaeIdCaUNaeId3MgUaUMMaBNaeIdba8YNaeIdxaBNaeIdKMgUaUMMa8YNaeId8KMMM:lNh83ka8Wa8UNhBdnaCTmba8KaLc8S2fgOIdwa8XNaOIdza80NaOIdaMg8Ua8UMMa8XNaOIdla8ZNaOIdCa8XNaOId3Mg8Ua8UMMa8ZNaOIdba80NaOIdxa8ZNaOIdKMg8Ua8UMMa80NaOId8KMMMh8UayaXaC2gYcdtfhHaDaLaC2gEcltfheaOIdyhUaChOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbkdndna8LmbJbbbbh8Wxeka8KaXc8S2fgOIdwaaaLcx2fgeIdwg80NaOIdzaeIdbg8ZNaOIdaMg8Wa8WMMa80NaOIdlaeIdlgUNaOIdCa80NaOId3Mg8Wa8WMMaUNaOIdba8ZNaOIdxaUNaOIdKMg8Wa8WMMa8ZNaOId8KMMMh8WayaEcdtfhHaDaYcltfheaOIdyh8YaChOinaHIdbg8Xa8Xa8YNaecxfIdba80aecwfIdbNa8ZaeIdbNaUaeclfIdbNMMMg8Xa8XM:tNa8WMh8WaHclfhHaeczfheaOcufgOmbka8W:lh8WkaBa8U:lMhBa83a8WMh83dndndna5aLfRbbc9:fPddbekaKaQfydbgQaLSmbaAaXcdtfydbhEindndna8EaQcdtgYfydbgecuSmbaAaecdtfydbaESmekdna8FaYfydbgecuSmbaAaecdtfydbaESmekaXheka8KaQc8S2fgOIdwaaaecx2fgHIdwg8XNaOIdzaHIdbg80NaOIdaMg8Ua8UMMa8XNaOIdlaHIdlg8ZNaOIdCa8XNaOId3Mg8Ua8UMMa8ZNaOIdba80NaOIdxa8ZNaOIdKMg8Ua8UMMa80NaOId8KMMMh8UayaeaC2cdtfhHaDaQaC2cltfheaOIdyhUaChOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbkaBa8U:lMhBaKaYfydbgQaL9hmbkka5aXfRbbci9hmea8LTmeaKaXcdtfydbgQaXSmeindndna8EaQcdtgYfydbgecuSmbaAaecdtfydbagSmekdna8FaYfydbgecuSmbaAaecdtfydbagSmekaLheka8KaQc8S2fgOIdwaaaecx2fgHIdwg8XNaOIdzaHIdbg80NaOIdaMg8Ua8UMMa8XNaOIdlaHIdlg8ZNaOIdCa8XNaOId3Mg8Ua8UMMa8ZNaOIdba80NaOIdxa8ZNaOIdKMg8Ua8UMMa80NaOId8KMMMh8UayaeaC2cdtfhHaDaQaC2cltfheaOIdyhUaChOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbka83a8U:lMh83aKaYfydbgQaX9hmbxdkkdna8Fa8Ea8EaQfydbaXSEaKaQfydbgYcdtfydbgQcu9hmbaKaXcdtfydbhQka8KaYc8S2fgOIdwaaaQcx2fgeIdwg8XNaOIdzaeIdbg80NaOIdaMg8Ua8UMMa8XNaOIdlaeIdlg8ZNaOIdCa8XNaOId3Mg8Ua8UMMa8ZNaOIdba80NaOIdxa8ZNaOIdKMg8Ua8UMMa80NaOId8KMMMh8UayaQaC2ggcdtfhHaDaYaC2gEcltfheaOIdyhUaChOinaHIdbg8Wa8WaUNaecxfIdba8XaecwfIdbNa80aeIdbNa8ZaeclfIdbNMMMg8Wa8WM:tNa8UMh8UaHclfhHaeczfheaOcufgOmbkdndna8LmbJbbbbh8Wxeka8KaQc8S2fgOIdwaaaYcx2fgeIdwg80NaOIdzaeIdbg8ZNaOIdaMg8Wa8WMMa80NaOIdlaeIdlgUNaOIdCa80NaOId3Mg8Wa8WMMaUNaOIdba8ZNaOIdxaUNaOIdKMg8Wa8WMMa8ZNaOId8KMMMh8WayaEcdtfhHaDagcltfheaOIdyh8YaChOinaHIdbg8Xa8Xa8YNaecxfIdba80aecwfIdbNa8ZaeIdbNaUaeclfIdbNMMMg8Xa8XM:tNa8WMh8WaHclfhHaeczfheaOcufgOmbka8W:lh8WkaBa8U:lMhBa83a8WMh83kaha83aBa83aB9DgeEUdwahaLaXaea8Lcb9hGgeEBdlahaXaLaeEBdba8Jcefg8Ja8N9hmbkascjdfcbcj;qbz:tjjjb8Aa9thea8NhHinascjdfaeydbcA4cF8FGgOcFAaOcFA6EcdtfgOaOydbcefBdbaecxfheaHcufgHmbkcbhecbhHinascjdfaefgOydbhQaOaHBdbaQaHfhHaeclfgecj;qb9hmbkcbhea9thHinascjdfaHydbcA4cF8FGgOcFAaOcFA6EcdtfgOaOydbgOcefBdba9paOcdtfaeBdbaHcxfhHa8Naecefge9hmbkadak9RgOci9Uh9udnalTmbcbhea8PhHinaHaeBdbaHclfhHalaecefge9hmbkkcbh9va9qcbalz:tjjjbh9waOcO9Uh9xa9uce4h9ycbh3cbh8Adnina9oa9pa8Acdtfydbcx2fg8JIdwg8Ua889Emea3a9u9pmeJFFuuh8Wdna9ya8N9pmba9oa9pa9ycdtfydbcx2fIdwJbb;aZNh8Wkdna8Ua8W9ETmba8Ua869ETmba3a9x0mdkdna9waAa8Jydlg8Mcdtg9zfgEydbgQfg9ARbba9waAa8Jydbggcdtg9Bfydbgefg9CRbbVmba5agfRbbh9Ddna9maecdtfgHclfydbgOaHydbgHSmbaOaH9RhLaaaQcx2fhYaaaecx2fhha9raHcitfhecbhHceh8Ldnindna8PaeydbcdtfydbgOaQSmba8PaeclfydbcdtfydbgXaQSmbaOaXSmbaaaXcx2fgXIdbaaaOcx2fgOIdbg8X:tg8UahIdlaOIdlg80:tg8YNahIdba8X:tgBaXIdla80:tg8WN:tg8Za8UaYIdla80:tg83NaYIdba8X:tg8Va8WN:tg80Na8WahIdwaOIdwgU:tg81Na8YaXIdwaU:tg8XN:tg8Ya8WaYIdwaU:tg85Na83a8XN:tg8WNa8XaBNa81a8UN:tgUa8Xa8VNa85a8UN:tg8UNMMa8Za8ZNa8Ya8YNaUaUNMMa80a80Na8Wa8WNa8Ua8UNMMN:rJbbj8:N9FmdkaecwfheaHcefgHaL6h8LaLaH9hmbkka8LceGTmba9ycefh9yxekdndndndna9Dc9:fPdebdkagheinaEydbhOdndna8EaecdtgHfydbgecuSmbaAaecdtfydbaOSmekdna8FaHfydbgecuSmbaAaecdtfydbaOSmeka8Mheka8PaHfaeBdbaKaHfydbgeag9hmbxikkdna8Fa8Ea8Ea9Bfydba8MSEaKa9Bfydbggcdtfydbgecu9hmbaKa9zfydbheka8Pa9Bfa8MBdbaeh8Mka8Pagcdtfa8MBdbka9Cce86bba9Ace86bba8JIdwg8Ua86a86a8U9DEh86a9vcefh9vcecda9DceSEa3fh3ka8Acefg8Aa8N9hmbkka9vTmddnalTmbcbhXcbhhindna8PahcdtgefydbgOahSmbaAaOcdtfydbhgdnahaAaefydb9hgEmba8Sagc8S2fgea8Sahc8S2fgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxaeaHIdzaeIdzMUdzaeaHIdCaeIdCMUdCaeaHIdKaeIdKMUdKaeaHId3aeId3MUd3aeaHIdaaeIdaMUdaaeaHId8KaeId8KMUd8KaeaHIdyaeIdyMUdyaITmbaIagcltfgeaIahcltfgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxkaCTmba8KaOc8S2fgea8Kahc8S2g8LfgHIdbaeIdbMUdbaeaHIdlaeIdlMUdlaeaHIdwaeIdwMUdwaeaHIdxaeIdxMUdxaeaHIdzaeIdzMUdzaeaHIdCaeIdCMUdCaeaHIdKaeIdKMUdKaeaHId3aeId3MUd3aeaHIdaaeIdaMUdaaeaHId8KaeId8KMUd8KaeaHIdyaeIdyMUdya9saO2hYaDhHaChQinaHaYfgeaHaXfgOIdbaeIdbMUdbaeclfgLaOclfIdbaLIdbMUdbaecwfgLaOcwfIdbaLIdbMUdbaecxfgeaOcxfIdbaeIdbMUdbaHczfhHaQcufgQmbkaEmbJbbbbJbbjZa8Sa8LfgeIdyg8U:va8UJbbbb9BEaeIdwaaagcx2fgHIdwg8UNaeIdzaHIdbg8WNaeIdaMg8Xa8XMMa8UNaeIdlaHIdlg8XNaeIdCa8UNaeId3Mg8Ua8UMMa8XNaeIdba8WNaeIdxa8XNaeIdKMg8Ua8UMMa8WNaeId8KMMM:lNg8Ua87a87a8U9DEh87kaXa9sfhXahcefghal9hmbkcbhHa8EheindnaeydbgOcuSmbdnaHa8PaOcdtgQfydbgO9hmbcuhOa8EaQfydbgQcuSmba8PaQcdtfydbhOkaeaOBdbkaeclfhealaHcefgH9hmbkcbhHa8FheindnaeydbgOcuSmbdnaHa8PaOcdtgQfydbgO9hmbcuhOa8FaQfydbgQcuSmba8PaQcdtfydbhOkaeaOBdbkaeclfhealaHcefgH9hmbkka87a86aCEh87cbhHabhecbhOindnaAa8PaeydbcdtfydbgXcdtfydbgQaAa8PaeclfydbcdtfydbgYcdtfydbgLSmbaQaAa8PaecwfydbcdtfydbggcdtfydbghSmbaLahSmbabaHcdtfgQaXBdbaQcwfagBdbaQclfaYBdbaHcifhHkaecxfheaOcifgOad6mbkdndna9imbaHhdxekdnaHak0mbaHhdxekdnaRa879FmbaHhdxekJFFuuhRcbhdabhecbhOindna9ka0aeydbgQcdtfydbcdtfIdbg8Ua879ETmbaeclf8Pdbh9EabadcdtfgLaQBdbaLclfa9E83dba8UaRaRa8U9EEhRadcifhdkaecxfheaOcifgOaH6mbkkadak0mbxdkkascNefabadalaAz:cjjjbkdndnadak0mbadhhxekdna9imbadhhxekdnaRa889FmbadhhxekcehLinaRJbb;aZNg8Ua88a8Ua889DEh8XJbbbbh8Udna6Tmba9khea6hHinaeIdbg8Wa8Ua8Wa8X9FEa8Ua8Wa8U9EEh8UaeclfheaHcufgHmbkkJFFuuhRcbhhabhecbhHindna9ka0aeydbgOcdtfydbcdtfIdbg8Wa8X9ETmbaeclf8Pdbh9EabahcdtfgQaOBdbaQclfa9E83dba8WaRaRa8W9EEhRahcifhhkaecxfheaHcifgHad6mbkdnaLahad9hVceGmbadhhxdka8Ua86a86a8U9DEh86ahak9nmecbhLahhdaRa889FmbkkdnamcjjjjdGTmba9qcbalz:tjjjbh8LdnahTmbabheahhHina8LaeydbgOfce86bba8LaAaOcdtfydbfce86bbaeclfheaHcufgHmbkkascNefabahalaAz:cjjjbdndndnalTmbcbhQasyd:yehEindna8LaQfRbbTmbdna5aQfRbbgecl0mbceaetcQGmekdnaAaQcdtgXfydbgeaQSmbaaaQcx2fgHaaaecx2fge8Pdb83dbaHcwfaecwfydbBdbxeka8SaQc8S2fgLIdyg9ca9cJL:3;rUNg8UMh88aLIdwg9ha8UMhRaLIdlgxa8UMh8VaLIdbg9Fa8UMhUaLIdag9Ga8UaaaQcx2fggIdwg89N:th81aLId3g9Ha8UagIdlg8:N:th85aLIdKg9IagIdbgZa8UN:th8YJbbbbhcaLIdCg9JJbbbbMh87aLIdzg9KJbbbbMhBaLIdxgWJbbbbMh83dndnaCTmbaQhOinJbbbba88a8KaOc8S2fgHIdyg8U:va8UJbbbb9BEh8UaDaOaC2cltfheaHIdaa88Na81Mh81aHId3a88Na85Mh85aHIdKa88Na8YMh8YaHIdCa88Na87Mh87aHIdza88NaBMhBaHIdxa88Na83Mh83aHIdwa88NaRMhRaHIdla88Na8VMh8VaHIdba88NaUMhUaChHina81aecxfIdbg8ZaecwfIdbg8WNa8UN:th81a85a8ZaeclfIdbg8XNa8UN:th85a87a8Wa8XNa8UN:th87aUaeIdbg80a80Na8UN:thUa8Ya8Za80Na8UN:th8YaBa8Wa80Na8UN:thBa83a8Xa80Na8UN:th83aRa8Wa8WNa8UN:thRa8Va8Xa8XNa8UN:th8VaeczfheaHcufgHmbkaKaOcdtfydbgOaQ9hmbkaITmbaIaQcltfgeIdxhSaeIdwhJaeIdlh9eaeIdbh8UxekJbbbbhSJbbbbhJJbbbbh9eJbbbbh8UkaBaU:vg8Xa8YNa81:ta87aBa83aU:vg8WN:tg81a8Va83a8WN:tg8Z:vg80a8Wa8YNa85:tg8VN:th85aJa8Ua8XN:ta9ea8Ua8WN:tg83a80N:tg87aRaBa8XN:ta81a80N:tgB:vgR:mh81a83a8Z:vgJ:mh9ednJbbbba8Ua8UaU:vgTN:ta83aJN:ta87aRN:tg83:la88J:983:g81Ng8U9ETmba81a85Na9ea8VNaTa8YNaS:tMMa83:vhckaU:la8U9ETmba8Z:la8U9ETmbaB:la8U9ETmbaT:macNa8X:ma81acNa85aB:vMgBNa8W:ma9eacNa80:maBNa8Va8Z:vMMg87Na8Y:maU:vMMMh88a9maXfgeclfydbgHaeydbge9RhYaEaecitfhXJbbbbh8UdnaHaeSg8JmbJbbbbh8UaXheaYhOinaaaeclfydbcx2fgHIdwa89:tg8Wa8WNaHIdbaZ:tg8Wa8WNaHIdla8::tg8Wa8WNMMg8Waaaeydbcx2fgHIdwa89:tg8Xa8XNaHIdbaZ:tg8Xa8XNaHIdla8::tg8Xa8XNMMg8Xa8Ua8Ua8X9DEg8Ua8Ua8W9DEh8UaecwfheaOcufgOmbkkaBa89:tg8Wa8WNa88aZ:tg8Wa8WNa87a8::tg8Wa8WNMMa8U:rg8Ua8UN9EmbaLId8Khcdna8JmbcbhOcehLdninaaaXclfydbcx2fgeIdbaaaXydbcx2fgHIdbg8X:tg8Ua8:aHIdlg80:tg8YNaZa8X:tg83aeIdla80:tg8WN:tg8Za8Ua87a80:tgRNa88a8X:tg8Va8WN:tg80Na8Wa89aHIdwgU:tg81Na8YaeIdwaU:tg8XN:tg8Ya8WaBaU:tg85NaRa8XN:tg8WNa8Xa83Na81a8UN:tgUa8Xa8VNa85a8UN:tg8UNMMa8Za8ZNa8Ya8YNaUaUNMMa80a80Na8Wa8WNa8Ua8UNMMN:rJbbj8:N9FmeaXcwfhXaOcefgOaY6hLaYaO9hmbkkaLceGmekJbbbbJbbjZa9c:va9cJbbbb9BEg8Ua9haBNa9Ka88Na9GMg8Wa8WMMaBNaxa87Na9JaBNa9HMg8Wa8WMMa87Na9Fa88NaWa87Na9IMg8Wa8WMMa88NacMMM:lNa8Ua9ha89Na9KaZNa9GMg8Wa8WMMa89Naxa8:Na9Ja89Na9HMg8Wa8WMMa8:Na9FaZNaWa8:Na9IMg8Wa8WMMaZNacMMM:lNJbb;aZNJ:983:g81M9EmbagaBUdwaga87Udlaga88UdbkaQcefgQal9hmbkaCTmecbhLindna8LaLfRbbTmbaAaLcdtgefydbaL9hmba5aLfhEaaaLcx2fhOaKaefh8JayaLaC2cdtfh8AcbhgincuhQdnaERbbci9hmbaLhQa8JydbgeaLSmbayagcdtgHfhXa8AaHfIdbh8UaLhQinaQhHcuhQdnaXaeaC2cdtfIdba8U9CmbaHcuSmbaHhQa8Kaec8S2fIdya8KaHc8S2fIdy9ETmbaehQkaKaecdtfydbgeaL9hmbkkayagcdtfhXaDagcltfhYaLheinaXaeaC2cdtfJbbbbJbbjZa8KaeaQaQcuSEgHc8S2fIdyg8U:va8UJbbbb9BEaYaHaC2cltfgHIdwaOIdwNaHIdbaOIdbNaHIdlaOIdlNMMaHIdxMNUdbaKaecdtfydbgeaL9hmbkagcefggaC9hmbkkaLcefgLalSmixbkkaCmekcbhCkaiavaoarawaCalaaayazasa8Rasc1efa5a8Laqz:hjjjbkdnamcjjjjlGTmbazmbahTmbcbhQabheina5aeydbgAfRbbc3thLaecwfgKydbhHdndna8EaAcdtgYfydbaeclfgXydbgOSmbcbhCa8FaOcdtfydbaA9hmekcjjjj94hCkaeaLaCVaAVBdba5aOfRbbc3thLdndna8EaOcdtfydbaHSmbcbhCa8FaHcdtfydbaO9hmekcjjjj94hCkaXaLaCVaOVBdba5aHfRbbc3thCdndna8EaHcdtfydbaASmbcbhOa8FaYfydbaH9hmekcjjjj94hOkaKaCaOVaHVBdbaecxfheaQcifgQah6mbkkdnazTmbahTmbahheinabazabydbcdtfydbBdbabclfhbaecufgembkkdnaPTmbaPana86:rNUdbkasyd;8egecdtasc:Ceffc98fhHdninaeTmeaHydbcbyd:m:jjjbH:bjjjbbaHc98fhHaecufhexbkkascj;sbf8Kjjjjbahk;Yieouabydlhvabydbclfcbaicdtz:tjjjbhoadci9UhrdnadTmbdnalTmbaehwadhDinaoalawydbcdtfydbcdtfgqaqydbcefBdbawclfhwaDcufgDmbxdkkaehwadhDinaoawydbcdtfgqaqydbcefBdbawclfhwaDcufgDmbkkdnaiTmbcbhDaohwinawydbhqawaDBdbawclfhwaqaDfhDaicufgimbkkdnadci6mbinaecwfydbhwaeclfydbhDaeydbhidnalTmbalawcdtfydbhwalaDcdtfydbhDalaicdtfydbhikavaoaicdtfgqydbcitfaDBdbavaqydbcitfawBdlaqaqydbcefBdbavaoaDcdtfgqydbcitfawBdbavaqydbcitfaiBdlaqaqydbcefBdbavaoawcdtfgwydbcitfaiBdbavawydbcitfaDBdlawawydbcefBdbaecxfhearcufgrmbkkabydbcbBdbk:todDue99aicd4aifhrcehwinawgDcethwaDar6mbkcuaDcdtgraDcFFFFi0Ecbyd1:jjjbHjjjjbbhwaoaoyd9GgqcefBd9GaoaqcdtfawBdbawcFearz:tjjjbhkdnaiTmbalcd4hlaDcufhxcbhminamhDdnavTmbavamcdtfydbhDkcbadaDal2cdtfgDydlgwawcjjjj94SEgwcH4aw7c:F:b:DD2cbaDydbgwawcjjjj94SEgwcH4aw7c;D;O:B8J27cbaDydwgDaDcjjjj94SEgDcH4aD7c:3F;N8N27axGhwamcdthPdndndnavTmbakawcdtfgrydbgDcuSmeadavaPfydbal2cdtfgsIdbhzcehqinaqhrdnadavaDcdtfydbal2cdtfgqIdbaz9CmbaqIdlasIdl9CmbaqIdwasIdw9BmlkarcefhqakawarfaxGgwcdtfgrydbgDcu9hmbxdkkakawcdtfgrydbgDcuSmbadamal2cdtfgsIdbhzcehqinaqhrdnadaDal2cdtfgqIdbaz9CmbaqIdlasIdl9CmbaqIdwasIdw9BmikarcefhqakawarfaxGgwcdtfgrydbgDcu9hmbkkaramBdbamhDkabaPfaDBdbamcefgmai9hmbkkakcbyd:m:jjjbH:bjjjbbaoaoyd9GcufBd9GdnaeTmbaiTmbcbhDaehwinawaDBdbawclfhwaiaDcefgD9hmbkcbhDaehwindnaDabydbgrSmbawaearcdtfgrydbBdbaraDBdbkawclfhwabclfhbaiaDcefgD9hmbkkk:hrdvuv998Jjjjjbca9Rgoczfcwfcbyd11jjbBdbaocb8Pdj1jjb83izaocwfcbydN1jjbBdbaocb8Pd:m1jjb83ibdnadTmbaicd4hrdnabmbdnalTmbcbhwinaealawcdtfydbar2cdtfhDcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkawcefgwad9hmbxikkarcdthwcbhDincbhiinaoczfaifgqaeaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkaeawfheaDcefgDad9hmbxdkkdnalTmbcbhwinabawcx2fgiaealawcdtfydbar2cdtfgDIdbUdbaiaDIdlUdlaiaDIdwUdwcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkawcefgwad9hmbxdkkarcdthlcbhwaehDinabawcx2fgiaeawar2cdtfgqIdbUdbaiaqIdlUdlaiaqIdwUdwcbhiinaoczfaifgqaDaifIdbgkaqIdbgxaxak9EEUdbaoaifgqakaqIdbgxaxak9DEUdbaiclfgicx9hmbkaDalfhDawcefgwad9hmbkkJbbbbaoIdbaoIdzgx:tgkakJbbbb9DEgkaoIdlaoIdCgm:tgPaPak9DEgkaoIdwaoIdKgP:tgsasak9DEhsdnabTmbadTmbJbbbbJbbjZas:vasJbbbb9BEhkinabakabIdbax:tNUdbabclfgoakaoIdbam:tNUdbabcwfgoakaoIdbaP:tNUdbabcxfhbadcufgdmbkkdnavTmbavaPUdwavamUdlavaxUdbkask:ZlewudnaeTmbcbhvabhoinaoavBdbaoclfhoaeavcefgv9hmbkkdnaiTmbcbhrinadarcdtfhwcbhDinalawaDcdtgvc:G1jjbfydbcdtfydbcdtfydbhodnabalawavfydbcdtfydbgqcdtfgkydbgvaqSmbinakabavgqcdtfgxydbgvBdbaxhkaqav9hmbkkdnabaocdtfgkydbgvaoSmbinakabavgocdtfgxydbgvBdbaxhkaoav9hmbkkdnaqaoSmbabaqaoaqao0Ecdtfaqaoaqao6EBdbkaDcefgDci9hmbkarcifgrai6mbkkdnaembcbskcbhxindnalaxcdtgvfydbax9hmbaxhodnabavfgDydbgvaxSmbaDhqinaqabavgocdtfgkydbgvBdbakhqaoav9hmbkkaDaoBdbkaxcefgxae9hmbkcbhvabhocbhkindndnavalydbgq9hmbdnavaoydbgq9hmbaoakBdbakcefhkxdkaoabaqcdtfydbBdbxekaoabaqcdtfydbBdbkaoclfhoalclfhlaeavcefgv9hmbkakk;Jiilud99duabcbaecltz:tjjjbhvdnalTmbadhoaihralhwinarcwfIdbhDarclfIdbhqavaoydbcltfgkarIdbakIdbMUdbakclfgxaqaxIdbMUdbakcwfgxaDaxIdbMUdbakcxfgkakIdbJbbjZMUdbaoclfhoarcxfhrawcufgwmbkkdnaeTmbavhraehkinarcxfgoIdbhDaocbBdbararIdbJbbbbJbbjZaD:vaDJbbbb9BEgDNUdbarclfgoaDaoIdbNUdbarcwfgoaDaoIdbNUdbarczfhrakcufgkmbkkdnalTmbinavadydbcltfgrcxfgkaicwfIdbarcwfIdb:tgDaDNaiIdbarIdb:tgDaDNaiclfIdbarclfIdb:tgDaDNMMgDakIdbgqaqaD9DEUdbadclfhdaicxfhialcufglmbkkdnaeTmbavcxfhrinabarIdbUdbarczfhrabclfhbaecufgembkkk:moerudnaoTmbaecd4hzdnavTmbaicd4hHavcdthOcbhAindnaPaAfRbbTmbaAhednaDTmbaDaAcdtfydbhekdnasTmbasaefRbbceGmekdnamaAfRbbclSmbabaeaz2cdtfgiaraAcx2fgCIdbakNaxIdbMUdbaiaCIdlakNaxIdlMUdlaiaCIdwakNaxIdwMUdwkadaeaH2cdtfhXaqheawhiavhCinaXaeydbcdtgQfaiIdbalaQfIdb:vUdbaeclfheaiclfhiaCcufgCmbkkawaOfhwaAcefgAao9hmbxdkkdnasmbcbheaDhiindnaPaefRbbTmbaehCdnaDTmbaiydbhCkamaefRbbclSmbabaCaz2cdtfgCarIdbakNaxIdbMUdbaCarclfIdbakNaxIdlMUdlaCarcwfIdbakNaxIdwMUdwkaiclfhiarcxfhraoaecefge9hmbxdkkdnaDTmbindnaPRbbTmbasaDydbgefRbbceGmbamRbbclSmbabaeaz2cdtfgearIdbakNaxIdbMUdbaearclfIdbakNaxIdlMUdlaearcwfIdbakNaxIdwMUdwkaPcefhPaDclfhDamcefhmarcxfhraocufgombxdkkazcdthicbheindnaPaefRbbTmbasaefRbbceGmbamaefRbbclSmbabarIdbakNaxIdbMUdbabclfarclfIdbakNaxIdlMUdbabcwfarcwfIdbakNaxIdwMUdbkarcxfhrabaifhbaoaecefge9hmbkkk8MbabaeadaialavcbcbcbcbcbaoarawaDz:bjjjbk8MbabaeadaialavaoarawaDaqakaxamaPz:bjjjbkRbababaeadaialavaoarawaDaqakaxcjjjjdVamz:bjjjbk:d8Koque99due99duq998Jjjjjbc;Wb9Rgq8Kjjjjbcbhkaqcxfcbc;Kbz:tjjjb8Aaqcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbgxBdxaqceBd2axaialavcbcbz:ejjjb8AaqcualcdtalcFFFFi0Egmcbyd1:jjjbHjjjjbbgiBdzaqcdBd2dndnJFF959eJbbjZawJbbjZawJbbjZ9DE:vawJ9VO:d869DEgw:lJbbb9p9DTmbaw:OhPxekcjjjj94hPkadci9Uhsarco9UhzdndnaombaPcd9imekdnalTmbaPcuf:YhwdnaoTmbcbhvaihHaxhOindndnaoavfRbbceGTmbavcjjjjlVhAxekdndnaOclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcqthAdndnaOcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXVhAdndnaOIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXcCtVhAkaHaABdbaHclfhHaOcxfhOalavcefgv9hmbxdkkaxhvaihOalhHindndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcCthAdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaXcqtaAVhAdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaOaAaXVBdbavcxfhvaOclfhOaHcufgHmbkkadTmbcbhkaehvcbhOinakaiavclfydbcdtfydbgHaiavcwfydbcdtfydbgA9haiavydbcdtfydbgXaH9haXaA9hGGfhkavcxfhvaOcifgOad6mbkkarci9UhQdndnaz:Z:rJbbbZMgw:lJbbb9p9DTmbaw:Ohvxekcjjjj94hvkaQ:ZhLcbhKc:bwhzdninakaQ9pmeazaP9Rcd9imeavazcufavaz9iEaPcefavaP9kEhYdnalTmbaYcuf:YhwdnaoTmbcbhOaihHaxhvindndnaoaOfRbbceGTmbaOcjjjjlVhAxekdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcqthAdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXVhAdndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaAaXcCtVhAkaHaABdbaHclfhHavcxfhvalaOcefgO9hmbxdkkaxhvaihOalhHindndnavIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhAxekcjjjj94hAkaAcCthAdndnavclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaXcqtaAVhAdndnavcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaOaAaXVBdbavcxfhvaOclfhOaHcufgHmbkkcbhOdnadTmbaehvcbhHinaOaiavclfydbcdtfydbgAaiavcwfydbcdtfydbgX9haiavydbcdtfydbgraA9haraX9hGGfhOavcxfhvaHcifgHad6mbkkJbbbbh8Adnas:ZgCaL:taY:Ygwaz:Y:tgENak:Zg3aO:Zg5:tNa3aL:tawaP:Y:tg8ENa5aC:tNMg8FJbbbb9BmbaCa3:ta8EaEa5aL:tNNNa8F:vh8AkdndnaOaQ0mbaOhkaYhPxekaOhsaYhzkdndnaKcl0mbdna8AawMJbbbZMgw:lJbbb9p9DTmbaw:Ohvxdkcjjjj94hvxekaPazfcd9ThvkaKcefgKcs9hmbkkdndndnakmbJbbjZhwcbhicdhvaDmexdkalcd4alfhHcehOinaOgvcethOavaH6mbkcbhOaqcuavcdtgYavcFFFFi0Ecbyd1:jjjbHjjjjbbgKBdCaqciBd2aqamcbyd1:jjjbHjjjjbbgzBdKaqclBd2dndndndnalTmbaPcuf:YhwaoTmecbhOaihAaxhHindndnaoaOfRbbceGTmbaOcjjjjlVhXxekdndnaHclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaXcqthXdndnaHcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohrxekcjjjj94hrkaXarVhXdndnaHIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohrxekcjjjj94hrkaXarcCtVhXkaAaXBdbaAclfhAaHcxfhHalaOcefgO9hmbxikkaKcFeaYz:tjjjb8AcbhPcbhvxdkaxhOaihHalhAindndnaOIdbawNJbbbZMgC:lJbbb9p9DTmbaC:OhXxekcjjjj94hXkaXcCthXdndnaOclfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohrxekcjjjj94hrkarcqtaXVhXdndnaOcwfIdbawNJbbbZMgC:lJbbb9p9DTmbaC:Ohrxekcjjjj94hrkaHaXarVBdbaOcxfhOaHclfhHaAcufgAmbkkaKcFeaYz:tjjjbhravcufhocbhPcbhYindndndnaraiaYcdtgKfydbgAcm4aA7c:v;t;h;Ev2gvcs4av7aoGgHcdtfgXydbgOcuSmbcehvinaiaOcdtgOfydbaASmdaHavfhOavcefhvaraOaoGgHcdtfgXydbgOcu9hmbkkaXaYBdbaPhvaPcefhPxekazaOfydbhvkazaKfavBdbaYcefgYal9hmbkcuaPc8S2gOaPc;D;O;f8U0Ehvkcbhraqavcbyd1:jjjbHjjjjbbgvBd3aqcvBd2avcbaOz:tjjjbhOdnadTmbaehiinJbbnnJbbjZazaiydbgAcdtfydbgvazaiclfydbgHcdtfydbgYSavazaicwfydbgXcdtfydbgKSGgoEh8EdnaxaHcx2fgHIdbaxaAcx2fgAIdbg5:tgCaxaXcx2fgXIdlaAIdlg8A:tgwNaXIdba5:tg3aHIdla8A:tg8FN:tgLaLNa8FaXIdwaAIdwgE:tgaNawaHIdwaE:tg8FN:tgwawNa8Fa3NaaaCN:tgCaCNMM:rg3Jbbbb9ETmbaLa3:vhLaCa3:vhCawa3:vhwkaOavc8S2fgvavIdbawa8Ea3:rNg3awNNg8FMUdbavaCa3aCNgaNghavIdlMUdlavaLa3aLNg8ENggavIdwMUdwavaaawNgaavIdxMUdxava8EawNg8JavIdzMUdzava8EaCNg8EavIdCMUdCavawa3aLaENawa5Na8AaCNMM:mg8ANg5NgwavIdKMUdKavaCa5NgCavId3MUd3avaLa5NgLavIdaMUdaava5a8ANg5avId8KMUd8Kava3avIdyMUdydnaombaOaYc8S2fgva8FavIdbMUdbavahavIdlMUdlavagavIdwMUdwavaaavIdxMUdxava8JavIdzMUdzava8EavIdCMUdCavawavIdKMUdKavaCavId3MUd3avaLavIdaMUdaava5avId8KMUd8Kava3avIdyMUdyaOaKc8S2fgva8FavIdbMUdbavahavIdlMUdlavagavIdwMUdwavaaavIdxMUdxava8JavIdzMUdzava8EavIdCMUdCavawavIdKMUdKavaCavId3MUd3avaLavIdaMUdaava5avId8KMUd8Kava3avIdyMUdykaicxfhiarcifgrad6mbkkcbhAaqcuaPcdtgvaPcFFFFi0Egicbyd1:jjjbHjjjjbbgHBdaaqcoBd2aqaicbyd1:jjjbHjjjjbbgiBd8KaqcrBd2aHcFeavz:tjjjbhYdnalTmbazhHinJbbbbJbbjZaOaHydbgXc8S2fgvIdygw:vawJbbbb9BEavIdwaxcwfIdbgwNavIdzaxIdbgCNavIdaMgLaLMMawNavIdlaxclfIdbgLNavIdCawNavId3MgwawMMaLNavIdbaCNavIdxaLNavIdKMgwawMMaCNavId8KMMM:lNhwdndnaYaXcdtgvfgXydbcuSmbaiavfIdbaw9ETmekaXaABdbaiavfawUdbkaHclfhHaxcxfhxalaAcefgA9hmbkkJbbbbhwdnaPTmbinaiIdbgCawawaC9DEhwaiclfhiaPcufgPmbkkakcd4akfhOcehiinaigvcethiavaO6mbkcbhiaqcuavcdtgOavcFFFFi0Ecbyd1:jjjbHjjjjbbgHBdyaHcFeaOz:tjjjbhXdnadTmbavcufhrcbhPcbhxindnazaeaxcdtfgvydbcdtfydbgiazavclfydbcdtfydbgOSmbaiazavcwfydbcdtfydbgvSmbaOavSmbaYavcdtfydbhAdndnaYaOcdtfydbgvaYaicdtfydbgi9pmbavaA9pmbaAhlaihoavhAxekdnaAai9pmbaAav9pmbaihlavhoxekavhlaAhoaihAkabaPcx2fgvaABdbavcwfaoBdbavclfalBdbdnaXaoc:3F;N8N2alc:F:b:DD27aAc;D;O:B8J27arGgOcdtfgvydbgicuSmbcehHinaHhvdnabaicx2fgiydbaA9hmbaiydlal9hmbaiydwaoSmikavcefhHaXaOavfarGgOcdtfgvydbgicu9hmbkkavaPBdbaPcefhPkaxcifgxad6mbkaPci2hikdnaDmbcwhvxdkaw:rhwcwhvkaDawUdbkavcdthvdninavTmeavc98fgvaqcxffydbcbyd:m:jjjbH:bjjjbbxbkkaqc;Wbf8Kjjjjbaik:2ldwue9:8Jjjjjbc;Wb9Rgr8Kjjjjbcbhwarcxfcbc;Kbz:tjjjb8AdnabaeSmbabaeadcdtzMjjjb8AkarcualcdtalcFFFFi0EgDcbyd1:jjjbHjjjjbbgqBdxarceBd2aqcbaialavcbarcxfz:djjjbcualcx2alc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbhkarcxfaryd2gxcdtgmfakBdbaraxcefgPBd2akaialavcbcbz:ejjjb8AarcxfaPcdtfaDcbyd1:jjjbHjjjjbbgvBdbaraxcdfgiBd2arcxfaicdtfcuavalaeadaqz:fjjjbgecltaecjjjjiGEcbyd1:jjjbHjjjjbbgiBdbaiaeavakalz:gjjjbdnadTmbaoaoNhocbhwabhlcbhkindnaiavalydbgecdtfydbcdtfIdbao9ETmbalclf8PdbhsabawcdtfgqaeBdbaqclfas83dbawcifhwkalcxfhlakcifgkad6mbkkaxcifhlamarcxffcwfhkdninalTmeakydbcbyd:m:jjjbH:bjjjbbakc98fhkalcufhlxbkkarc;Wbf8Kjjjjbawk:XCoDud99vue99vuo998Jjjjjbc;Wb9Rgw8KjjjjbdndnarmbcbhDxekawcxfcbc;Kbz:tjjjb8Aawcuadcx2adc;v:Q;v:Qe0Ecbyd1:jjjbHjjjjbbgqBdxawceBd2aqaeadaicbcbz:ejjjb8AawcuadcdtadcFFFFi0Egkcbyd1:jjjbHjjjjbbgxBdzawcdBd2adcd4adfhmceheinaegicetheaiam6mbkcbhPawcuaicdtgsaicFFFFi0Ecbyd1:jjjbHjjjjbbgzBdCawciBd2dndnar:ZgH:rJbbbZMgO:lJbbb9p9DTmbaO:Ohexekcjjjj94hekaicufhAc:bwhDcbhCadhXcbhQinaeaDcufaeaD9iEaPcefaeaP9kEhLdndnadTmbaLcuf:YhOaqhiaxheadhmindndnaiIdbaONJbbbZMgK:lJbbb9p9DTmbaK:OhYxekcjjjj94hYkaYcCthYdndnaiclfIdbaONJbbbZMgK:lJbbb9p9DTmbaK:Oh8Axekcjjjj94h8Aka8AcqtaYVhYdndnaicwfIdbaONJbbbZMgK:lJbbb9p9DTmbaK:Oh8Axekcjjjj94h8AkaeaYa8AVBdbaicxfhiaeclfheamcufgmmbkazcFeasz:tjjjbhEcbh3cbh5indnaEaxa5cdtfydbgYcm4aY7c:v;t;h;Ev2gics4ai7aAGgmcdtfg8AydbgecuSmbaeaYSmbcehiinaEamaifaAGgmcdtfg8AydbgecuSmeaicefhiaeaY9hmbkka8AaYBdba3aecuSfh3a5cefg5ad9hmbxdkkazcFeasz:tjjjb8Acbh3kJbbbbh8EdnaX:ZgKaH:taL:YgOaD:Y:tg8FNaC:Zgaa3:Zgh:tNaaaH:taOaP:Y:tggNahaK:tNMg8JJbbbb9BmbaKaa:taga8FahaH:tNNNa8J:vh8EkaPaLa3ar0giEhPaCa3aiEhCdna3arSmbaLaDaiEgDaP9Rcd9imbdndnaQcl0mbdna8EaOMJbbbZMgO:lJbbb9p9DTmbaO:Ohexdkcjjjj94hexekaPaDfcd9Theka3aXaiEhXaQcefgQcs9hmekkdndnaCmbcihicbhDxekcbhiawakcbyd1:jjjbHjjjjbbg5BdKawclBd2aPcuf:YhKdndnadTmbaqhiaxheadhmindndnaiIdbaKNJbbbZMgO:lJbbb9p9DTmbaO:OhYxekcjjjj94hYkaYcCthYdndnaiclfIdbaKNJbbbZMgO:lJbbb9p9DTmbaO:Oh8Axekcjjjj94h8Aka8AcqtaYVhYdndnaicwfIdbaKNJbbbZMgO:lJbbb9p9DTmbaO:Oh8Axekcjjjj94h8AkaeaYa8AVBdbaicxfhiaeclfheamcufgmmbkazcFeasz:tjjjbhEcbhDcbh3indndndnaEaxa3cdtgLfydbgYcm4aY7c:v;t;h;Ev2gics4ai7aAGgmcdtfg8AydbgecuSmbcehiinaxaecdtgefydbaYSmdamaifheaicefhiaEaeaAGgmcdtfg8Aydbgecu9hmbkka8Aa3BdbaDhiaDcefhDxeka5aefydbhika5aLfaiBdba3cefg3ad9hmbkcuaDc32giaDc;j:KM;jb0EhexekazcFeasz:tjjjb8AcbhDcbhekawaecbyd1:jjjbHjjjjbbgeBd3awcvBd2aecbaiz:tjjjbh8Aavcd4hxdnadTmbdnalTmbaxcdthEa5hYaqhealhmadhAina8AaYydbc32fgiaeIdbaiIdbMUdbaiaeclfIdbaiIdlMUdlaiaecwfIdbaiIdwMUdwaiamIdbaiIdxMUdxaiamclfIdbaiIdzMUdzaiamcwfIdbaiIdCMUdCaiaiIdKJbbjZMUdKaYclfhYaecxfheamaEfhmaAcufgAmbxdkka5hmaqheadhYina8Aamydbc32fgiaeIdbaiIdbMUdbaiaeclfIdbaiIdlMUdlaiaecwfIdbaiIdwMUdwaiaiIdxJbbbbMUdxaiaiIdzJbbbbMUdzaiaiIdCJbbbbMUdCaiaiIdKJbbjZMUdKamclfhmaecxfheaYcufgYmbkkdnaDTmba8AhiaDheinaiaiIdbJbbbbJbbjZaicKfIdbgO:vaOJbbbb9BEgONUdbaiclfgmaOamIdbNUdbaicwfgmaOamIdbNUdbaicxfgmaOamIdbNUdbaiczfgmaOamIdbNUdbaicCfgmaOamIdbNUdbaic3fhiaecufgembkkcbhYawcuaDcdtgLaDcFFFFi0Egicbyd1:jjjbHjjjjbbgeBdaawcoBd2awaicbyd1:jjjbHjjjjbbgEBd8KaecFeaLz:tjjjbh3dnadTmbJbbjZJbbjZaK:vaPceSEaoNgOaONhKaxcdthxalheinaKaec;81jjbalEgmIdwa8Aa5ydbgAc32fgiIdC:tgOaONamIdbaiIdx:tgOaONamIdlaiIdz:tgOaONMMNaqcwfIdbaiIdw:tgOaONaqIdbaiIdb:tgOaONaqclfIdbaiIdl:tgOaONMMMhOdndna3aAcdtgifgmydbcuSmbaEaifIdbaO9ETmekamaYBdbaEaifaOUdbka5clfh5aqcxfhqaeaxfheadaYcefgY9hmbkkaba3aLzMjjjb8AcrhikaicdthiinaiTmeaic98fgiawcxffydbcbyd:m:jjjbH:bjjjbbxbkkawc;Wbf8KjjjjbaDk:Ydidui99ducbhi8Jjjjjbca9Rglczfcwfcbyd11jjbBdbalcb8Pdj1jjb83izalcwfcbydN1jjbBdbalcb8Pd:m1jjb83ibdndnaembJbbjFhvJbbjFhoJbbjFhrxekadcd4cdthwincbhdinalczfadfgDabadfIdbgvaDIdbgoaoav9EEUdbaladfgDavaDIdbgoaoav9DEUdbadclfgdcx9hmbkabawfhbaicefgiae9hmbkalIdwalIdK:thralIdlalIdC:thoalIdbalIdz:thvkJbbbbavavJbbbb9DEgvaoaoav9DEgvararav9DEk9DeeuabcFeaicdtz:tjjjbhlcbhbdnadTmbindnalaeydbcdtfgiydbcu9hmbaiabBdbabcefhbkaeclfheadcufgdmbkkabk;7idqui998Jjjjjbc;Wb9Rgl8Kjjjjbalcxfcbc;Kbz:tjjjb8Aadcd4adfhvcehoinaogrcethoarav6mbkalcuarcdtgoarcFFFFi0Ecbyd1:jjjbHjjjjbbgvBdxavcFeaoz:tjjjbhwdnadTmbaicd4hDarcufhqcbhkindndnawcbaeakaD2cdtfgrydlgiaicjjjj94SEgocH4ao7c:F:b:DD2cbarydbgxaxcjjjj94SEgocH4ao7c;D;O:B8J27cbarydwgmamcjjjj94SEgrcH4ar7c:3F;N8N27aqGgvcdtfgrydbgocuSmbam::hPai::hsax::hzcehiinaihrdnaeaoaD2cdtfgiIdbaz9CmbaiIdlas9CmbaiIdwaP9BmikarcefhiawavarfaqGgvcdtfgrydbgocu9hmbkkarakBdbakhokabakcdtfaoBdbakcefgkad9hmbkkcbhrdninarc98Smealcxfarfydbcbyd:m:jjjbH:bjjjbbarc98fhrxbkkalc;Wbf8Kjjjjbk9teiucbcbyd:q:jjjbgeabcifc98GfgbBd:q:jjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;teeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiaeydlBdlaiaeydwBdwaiaeydxBdxaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk:3eedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdxaialBdwaialBdlaialBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabk9teiucbcbyd:q:jjjbgeabcrfc94GfgbBd:q:jjjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaikTeeucbabcbyd:q:jjjbge9Rcifc98GaefgbBd:q:jjjbdnabZbcztge9nmbabae9RcFFifcz4nb8Akkk:Iedbcjwk1eFFuuFFuuFFuuFFuFFFuFFFuFbbbbbbbbebbbdbbbbbbbebbbebbbdbbbbbbbbbbbeeeeebebbebbebebbbeebbbbbbbbbbbbeeeeeebebbeeebeebbbbebebbbbbbbbbbbbbbbbbbc1Dkxebbbdbbb:GNbb'; // embed! wasm
|
|
7779
|
+
|
|
7780
|
+
var wasmpack = new Uint8Array([
|
|
7781
|
+
32, 0, 65, 2, 1, 106, 34, 33, 3, 128, 11, 4, 13, 64, 6, 253, 10, 7, 15, 116, 127, 5, 8, 12, 40, 16, 19, 54, 20, 9, 27, 255, 113, 17, 42, 67,
|
|
7782
|
+
24, 23, 146, 148, 18, 14, 22, 45, 70, 69, 56, 114, 101, 21, 25, 63, 75, 136, 108, 28, 118, 29, 73, 115,
|
|
7783
|
+
]);
|
|
7784
|
+
|
|
7785
|
+
if (typeof WebAssembly !== 'object') {
|
|
7786
|
+
return {
|
|
7787
|
+
supported: false,
|
|
7788
|
+
};
|
|
7789
|
+
}
|
|
7790
|
+
|
|
7791
|
+
var instance;
|
|
7792
|
+
|
|
7793
|
+
var ready = WebAssembly.instantiate(unpack(wasm), {}).then(function (result) {
|
|
7794
|
+
instance = result.instance;
|
|
7795
|
+
instance.exports.__wasm_call_ctors();
|
|
7796
|
+
});
|
|
7797
|
+
|
|
7798
|
+
function unpack(data) {
|
|
7799
|
+
var result = new Uint8Array(data.length);
|
|
7800
|
+
for (var i = 0; i < data.length; ++i) {
|
|
7801
|
+
var ch = data.charCodeAt(i);
|
|
7802
|
+
result[i] = ch > 96 ? ch - 97 : ch > 64 ? ch - 39 : ch + 4;
|
|
7803
|
+
}
|
|
7804
|
+
var write = 0;
|
|
7805
|
+
for (var i = 0; i < data.length; ++i) {
|
|
7806
|
+
result[write++] = result[i] < 60 ? wasmpack[result[i]] : (result[i] - 60) * 64 + result[++i];
|
|
7807
|
+
}
|
|
7808
|
+
return result.buffer.slice(0, write);
|
|
7809
|
+
}
|
|
7810
|
+
|
|
7811
|
+
function assert(cond) {
|
|
7812
|
+
if (!cond) {
|
|
7813
|
+
throw new Error('Assertion failed');
|
|
7814
|
+
}
|
|
7815
|
+
}
|
|
7816
|
+
|
|
7817
|
+
function bytes(view) {
|
|
7818
|
+
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
7819
|
+
}
|
|
7820
|
+
|
|
7821
|
+
function genremap(fun, positions, vertices, stride) {
|
|
7822
|
+
var sbrk = instance.exports.sbrk;
|
|
7823
|
+
var rp = sbrk(vertices * 4);
|
|
7824
|
+
var sp = sbrk(vertices * stride * 4);
|
|
7825
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7826
|
+
heap.set(bytes(positions), sp);
|
|
7827
|
+
fun(rp, sp, vertices, stride * 4);
|
|
7828
|
+
// heap may have grown
|
|
7829
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7830
|
+
var remap = new Uint32Array(vertices);
|
|
7831
|
+
new Uint8Array(remap.buffer).set(heap.subarray(rp, rp + vertices * 4));
|
|
7832
|
+
sbrk(rp - sbrk(0));
|
|
7833
|
+
return remap;
|
|
7834
|
+
}
|
|
7835
|
+
|
|
7836
|
+
function reorder(fun, indices, vertices) {
|
|
7837
|
+
var sbrk = instance.exports.sbrk;
|
|
7838
|
+
var ip = sbrk(indices.length * 4);
|
|
7839
|
+
var rp = sbrk(vertices * 4);
|
|
7840
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7841
|
+
var indices8 = bytes(indices);
|
|
7842
|
+
heap.set(indices8, ip);
|
|
7843
|
+
var unique = fun(rp, ip, indices.length, vertices);
|
|
7844
|
+
// heap may have grown
|
|
7845
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7846
|
+
var remap = new Uint32Array(vertices);
|
|
7847
|
+
new Uint8Array(remap.buffer).set(heap.subarray(rp, rp + vertices * 4));
|
|
7848
|
+
indices8.set(heap.subarray(ip, ip + indices.length * 4));
|
|
7849
|
+
sbrk(ip - sbrk(0));
|
|
7850
|
+
|
|
7851
|
+
for (var i = 0; i < indices.length; ++i) indices[i] = remap[indices[i]];
|
|
7852
|
+
|
|
7853
|
+
return [remap, unique];
|
|
7854
|
+
}
|
|
7855
|
+
|
|
7856
|
+
function maxindex(source) {
|
|
7857
|
+
var result = 0;
|
|
7858
|
+
for (var i = 0; i < source.length; ++i) {
|
|
7859
|
+
var index = source[i];
|
|
7860
|
+
result = result < index ? index : result;
|
|
7861
|
+
}
|
|
7862
|
+
return result;
|
|
7863
|
+
}
|
|
7864
|
+
|
|
7865
|
+
function simplify(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, options) {
|
|
7866
|
+
var sbrk = instance.exports.sbrk;
|
|
7867
|
+
var te = sbrk(4);
|
|
7868
|
+
var ti = sbrk(index_count * 4);
|
|
7869
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
7870
|
+
var si = sbrk(index_count * 4);
|
|
7871
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7872
|
+
heap.set(bytes(vertex_positions), sp);
|
|
7873
|
+
heap.set(bytes(indices), si);
|
|
7874
|
+
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, target_index_count, target_error, options, te);
|
|
7875
|
+
// heap may have grown
|
|
7876
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7877
|
+
var target = new Uint32Array(result);
|
|
7878
|
+
bytes(target).set(heap.subarray(ti, ti + result * 4));
|
|
7879
|
+
var error = new Float32Array(1);
|
|
7880
|
+
bytes(error).set(heap.subarray(te, te + 4));
|
|
7881
|
+
sbrk(te - sbrk(0));
|
|
7882
|
+
return [target, error[0]];
|
|
7883
|
+
}
|
|
7884
|
+
|
|
7885
|
+
function simplifyAttr(
|
|
7886
|
+
fun,
|
|
7887
|
+
indices,
|
|
7888
|
+
index_count,
|
|
7889
|
+
vertex_positions,
|
|
7890
|
+
vertex_count,
|
|
7891
|
+
vertex_positions_stride,
|
|
7892
|
+
vertex_attributes,
|
|
7893
|
+
vertex_attributes_stride,
|
|
7894
|
+
attribute_weights,
|
|
7895
|
+
vertex_lock,
|
|
7896
|
+
target_index_count,
|
|
7897
|
+
target_error,
|
|
7898
|
+
options
|
|
7899
|
+
) {
|
|
7900
|
+
var sbrk = instance.exports.sbrk;
|
|
7901
|
+
var te = sbrk(4);
|
|
7902
|
+
var ti = sbrk(index_count * 4);
|
|
7903
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
7904
|
+
var sa = sbrk(vertex_count * vertex_attributes_stride);
|
|
7905
|
+
var sw = sbrk(attribute_weights.length * 4);
|
|
7906
|
+
var si = sbrk(index_count * 4);
|
|
7907
|
+
var vl = vertex_lock ? sbrk(vertex_count) : 0;
|
|
7908
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7909
|
+
heap.set(bytes(vertex_positions), sp);
|
|
7910
|
+
heap.set(bytes(vertex_attributes), sa);
|
|
7911
|
+
heap.set(bytes(attribute_weights), sw);
|
|
7912
|
+
heap.set(bytes(indices), si);
|
|
7913
|
+
if (vertex_lock) {
|
|
7914
|
+
heap.set(bytes(vertex_lock), vl);
|
|
7915
|
+
}
|
|
7916
|
+
var result = fun(
|
|
7917
|
+
ti,
|
|
7918
|
+
si,
|
|
7919
|
+
index_count,
|
|
7920
|
+
sp,
|
|
7921
|
+
vertex_count,
|
|
7922
|
+
vertex_positions_stride,
|
|
7923
|
+
sa,
|
|
7924
|
+
vertex_attributes_stride,
|
|
7925
|
+
sw,
|
|
7926
|
+
attribute_weights.length,
|
|
7927
|
+
vl,
|
|
7928
|
+
target_index_count,
|
|
7929
|
+
target_error,
|
|
7930
|
+
options,
|
|
7931
|
+
te
|
|
7932
|
+
);
|
|
7933
|
+
// heap may have grown
|
|
7934
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7935
|
+
var target = new Uint32Array(result);
|
|
7936
|
+
bytes(target).set(heap.subarray(ti, ti + result * 4));
|
|
7937
|
+
var error = new Float32Array(1);
|
|
7938
|
+
bytes(error).set(heap.subarray(te, te + 4));
|
|
7939
|
+
sbrk(te - sbrk(0));
|
|
7940
|
+
return [target, error[0]];
|
|
7941
|
+
}
|
|
7942
|
+
|
|
7943
|
+
function simplifyUpdate(
|
|
7944
|
+
fun,
|
|
7945
|
+
indices,
|
|
7946
|
+
index_count,
|
|
7947
|
+
vertex_positions,
|
|
7948
|
+
vertex_count,
|
|
7949
|
+
vertex_positions_stride,
|
|
7950
|
+
vertex_attributes,
|
|
7951
|
+
vertex_attributes_stride,
|
|
7952
|
+
attribute_weights,
|
|
7953
|
+
vertex_lock,
|
|
7954
|
+
target_index_count,
|
|
7955
|
+
target_error,
|
|
7956
|
+
options
|
|
7957
|
+
) {
|
|
7958
|
+
var sbrk = instance.exports.sbrk;
|
|
7959
|
+
var te = sbrk(4);
|
|
7960
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
7961
|
+
var sa = sbrk(vertex_count * vertex_attributes_stride);
|
|
7962
|
+
var sw = sbrk(attribute_weights.length * 4);
|
|
7963
|
+
var si = sbrk(index_count * 4);
|
|
7964
|
+
var vl = vertex_lock ? sbrk(vertex_count) : 0;
|
|
7965
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7966
|
+
heap.set(bytes(vertex_positions), sp);
|
|
7967
|
+
heap.set(bytes(vertex_attributes), sa);
|
|
7968
|
+
heap.set(bytes(attribute_weights), sw);
|
|
7969
|
+
heap.set(bytes(indices), si);
|
|
7970
|
+
if (vertex_lock) {
|
|
7971
|
+
heap.set(bytes(vertex_lock), vl);
|
|
7972
|
+
}
|
|
7973
|
+
var result = fun(
|
|
7974
|
+
si,
|
|
7975
|
+
index_count,
|
|
7976
|
+
sp,
|
|
7977
|
+
vertex_count,
|
|
7978
|
+
vertex_positions_stride,
|
|
7979
|
+
sa,
|
|
7980
|
+
vertex_attributes_stride,
|
|
7981
|
+
sw,
|
|
7982
|
+
attribute_weights.length,
|
|
7983
|
+
vl,
|
|
7984
|
+
target_index_count,
|
|
7985
|
+
target_error,
|
|
7986
|
+
options,
|
|
7987
|
+
te
|
|
7988
|
+
);
|
|
7989
|
+
// heap may have grown
|
|
7990
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
7991
|
+
bytes(indices).set(heap.subarray(si, si + result * 4));
|
|
7992
|
+
bytes(vertex_positions).set(heap.subarray(sp, sp + vertex_count * vertex_positions_stride));
|
|
7993
|
+
bytes(vertex_attributes).set(heap.subarray(sa, sa + vertex_count * vertex_attributes_stride));
|
|
7994
|
+
var error = new Float32Array(1);
|
|
7995
|
+
bytes(error).set(heap.subarray(te, te + 4));
|
|
7996
|
+
sbrk(te - sbrk(0));
|
|
7997
|
+
return [result, error[0]];
|
|
7998
|
+
}
|
|
7999
|
+
|
|
8000
|
+
function simplifyScale(fun, vertex_positions, vertex_count, vertex_positions_stride) {
|
|
8001
|
+
var sbrk = instance.exports.sbrk;
|
|
8002
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
8003
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8004
|
+
heap.set(bytes(vertex_positions), sp);
|
|
8005
|
+
var result = fun(sp, vertex_count, vertex_positions_stride);
|
|
8006
|
+
sbrk(sp - sbrk(0));
|
|
8007
|
+
return result;
|
|
8008
|
+
}
|
|
8009
|
+
|
|
8010
|
+
function simplifyPoints(
|
|
8011
|
+
fun,
|
|
8012
|
+
vertex_positions,
|
|
8013
|
+
vertex_count,
|
|
8014
|
+
vertex_positions_stride,
|
|
8015
|
+
vertex_colors,
|
|
8016
|
+
vertex_colors_stride,
|
|
8017
|
+
color_weight,
|
|
8018
|
+
target_vertex_count
|
|
8019
|
+
) {
|
|
8020
|
+
var sbrk = instance.exports.sbrk;
|
|
8021
|
+
var ti = sbrk(target_vertex_count * 4);
|
|
8022
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
8023
|
+
var sc = sbrk(vertex_count * vertex_colors_stride);
|
|
8024
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8025
|
+
heap.set(bytes(vertex_positions), sp);
|
|
8026
|
+
if (vertex_colors) {
|
|
8027
|
+
heap.set(bytes(vertex_colors), sc);
|
|
8028
|
+
}
|
|
8029
|
+
var result = fun(ti, sp, vertex_count, vertex_positions_stride, sc, vertex_colors_stride, color_weight, target_vertex_count);
|
|
8030
|
+
// heap may have grown
|
|
8031
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8032
|
+
var target = new Uint32Array(result);
|
|
8033
|
+
bytes(target).set(heap.subarray(ti, ti + result * 4));
|
|
8034
|
+
sbrk(ti - sbrk(0));
|
|
8035
|
+
return target;
|
|
8036
|
+
}
|
|
8037
|
+
|
|
8038
|
+
function simplifySloppy(
|
|
8039
|
+
fun,
|
|
8040
|
+
indices,
|
|
8041
|
+
index_count,
|
|
8042
|
+
vertex_positions,
|
|
8043
|
+
vertex_count,
|
|
8044
|
+
vertex_positions_stride,
|
|
8045
|
+
vertex_lock,
|
|
8046
|
+
target_index_count,
|
|
8047
|
+
target_error
|
|
8048
|
+
) {
|
|
8049
|
+
var sbrk = instance.exports.sbrk;
|
|
8050
|
+
var te = sbrk(4);
|
|
8051
|
+
var ti = sbrk(index_count * 4);
|
|
8052
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
8053
|
+
var si = sbrk(index_count * 4);
|
|
8054
|
+
var vl = vertex_lock ? sbrk(vertex_count) : 0;
|
|
8055
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8056
|
+
heap.set(bytes(vertex_positions), sp);
|
|
8057
|
+
heap.set(bytes(indices), si);
|
|
8058
|
+
if (vertex_lock) {
|
|
8059
|
+
heap.set(bytes(vertex_lock), vl);
|
|
8060
|
+
}
|
|
8061
|
+
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, vl, target_index_count, target_error, te);
|
|
8062
|
+
// heap may have grown
|
|
8063
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8064
|
+
var target = new Uint32Array(result);
|
|
8065
|
+
bytes(target).set(heap.subarray(ti, ti + result * 4));
|
|
8066
|
+
var error = new Float32Array(1);
|
|
8067
|
+
bytes(error).set(heap.subarray(te, te + 4));
|
|
8068
|
+
sbrk(te - sbrk(0));
|
|
8069
|
+
return [target, error[0]];
|
|
8070
|
+
}
|
|
8071
|
+
|
|
8072
|
+
function simplifyPrune(fun, indices, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_error) {
|
|
8073
|
+
var sbrk = instance.exports.sbrk;
|
|
8074
|
+
var ti = sbrk(index_count * 4);
|
|
8075
|
+
var sp = sbrk(vertex_count * vertex_positions_stride);
|
|
8076
|
+
var si = sbrk(index_count * 4);
|
|
8077
|
+
var heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8078
|
+
heap.set(bytes(vertex_positions), sp);
|
|
8079
|
+
heap.set(bytes(indices), si);
|
|
8080
|
+
var result = fun(ti, si, index_count, sp, vertex_count, vertex_positions_stride, target_error);
|
|
8081
|
+
// heap may have grown
|
|
8082
|
+
heap = new Uint8Array(instance.exports.memory.buffer);
|
|
8083
|
+
var target = new Uint32Array(result);
|
|
8084
|
+
bytes(target).set(heap.subarray(ti, ti + result * 4));
|
|
8085
|
+
sbrk(ti - sbrk(0));
|
|
8086
|
+
return target;
|
|
8087
|
+
}
|
|
8088
|
+
|
|
8089
|
+
var simplifyOptions = {
|
|
8090
|
+
LockBorder: 1,
|
|
8091
|
+
Sparse: 2,
|
|
8092
|
+
ErrorAbsolute: 4,
|
|
8093
|
+
Prune: 8,
|
|
8094
|
+
Regularize: 16,
|
|
8095
|
+
Permissive: 32,
|
|
8096
|
+
_InternalDebug: 1 << 30, // internal, don't use!
|
|
8097
|
+
};
|
|
8098
|
+
|
|
8099
|
+
return {
|
|
8100
|
+
ready: ready,
|
|
8101
|
+
supported: true,
|
|
8102
|
+
|
|
8103
|
+
compactMesh: function (indices) {
|
|
8104
|
+
assert(
|
|
8105
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8106
|
+
);
|
|
8107
|
+
assert(indices.length % 3 == 0);
|
|
8108
|
+
|
|
8109
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8110
|
+
return reorder(instance.exports.meshopt_optimizeVertexFetchRemap, indices32, maxindex(indices) + 1);
|
|
8111
|
+
},
|
|
8112
|
+
|
|
8113
|
+
generatePositionRemap: function (vertex_positions, vertex_positions_stride) {
|
|
8114
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8115
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8116
|
+
assert(vertex_positions_stride >= 3);
|
|
8117
|
+
|
|
8118
|
+
return genremap(
|
|
8119
|
+
instance.exports.meshopt_generatePositionRemap,
|
|
8120
|
+
vertex_positions,
|
|
8121
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8122
|
+
vertex_positions_stride
|
|
8123
|
+
);
|
|
8124
|
+
},
|
|
8125
|
+
|
|
8126
|
+
simplify: function (indices, vertex_positions, vertex_positions_stride, target_index_count, target_error, flags) {
|
|
8127
|
+
assert(
|
|
8128
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8129
|
+
);
|
|
8130
|
+
assert(indices.length % 3 == 0);
|
|
8131
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8132
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8133
|
+
assert(vertex_positions_stride >= 3);
|
|
8134
|
+
assert(target_index_count >= 0 && target_index_count <= indices.length);
|
|
8135
|
+
assert(target_index_count % 3 == 0);
|
|
8136
|
+
assert(target_error >= 0);
|
|
8137
|
+
|
|
8138
|
+
var options = 0;
|
|
8139
|
+
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
|
|
8140
|
+
assert(flags[i] in simplifyOptions);
|
|
8141
|
+
options |= simplifyOptions[flags[i]];
|
|
8142
|
+
}
|
|
8143
|
+
|
|
8144
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8145
|
+
var result = simplify(
|
|
8146
|
+
instance.exports.meshopt_simplify,
|
|
8147
|
+
indices32,
|
|
8148
|
+
indices.length,
|
|
8149
|
+
vertex_positions,
|
|
8150
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8151
|
+
vertex_positions_stride * 4,
|
|
8152
|
+
target_index_count,
|
|
8153
|
+
target_error,
|
|
8154
|
+
options
|
|
8155
|
+
);
|
|
8156
|
+
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
|
|
8157
|
+
|
|
8158
|
+
return result;
|
|
8159
|
+
},
|
|
8160
|
+
|
|
8161
|
+
simplifyWithAttributes: function (
|
|
8162
|
+
indices,
|
|
8163
|
+
vertex_positions,
|
|
8164
|
+
vertex_positions_stride,
|
|
8165
|
+
vertex_attributes,
|
|
8166
|
+
vertex_attributes_stride,
|
|
8167
|
+
attribute_weights,
|
|
8168
|
+
vertex_lock,
|
|
8169
|
+
target_index_count,
|
|
8170
|
+
target_error,
|
|
8171
|
+
flags
|
|
8172
|
+
) {
|
|
8173
|
+
assert(
|
|
8174
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8175
|
+
);
|
|
8176
|
+
assert(indices.length % 3 == 0);
|
|
8177
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8178
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8179
|
+
assert(vertex_positions_stride >= 3);
|
|
8180
|
+
assert(vertex_attributes instanceof Float32Array);
|
|
8181
|
+
assert(vertex_attributes.length == vertex_attributes_stride * (vertex_positions.length / vertex_positions_stride));
|
|
8182
|
+
assert(vertex_attributes_stride >= 0);
|
|
8183
|
+
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
|
|
8184
|
+
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
|
|
8185
|
+
assert(target_index_count >= 0 && target_index_count <= indices.length);
|
|
8186
|
+
assert(target_index_count % 3 == 0);
|
|
8187
|
+
assert(target_error >= 0);
|
|
8188
|
+
assert(Array.isArray(attribute_weights));
|
|
8189
|
+
assert(vertex_attributes_stride >= attribute_weights.length);
|
|
8190
|
+
assert(attribute_weights.length <= 32);
|
|
8191
|
+
for (var i = 0; i < attribute_weights.length; ++i) {
|
|
8192
|
+
assert(attribute_weights[i] >= 0);
|
|
8193
|
+
}
|
|
8194
|
+
|
|
8195
|
+
var options = 0;
|
|
8196
|
+
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
|
|
8197
|
+
assert(flags[i] in simplifyOptions);
|
|
8198
|
+
options |= simplifyOptions[flags[i]];
|
|
8199
|
+
}
|
|
8200
|
+
|
|
8201
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8202
|
+
var result = simplifyAttr(
|
|
8203
|
+
instance.exports.meshopt_simplifyWithAttributes,
|
|
8204
|
+
indices32,
|
|
8205
|
+
indices.length,
|
|
8206
|
+
vertex_positions,
|
|
8207
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8208
|
+
vertex_positions_stride * 4,
|
|
8209
|
+
vertex_attributes,
|
|
8210
|
+
vertex_attributes_stride * 4,
|
|
8211
|
+
new Float32Array(attribute_weights),
|
|
8212
|
+
vertex_lock,
|
|
8213
|
+
target_index_count,
|
|
8214
|
+
target_error,
|
|
8215
|
+
options
|
|
8216
|
+
);
|
|
8217
|
+
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
|
|
8218
|
+
|
|
8219
|
+
return result;
|
|
8220
|
+
},
|
|
8221
|
+
|
|
8222
|
+
simplifyWithUpdate: function (
|
|
8223
|
+
indices,
|
|
8224
|
+
vertex_positions,
|
|
8225
|
+
vertex_positions_stride,
|
|
8226
|
+
vertex_attributes,
|
|
8227
|
+
vertex_attributes_stride,
|
|
8228
|
+
attribute_weights,
|
|
8229
|
+
vertex_lock,
|
|
8230
|
+
target_index_count,
|
|
8231
|
+
target_error,
|
|
8232
|
+
flags
|
|
8233
|
+
) {
|
|
8234
|
+
assert(
|
|
8235
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8236
|
+
);
|
|
8237
|
+
assert(indices.length % 3 == 0);
|
|
8238
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8239
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8240
|
+
assert(vertex_positions_stride >= 3);
|
|
8241
|
+
assert(vertex_attributes instanceof Float32Array);
|
|
8242
|
+
assert(vertex_attributes.length == vertex_attributes_stride * (vertex_positions.length / vertex_positions_stride));
|
|
8243
|
+
assert(vertex_attributes_stride >= 0);
|
|
8244
|
+
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
|
|
8245
|
+
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
|
|
8246
|
+
assert(target_index_count >= 0 && target_index_count <= indices.length);
|
|
8247
|
+
assert(target_index_count % 3 == 0);
|
|
8248
|
+
assert(target_error >= 0);
|
|
8249
|
+
assert(Array.isArray(attribute_weights));
|
|
8250
|
+
assert(vertex_attributes_stride >= attribute_weights.length);
|
|
8251
|
+
assert(attribute_weights.length <= 32);
|
|
8252
|
+
for (var i = 0; i < attribute_weights.length; ++i) {
|
|
8253
|
+
assert(attribute_weights[i] >= 0);
|
|
8254
|
+
}
|
|
8255
|
+
|
|
8256
|
+
var options = 0;
|
|
8257
|
+
for (var i = 0; i < (flags ? flags.length : 0); ++i) {
|
|
8258
|
+
assert(flags[i] in simplifyOptions);
|
|
8259
|
+
options |= simplifyOptions[flags[i]];
|
|
8260
|
+
}
|
|
8261
|
+
|
|
8262
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8263
|
+
var result = simplifyUpdate(
|
|
8264
|
+
instance.exports.meshopt_simplifyWithUpdate,
|
|
8265
|
+
indices32,
|
|
8266
|
+
indices.length,
|
|
8267
|
+
vertex_positions,
|
|
8268
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8269
|
+
vertex_positions_stride * 4,
|
|
8270
|
+
vertex_attributes,
|
|
8271
|
+
vertex_attributes_stride * 4,
|
|
8272
|
+
new Float32Array(attribute_weights),
|
|
8273
|
+
vertex_lock,
|
|
8274
|
+
target_index_count,
|
|
8275
|
+
target_error,
|
|
8276
|
+
options
|
|
8277
|
+
);
|
|
8278
|
+
if (indices !== indices32) {
|
|
8279
|
+
// copy back indices if they were converted to Uint32Array
|
|
8280
|
+
for (var i = 0; i < result[0]; ++i) {
|
|
8281
|
+
indices[i] = indices32[i];
|
|
8282
|
+
}
|
|
8283
|
+
}
|
|
8284
|
+
return result;
|
|
8285
|
+
},
|
|
8286
|
+
|
|
8287
|
+
getScale: function (vertex_positions, vertex_positions_stride) {
|
|
8288
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8289
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8290
|
+
assert(vertex_positions_stride >= 3);
|
|
8291
|
+
return simplifyScale(
|
|
8292
|
+
instance.exports.meshopt_simplifyScale,
|
|
8293
|
+
vertex_positions,
|
|
8294
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8295
|
+
vertex_positions_stride * 4
|
|
8296
|
+
);
|
|
8297
|
+
},
|
|
8298
|
+
|
|
8299
|
+
simplifyPoints: function (vertex_positions, vertex_positions_stride, target_vertex_count, vertex_colors, vertex_colors_stride, color_weight) {
|
|
8300
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8301
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8302
|
+
assert(vertex_positions_stride >= 3);
|
|
8303
|
+
assert(target_vertex_count >= 0 && target_vertex_count <= vertex_positions.length / vertex_positions_stride);
|
|
8304
|
+
if (vertex_colors) {
|
|
8305
|
+
assert(vertex_colors instanceof Float32Array);
|
|
8306
|
+
assert(vertex_colors.length % vertex_colors_stride == 0);
|
|
8307
|
+
assert(vertex_colors_stride >= 3);
|
|
8308
|
+
assert(vertex_positions.length / vertex_positions_stride == vertex_colors.length / vertex_colors_stride);
|
|
8309
|
+
return simplifyPoints(
|
|
8310
|
+
instance.exports.meshopt_simplifyPoints,
|
|
8311
|
+
vertex_positions,
|
|
8312
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8313
|
+
vertex_positions_stride * 4,
|
|
8314
|
+
vertex_colors,
|
|
8315
|
+
vertex_colors_stride * 4,
|
|
8316
|
+
color_weight,
|
|
8317
|
+
target_vertex_count
|
|
8318
|
+
);
|
|
8319
|
+
} else {
|
|
8320
|
+
return simplifyPoints(
|
|
8321
|
+
instance.exports.meshopt_simplifyPoints,
|
|
8322
|
+
vertex_positions,
|
|
8323
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8324
|
+
vertex_positions_stride * 4,
|
|
8325
|
+
undefined,
|
|
8326
|
+
0,
|
|
8327
|
+
0,
|
|
8328
|
+
target_vertex_count
|
|
8329
|
+
);
|
|
8330
|
+
}
|
|
8331
|
+
},
|
|
8332
|
+
|
|
8333
|
+
simplifySloppy: function (indices, vertex_positions, vertex_positions_stride, vertex_lock, target_index_count, target_error) {
|
|
8334
|
+
assert(
|
|
8335
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8336
|
+
);
|
|
8337
|
+
assert(indices.length % 3 == 0);
|
|
8338
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8339
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8340
|
+
assert(vertex_positions_stride >= 3);
|
|
8341
|
+
assert(vertex_lock == null || vertex_lock instanceof Uint8Array);
|
|
8342
|
+
assert(vertex_lock == null || vertex_lock.length == vertex_positions.length / vertex_positions_stride);
|
|
8343
|
+
assert(target_index_count >= 0 && target_index_count <= indices.length);
|
|
8344
|
+
assert(target_index_count % 3 == 0);
|
|
8345
|
+
assert(target_error >= 0);
|
|
8346
|
+
|
|
8347
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8348
|
+
var result = simplifySloppy(
|
|
8349
|
+
instance.exports.meshopt_simplifySloppy,
|
|
8350
|
+
indices32,
|
|
8351
|
+
indices.length,
|
|
8352
|
+
vertex_positions,
|
|
8353
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8354
|
+
vertex_positions_stride * 4,
|
|
8355
|
+
vertex_lock,
|
|
8356
|
+
target_index_count,
|
|
8357
|
+
target_error
|
|
8358
|
+
);
|
|
8359
|
+
result[0] = indices instanceof Uint32Array ? result[0] : new indices.constructor(result[0]);
|
|
8360
|
+
|
|
8361
|
+
return result;
|
|
8362
|
+
},
|
|
8363
|
+
|
|
8364
|
+
simplifyPrune: function (indices, vertex_positions, vertex_positions_stride, target_error) {
|
|
8365
|
+
assert(
|
|
8366
|
+
indices instanceof Uint32Array || indices instanceof Int32Array || indices instanceof Uint16Array || indices instanceof Int16Array
|
|
8367
|
+
);
|
|
8368
|
+
assert(indices.length % 3 == 0);
|
|
8369
|
+
assert(vertex_positions instanceof Float32Array);
|
|
8370
|
+
assert(vertex_positions.length % vertex_positions_stride == 0);
|
|
8371
|
+
assert(vertex_positions_stride >= 3);
|
|
8372
|
+
assert(target_error >= 0);
|
|
8373
|
+
|
|
8374
|
+
var indices32 = indices.BYTES_PER_ELEMENT == 4 ? indices : new Uint32Array(indices);
|
|
8375
|
+
var result = simplifyPrune(
|
|
8376
|
+
instance.exports.meshopt_simplifyPrune,
|
|
8377
|
+
indices32,
|
|
8378
|
+
indices.length,
|
|
8379
|
+
vertex_positions,
|
|
8380
|
+
vertex_positions.length / vertex_positions_stride,
|
|
8381
|
+
vertex_positions_stride * 4,
|
|
8382
|
+
target_error
|
|
8383
|
+
);
|
|
8384
|
+
result = indices instanceof Uint32Array ? result : new indices.constructor(result);
|
|
8385
|
+
|
|
8386
|
+
return result;
|
|
8387
|
+
},
|
|
8388
|
+
};
|
|
8389
|
+
})();
|
|
8390
|
+
|
|
8391
|
+
/**
|
|
8392
|
+
* Build a minimal GLB (glTF 2.0 binary) file containing a single triangle mesh.
|
|
8393
|
+
*
|
|
8394
|
+
* The output contains only positions and triangle indices — no normals,
|
|
8395
|
+
* UVs, or materials — suitable for collision meshes.
|
|
8396
|
+
*
|
|
8397
|
+
* @param positions - Vertex positions (3 floats per vertex)
|
|
8398
|
+
* @param indices - Triangle indices (3 per triangle, unsigned 32-bit)
|
|
8399
|
+
* @returns GLB file as a Uint8Array
|
|
8400
|
+
*/
|
|
8401
|
+
function buildCollisionGlb(positions, indices) {
|
|
8402
|
+
const vertexCount = positions.length / 3;
|
|
8403
|
+
const indexCount = indices.length;
|
|
8404
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
8405
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
8406
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
8407
|
+
const x = positions[i], y = positions[i + 1], z = positions[i + 2];
|
|
8408
|
+
if (x < minX)
|
|
8409
|
+
minX = x;
|
|
8410
|
+
if (y < minY)
|
|
8411
|
+
minY = y;
|
|
8412
|
+
if (z < minZ)
|
|
8413
|
+
minZ = z;
|
|
8414
|
+
if (x > maxX)
|
|
8415
|
+
maxX = x;
|
|
8416
|
+
if (y > maxY)
|
|
8417
|
+
maxY = y;
|
|
8418
|
+
if (z > maxZ)
|
|
8419
|
+
maxZ = z;
|
|
8420
|
+
}
|
|
8421
|
+
const positionsByteLength = positions.byteLength;
|
|
8422
|
+
const indicesByteLength = indices.byteLength;
|
|
8423
|
+
const totalBinSize = positionsByteLength + indicesByteLength;
|
|
8424
|
+
const gltf = {
|
|
8425
|
+
asset: { version: '2.0', generator: 'splat-transform' },
|
|
8426
|
+
scene: 0,
|
|
8427
|
+
scenes: [{ nodes: [0] }],
|
|
8428
|
+
nodes: [{ mesh: 0 }],
|
|
8429
|
+
meshes: [{
|
|
8430
|
+
primitives: [{
|
|
8431
|
+
attributes: { POSITION: 0 },
|
|
8432
|
+
indices: 1
|
|
8433
|
+
}]
|
|
8434
|
+
}],
|
|
8435
|
+
accessors: [
|
|
8436
|
+
{
|
|
8437
|
+
bufferView: 0,
|
|
8438
|
+
componentType: 5126, // FLOAT
|
|
8439
|
+
count: vertexCount,
|
|
8440
|
+
type: 'VEC3',
|
|
8441
|
+
min: [minX, minY, minZ],
|
|
8442
|
+
max: [maxX, maxY, maxZ]
|
|
8443
|
+
},
|
|
8444
|
+
{
|
|
8445
|
+
bufferView: 1,
|
|
8446
|
+
componentType: 5125, // UNSIGNED_INT
|
|
8447
|
+
count: indexCount,
|
|
8448
|
+
type: 'SCALAR'
|
|
8449
|
+
}
|
|
8450
|
+
],
|
|
8451
|
+
bufferViews: [
|
|
8452
|
+
{
|
|
8453
|
+
buffer: 0,
|
|
8454
|
+
byteOffset: 0,
|
|
8455
|
+
byteLength: positionsByteLength,
|
|
8456
|
+
target: 34962 // ARRAY_BUFFER
|
|
8457
|
+
},
|
|
8458
|
+
{
|
|
8459
|
+
buffer: 0,
|
|
8460
|
+
byteOffset: positionsByteLength,
|
|
8461
|
+
byteLength: indicesByteLength,
|
|
8462
|
+
target: 34963 // ELEMENT_ARRAY_BUFFER
|
|
8463
|
+
}
|
|
8464
|
+
],
|
|
8465
|
+
buffers: [{ byteLength: totalBinSize }]
|
|
8466
|
+
};
|
|
8467
|
+
const jsonString = JSON.stringify(gltf);
|
|
8468
|
+
const jsonEncoder = new TextEncoder();
|
|
8469
|
+
const jsonBytes = jsonEncoder.encode(jsonString);
|
|
8470
|
+
// JSON chunk must be padded to 4-byte alignment with spaces (0x20)
|
|
8471
|
+
const jsonPadding = (4 - (jsonBytes.length % 4)) % 4;
|
|
8472
|
+
const jsonChunkLength = jsonBytes.length + jsonPadding;
|
|
8473
|
+
// BIN chunk must be padded to 4-byte alignment with zeros
|
|
8474
|
+
const binPadding = (4 - (totalBinSize % 4)) % 4;
|
|
8475
|
+
const binChunkLength = totalBinSize + binPadding;
|
|
8476
|
+
// GLB layout: header (12) + JSON chunk header (8) + JSON data + BIN chunk header (8) + BIN data
|
|
8477
|
+
const totalLength = 12 + 8 + jsonChunkLength + 8 + binChunkLength;
|
|
8478
|
+
const buffer = new ArrayBuffer(totalLength);
|
|
8479
|
+
const view = new DataView(buffer);
|
|
8480
|
+
const byteArray = new Uint8Array(buffer);
|
|
8481
|
+
let offset = 0;
|
|
8482
|
+
// GLB header
|
|
8483
|
+
view.setUint32(offset, 0x46546C67, true);
|
|
8484
|
+
offset += 4; // magic: "glTF"
|
|
8485
|
+
view.setUint32(offset, 2, true);
|
|
8486
|
+
offset += 4; // version: 2
|
|
8487
|
+
view.setUint32(offset, totalLength, true);
|
|
8488
|
+
offset += 4; // total length
|
|
8489
|
+
// JSON chunk header
|
|
8490
|
+
view.setUint32(offset, jsonChunkLength, true);
|
|
8491
|
+
offset += 4;
|
|
8492
|
+
view.setUint32(offset, 0x4E4F534A, true);
|
|
8493
|
+
offset += 4; // type: "JSON"
|
|
8494
|
+
// JSON chunk data
|
|
8495
|
+
byteArray.set(jsonBytes, offset);
|
|
8496
|
+
offset += jsonBytes.length;
|
|
8497
|
+
for (let i = 0; i < jsonPadding; i++) {
|
|
8498
|
+
byteArray[offset++] = 0x20;
|
|
8499
|
+
}
|
|
8500
|
+
// BIN chunk header
|
|
8501
|
+
view.setUint32(offset, binChunkLength, true);
|
|
8502
|
+
offset += 4;
|
|
8503
|
+
view.setUint32(offset, 0x004E4942, true);
|
|
8504
|
+
offset += 4; // type: "BIN\0"
|
|
8505
|
+
// BIN chunk data: positions then indices
|
|
8506
|
+
byteArray.set(new Uint8Array(positions.buffer, positions.byteOffset, positionsByteLength), offset);
|
|
8507
|
+
offset += positionsByteLength;
|
|
8508
|
+
byteArray.set(new Uint8Array(indices.buffer, indices.byteOffset, indicesByteLength), offset);
|
|
8509
|
+
return byteArray;
|
|
8510
|
+
}
|
|
8511
|
+
|
|
7663
8512
|
/**
|
|
7664
8513
|
* Compute axis-aligned bounding box half-extents for all Gaussians in a DataTable.
|
|
7665
8514
|
*
|
|
@@ -8525,6 +9374,525 @@ class GpuVoxelization {
|
|
|
8525
9374
|
}
|
|
8526
9375
|
}
|
|
8527
9376
|
|
|
9377
|
+
// ============================================================================
|
|
9378
|
+
// Voxel bit helpers
|
|
9379
|
+
// ============================================================================
|
|
9380
|
+
// Bit layout within a 4x4x4 block: bitIdx = lx + ly*4 + lz*16
|
|
9381
|
+
// lo = bits 0-31 (lz 0-1), hi = bits 32-63 (lz 2-3)
|
|
9382
|
+
/**
|
|
9383
|
+
* Test whether a voxel is occupied within a block's bitmask.
|
|
9384
|
+
*
|
|
9385
|
+
* @param lo - Lower 32 bits of the block mask
|
|
9386
|
+
* @param hi - Upper 32 bits of the block mask
|
|
9387
|
+
* @param lx - Local x coordinate (0-3)
|
|
9388
|
+
* @param ly - Local y coordinate (0-3)
|
|
9389
|
+
* @param lz - Local z coordinate (0-3)
|
|
9390
|
+
* @returns True if the voxel is occupied
|
|
9391
|
+
*/
|
|
9392
|
+
function isVoxelSet(lo, hi, lx, ly, lz) {
|
|
9393
|
+
const bitIdx = lx + ly * 4 + lz * 16;
|
|
9394
|
+
if (bitIdx < 32) {
|
|
9395
|
+
return (lo & (1 << bitIdx)) !== 0;
|
|
9396
|
+
}
|
|
9397
|
+
return (hi & (1 << (bitIdx - 32))) !== 0;
|
|
9398
|
+
}
|
|
9399
|
+
// ============================================================================
|
|
9400
|
+
// Occupancy grid from BlockAccumulator
|
|
9401
|
+
// ============================================================================
|
|
9402
|
+
/**
|
|
9403
|
+
* Build a fast-lookup occupancy structure from a BlockAccumulator.
|
|
9404
|
+
* Returns a function that queries whether a voxel at global coordinates
|
|
9405
|
+
* (vx, vy, vz) is occupied.
|
|
9406
|
+
*
|
|
9407
|
+
* @param accumulator - Block data
|
|
9408
|
+
* @returns Lookup function (vx, vy, vz) => boolean
|
|
9409
|
+
*/
|
|
9410
|
+
function buildOccupancyLookup(accumulator) {
|
|
9411
|
+
// Map from "bx,by,bz" encoded as single number to {lo,hi} or solid flag
|
|
9412
|
+
// Block key = bx + by * stride + bz * stride^2 where stride is large enough
|
|
9413
|
+
const mixed = accumulator.getMixedBlocks();
|
|
9414
|
+
const solid = accumulator.getSolidBlocks();
|
|
9415
|
+
// Use a Map<number, number> where value encodes index into mask arrays.
|
|
9416
|
+
// For solid blocks, store -1 as sentinel.
|
|
9417
|
+
const blockMap = new Map();
|
|
9418
|
+
for (let i = 0; i < mixed.morton.length; i++) {
|
|
9419
|
+
blockMap.set(mixed.morton[i], i);
|
|
9420
|
+
}
|
|
9421
|
+
for (let i = 0; i < solid.length; i++) {
|
|
9422
|
+
blockMap.set(solid[i], -1);
|
|
9423
|
+
}
|
|
9424
|
+
const masks = mixed.masks;
|
|
9425
|
+
return (vx, vy, vz) => {
|
|
9426
|
+
if (vx < 0 || vy < 0 || vz < 0)
|
|
9427
|
+
return false;
|
|
9428
|
+
const bx = vx >> 2;
|
|
9429
|
+
const by = vy >> 2;
|
|
9430
|
+
const bz = vz >> 2;
|
|
9431
|
+
const entry = blockMap.get(xyzToMorton(bx, by, bz));
|
|
9432
|
+
if (entry === undefined)
|
|
9433
|
+
return false;
|
|
9434
|
+
if (entry === -1)
|
|
9435
|
+
return true; // solid block
|
|
9436
|
+
const lo = masks[entry * 2];
|
|
9437
|
+
const hi = masks[entry * 2 + 1];
|
|
9438
|
+
return isVoxelSet(lo, hi, vx & 3, vy & 3, vz & 3);
|
|
9439
|
+
};
|
|
9440
|
+
}
|
|
9441
|
+
// ============================================================================
|
|
9442
|
+
// Marching Cubes
|
|
9443
|
+
// ============================================================================
|
|
9444
|
+
/**
|
|
9445
|
+
* Extract a triangle mesh from a BlockAccumulator using marching cubes.
|
|
9446
|
+
*
|
|
9447
|
+
* Each voxel is treated as a cell in the marching cubes grid. Corner values
|
|
9448
|
+
* are binary (0 = empty, 1 = occupied) with a 0.5 threshold. Vertices are
|
|
9449
|
+
* placed at edge midpoints, producing a mesh that follows voxel boundaries.
|
|
9450
|
+
*
|
|
9451
|
+
* @param accumulator - Voxel block data after filtering
|
|
9452
|
+
* @param gridBounds - Grid bounds aligned to block boundaries
|
|
9453
|
+
* @param voxelResolution - Size of each voxel in world units
|
|
9454
|
+
* @returns Mesh with positions and indices
|
|
9455
|
+
*/
|
|
9456
|
+
function marchingCubes(accumulator, gridBounds, voxelResolution) {
|
|
9457
|
+
const isOccupied = buildOccupancyLookup(accumulator);
|
|
9458
|
+
// Collect all voxel coordinates that need processing.
|
|
9459
|
+
// We need to check every cell where at least one corner differs from
|
|
9460
|
+
// the others, which means we need to check occupied voxels and their
|
|
9461
|
+
// immediate neighbors.
|
|
9462
|
+
const mixed = accumulator.getMixedBlocks();
|
|
9463
|
+
const solid = accumulator.getSolidBlocks();
|
|
9464
|
+
// Collect set of all block coordinates that exist
|
|
9465
|
+
const blockSet = new Set();
|
|
9466
|
+
for (let i = 0; i < mixed.morton.length; i++) {
|
|
9467
|
+
blockSet.add(mixed.morton[i]);
|
|
9468
|
+
}
|
|
9469
|
+
for (let i = 0; i < solid.length; i++) {
|
|
9470
|
+
blockSet.add(solid[i]);
|
|
9471
|
+
}
|
|
9472
|
+
// For each block, we process a 4x4x4 region of marching cubes cells.
|
|
9473
|
+
// Each cell at (vx, vy, vz) has corners at (vx..vx+1, vy..vy+1, vz..vz+1).
|
|
9474
|
+
// We only generate triangles for cells that have mixed corners (not all same).
|
|
9475
|
+
// Vertex deduplication: edge ID -> vertex index
|
|
9476
|
+
// Edge ID encodes the voxel coordinate and edge direction
|
|
9477
|
+
const vertexMap = new Map();
|
|
9478
|
+
const positions = [];
|
|
9479
|
+
const indices = [];
|
|
9480
|
+
const originX = gridBounds.min.x;
|
|
9481
|
+
const originY = gridBounds.min.y;
|
|
9482
|
+
const originZ = gridBounds.min.z;
|
|
9483
|
+
// Compute strides from actual grid dimensions (+3 for the -1 boundary
|
|
9484
|
+
// extension, the far edge +1, and one extra for safety).
|
|
9485
|
+
const strideX = Math.round((gridBounds.max.x - gridBounds.min.x) / voxelResolution) + 3;
|
|
9486
|
+
const strideXY = strideX * (Math.round((gridBounds.max.y - gridBounds.min.y) / voxelResolution) + 3);
|
|
9487
|
+
// Get or create a vertex at the midpoint of an edge.
|
|
9488
|
+
// Edge is identified by the lower corner voxel coordinate and axis (0=x, 1=y, 2=z).
|
|
9489
|
+
const getVertex = (vx, vy, vz, axis) => {
|
|
9490
|
+
// Pack (vx, vy, vz, axis) into a single key. Offset by 1 so that
|
|
9491
|
+
// vx = -1 (from the boundary extension) maps to 0, keeping keys non-negative.
|
|
9492
|
+
const key = ((vx + 1) + (vy + 1) * strideX + (vz + 1) * strideXY) * 3 + axis;
|
|
9493
|
+
let idx = vertexMap.get(key);
|
|
9494
|
+
if (idx !== undefined)
|
|
9495
|
+
return idx;
|
|
9496
|
+
idx = positions.length / 3;
|
|
9497
|
+
let px = originX + vx * voxelResolution;
|
|
9498
|
+
let py = originY + vy * voxelResolution;
|
|
9499
|
+
let pz = originZ + vz * voxelResolution;
|
|
9500
|
+
// Place vertex at edge midpoint (binary field -> always at 0.5)
|
|
9501
|
+
if (axis === 0)
|
|
9502
|
+
px += voxelResolution * 0.5;
|
|
9503
|
+
else if (axis === 1)
|
|
9504
|
+
py += voxelResolution * 0.5;
|
|
9505
|
+
else
|
|
9506
|
+
pz += voxelResolution * 0.5;
|
|
9507
|
+
positions.push(px, py, pz);
|
|
9508
|
+
vertexMap.set(key, idx);
|
|
9509
|
+
return idx;
|
|
9510
|
+
};
|
|
9511
|
+
// Process all blocks and their boundary neighbors
|
|
9512
|
+
const allMortons = [];
|
|
9513
|
+
blockSet.forEach(m => allMortons.push(m));
|
|
9514
|
+
for (let bi = 0; bi < allMortons.length; bi++) {
|
|
9515
|
+
const morton = allMortons[bi];
|
|
9516
|
+
const [bx, by, bz] = mortonToXYZ(morton);
|
|
9517
|
+
// Iterate -1..3 to include the boundary layer in the negative
|
|
9518
|
+
// direction. Cells at lx/ly/lz = -1 straddle the block edge and
|
|
9519
|
+
// are needed to close the surface where no neighboring block exists.
|
|
9520
|
+
for (let lz = -1; lz < 4; lz++) {
|
|
9521
|
+
for (let ly = -1; ly < 4; ly++) {
|
|
9522
|
+
for (let lx = -1; lx < 4; lx++) {
|
|
9523
|
+
const vx = bx * 4 + lx;
|
|
9524
|
+
const vy = by * 4 + ly;
|
|
9525
|
+
const vz = bz * 4 + lz;
|
|
9526
|
+
// Determine which block owns this cell
|
|
9527
|
+
const ownerBx = vx >> 2;
|
|
9528
|
+
const ownerBy = vy >> 2;
|
|
9529
|
+
const ownerBz = vz >> 2;
|
|
9530
|
+
if (ownerBx !== bx || ownerBy !== by || ownerBz !== bz) {
|
|
9531
|
+
// Cell belongs to a different block — skip if that
|
|
9532
|
+
// block exists (it will process the cell itself).
|
|
9533
|
+
// Guard negative coords: xyzToMorton assumes non-negative inputs.
|
|
9534
|
+
if (ownerBx >= 0 && ownerBy >= 0 && ownerBz >= 0 &&
|
|
9535
|
+
blockSet.has(xyzToMorton(ownerBx, ownerBy, ownerBz)))
|
|
9536
|
+
continue;
|
|
9537
|
+
}
|
|
9538
|
+
// Get corner values for this cell (8 corners)
|
|
9539
|
+
// Corners: (vx,vy,vz), (vx+1,vy,vz), (vx+1,vy+1,vz), (vx,vy+1,vz),
|
|
9540
|
+
// (vx,vy,vz+1), (vx+1,vy,vz+1), (vx+1,vy+1,vz+1), (vx,vy+1,vz+1)
|
|
9541
|
+
const c0 = isOccupied(vx, vy, vz) ? 1 : 0;
|
|
9542
|
+
const c1 = isOccupied(vx + 1, vy, vz) ? 1 : 0;
|
|
9543
|
+
const c2 = isOccupied(vx + 1, vy + 1, vz) ? 1 : 0;
|
|
9544
|
+
const c3 = isOccupied(vx, vy + 1, vz) ? 1 : 0;
|
|
9545
|
+
const c4 = isOccupied(vx, vy, vz + 1) ? 1 : 0;
|
|
9546
|
+
const c5 = isOccupied(vx + 1, vy, vz + 1) ? 1 : 0;
|
|
9547
|
+
const c6 = isOccupied(vx + 1, vy + 1, vz + 1) ? 1 : 0;
|
|
9548
|
+
const c7 = isOccupied(vx, vy + 1, vz + 1) ? 1 : 0;
|
|
9549
|
+
const cubeIndex = c0 | (c1 << 1) | (c2 << 2) | (c3 << 3) |
|
|
9550
|
+
(c4 << 4) | (c5 << 5) | (c6 << 6) | (c7 << 7);
|
|
9551
|
+
if (cubeIndex === 0 || cubeIndex === 255)
|
|
9552
|
+
continue;
|
|
9553
|
+
const edges = EDGE_TABLE[cubeIndex]; // eslint-disable-line no-use-before-define
|
|
9554
|
+
if (edges === 0)
|
|
9555
|
+
continue;
|
|
9556
|
+
// Compute vertices on active edges
|
|
9557
|
+
// Edge -> vertex mapping using getVertex with (corner voxel coord, axis)
|
|
9558
|
+
const edgeVerts = new Array(12);
|
|
9559
|
+
if (edges & 1)
|
|
9560
|
+
edgeVerts[0] = getVertex(vx, vy, vz, 0); // edge 0: x-axis at (vx, vy, vz)
|
|
9561
|
+
if (edges & 2)
|
|
9562
|
+
edgeVerts[1] = getVertex(vx + 1, vy, vz, 1); // edge 1: y-axis at (vx+1, vy, vz)
|
|
9563
|
+
if (edges & 4)
|
|
9564
|
+
edgeVerts[2] = getVertex(vx, vy + 1, vz, 0); // edge 2: x-axis at (vx, vy+1, vz)
|
|
9565
|
+
if (edges & 8)
|
|
9566
|
+
edgeVerts[3] = getVertex(vx, vy, vz, 1); // edge 3: y-axis at (vx, vy, vz)
|
|
9567
|
+
if (edges & 16)
|
|
9568
|
+
edgeVerts[4] = getVertex(vx, vy, vz + 1, 0); // edge 4: x-axis at (vx, vy, vz+1)
|
|
9569
|
+
if (edges & 32)
|
|
9570
|
+
edgeVerts[5] = getVertex(vx + 1, vy, vz + 1, 1); // edge 5: y-axis at (vx+1, vy, vz+1)
|
|
9571
|
+
if (edges & 64)
|
|
9572
|
+
edgeVerts[6] = getVertex(vx, vy + 1, vz + 1, 0); // edge 6: x-axis at (vx, vy+1, vz+1)
|
|
9573
|
+
if (edges & 128)
|
|
9574
|
+
edgeVerts[7] = getVertex(vx, vy, vz + 1, 1); // edge 7: y-axis at (vx, vy, vz+1)
|
|
9575
|
+
if (edges & 256)
|
|
9576
|
+
edgeVerts[8] = getVertex(vx, vy, vz, 2); // edge 8: z-axis at (vx, vy, vz)
|
|
9577
|
+
if (edges & 512)
|
|
9578
|
+
edgeVerts[9] = getVertex(vx + 1, vy, vz, 2); // edge 9: z-axis at (vx+1, vy, vz)
|
|
9579
|
+
if (edges & 1024)
|
|
9580
|
+
edgeVerts[10] = getVertex(vx + 1, vy + 1, vz, 2); // edge 10: z-axis at (vx+1, vy+1, vz)
|
|
9581
|
+
if (edges & 2048)
|
|
9582
|
+
edgeVerts[11] = getVertex(vx, vy + 1, vz, 2); // edge 11: z-axis at (vx, vy+1, vz)
|
|
9583
|
+
// Emit triangles (reversed winding to face outward)
|
|
9584
|
+
const triRow = TRI_TABLE[cubeIndex]; // eslint-disable-line no-use-before-define
|
|
9585
|
+
for (let t = 0; t < triRow.length; t += 3) {
|
|
9586
|
+
indices.push(edgeVerts[triRow[t]], edgeVerts[triRow[t + 2]], edgeVerts[triRow[t + 1]]);
|
|
9587
|
+
}
|
|
9588
|
+
}
|
|
9589
|
+
}
|
|
9590
|
+
}
|
|
9591
|
+
}
|
|
9592
|
+
return {
|
|
9593
|
+
positions: new Float32Array(positions),
|
|
9594
|
+
indices: new Uint32Array(indices)
|
|
9595
|
+
};
|
|
9596
|
+
}
|
|
9597
|
+
// ============================================================================
|
|
9598
|
+
// Marching Cubes Lookup Tables
|
|
9599
|
+
// ============================================================================
|
|
9600
|
+
// Standard tables from Paul Bourke's polygonising a scalar field.
|
|
9601
|
+
// EDGE_TABLE: 256 entries, each a 12-bit mask of which edges are intersected.
|
|
9602
|
+
// TRI_TABLE: 256 entries, each an array of edge indices forming triangles.
|
|
9603
|
+
const EDGE_TABLE = [
|
|
9604
|
+
0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
|
9605
|
+
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
|
|
9606
|
+
0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
|
|
9607
|
+
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
|
|
9608
|
+
0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
|
|
9609
|
+
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
|
|
9610
|
+
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
|
9611
|
+
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
|
|
9612
|
+
0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,
|
|
9613
|
+
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
|
|
9614
|
+
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,
|
|
9615
|
+
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
|
9616
|
+
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,
|
|
9617
|
+
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
|
|
9618
|
+
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,
|
|
9619
|
+
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
|
9620
|
+
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
|
|
9621
|
+
0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
|
9622
|
+
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
|
|
9623
|
+
0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
|
|
9624
|
+
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
|
|
9625
|
+
0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
|
9626
|
+
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
|
|
9627
|
+
0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
|
|
9628
|
+
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
|
|
9629
|
+
0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
|
|
9630
|
+
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
|
|
9631
|
+
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
|
|
9632
|
+
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
|
|
9633
|
+
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
|
|
9634
|
+
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
|
|
9635
|
+
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
|
|
9636
|
+
];
|
|
9637
|
+
const TRI_TABLE = [
|
|
9638
|
+
[],
|
|
9639
|
+
[0, 8, 3],
|
|
9640
|
+
[0, 1, 9],
|
|
9641
|
+
[1, 8, 3, 9, 8, 1],
|
|
9642
|
+
[1, 2, 10],
|
|
9643
|
+
[0, 8, 3, 1, 2, 10],
|
|
9644
|
+
[9, 2, 10, 0, 2, 9],
|
|
9645
|
+
[2, 8, 3, 2, 10, 8, 10, 9, 8],
|
|
9646
|
+
[3, 11, 2],
|
|
9647
|
+
[0, 11, 2, 8, 11, 0],
|
|
9648
|
+
[1, 9, 0, 2, 3, 11],
|
|
9649
|
+
[1, 11, 2, 1, 9, 11, 9, 8, 11],
|
|
9650
|
+
[3, 10, 1, 11, 10, 3],
|
|
9651
|
+
[0, 10, 1, 0, 8, 10, 8, 11, 10],
|
|
9652
|
+
[3, 9, 0, 3, 11, 9, 11, 10, 9],
|
|
9653
|
+
[9, 8, 10, 10, 8, 11],
|
|
9654
|
+
[4, 7, 8],
|
|
9655
|
+
[4, 3, 0, 7, 3, 4],
|
|
9656
|
+
[0, 1, 9, 8, 4, 7],
|
|
9657
|
+
[4, 1, 9, 4, 7, 1, 7, 3, 1],
|
|
9658
|
+
[1, 2, 10, 8, 4, 7],
|
|
9659
|
+
[3, 4, 7, 3, 0, 4, 1, 2, 10],
|
|
9660
|
+
[9, 2, 10, 9, 0, 2, 8, 4, 7],
|
|
9661
|
+
[2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4],
|
|
9662
|
+
[8, 4, 7, 3, 11, 2],
|
|
9663
|
+
[11, 4, 7, 11, 2, 4, 2, 0, 4],
|
|
9664
|
+
[9, 0, 1, 8, 4, 7, 2, 3, 11],
|
|
9665
|
+
[4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1],
|
|
9666
|
+
[3, 10, 1, 3, 11, 10, 7, 8, 4],
|
|
9667
|
+
[1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4],
|
|
9668
|
+
[4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3],
|
|
9669
|
+
[4, 7, 11, 4, 11, 9, 9, 11, 10],
|
|
9670
|
+
[9, 5, 4],
|
|
9671
|
+
[9, 5, 4, 0, 8, 3],
|
|
9672
|
+
[0, 5, 4, 1, 5, 0],
|
|
9673
|
+
[8, 5, 4, 8, 3, 5, 3, 1, 5],
|
|
9674
|
+
[1, 2, 10, 9, 5, 4],
|
|
9675
|
+
[3, 0, 8, 1, 2, 10, 4, 9, 5],
|
|
9676
|
+
[5, 2, 10, 5, 4, 2, 4, 0, 2],
|
|
9677
|
+
[2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8],
|
|
9678
|
+
[9, 5, 4, 2, 3, 11],
|
|
9679
|
+
[0, 11, 2, 0, 8, 11, 4, 9, 5],
|
|
9680
|
+
[0, 5, 4, 0, 1, 5, 2, 3, 11],
|
|
9681
|
+
[2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5],
|
|
9682
|
+
[10, 3, 11, 10, 1, 3, 9, 5, 4],
|
|
9683
|
+
[4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10],
|
|
9684
|
+
[5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3],
|
|
9685
|
+
[5, 4, 8, 5, 8, 10, 10, 8, 11],
|
|
9686
|
+
[9, 7, 8, 5, 7, 9],
|
|
9687
|
+
[9, 3, 0, 9, 5, 3, 5, 7, 3],
|
|
9688
|
+
[0, 7, 8, 0, 1, 7, 1, 5, 7],
|
|
9689
|
+
[1, 5, 3, 3, 5, 7],
|
|
9690
|
+
[9, 7, 8, 9, 5, 7, 10, 1, 2],
|
|
9691
|
+
[10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3],
|
|
9692
|
+
[8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2],
|
|
9693
|
+
[2, 10, 5, 2, 5, 3, 3, 5, 7],
|
|
9694
|
+
[7, 9, 5, 7, 8, 9, 3, 11, 2],
|
|
9695
|
+
[9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11],
|
|
9696
|
+
[2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7],
|
|
9697
|
+
[11, 2, 1, 11, 1, 7, 7, 1, 5],
|
|
9698
|
+
[9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11],
|
|
9699
|
+
[5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0],
|
|
9700
|
+
[11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0],
|
|
9701
|
+
[11, 10, 5, 7, 11, 5],
|
|
9702
|
+
[10, 6, 5],
|
|
9703
|
+
[0, 8, 3, 5, 10, 6],
|
|
9704
|
+
[9, 0, 1, 5, 10, 6],
|
|
9705
|
+
[1, 8, 3, 1, 9, 8, 5, 10, 6],
|
|
9706
|
+
[1, 6, 5, 2, 6, 1],
|
|
9707
|
+
[1, 6, 5, 1, 2, 6, 3, 0, 8],
|
|
9708
|
+
[9, 6, 5, 9, 0, 6, 0, 2, 6],
|
|
9709
|
+
[5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8],
|
|
9710
|
+
[2, 3, 11, 10, 6, 5],
|
|
9711
|
+
[11, 0, 8, 11, 2, 0, 10, 6, 5],
|
|
9712
|
+
[0, 1, 9, 2, 3, 11, 5, 10, 6],
|
|
9713
|
+
[5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11],
|
|
9714
|
+
[6, 3, 11, 6, 5, 3, 5, 1, 3],
|
|
9715
|
+
[0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6],
|
|
9716
|
+
[3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9],
|
|
9717
|
+
[6, 5, 9, 6, 9, 11, 11, 9, 8],
|
|
9718
|
+
[5, 10, 6, 4, 7, 8],
|
|
9719
|
+
[4, 3, 0, 4, 7, 3, 6, 5, 10],
|
|
9720
|
+
[1, 9, 0, 5, 10, 6, 8, 4, 7],
|
|
9721
|
+
[10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4],
|
|
9722
|
+
[6, 1, 2, 6, 5, 1, 4, 7, 8],
|
|
9723
|
+
[1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7],
|
|
9724
|
+
[8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6],
|
|
9725
|
+
[7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9],
|
|
9726
|
+
[3, 11, 2, 7, 8, 4, 10, 6, 5],
|
|
9727
|
+
[5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11],
|
|
9728
|
+
[0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6],
|
|
9729
|
+
[9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6],
|
|
9730
|
+
[8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6],
|
|
9731
|
+
[5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11],
|
|
9732
|
+
[0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7],
|
|
9733
|
+
[6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9],
|
|
9734
|
+
[10, 4, 9, 6, 4, 10],
|
|
9735
|
+
[4, 10, 6, 4, 9, 10, 0, 8, 3],
|
|
9736
|
+
[10, 0, 1, 10, 6, 0, 6, 4, 0],
|
|
9737
|
+
[8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10],
|
|
9738
|
+
[1, 4, 9, 1, 2, 4, 2, 6, 4],
|
|
9739
|
+
[3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4],
|
|
9740
|
+
[0, 2, 4, 4, 2, 6],
|
|
9741
|
+
[8, 3, 2, 8, 2, 4, 4, 2, 6],
|
|
9742
|
+
[10, 4, 9, 10, 6, 4, 11, 2, 3],
|
|
9743
|
+
[0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6],
|
|
9744
|
+
[3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10],
|
|
9745
|
+
[6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1],
|
|
9746
|
+
[9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3],
|
|
9747
|
+
[8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1],
|
|
9748
|
+
[3, 11, 6, 3, 6, 0, 0, 6, 4],
|
|
9749
|
+
[6, 4, 8, 11, 6, 8],
|
|
9750
|
+
[7, 10, 6, 7, 8, 10, 8, 9, 10],
|
|
9751
|
+
[0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10],
|
|
9752
|
+
[10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0],
|
|
9753
|
+
[10, 6, 7, 10, 7, 1, 1, 7, 3],
|
|
9754
|
+
[1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7],
|
|
9755
|
+
[2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9],
|
|
9756
|
+
[7, 8, 0, 7, 0, 6, 6, 0, 2],
|
|
9757
|
+
[7, 3, 2, 6, 7, 2],
|
|
9758
|
+
[2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7],
|
|
9759
|
+
[2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7],
|
|
9760
|
+
[1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11],
|
|
9761
|
+
[11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1],
|
|
9762
|
+
[8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6],
|
|
9763
|
+
[0, 9, 1, 11, 6, 7],
|
|
9764
|
+
[7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0],
|
|
9765
|
+
[7, 11, 6],
|
|
9766
|
+
[7, 6, 11],
|
|
9767
|
+
[3, 0, 8, 11, 7, 6],
|
|
9768
|
+
[0, 1, 9, 11, 7, 6],
|
|
9769
|
+
[8, 1, 9, 8, 3, 1, 11, 7, 6],
|
|
9770
|
+
[10, 1, 2, 6, 11, 7],
|
|
9771
|
+
[1, 2, 10, 3, 0, 8, 6, 11, 7],
|
|
9772
|
+
[2, 9, 0, 2, 10, 9, 6, 11, 7],
|
|
9773
|
+
[6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8],
|
|
9774
|
+
[7, 2, 3, 6, 2, 7],
|
|
9775
|
+
[7, 0, 8, 7, 6, 0, 6, 2, 0],
|
|
9776
|
+
[2, 7, 6, 2, 3, 7, 0, 1, 9],
|
|
9777
|
+
[1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6],
|
|
9778
|
+
[10, 7, 6, 10, 1, 7, 1, 3, 7],
|
|
9779
|
+
[10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8],
|
|
9780
|
+
[0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7],
|
|
9781
|
+
[7, 6, 10, 7, 10, 8, 8, 10, 9],
|
|
9782
|
+
[6, 8, 4, 11, 8, 6],
|
|
9783
|
+
[3, 6, 11, 3, 0, 6, 0, 4, 6],
|
|
9784
|
+
[8, 6, 11, 8, 4, 6, 9, 0, 1],
|
|
9785
|
+
[9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6],
|
|
9786
|
+
[6, 8, 4, 6, 11, 8, 2, 10, 1],
|
|
9787
|
+
[1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6],
|
|
9788
|
+
[4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9],
|
|
9789
|
+
[10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3],
|
|
9790
|
+
[8, 2, 3, 8, 4, 2, 4, 6, 2],
|
|
9791
|
+
[0, 4, 2, 4, 6, 2],
|
|
9792
|
+
[1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8],
|
|
9793
|
+
[1, 9, 4, 1, 4, 2, 2, 4, 6],
|
|
9794
|
+
[8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1],
|
|
9795
|
+
[10, 1, 0, 10, 0, 6, 6, 0, 4],
|
|
9796
|
+
[4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3],
|
|
9797
|
+
[10, 9, 4, 6, 10, 4],
|
|
9798
|
+
[4, 9, 5, 7, 6, 11],
|
|
9799
|
+
[0, 8, 3, 4, 9, 5, 11, 7, 6],
|
|
9800
|
+
[5, 0, 1, 5, 4, 0, 7, 6, 11],
|
|
9801
|
+
[11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5],
|
|
9802
|
+
[9, 5, 4, 10, 1, 2, 7, 6, 11],
|
|
9803
|
+
[6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5],
|
|
9804
|
+
[7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2],
|
|
9805
|
+
[3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6],
|
|
9806
|
+
[7, 2, 3, 7, 6, 2, 5, 4, 9],
|
|
9807
|
+
[9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7],
|
|
9808
|
+
[3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0],
|
|
9809
|
+
[6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8],
|
|
9810
|
+
[9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7],
|
|
9811
|
+
[1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4],
|
|
9812
|
+
[4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10],
|
|
9813
|
+
[7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10],
|
|
9814
|
+
[6, 9, 5, 6, 11, 9, 11, 8, 9],
|
|
9815
|
+
[3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5],
|
|
9816
|
+
[0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11],
|
|
9817
|
+
[6, 11, 3, 6, 3, 5, 5, 3, 1],
|
|
9818
|
+
[1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6],
|
|
9819
|
+
[0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10],
|
|
9820
|
+
[11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5],
|
|
9821
|
+
[6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3],
|
|
9822
|
+
[5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2],
|
|
9823
|
+
[9, 5, 6, 9, 6, 0, 0, 6, 2],
|
|
9824
|
+
[1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8],
|
|
9825
|
+
[1, 5, 6, 2, 1, 6],
|
|
9826
|
+
[1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6],
|
|
9827
|
+
[10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0],
|
|
9828
|
+
[0, 3, 8, 5, 6, 10],
|
|
9829
|
+
[10, 5, 6],
|
|
9830
|
+
[11, 5, 10, 7, 5, 11],
|
|
9831
|
+
[11, 5, 10, 11, 7, 5, 8, 3, 0],
|
|
9832
|
+
[5, 11, 7, 5, 10, 11, 1, 9, 0],
|
|
9833
|
+
[10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1],
|
|
9834
|
+
[11, 1, 2, 11, 7, 1, 7, 5, 1],
|
|
9835
|
+
[0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11],
|
|
9836
|
+
[9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7],
|
|
9837
|
+
[7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2],
|
|
9838
|
+
[2, 5, 10, 2, 3, 5, 3, 7, 5],
|
|
9839
|
+
[8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5],
|
|
9840
|
+
[9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2],
|
|
9841
|
+
[9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2],
|
|
9842
|
+
[1, 3, 5, 3, 7, 5],
|
|
9843
|
+
[0, 8, 7, 0, 7, 1, 1, 7, 5],
|
|
9844
|
+
[9, 0, 3, 9, 3, 5, 5, 3, 7],
|
|
9845
|
+
[9, 8, 7, 5, 9, 7],
|
|
9846
|
+
[5, 8, 4, 5, 10, 8, 10, 11, 8],
|
|
9847
|
+
[5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0],
|
|
9848
|
+
[0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5],
|
|
9849
|
+
[10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4],
|
|
9850
|
+
[2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8],
|
|
9851
|
+
[0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11],
|
|
9852
|
+
[0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5],
|
|
9853
|
+
[9, 4, 5, 2, 11, 3],
|
|
9854
|
+
[2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4],
|
|
9855
|
+
[5, 10, 2, 5, 2, 4, 4, 2, 0],
|
|
9856
|
+
[3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9],
|
|
9857
|
+
[5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2],
|
|
9858
|
+
[8, 4, 5, 8, 5, 3, 3, 5, 1],
|
|
9859
|
+
[0, 4, 5, 1, 0, 5],
|
|
9860
|
+
[8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5],
|
|
9861
|
+
[9, 4, 5],
|
|
9862
|
+
[4, 11, 7, 4, 9, 11, 9, 10, 11],
|
|
9863
|
+
[0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11],
|
|
9864
|
+
[1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11],
|
|
9865
|
+
[3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4],
|
|
9866
|
+
[4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2],
|
|
9867
|
+
[9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3],
|
|
9868
|
+
[11, 7, 4, 11, 4, 2, 2, 4, 0],
|
|
9869
|
+
[11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4],
|
|
9870
|
+
[2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9],
|
|
9871
|
+
[9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7],
|
|
9872
|
+
[3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10],
|
|
9873
|
+
[1, 10, 2, 8, 7, 4],
|
|
9874
|
+
[4, 9, 1, 4, 1, 7, 7, 1, 3],
|
|
9875
|
+
[4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1],
|
|
9876
|
+
[4, 0, 3, 7, 4, 3],
|
|
9877
|
+
[4, 8, 7],
|
|
9878
|
+
[9, 10, 8, 10, 11, 8],
|
|
9879
|
+
[3, 0, 9, 3, 9, 11, 11, 9, 10],
|
|
9880
|
+
[0, 1, 10, 0, 10, 8, 8, 10, 11],
|
|
9881
|
+
[3, 1, 10, 11, 3, 10],
|
|
9882
|
+
[1, 2, 11, 1, 11, 9, 9, 11, 8],
|
|
9883
|
+
[3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9],
|
|
9884
|
+
[0, 2, 11, 8, 0, 11],
|
|
9885
|
+
[3, 2, 11],
|
|
9886
|
+
[2, 3, 8, 2, 8, 10, 10, 8, 9],
|
|
9887
|
+
[9, 10, 2, 0, 9, 2],
|
|
9888
|
+
[2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8],
|
|
9889
|
+
[1, 10, 2],
|
|
9890
|
+
[1, 3, 8, 9, 1, 8],
|
|
9891
|
+
[0, 9, 1],
|
|
9892
|
+
[0, 3, 8],
|
|
9893
|
+
[]
|
|
9894
|
+
];
|
|
9895
|
+
|
|
8528
9896
|
// ============================================================================
|
|
8529
9897
|
// Edge mask constants for 4x4x4 voxel blocks
|
|
8530
9898
|
// ============================================================================
|
|
@@ -8794,9 +10162,10 @@ const writeOctreeFiles = async (fs, jsonFilename, octree) => {
|
|
|
8794
10162
|
* Voxelizes Gaussian splat data and writes the result as a sparse voxel octree.
|
|
8795
10163
|
*
|
|
8796
10164
|
* This function performs GPU-accelerated voxelization of Gaussian splat data
|
|
8797
|
-
* and outputs two files:
|
|
10165
|
+
* and outputs two or three files:
|
|
8798
10166
|
* - `filename` (.voxel.json) - JSON metadata including bounds, resolution, and array sizes
|
|
8799
10167
|
* - Corresponding .voxel.bin - Binary octree data (nodes + leafData as Uint32 arrays)
|
|
10168
|
+
* - Corresponding .collision.glb - Triangle mesh extracted via marching cubes (GLB format, optional)
|
|
8800
10169
|
*
|
|
8801
10170
|
* The binary file layout is:
|
|
8802
10171
|
* - Bytes 0 to (nodeCount * 4 - 1): nodes array (Uint32, little-endian)
|
|
@@ -8815,16 +10184,17 @@ const writeOctreeFiles = async (fs, jsonFilename, octree) => {
|
|
|
8815
10184
|
* dataTable: myDataTable,
|
|
8816
10185
|
* voxelResolution: 0.05,
|
|
8817
10186
|
* opacityCutoff: 0.5,
|
|
10187
|
+
* collisionMesh: true,
|
|
8818
10188
|
* createDevice: async () => myGraphicsDevice
|
|
8819
10189
|
* }, fs);
|
|
8820
10190
|
* ```
|
|
8821
10191
|
*/
|
|
8822
10192
|
const writeVoxel = async (options, fs) => {
|
|
8823
|
-
const { filename, dataTable, voxelResolution = 0.05, opacityCutoff = 0.5, createDevice } = options;
|
|
10193
|
+
const { filename, dataTable, voxelResolution = 0.05, opacityCutoff = 0.5, createDevice, collisionMesh = false, meshSimplify = 0.25 } = options;
|
|
8824
10194
|
if (!createDevice) {
|
|
8825
10195
|
throw new Error('writeVoxel requires a createDevice function for GPU voxelization');
|
|
8826
10196
|
}
|
|
8827
|
-
logger.progress.begin(
|
|
10197
|
+
logger.progress.begin(collisionMesh ? 7 : 5);
|
|
8828
10198
|
const extentsResult = computeGaussianExtents(dataTable);
|
|
8829
10199
|
const bounds = extentsResult.sceneBounds;
|
|
8830
10200
|
logger.progress.step('Building BVH');
|
|
@@ -8996,10 +10366,61 @@ const writeVoxel = async (options, fs) => {
|
|
|
8996
10366
|
gpuVoxelization.destroy();
|
|
8997
10367
|
logger.progress.step('Filtering');
|
|
8998
10368
|
accumulator = filterAndFillBlocks(accumulator);
|
|
10369
|
+
let glbBytes = null;
|
|
10370
|
+
if (collisionMesh) {
|
|
10371
|
+
logger.progress.step('Extracting collision mesh');
|
|
10372
|
+
const rawMesh = marchingCubes(accumulator, gridBounds, voxelResolution);
|
|
10373
|
+
logger.log(`collision mesh (raw): ${rawMesh.positions.length / 3} vertices, ${rawMesh.indices.length / 3} triangles`);
|
|
10374
|
+
if (rawMesh.indices.length < 3) {
|
|
10375
|
+
logger.progress.step('Simplifying collision mesh');
|
|
10376
|
+
logger.log('collision mesh: no triangles generated, skipping GLB output');
|
|
10377
|
+
}
|
|
10378
|
+
else {
|
|
10379
|
+
logger.progress.step('Simplifying collision mesh');
|
|
10380
|
+
await MeshoptSimplifier.ready;
|
|
10381
|
+
const clampedSimplify = Number.isFinite(meshSimplify) ? Math.min(1, Math.max(0, meshSimplify)) : 0.25;
|
|
10382
|
+
const targetIndexCount = Math.max(3, Math.min(rawMesh.indices.length, Math.floor(rawMesh.indices.length * clampedSimplify / 3) * 3));
|
|
10383
|
+
const [simplifiedIndices] = MeshoptSimplifier.simplify(rawMesh.indices, rawMesh.positions, 3, targetIndexCount, voxelResolution, ['ErrorAbsolute']);
|
|
10384
|
+
const vertexRemap = new Map();
|
|
10385
|
+
let newVertexCount = 0;
|
|
10386
|
+
for (let i = 0; i < simplifiedIndices.length; i++) {
|
|
10387
|
+
if (!vertexRemap.has(simplifiedIndices[i])) {
|
|
10388
|
+
vertexRemap.set(simplifiedIndices[i], newVertexCount++);
|
|
10389
|
+
}
|
|
10390
|
+
}
|
|
10391
|
+
const compactPositions = new Float32Array(newVertexCount * 3);
|
|
10392
|
+
for (const [oldIdx, newIdx] of vertexRemap) {
|
|
10393
|
+
compactPositions[newIdx * 3] = rawMesh.positions[oldIdx * 3];
|
|
10394
|
+
compactPositions[newIdx * 3 + 1] = rawMesh.positions[oldIdx * 3 + 1];
|
|
10395
|
+
compactPositions[newIdx * 3 + 2] = rawMesh.positions[oldIdx * 3 + 2];
|
|
10396
|
+
}
|
|
10397
|
+
const compactIndices = new Uint32Array(simplifiedIndices.length);
|
|
10398
|
+
for (let i = 0; i < simplifiedIndices.length; i++) {
|
|
10399
|
+
compactIndices[i] = vertexRemap.get(simplifiedIndices[i]);
|
|
10400
|
+
}
|
|
10401
|
+
const reduction = (1 - simplifiedIndices.length / rawMesh.indices.length) * 100;
|
|
10402
|
+
logger.log(`collision mesh (simplified): ${newVertexCount} vertices, ${simplifiedIndices.length / 3} triangles (${reduction.toFixed(0)}% reduction)`);
|
|
10403
|
+
glbBytes = buildCollisionGlb(compactPositions, compactIndices);
|
|
10404
|
+
}
|
|
10405
|
+
}
|
|
10406
|
+
logger.progress.step('Building octree');
|
|
8999
10407
|
const octree = buildSparseOctree(accumulator, gridBounds, bounds, // Original scene bounds
|
|
9000
10408
|
voxelResolution);
|
|
10409
|
+
logger.log(`octree: depth=${octree.treeDepth}, interior=${octree.numInteriorNodes}, mixed=${octree.numMixedLeaves}`);
|
|
9001
10410
|
logger.progress.step('Writing');
|
|
9002
10411
|
await writeOctreeFiles(fs, filename, octree);
|
|
10412
|
+
if (glbBytes) {
|
|
10413
|
+
const glbFilename = filename.replace('.voxel.json', '.collision.glb');
|
|
10414
|
+
logger.log(`writing '${glbFilename}'...`);
|
|
10415
|
+
await writeFile$1(fs, glbFilename, glbBytes);
|
|
10416
|
+
}
|
|
10417
|
+
const totalBytes = (octree.nodes.length + octree.leafData.length) * 4;
|
|
10418
|
+
if (glbBytes) {
|
|
10419
|
+
logger.log(`total size: octree ${(totalBytes / 1024).toFixed(1)} KB, collision mesh ${(glbBytes.length / 1024).toFixed(1)} KB`);
|
|
10420
|
+
}
|
|
10421
|
+
else {
|
|
10422
|
+
logger.log(`total size: ${(totalBytes / 1024).toFixed(1)} KB`);
|
|
10423
|
+
}
|
|
9003
10424
|
};
|
|
9004
10425
|
|
|
9005
10426
|
/**
|
|
@@ -9132,6 +10553,8 @@ const writeFile = async (writeOptions, fs) => {
|
|
|
9132
10553
|
dataTable,
|
|
9133
10554
|
voxelResolution: options.voxelResolution,
|
|
9134
10555
|
opacityCutoff: options.opacityCutoff,
|
|
10556
|
+
collisionMesh: options.collisionMesh,
|
|
10557
|
+
meshSimplify: options.meshSimplify,
|
|
9135
10558
|
createDevice
|
|
9136
10559
|
}, fs);
|
|
9137
10560
|
break;
|
|
@@ -9385,5 +10808,5 @@ const processDataTable = (dataTable, processActions) => {
|
|
|
9385
10808
|
return result;
|
|
9386
10809
|
};
|
|
9387
10810
|
|
|
9388
|
-
export { BufferedReadStream, Column, DataTable, MemoryFileSystem, MemoryReadFileSystem, ReadStream, UrlReadFileSystem, WebPCodec, ZipFileSystem, ZipReadFileSystem, combine, computeSummary, getInputFormat, getOutputFormat, logger, processDataTable, readFile, readKsplat, readLcc, readMjs, readPly, readSog, readSplat, readSpz, readVoxel, simplifyGaussians, sortByVisibility, sortMortonOrder, transform, writeCompressedPly, writeCsv, writeFile, writeGlb, writeHtml, writeLod, writePly, writeSog, writeVoxel };
|
|
10811
|
+
export { BufferedReadStream, Column, DataTable, MemoryFileSystem, MemoryReadFileSystem, ReadStream, UrlReadFileSystem, WebPCodec, ZipFileSystem, ZipReadFileSystem, combine, computeSummary, getInputFormat, getOutputFormat, logger, marchingCubes, processDataTable, readFile, readKsplat, readLcc, readMjs, readPly, readSog, readSplat, readSpz, readVoxel, simplifyGaussians, sortByVisibility, sortMortonOrder, transform, writeCompressedPly, writeCsv, writeFile, writeGlb, writeHtml, writeLod, writePly, writeSog, writeVoxel };
|
|
9389
10812
|
//# sourceMappingURL=index.mjs.map
|