@manycore/aholo-splat-transform 1.2.6
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/CHANGELOG.md +102 -0
- package/README.md +33 -0
- package/bin/cli.js +118 -0
- package/dist/SplatData.d.ts +67 -0
- package/dist/SplatData.js +156 -0
- package/dist/constant.d.ts +3 -0
- package/dist/constant.js +13 -0
- package/dist/file/IFile.d.ts +5 -0
- package/dist/file/IFile.js +1 -0
- package/dist/file/index.d.ts +7 -0
- package/dist/file/index.js +6 -0
- package/dist/file/ksplat.d.ts +12 -0
- package/dist/file/ksplat.js +232 -0
- package/dist/file/lcc.d.ts +11 -0
- package/dist/file/lcc.js +157 -0
- package/dist/file/ply.d.ts +13 -0
- package/dist/file/ply.js +388 -0
- package/dist/file/sog.d.ts +80 -0
- package/dist/file/sog.js +504 -0
- package/dist/file/splat.d.ts +6 -0
- package/dist/file/splat.js +99 -0
- package/dist/file/spz.d.ts +8 -0
- package/dist/file/spz.js +400 -0
- package/dist/file/voxel.d.ts +37 -0
- package/dist/file/voxel.js +280 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +54 -0
- package/dist/native/cpp/bin/linux/binding.node +0 -0
- package/dist/native/cpp/bin/windows/binding.node +0 -0
- package/dist/native/index.d.ts +54 -0
- package/dist/native/index.js +128 -0
- package/dist/tasks/AutoChunkLodTask.d.ts +13 -0
- package/dist/tasks/AutoChunkLodTask.js +117 -0
- package/dist/tasks/AutoLodTask.d.ts +10 -0
- package/dist/tasks/AutoLodTask.js +20 -0
- package/dist/tasks/BaseTask.d.ts +15 -0
- package/dist/tasks/BaseTask.js +5 -0
- package/dist/tasks/FlexLodTask.d.ts +12 -0
- package/dist/tasks/FlexLodTask.js +44 -0
- package/dist/tasks/ModifyTask.d.ts +9 -0
- package/dist/tasks/ModifyTask.js +156 -0
- package/dist/tasks/ReadTask.d.ts +8 -0
- package/dist/tasks/ReadTask.js +29 -0
- package/dist/tasks/SkeletonLodTask.d.ts +10 -0
- package/dist/tasks/SkeletonLodTask.js +156 -0
- package/dist/tasks/VoxelTask.d.ts +30 -0
- package/dist/tasks/VoxelTask.js +37 -0
- package/dist/tasks/WriteTask.d.ts +11 -0
- package/dist/tasks/WriteTask.js +70 -0
- package/dist/utils/BufferReader.d.ts +12 -0
- package/dist/utils/BufferReader.js +47 -0
- package/dist/utils/Logger.d.ts +11 -0
- package/dist/utils/Logger.js +38 -0
- package/dist/utils/StreamChunkDecoder.d.ts +16 -0
- package/dist/utils/StreamChunkDecoder.js +36 -0
- package/dist/utils/index.d.ts +27 -0
- package/dist/utils/index.js +101 -0
- package/dist/utils/k-means.d.ts +4 -0
- package/dist/utils/k-means.js +350 -0
- package/dist/utils/math.d.ts +46 -0
- package/dist/utils/math.js +351 -0
- package/dist/utils/quantize-1d.d.ts +4 -0
- package/dist/utils/quantize-1d.js +164 -0
- package/dist/utils/sh-rotate.d.ts +2 -0
- package/dist/utils/sh-rotate.js +175 -0
- package/dist/utils/splat.d.ts +20 -0
- package/dist/utils/splat.js +378 -0
- package/dist/utils/voxel/common.d.ts +162 -0
- package/dist/utils/voxel/common.js +1700 -0
- package/dist/utils/voxel/coplanar-merge.d.ts +63 -0
- package/dist/utils/voxel/coplanar-merge.js +819 -0
- package/dist/utils/voxel/gpu-dilation.d.ts +2 -0
- package/dist/utils/voxel/gpu-dilation.js +665 -0
- package/dist/utils/voxel/marching-cubes.d.ts +42 -0
- package/dist/utils/voxel/marching-cubes.js +1657 -0
- package/dist/utils/voxel/mesh.d.ts +3 -0
- package/dist/utils/voxel/mesh.js +130 -0
- package/dist/utils/voxel/nav.d.ts +29 -0
- package/dist/utils/voxel/nav.js +1043 -0
- package/dist/utils/voxel/postprocess.d.ts +23 -0
- package/dist/utils/voxel/postprocess.js +375 -0
- package/dist/utils/voxel/voxel-faces.d.ts +18 -0
- package/dist/utils/voxel/voxel-faces.js +663 -0
- package/dist/utils/voxel/voxelize.d.ts +33 -0
- package/dist/utils/voxel/voxelize.js +1193 -0
- package/dist/utils/webgpu.d.ts +8 -0
- package/dist/utils/webgpu.js +122 -0
- package/package.json +32 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rotate spherical harmonics up to band 3 based on https://github.com/andrewwillmott/sh-lib
|
|
3
|
+
* This implementation calculates the rotation factors during construction which can then
|
|
4
|
+
* be used to rotate multiple spherical harmonics cheaply.
|
|
5
|
+
*/
|
|
6
|
+
const kSqrt03_02 = Math.sqrt(3.0 / 2.0);
|
|
7
|
+
const kSqrt01_03 = Math.sqrt(1.0 / 3.0);
|
|
8
|
+
const kSqrt02_03 = Math.sqrt(2.0 / 3.0);
|
|
9
|
+
const kSqrt04_03 = Math.sqrt(4.0 / 3.0);
|
|
10
|
+
const kSqrt01_04 = Math.sqrt(1.0 / 4.0);
|
|
11
|
+
const kSqrt03_04 = Math.sqrt(3.0 / 4.0);
|
|
12
|
+
const kSqrt01_05 = Math.sqrt(1.0 / 5.0);
|
|
13
|
+
const kSqrt03_05 = Math.sqrt(3.0 / 5.0);
|
|
14
|
+
const kSqrt06_05 = Math.sqrt(6.0 / 5.0);
|
|
15
|
+
const kSqrt08_05 = Math.sqrt(8.0 / 5.0);
|
|
16
|
+
const kSqrt09_05 = Math.sqrt(9.0 / 5.0);
|
|
17
|
+
const kSqrt01_06 = Math.sqrt(1.0 / 6.0);
|
|
18
|
+
const kSqrt05_06 = Math.sqrt(5.0 / 6.0);
|
|
19
|
+
const kSqrt03_08 = Math.sqrt(3.0 / 8.0);
|
|
20
|
+
const kSqrt05_08 = Math.sqrt(5.0 / 8.0);
|
|
21
|
+
const kSqrt09_08 = Math.sqrt(9.0 / 8.0);
|
|
22
|
+
const kSqrt05_09 = Math.sqrt(5.0 / 9.0);
|
|
23
|
+
const kSqrt08_09 = Math.sqrt(8.0 / 9.0);
|
|
24
|
+
const kSqrt01_10 = Math.sqrt(1.0 / 10.0);
|
|
25
|
+
const kSqrt03_10 = Math.sqrt(3.0 / 10.0);
|
|
26
|
+
const kSqrt01_12 = Math.sqrt(1.0 / 12.0);
|
|
27
|
+
const kSqrt04_15 = Math.sqrt(4.0 / 15.0);
|
|
28
|
+
const kSqrt01_16 = Math.sqrt(1.0 / 16.0);
|
|
29
|
+
const kSqrt15_16 = Math.sqrt(15.0 / 16.0);
|
|
30
|
+
const kSqrt01_18 = Math.sqrt(1.0 / 18.0);
|
|
31
|
+
const kSqrt01_60 = Math.sqrt(1.0 / 60.0);
|
|
32
|
+
export function createSHRotateFn(mat) {
|
|
33
|
+
const rot = mat.elements;
|
|
34
|
+
const sh1 = [
|
|
35
|
+
[rot[4], -rot[7], rot[1]],
|
|
36
|
+
[-rot[5], rot[8], -rot[2]],
|
|
37
|
+
[rot[3], -rot[6], rot[0]],
|
|
38
|
+
];
|
|
39
|
+
const sh2 = [
|
|
40
|
+
[
|
|
41
|
+
kSqrt01_04 * ((sh1[2][2] * sh1[0][0] + sh1[2][0] * sh1[0][2]) + (sh1[0][2] * sh1[2][0] + sh1[0][0] * sh1[2][2])),
|
|
42
|
+
(sh1[2][1] * sh1[0][0] + sh1[0][1] * sh1[2][0]),
|
|
43
|
+
kSqrt03_04 * (sh1[2][1] * sh1[0][1] + sh1[0][1] * sh1[2][1]),
|
|
44
|
+
(sh1[2][1] * sh1[0][2] + sh1[0][1] * sh1[2][2]),
|
|
45
|
+
kSqrt01_04 * ((sh1[2][2] * sh1[0][2] - sh1[2][0] * sh1[0][0]) + (sh1[0][2] * sh1[2][2] - sh1[0][0] * sh1[2][0])),
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
kSqrt01_04 * ((sh1[1][2] * sh1[0][0] + sh1[1][0] * sh1[0][2]) + (sh1[0][2] * sh1[1][0] + sh1[0][0] * sh1[1][2])),
|
|
49
|
+
sh1[1][1] * sh1[0][0] + sh1[0][1] * sh1[1][0],
|
|
50
|
+
kSqrt03_04 * (sh1[1][1] * sh1[0][1] + sh1[0][1] * sh1[1][1]),
|
|
51
|
+
sh1[1][1] * sh1[0][2] + sh1[0][1] * sh1[1][2],
|
|
52
|
+
kSqrt01_04 * ((sh1[1][2] * sh1[0][2] - sh1[1][0] * sh1[0][0]) + (sh1[0][2] * sh1[1][2] - sh1[0][0] * sh1[1][0])),
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
kSqrt01_03 * (sh1[1][2] * sh1[1][0] + sh1[1][0] * sh1[1][2]) - kSqrt01_12 * ((sh1[2][2] * sh1[2][0] + sh1[2][0] * sh1[2][2]) + (sh1[0][2] * sh1[0][0] + sh1[0][0] * sh1[0][2])),
|
|
56
|
+
kSqrt04_03 * sh1[1][1] * sh1[1][0] - kSqrt01_03 * (sh1[2][1] * sh1[2][0] + sh1[0][1] * sh1[0][0]),
|
|
57
|
+
sh1[1][1] * sh1[1][1] - kSqrt01_04 * (sh1[2][1] * sh1[2][1] + sh1[0][1] * sh1[0][1]),
|
|
58
|
+
kSqrt04_03 * sh1[1][1] * sh1[1][2] - kSqrt01_03 * (sh1[2][1] * sh1[2][2] + sh1[0][1] * sh1[0][2]),
|
|
59
|
+
kSqrt01_03 * (sh1[1][2] * sh1[1][2] - sh1[1][0] * sh1[1][0]) - kSqrt01_12 * ((sh1[2][2] * sh1[2][2] - sh1[2][0] * sh1[2][0]) + (sh1[0][2] * sh1[0][2] - sh1[0][0] * sh1[0][0])),
|
|
60
|
+
], [
|
|
61
|
+
kSqrt01_04 * ((sh1[1][2] * sh1[2][0] + sh1[1][0] * sh1[2][2]) + (sh1[2][2] * sh1[1][0] + sh1[2][0] * sh1[1][2])),
|
|
62
|
+
sh1[1][1] * sh1[2][0] + sh1[2][1] * sh1[1][0],
|
|
63
|
+
kSqrt03_04 * (sh1[1][1] * sh1[2][1] + sh1[2][1] * sh1[1][1]),
|
|
64
|
+
sh1[1][1] * sh1[2][2] + sh1[2][1] * sh1[1][2],
|
|
65
|
+
kSqrt01_04 * ((sh1[1][2] * sh1[2][2] - sh1[1][0] * sh1[2][0]) + (sh1[2][2] * sh1[1][2] - sh1[2][0] * sh1[1][0])),
|
|
66
|
+
],
|
|
67
|
+
[
|
|
68
|
+
kSqrt01_04 * ((sh1[2][2] * sh1[2][0] + sh1[2][0] * sh1[2][2]) - (sh1[0][2] * sh1[0][0] + sh1[0][0] * sh1[0][2])),
|
|
69
|
+
(sh1[2][1] * sh1[2][0] - sh1[0][1] * sh1[0][0]),
|
|
70
|
+
kSqrt03_04 * (sh1[2][1] * sh1[2][1] - sh1[0][1] * sh1[0][1]),
|
|
71
|
+
(sh1[2][1] * sh1[2][2] - sh1[0][1] * sh1[0][2]),
|
|
72
|
+
kSqrt01_04 * ((sh1[2][2] * sh1[2][2] - sh1[2][0] * sh1[2][0]) - (sh1[0][2] * sh1[0][2] - sh1[0][0] * sh1[0][0])),
|
|
73
|
+
],
|
|
74
|
+
];
|
|
75
|
+
const sh3 = [
|
|
76
|
+
[
|
|
77
|
+
kSqrt01_04 * ((sh1[2][2] * sh2[0][0] + sh1[2][0] * sh2[0][4]) + (sh1[0][2] * sh2[4][0] + sh1[0][0] * sh2[4][4])),
|
|
78
|
+
kSqrt03_02 * (sh1[2][1] * sh2[0][0] + sh1[0][1] * sh2[4][0]),
|
|
79
|
+
kSqrt15_16 * (sh1[2][1] * sh2[0][1] + sh1[0][1] * sh2[4][1]),
|
|
80
|
+
kSqrt05_06 * (sh1[2][1] * sh2[0][2] + sh1[0][1] * sh2[4][2]),
|
|
81
|
+
kSqrt15_16 * (sh1[2][1] * sh2[0][3] + sh1[0][1] * sh2[4][3]),
|
|
82
|
+
kSqrt03_02 * (sh1[2][1] * sh2[0][4] + sh1[0][1] * sh2[4][4]),
|
|
83
|
+
kSqrt01_04 * ((sh1[2][2] * sh2[0][4] - sh1[2][0] * sh2[0][0]) + (sh1[0][2] * sh2[4][4] - sh1[0][0] * sh2[4][0])),
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
kSqrt01_06 * (sh1[1][2] * sh2[0][0] + sh1[1][0] * sh2[0][4]) + kSqrt01_06 * ((sh1[2][2] * sh2[1][0] + sh1[2][0] * sh2[1][4]) + (sh1[0][2] * sh2[3][0] + sh1[0][0] * sh2[3][4])),
|
|
87
|
+
sh1[1][1] * sh2[0][0] + (sh1[2][1] * sh2[1][0] + sh1[0][1] * sh2[3][0]),
|
|
88
|
+
kSqrt05_08 * sh1[1][1] * sh2[0][1] + kSqrt05_08 * (sh1[2][1] * sh2[1][1] + sh1[0][1] * sh2[3][1]),
|
|
89
|
+
kSqrt05_09 * sh1[1][1] * sh2[0][2] + kSqrt05_09 * (sh1[2][1] * sh2[1][2] + sh1[0][1] * sh2[3][2]),
|
|
90
|
+
kSqrt05_08 * sh1[1][1] * sh2[0][3] + kSqrt05_08 * (sh1[2][1] * sh2[1][3] + sh1[0][1] * sh2[3][3]),
|
|
91
|
+
sh1[1][1] * sh2[0][4] + (sh1[2][1] * sh2[1][4] + sh1[0][1] * sh2[3][4]),
|
|
92
|
+
kSqrt01_06 * (sh1[1][2] * sh2[0][4] - sh1[1][0] * sh2[0][0]) + kSqrt01_06 * ((sh1[2][2] * sh2[1][4] - sh1[2][0] * sh2[1][0]) + (sh1[0][2] * sh2[3][4] - sh1[0][0] * sh2[3][0])),
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
kSqrt04_15 * (sh1[1][2] * sh2[1][0] + sh1[1][0] * sh2[1][4]) + kSqrt01_05 * (sh1[0][2] * sh2[2][0] + sh1[0][0] * sh2[2][4]) - kSqrt01_60 * ((sh1[2][2] * sh2[0][0] + sh1[2][0] * sh2[0][4]) - (sh1[0][2] * sh2[4][0] + sh1[0][0] * sh2[4][4])),
|
|
96
|
+
kSqrt08_05 * sh1[1][1] * sh2[1][0] + kSqrt06_05 * sh1[0][1] * sh2[2][0] - kSqrt01_10 * (sh1[2][1] * sh2[0][0] - sh1[0][1] * sh2[4][0]),
|
|
97
|
+
sh1[1][1] * sh2[1][1] + kSqrt03_04 * sh1[0][1] * sh2[2][1] - kSqrt01_16 * (sh1[2][1] * sh2[0][1] - sh1[0][1] * sh2[4][1]),
|
|
98
|
+
kSqrt08_09 * sh1[1][1] * sh2[1][2] + kSqrt02_03 * sh1[0][1] * sh2[2][2] - kSqrt01_18 * (sh1[2][1] * sh2[0][2] - sh1[0][1] * sh2[4][2]),
|
|
99
|
+
sh1[1][1] * sh2[1][3] + kSqrt03_04 * sh1[0][1] * sh2[2][3] - kSqrt01_16 * (sh1[2][1] * sh2[0][3] - sh1[0][1] * sh2[4][3]),
|
|
100
|
+
kSqrt08_05 * sh1[1][1] * sh2[1][4] + kSqrt06_05 * sh1[0][1] * sh2[2][4] - kSqrt01_10 * (sh1[2][1] * sh2[0][4] - sh1[0][1] * sh2[4][4]),
|
|
101
|
+
kSqrt04_15 * (sh1[1][2] * sh2[1][4] - sh1[1][0] * sh2[1][0]) + kSqrt01_05 * (sh1[0][2] * sh2[2][4] - sh1[0][0] * sh2[2][0]) - kSqrt01_60 * ((sh1[2][2] * sh2[0][4] - sh1[2][0] * sh2[0][0]) - (sh1[0][2] * sh2[4][4] - sh1[0][0] * sh2[4][0])),
|
|
102
|
+
],
|
|
103
|
+
[
|
|
104
|
+
kSqrt03_10 * (sh1[1][2] * sh2[2][0] + sh1[1][0] * sh2[2][4]) - kSqrt01_10 * ((sh1[2][2] * sh2[3][0] + sh1[2][0] * sh2[3][4]) + (sh1[0][2] * sh2[1][0] + sh1[0][0] * sh2[1][4])),
|
|
105
|
+
kSqrt09_05 * sh1[1][1] * sh2[2][0] - kSqrt03_05 * (sh1[2][1] * sh2[3][0] + sh1[0][1] * sh2[1][0]),
|
|
106
|
+
kSqrt09_08 * sh1[1][1] * sh2[2][1] - kSqrt03_08 * (sh1[2][1] * sh2[3][1] + sh1[0][1] * sh2[1][1]),
|
|
107
|
+
sh1[1][1] * sh2[2][2] - kSqrt01_03 * (sh1[2][1] * sh2[3][2] + sh1[0][1] * sh2[1][2]),
|
|
108
|
+
kSqrt09_08 * sh1[1][1] * sh2[2][3] - kSqrt03_08 * (sh1[2][1] * sh2[3][3] + sh1[0][1] * sh2[1][3]),
|
|
109
|
+
kSqrt09_05 * sh1[1][1] * sh2[2][4] - kSqrt03_05 * (sh1[2][1] * sh2[3][4] + sh1[0][1] * sh2[1][4]),
|
|
110
|
+
kSqrt03_10 * (sh1[1][2] * sh2[2][4] - sh1[1][0] * sh2[2][0]) - kSqrt01_10 * ((sh1[2][2] * sh2[3][4] - sh1[2][0] * sh2[3][0]) + (sh1[0][2] * sh2[1][4] - sh1[0][0] * sh2[1][0])),
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
kSqrt04_15 * (sh1[1][2] * sh2[3][0] + sh1[1][0] * sh2[3][4]) + kSqrt01_05 * (sh1[2][2] * sh2[2][0] + sh1[2][0] * sh2[2][4]) - kSqrt01_60 * ((sh1[2][2] * sh2[4][0] + sh1[2][0] * sh2[4][4]) + (sh1[0][2] * sh2[0][0] + sh1[0][0] * sh2[0][4])),
|
|
114
|
+
kSqrt08_05 * sh1[1][1] * sh2[3][0] + kSqrt06_05 * sh1[2][1] * sh2[2][0] - kSqrt01_10 * (sh1[2][1] * sh2[4][0] + sh1[0][1] * sh2[0][0]),
|
|
115
|
+
sh1[1][1] * sh2[3][1] + kSqrt03_04 * sh1[2][1] * sh2[2][1] - kSqrt01_16 * (sh1[2][1] * sh2[4][1] + sh1[0][1] * sh2[0][1]),
|
|
116
|
+
kSqrt08_09 * sh1[1][1] * sh2[3][2] + kSqrt02_03 * sh1[2][1] * sh2[2][2] - kSqrt01_18 * (sh1[2][1] * sh2[4][2] + sh1[0][1] * sh2[0][2]),
|
|
117
|
+
sh1[1][1] * sh2[3][3] + kSqrt03_04 * sh1[2][1] * sh2[2][3] - kSqrt01_16 * (sh1[2][1] * sh2[4][3] + sh1[0][1] * sh2[0][3]),
|
|
118
|
+
kSqrt08_05 * sh1[1][1] * sh2[3][4] + kSqrt06_05 * sh1[2][1] * sh2[2][4] - kSqrt01_10 * (sh1[2][1] * sh2[4][4] + sh1[0][1] * sh2[0][4]),
|
|
119
|
+
kSqrt04_15 * (sh1[1][2] * sh2[3][4] - sh1[1][0] * sh2[3][0]) + kSqrt01_05 * (sh1[2][2] * sh2[2][4] - sh1[2][0] * sh2[2][0]) - kSqrt01_60 * ((sh1[2][2] * sh2[4][4] - sh1[2][0] * sh2[4][0]) + (sh1[0][2] * sh2[0][4] - sh1[0][0] * sh2[0][0])),
|
|
120
|
+
],
|
|
121
|
+
[
|
|
122
|
+
kSqrt01_06 * (sh1[1][2] * sh2[4][0] + sh1[1][0] * sh2[4][4]) + kSqrt01_06 * ((sh1[2][2] * sh2[3][0] + sh1[2][0] * sh2[3][4]) - (sh1[0][2] * sh2[1][0] + sh1[0][0] * sh2[1][4])),
|
|
123
|
+
sh1[1][1] * sh2[4][0] + (sh1[2][1] * sh2[3][0] - sh1[0][1] * sh2[1][0]),
|
|
124
|
+
kSqrt05_08 * sh1[1][1] * sh2[4][1] + kSqrt05_08 * (sh1[2][1] * sh2[3][1] - sh1[0][1] * sh2[1][1]),
|
|
125
|
+
kSqrt05_09 * sh1[1][1] * sh2[4][2] + kSqrt05_09 * (sh1[2][1] * sh2[3][2] - sh1[0][1] * sh2[1][2]),
|
|
126
|
+
kSqrt05_08 * sh1[1][1] * sh2[4][3] + kSqrt05_08 * (sh1[2][1] * sh2[3][3] - sh1[0][1] * sh2[1][3]),
|
|
127
|
+
sh1[1][1] * sh2[4][4] + (sh1[2][1] * sh2[3][4] - sh1[0][1] * sh2[1][4]),
|
|
128
|
+
kSqrt01_06 * (sh1[1][2] * sh2[4][4] - sh1[1][0] * sh2[4][0]) + kSqrt01_06 * ((sh1[2][2] * sh2[3][4] - sh1[2][0] * sh2[3][0]) - (sh1[0][2] * sh2[1][4] - sh1[0][0] * sh2[1][0])),
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
kSqrt01_04 * ((sh1[2][2] * sh2[4][0] + sh1[2][0] * sh2[4][4]) - (sh1[0][2] * sh2[0][0] + sh1[0][0] * sh2[0][4])),
|
|
132
|
+
kSqrt03_02 * (sh1[2][1] * sh2[4][0] - sh1[0][1] * sh2[0][0]),
|
|
133
|
+
kSqrt15_16 * (sh1[2][1] * sh2[4][1] - sh1[0][1] * sh2[0][1]),
|
|
134
|
+
kSqrt05_06 * (sh1[2][1] * sh2[4][2] - sh1[0][1] * sh2[0][2]),
|
|
135
|
+
kSqrt15_16 * (sh1[2][1] * sh2[4][3] - sh1[0][1] * sh2[0][3]),
|
|
136
|
+
kSqrt03_02 * (sh1[2][1] * sh2[4][4] - sh1[0][1] * sh2[0][4]),
|
|
137
|
+
kSqrt01_04 * ((sh1[2][2] * sh2[4][4] - sh1[2][0] * sh2[4][0]) - (sh1[0][2] * sh2[0][4] - sh1[0][0] * sh2[0][0])),
|
|
138
|
+
],
|
|
139
|
+
];
|
|
140
|
+
const dp = (n, start, a, b) => {
|
|
141
|
+
let sum = 0;
|
|
142
|
+
for (let i = 0; i < n; i++) {
|
|
143
|
+
sum += a[start + i] * b[i];
|
|
144
|
+
}
|
|
145
|
+
return sum;
|
|
146
|
+
};
|
|
147
|
+
const temp = new Float32Array(15);
|
|
148
|
+
return (shN) => {
|
|
149
|
+
temp.set(shN);
|
|
150
|
+
if (shN.length < 3) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
shN[0] = dp(3, 0, temp, sh1[0]);
|
|
154
|
+
shN[1] = dp(3, 0, temp, sh1[1]);
|
|
155
|
+
shN[2] = dp(3, 0, temp, sh1[2]);
|
|
156
|
+
if (shN.length < 8) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
shN[3] = dp(5, 3, temp, sh2[0]);
|
|
160
|
+
shN[4] = dp(5, 3, temp, sh2[1]);
|
|
161
|
+
shN[5] = dp(5, 3, temp, sh2[2]);
|
|
162
|
+
shN[6] = dp(5, 3, temp, sh2[3]);
|
|
163
|
+
shN[7] = dp(5, 3, temp, sh2[4]);
|
|
164
|
+
if (shN.length < 15) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
shN[8] = dp(7, 8, temp, sh3[0]);
|
|
168
|
+
shN[9] = dp(7, 8, temp, sh3[1]);
|
|
169
|
+
shN[10] = dp(7, 8, temp, sh3[2]);
|
|
170
|
+
shN[11] = dp(7, 8, temp, sh3[3]);
|
|
171
|
+
shN[12] = dp(7, 8, temp, sh3[4]);
|
|
172
|
+
shN[13] = dp(7, 8, temp, sh3[5]);
|
|
173
|
+
shN[14] = dp(7, 8, temp, sh3[6]);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IFile } from '../file/index.js';
|
|
2
|
+
import { SplatData } from '../SplatData.js';
|
|
3
|
+
export declare enum SplatFileType {
|
|
4
|
+
PLY = 0,
|
|
5
|
+
SPZ = 1,
|
|
6
|
+
USPZ = 2,// not gzip spz
|
|
7
|
+
SPLAT = 3,
|
|
8
|
+
KSPLAT = 4,
|
|
9
|
+
SOG = 5,
|
|
10
|
+
LCC = 6
|
|
11
|
+
}
|
|
12
|
+
export declare function detectSplatFileType(filename: string, buffer?: Uint8Array): SplatFileType | undefined;
|
|
13
|
+
export declare function createSplatFile(path: string, buffer?: Uint8Array, compressLevel?: number): IFile;
|
|
14
|
+
export declare function combineSplatData(source: SplatData[]): SplatData;
|
|
15
|
+
export declare function computeDenseBox(data: SplatData, ratio?: number): {
|
|
16
|
+
min: number[];
|
|
17
|
+
max: number[];
|
|
18
|
+
};
|
|
19
|
+
export declare function mortonSort(splat: SplatData): Uint32Array;
|
|
20
|
+
export declare function fastDeleteSplat(splat: SplatData, indices: number[]): void;
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { unzipSync } from 'fflate';
|
|
2
|
+
import { PlyFile, SpzFile, KsplatFile, SplatFile, SogFile, LccFile } from '../file/index.js';
|
|
3
|
+
import { SplatData } from '../SplatData.js';
|
|
4
|
+
import { SH_MAPS } from '../constant.js';
|
|
5
|
+
export var SplatFileType;
|
|
6
|
+
(function (SplatFileType) {
|
|
7
|
+
SplatFileType[SplatFileType["PLY"] = 0] = "PLY";
|
|
8
|
+
SplatFileType[SplatFileType["SPZ"] = 1] = "SPZ";
|
|
9
|
+
SplatFileType[SplatFileType["USPZ"] = 2] = "USPZ";
|
|
10
|
+
SplatFileType[SplatFileType["SPLAT"] = 3] = "SPLAT";
|
|
11
|
+
SplatFileType[SplatFileType["KSPLAT"] = 4] = "KSPLAT";
|
|
12
|
+
SplatFileType[SplatFileType["SOG"] = 5] = "SOG";
|
|
13
|
+
SplatFileType[SplatFileType["LCC"] = 6] = "LCC";
|
|
14
|
+
})(SplatFileType || (SplatFileType = {}));
|
|
15
|
+
export function detectSplatFileType(filename, buffer = new Uint8Array()) {
|
|
16
|
+
let ext = filename.split('.').pop();
|
|
17
|
+
if (ext === 'zip') {
|
|
18
|
+
unzipSync(buffer, {
|
|
19
|
+
filter: file => {
|
|
20
|
+
const { name } = file;
|
|
21
|
+
if (name.endsWith('meta.json')) {
|
|
22
|
+
ext = 'sog';
|
|
23
|
+
}
|
|
24
|
+
else if (name.endsWith('meta.lcc')) {
|
|
25
|
+
ext = 'lcc';
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else if (ext === 'json') {
|
|
32
|
+
// fast check sog json
|
|
33
|
+
const json = JSON.parse(new TextDecoder().decode(buffer));
|
|
34
|
+
const isSogMetadata = ['means', 'scales', 'quats', 'sh0'].every(k => !!json[k]);
|
|
35
|
+
if (isSogMetadata) {
|
|
36
|
+
ext = 'sog';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
let type;
|
|
40
|
+
switch (ext) {
|
|
41
|
+
case 'ply': {
|
|
42
|
+
type = SplatFileType.PLY;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'spz': {
|
|
46
|
+
type = SplatFileType.SPZ;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'uspz': {
|
|
50
|
+
type = SplatFileType.USPZ;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case 'splat': {
|
|
54
|
+
type = SplatFileType.SPLAT;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 'ksplat': {
|
|
58
|
+
type = SplatFileType.KSPLAT;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case 'sog': {
|
|
62
|
+
type = SplatFileType.SOG;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case 'lcc': {
|
|
66
|
+
type = SplatFileType.LCC;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
default: {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return type;
|
|
74
|
+
}
|
|
75
|
+
export function createSplatFile(path, buffer = new Uint8Array(), compressLevel = 6) {
|
|
76
|
+
const type = detectSplatFileType(path, buffer);
|
|
77
|
+
if (type === undefined) {
|
|
78
|
+
throw new Error(`Unsupported file format: ${path}`);
|
|
79
|
+
}
|
|
80
|
+
let file;
|
|
81
|
+
switch (type) {
|
|
82
|
+
case SplatFileType.PLY: {
|
|
83
|
+
file = new PlyFile();
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case SplatFileType.SPZ: {
|
|
87
|
+
file = new SpzFile(compressLevel);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case SplatFileType.USPZ: {
|
|
91
|
+
file = new SpzFile(-1);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case SplatFileType.KSPLAT: {
|
|
95
|
+
file = new KsplatFile();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case SplatFileType.SPLAT: {
|
|
99
|
+
file = new SplatFile();
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case SplatFileType.SOG: {
|
|
103
|
+
file = new SogFile();
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case SplatFileType.LCC: {
|
|
107
|
+
file = new LccFile();
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return file;
|
|
112
|
+
}
|
|
113
|
+
export function combineSplatData(source) {
|
|
114
|
+
const target = new SplatData().init(source.reduce((p, c) => p + c.counts, 0), Math.max(...source.map(v => v.shDegree)));
|
|
115
|
+
const single = {
|
|
116
|
+
x: 0, y: 0, z: 0,
|
|
117
|
+
sx: 0, sy: 0, sz: 0,
|
|
118
|
+
qx: 0, qy: 0, qz: 0, qw: 0,
|
|
119
|
+
r: 0, g: 0, b: 0, a: 0,
|
|
120
|
+
shN: new Array(SH_MAPS[target.shDegree]),
|
|
121
|
+
};
|
|
122
|
+
const shN = single.shN;
|
|
123
|
+
let index = 0;
|
|
124
|
+
for (let i = 0; i < source.length; i++) {
|
|
125
|
+
const splat = source[i];
|
|
126
|
+
const { counts } = splat;
|
|
127
|
+
for (let j = 0; j < counts; j++) {
|
|
128
|
+
splat.get(j, single);
|
|
129
|
+
splat.getShN(j, shN);
|
|
130
|
+
target.set(index, single);
|
|
131
|
+
target.setShN(index, shN);
|
|
132
|
+
index++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return target;
|
|
136
|
+
}
|
|
137
|
+
const VOXEL_COUNTS = 65535;
|
|
138
|
+
export function computeDenseBox(data, ratio = 0.98) {
|
|
139
|
+
if (data.counts === 0) {
|
|
140
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
141
|
+
}
|
|
142
|
+
const xCol = data.table[0 /* ColIdx.x */];
|
|
143
|
+
const yCol = data.table[1 /* ColIdx.y */];
|
|
144
|
+
const zCol = data.table[2 /* ColIdx.z */];
|
|
145
|
+
let minX = Infinity;
|
|
146
|
+
let minY = Infinity;
|
|
147
|
+
let minZ = Infinity;
|
|
148
|
+
let maxX = -Infinity;
|
|
149
|
+
let maxY = -Infinity;
|
|
150
|
+
let maxZ = -Infinity;
|
|
151
|
+
for (let i = 0; i < data.counts; i++) {
|
|
152
|
+
const x = xCol[i];
|
|
153
|
+
const y = yCol[i];
|
|
154
|
+
const z = zCol[i];
|
|
155
|
+
if (x < minX) {
|
|
156
|
+
minX = x;
|
|
157
|
+
}
|
|
158
|
+
if (x > maxX) {
|
|
159
|
+
maxX = x;
|
|
160
|
+
}
|
|
161
|
+
if (y < minY) {
|
|
162
|
+
minY = y;
|
|
163
|
+
}
|
|
164
|
+
if (y > maxY) {
|
|
165
|
+
maxY = y;
|
|
166
|
+
}
|
|
167
|
+
if (z < minZ) {
|
|
168
|
+
minZ = z;
|
|
169
|
+
}
|
|
170
|
+
if (z > maxZ) {
|
|
171
|
+
maxZ = z;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const scaleX = VOXEL_COUNTS / Math.max(maxX - minX, 1e-9);
|
|
175
|
+
const scaleY = VOXEL_COUNTS / Math.max(maxY - minY, 1e-9);
|
|
176
|
+
const scaleZ = VOXEL_COUNTS / Math.max(maxZ - minZ, 1e-9);
|
|
177
|
+
const xChunks = new Uint32Array(VOXEL_COUNTS);
|
|
178
|
+
const yChunks = new Uint32Array(VOXEL_COUNTS);
|
|
179
|
+
const zChunks = new Uint32Array(VOXEL_COUNTS);
|
|
180
|
+
for (let i = 0; i < data.counts; i++) {
|
|
181
|
+
xChunks[((xCol[i] - minX) * scaleX) | 0]++;
|
|
182
|
+
yChunks[((yCol[i] - minY) * scaleY) | 0]++;
|
|
183
|
+
zChunks[((zCol[i] - minZ) * scaleZ) | 0]++;
|
|
184
|
+
}
|
|
185
|
+
const K = Math.ceil(data.counts * (1 - ratio));
|
|
186
|
+
let startX = 0;
|
|
187
|
+
let endX = VOXEL_COUNTS - 1;
|
|
188
|
+
let startY = 0;
|
|
189
|
+
let endY = VOXEL_COUNTS - 1;
|
|
190
|
+
let startZ = 0;
|
|
191
|
+
let endZ = VOXEL_COUNTS - 1;
|
|
192
|
+
let count = data.counts;
|
|
193
|
+
while (count > K) {
|
|
194
|
+
const xs = xChunks[startX];
|
|
195
|
+
const xe = xChunks[endX];
|
|
196
|
+
const ys = yChunks[startY];
|
|
197
|
+
const ye = yChunks[endY];
|
|
198
|
+
const zs = zChunks[startZ];
|
|
199
|
+
const ze = zChunks[endZ];
|
|
200
|
+
let min = xs;
|
|
201
|
+
let minKey = 'startX';
|
|
202
|
+
if (xe < min) {
|
|
203
|
+
min = xe;
|
|
204
|
+
minKey = 'endX';
|
|
205
|
+
}
|
|
206
|
+
if (ys < min) {
|
|
207
|
+
min = ys;
|
|
208
|
+
minKey = 'startY';
|
|
209
|
+
}
|
|
210
|
+
if (ye < min) {
|
|
211
|
+
min = ye;
|
|
212
|
+
minKey = 'endY';
|
|
213
|
+
}
|
|
214
|
+
if (zs < min) {
|
|
215
|
+
min = zs;
|
|
216
|
+
minKey = 'startZ';
|
|
217
|
+
}
|
|
218
|
+
if (ze < min) {
|
|
219
|
+
min = ze;
|
|
220
|
+
minKey = 'endZ';
|
|
221
|
+
}
|
|
222
|
+
switch (minKey) {
|
|
223
|
+
case 'startX':
|
|
224
|
+
startX++;
|
|
225
|
+
break;
|
|
226
|
+
case 'endX':
|
|
227
|
+
endX--;
|
|
228
|
+
break;
|
|
229
|
+
case 'startY':
|
|
230
|
+
startY++;
|
|
231
|
+
break;
|
|
232
|
+
case 'endY':
|
|
233
|
+
endY--;
|
|
234
|
+
break;
|
|
235
|
+
case 'startZ':
|
|
236
|
+
startZ++;
|
|
237
|
+
break;
|
|
238
|
+
case 'endZ':
|
|
239
|
+
endZ--;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
count -= min;
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
min: [(startX / scaleX) + minX, (startY / scaleY) + minY, (startZ / scaleZ) + minZ],
|
|
246
|
+
max: [(endX / scaleX) + minX, (endY / scaleY) + minY, (endZ / scaleZ) + minZ],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// https://github.com/playcanvas/splat-transform/blob/main/src/lib/data-table/data-table.ts
|
|
250
|
+
export function mortonSort(splat) {
|
|
251
|
+
const result = new Uint32Array(splat.counts);
|
|
252
|
+
const xCol = splat.table[0 /* ColIdx.x */];
|
|
253
|
+
const yCol = splat.table[1 /* ColIdx.y */];
|
|
254
|
+
const zCol = splat.table[2 /* ColIdx.z */];
|
|
255
|
+
for (let i = 0; i < result.length; ++i) {
|
|
256
|
+
result[i] = i;
|
|
257
|
+
}
|
|
258
|
+
const generate = (indices) => {
|
|
259
|
+
if (indices.length === 0) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
// https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
|
|
263
|
+
const encodeMorton3 = (x, y, z) => {
|
|
264
|
+
const Part1By2 = (x) => {
|
|
265
|
+
x &= 0x000003ff;
|
|
266
|
+
x = (x ^ (x << 16)) & 0xff0000ff;
|
|
267
|
+
x = (x ^ (x << 8)) & 0x0300f00f;
|
|
268
|
+
x = (x ^ (x << 4)) & 0x030c30c3;
|
|
269
|
+
x = (x ^ (x << 2)) & 0x09249249;
|
|
270
|
+
return x;
|
|
271
|
+
};
|
|
272
|
+
return (Part1By2(z) << 2) + (Part1By2(y) << 1) + Part1By2(x);
|
|
273
|
+
};
|
|
274
|
+
let mx = Infinity;
|
|
275
|
+
let my = Infinity;
|
|
276
|
+
let mz = Infinity;
|
|
277
|
+
let Mx = -Infinity;
|
|
278
|
+
let My = -Infinity;
|
|
279
|
+
let Mz = -Infinity;
|
|
280
|
+
// calculate scene extents across all splats (using sort centers, because they're in world space)
|
|
281
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
282
|
+
const ri = indices[i];
|
|
283
|
+
const x = xCol[ri];
|
|
284
|
+
const y = yCol[ri];
|
|
285
|
+
const z = zCol[ri];
|
|
286
|
+
if (x < mx) {
|
|
287
|
+
mx = x;
|
|
288
|
+
}
|
|
289
|
+
if (x > Mx) {
|
|
290
|
+
Mx = x;
|
|
291
|
+
}
|
|
292
|
+
if (y < my) {
|
|
293
|
+
my = y;
|
|
294
|
+
}
|
|
295
|
+
if (y > My) {
|
|
296
|
+
My = y;
|
|
297
|
+
}
|
|
298
|
+
if (z < mz) {
|
|
299
|
+
mz = z;
|
|
300
|
+
}
|
|
301
|
+
if (z > Mz) {
|
|
302
|
+
Mz = z;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const xlen = Mx - mx;
|
|
306
|
+
const ylen = My - my;
|
|
307
|
+
const zlen = Mz - mz;
|
|
308
|
+
if (!isFinite(xlen) || !isFinite(ylen) || !isFinite(zlen)) {
|
|
309
|
+
console.debug('invalid extents', xlen, ylen, zlen);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// all points are identical
|
|
313
|
+
if (xlen === 0 && ylen === 0 && zlen === 0) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const xmul = (xlen === 0) ? 0 : 1024 / xlen;
|
|
317
|
+
const ymul = (ylen === 0) ? 0 : 1024 / ylen;
|
|
318
|
+
const zmul = (zlen === 0) ? 0 : 1024 / zlen;
|
|
319
|
+
const morton = new Uint32Array(indices.length);
|
|
320
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
321
|
+
const ri = indices[i];
|
|
322
|
+
const x = xCol[ri];
|
|
323
|
+
const y = yCol[ri];
|
|
324
|
+
const z = zCol[ri];
|
|
325
|
+
const ix = Math.min(1023, (x - mx) * xmul) >>> 0;
|
|
326
|
+
const iy = Math.min(1023, (y - my) * ymul) >>> 0;
|
|
327
|
+
const iz = Math.min(1023, (z - mz) * zmul) >>> 0;
|
|
328
|
+
morton[i] = encodeMorton3(ix, iy, iz);
|
|
329
|
+
}
|
|
330
|
+
// sort indices by morton code
|
|
331
|
+
const order = new Uint32Array(indices.length);
|
|
332
|
+
for (let i = 0; i < order.length; i++) {
|
|
333
|
+
order[i] = i;
|
|
334
|
+
}
|
|
335
|
+
order.sort((a, b) => morton[a] - morton[b]);
|
|
336
|
+
const tmpIndices = indices.slice();
|
|
337
|
+
for (let i = 0; i < indices.length; ++i) {
|
|
338
|
+
indices[i] = tmpIndices[order[i]];
|
|
339
|
+
}
|
|
340
|
+
// sort the largest buckets recursively
|
|
341
|
+
let start = 0;
|
|
342
|
+
let end = 1;
|
|
343
|
+
while (start < indices.length) {
|
|
344
|
+
while (end < indices.length && morton[order[end]] === morton[order[start]]) {
|
|
345
|
+
++end;
|
|
346
|
+
}
|
|
347
|
+
if (end - start > 256) {
|
|
348
|
+
generate(indices.subarray(start, end));
|
|
349
|
+
}
|
|
350
|
+
start = end;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
generate(result);
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
export function fastDeleteSplat(splat, indices) {
|
|
357
|
+
const { counts, table } = splat;
|
|
358
|
+
const map = new Uint32Array(counts - indices.length);
|
|
359
|
+
let write = 0;
|
|
360
|
+
let removeIdx = 0;
|
|
361
|
+
for (let read = 0; read < counts; read++) {
|
|
362
|
+
if (removeIdx < indices.length && read === indices[removeIdx]) {
|
|
363
|
+
removeIdx++;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
map[write++] = read;
|
|
367
|
+
}
|
|
368
|
+
for (let i = 0; i < table.length; i++) {
|
|
369
|
+
const col = table[i];
|
|
370
|
+
for (let j = 0; j < map.length; j++) {
|
|
371
|
+
col[j] = col[map[j]];
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
splat.counts -= indices.length;
|
|
375
|
+
for (let i = 0; i < table.length; i++) {
|
|
376
|
+
table[i] = table[i].subarray(0, splat.counts);
|
|
377
|
+
}
|
|
378
|
+
}
|