@babylonjs/loaders 8.30.0 → 8.30.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/SPLAT/sog.d.ts +84 -0
- package/SPLAT/sog.js +295 -0
- package/SPLAT/sog.js.map +1 -0
- package/SPLAT/splatDefs.d.ts +22 -0
- package/SPLAT/splatDefs.js +11 -0
- package/SPLAT/splatDefs.js.map +1 -0
- package/SPLAT/splatFileLoader.d.ts +7 -1
- package/SPLAT/splatFileLoader.js +61 -176
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/SPLAT/splatFileLoader.metadata.d.ts +6 -0
- package/SPLAT/splatFileLoader.metadata.js +4 -0
- package/SPLAT/splatFileLoader.metadata.js.map +1 -1
- package/SPLAT/spz.d.ts +11 -0
- package/SPLAT/spz.js +177 -0
- package/SPLAT/spz.js.map +1 -0
- package/package.json +3 -3
package/SPLAT/spz.js
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/promise-function-async */
|
2
|
+
import { Scalar } from "@babylonjs/core/Maths/math.scalar.js";
|
3
|
+
/**
|
4
|
+
* Parses SPZ data and returns a promise resolving to an IParsedPLY object.
|
5
|
+
* @param data The ArrayBuffer containing SPZ data.
|
6
|
+
* @param scene The Babylon.js scene.
|
7
|
+
* @param loadingOptions Options for loading Gaussian Splatting files.
|
8
|
+
* @returns A promise resolving to the parsed SPZ data.
|
9
|
+
*/
|
10
|
+
export function ParseSpz(data, scene, loadingOptions) {
|
11
|
+
const ubuf = new Uint8Array(data);
|
12
|
+
const ubufu32 = new Uint32Array(data.slice(0, 12)); // Only need ubufu32[0] to [2]
|
13
|
+
// debug infos
|
14
|
+
const splatCount = ubufu32[2];
|
15
|
+
const shDegree = ubuf[12];
|
16
|
+
const fractionalBits = ubuf[13];
|
17
|
+
const flags = ubuf[14];
|
18
|
+
const reserved = ubuf[15];
|
19
|
+
const version = ubufu32[1];
|
20
|
+
// check magic and version
|
21
|
+
if (reserved || ubufu32[0] != 0x5053474e || (version != 2 && version != 3)) {
|
22
|
+
// reserved must be 0
|
23
|
+
return new Promise((resolve) => {
|
24
|
+
resolve({ mode: 3 /* Mode.Reject */, data: buffer, hasVertexColors: false });
|
25
|
+
});
|
26
|
+
}
|
27
|
+
const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32
|
28
|
+
const buffer = new ArrayBuffer(rowOutputLength * splatCount);
|
29
|
+
const positionScale = 1.0 / (1 << fractionalBits);
|
30
|
+
const int32View = new Int32Array(1);
|
31
|
+
const uint8View = new Uint8Array(int32View.buffer);
|
32
|
+
const read24bComponent = function (u8, offset) {
|
33
|
+
uint8View[0] = u8[offset + 0];
|
34
|
+
uint8View[1] = u8[offset + 1];
|
35
|
+
uint8View[2] = u8[offset + 2];
|
36
|
+
uint8View[3] = u8[offset + 2] & 0x80 ? 0xff : 0x00;
|
37
|
+
return int32View[0] * positionScale;
|
38
|
+
};
|
39
|
+
let byteOffset = 16;
|
40
|
+
const position = new Float32Array(buffer);
|
41
|
+
const scale = new Float32Array(buffer);
|
42
|
+
const rgba = new Uint8ClampedArray(buffer);
|
43
|
+
const rot = new Uint8ClampedArray(buffer);
|
44
|
+
let coordinateSign = 1;
|
45
|
+
let quaternionOffset = 0;
|
46
|
+
if (!loadingOptions.flipY) {
|
47
|
+
coordinateSign = -1;
|
48
|
+
quaternionOffset = 255;
|
49
|
+
}
|
50
|
+
// positions
|
51
|
+
for (let i = 0; i < splatCount; i++) {
|
52
|
+
position[i * 8 + 0] = read24bComponent(ubuf, byteOffset + 0);
|
53
|
+
position[i * 8 + 1] = coordinateSign * read24bComponent(ubuf, byteOffset + 3);
|
54
|
+
position[i * 8 + 2] = coordinateSign * read24bComponent(ubuf, byteOffset + 6);
|
55
|
+
byteOffset += 9;
|
56
|
+
}
|
57
|
+
// colors
|
58
|
+
const shC0 = 0.282;
|
59
|
+
for (let i = 0; i < splatCount; i++) {
|
60
|
+
for (let component = 0; component < 3; component++) {
|
61
|
+
const byteValue = ubuf[byteOffset + splatCount + i * 3 + component];
|
62
|
+
// 0.15 is hard coded value from spz
|
63
|
+
// Scale factor for DC color components. To convert to RGB, we should multiply by 0.282, but it can
|
64
|
+
// be useful to represent base colors that are out of range if the higher spherical harmonics bands
|
65
|
+
// bring them back into range so we multiply by a smaller value.
|
66
|
+
const value = (byteValue - 127.5) / (0.15 * 255);
|
67
|
+
rgba[i * 32 + 24 + component] = Scalar.Clamp((0.5 + shC0 * value) * 255, 0, 255);
|
68
|
+
}
|
69
|
+
rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i];
|
70
|
+
}
|
71
|
+
byteOffset += splatCount * 4;
|
72
|
+
// scales
|
73
|
+
for (let i = 0; i < splatCount; i++) {
|
74
|
+
scale[i * 8 + 3 + 0] = Math.exp(ubuf[byteOffset + 0] / 16.0 - 10.0);
|
75
|
+
scale[i * 8 + 3 + 1] = Math.exp(ubuf[byteOffset + 1] / 16.0 - 10.0);
|
76
|
+
scale[i * 8 + 3 + 2] = Math.exp(ubuf[byteOffset + 2] / 16.0 - 10.0);
|
77
|
+
byteOffset += 3;
|
78
|
+
}
|
79
|
+
// convert quaternion
|
80
|
+
if (version >= 3) {
|
81
|
+
/*
|
82
|
+
In version 3, rotations are represented as the smallest three components of the normalized rotation quaternion, for optimal rotation accuracy.
|
83
|
+
The largest component can be derived from the others and is not stored. Its index is stored on 2 bits
|
84
|
+
and each of the smallest three components is encoded as a 10-bit signed integer.
|
85
|
+
*/
|
86
|
+
const sqrt12 = Math.SQRT1_2;
|
87
|
+
for (let i = 0; i < splatCount; i++) {
|
88
|
+
const r = [ubuf[byteOffset + 0], ubuf[byteOffset + 1], ubuf[byteOffset + 2], ubuf[byteOffset + 3]];
|
89
|
+
const comp = r[0] + (r[1] << 8) + (r[2] << 16) + (r[3] << 24);
|
90
|
+
const cmask = (1 << 9) - 1;
|
91
|
+
const rotation = [];
|
92
|
+
const iLargest = comp >>> 30;
|
93
|
+
let remaining = comp;
|
94
|
+
let sumSquares = 0;
|
95
|
+
for (let i = 3; i >= 0; --i) {
|
96
|
+
if (i !== iLargest) {
|
97
|
+
const mag = remaining & cmask;
|
98
|
+
const negbit = (remaining >>> 9) & 0x1;
|
99
|
+
remaining = remaining >>> 10;
|
100
|
+
rotation[i] = sqrt12 * (mag / cmask);
|
101
|
+
if (negbit === 1) {
|
102
|
+
rotation[i] = -rotation[i];
|
103
|
+
}
|
104
|
+
// accumulate the sum of squares
|
105
|
+
sumSquares += rotation[i] * rotation[i];
|
106
|
+
}
|
107
|
+
}
|
108
|
+
const square = 1 - sumSquares;
|
109
|
+
rotation[iLargest] = Math.sqrt(Math.max(square, 0));
|
110
|
+
rotation[1] *= coordinateSign;
|
111
|
+
rotation[2] *= coordinateSign;
|
112
|
+
const shuffle = [3, 0, 1, 2]; // shuffle to match the order of the quaternion components in the splat file
|
113
|
+
for (let j = 0; j < 4; j++) {
|
114
|
+
rot[i * 32 + 28 + j] = Math.round(127.5 + rotation[shuffle[j]] * 127.5);
|
115
|
+
}
|
116
|
+
byteOffset += 4;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
else {
|
120
|
+
/*
|
121
|
+
In version 2, rotations are represented as the `(x, y, z)` components of the normalized rotation quaternion. The
|
122
|
+
`w` component can be derived from the others and is not stored. Each component is encoded as an
|
123
|
+
8-bit signed integer.
|
124
|
+
*/
|
125
|
+
for (let i = 0; i < splatCount; i++) {
|
126
|
+
const x = ubuf[byteOffset + 0];
|
127
|
+
const y = ubuf[byteOffset + 1] * coordinateSign + quaternionOffset;
|
128
|
+
const z = ubuf[byteOffset + 2] * coordinateSign + quaternionOffset;
|
129
|
+
const nx = x / 127.5 - 1;
|
130
|
+
const ny = y / 127.5 - 1;
|
131
|
+
const nz = z / 127.5 - 1;
|
132
|
+
rot[i * 32 + 28 + 1] = x;
|
133
|
+
rot[i * 32 + 28 + 2] = y;
|
134
|
+
rot[i * 32 + 28 + 3] = z;
|
135
|
+
const v = 1 - (nx * nx + ny * ny + nz * nz);
|
136
|
+
rot[i * 32 + 28 + 0] = 127.5 + Math.sqrt(v < 0 ? 0 : v) * 127.5;
|
137
|
+
byteOffset += 3;
|
138
|
+
}
|
139
|
+
}
|
140
|
+
//SH
|
141
|
+
if (shDegree) {
|
142
|
+
// shVectorCount is : 3 for dim = 1, 8 for dim = 2 and 15 for dim = 3
|
143
|
+
// number of vec3 vector needed per splat
|
144
|
+
const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color
|
145
|
+
// number of component values : 3 per vector3 (45)
|
146
|
+
const shComponentCount = shVectorCount * 3;
|
147
|
+
const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component
|
148
|
+
let shIndexRead = byteOffset;
|
149
|
+
// sh is an array of uint8array that will be used to create sh textures
|
150
|
+
const sh = [];
|
151
|
+
const engine = scene.getEngine();
|
152
|
+
const width = engine.getCaps().maxTextureSize;
|
153
|
+
const height = Math.ceil(splatCount / width);
|
154
|
+
// create array for the number of textures needed.
|
155
|
+
for (let textureIndex = 0; textureIndex < textureCount; textureIndex++) {
|
156
|
+
const texture = new Uint8Array(height * width * 4 * 4); // 4 components per texture, 4 sh per component
|
157
|
+
sh.push(texture);
|
158
|
+
}
|
159
|
+
for (let i = 0; i < splatCount; i++) {
|
160
|
+
for (let shIndexWrite = 0; shIndexWrite < shComponentCount; shIndexWrite++) {
|
161
|
+
const shValue = ubuf[shIndexRead++];
|
162
|
+
const textureIndex = Math.floor(shIndexWrite / 16);
|
163
|
+
const shArray = sh[textureIndex];
|
164
|
+
const byteIndexInTexture = shIndexWrite % 16; // [0..15]
|
165
|
+
const offsetPerSplat = i * 16; // 16 sh values per texture per splat.
|
166
|
+
shArray[byteIndexInTexture + offsetPerSplat] = shValue;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
return new Promise((resolve) => {
|
170
|
+
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, sh: sh, trainedWithAntialiasing: !!flags });
|
171
|
+
});
|
172
|
+
}
|
173
|
+
return new Promise((resolve) => {
|
174
|
+
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, trainedWithAntialiasing: !!flags });
|
175
|
+
});
|
176
|
+
}
|
177
|
+
//# sourceMappingURL=spz.js.map
|
package/SPLAT/spz.js.map
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"spz.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/spz.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/promise-function-async */\r\nimport { Scalar } from \"core/Maths/math.scalar\";\r\nimport type { Scene } from \"core/scene\";\r\nimport type { SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { Mode } from \"./splatDefs\";\r\nimport type { IParsedPLY } from \"./splatDefs\";\r\n\r\n/**\r\n * Parses SPZ data and returns a promise resolving to an IParsedPLY object.\r\n * @param data The ArrayBuffer containing SPZ data.\r\n * @param scene The Babylon.js scene.\r\n * @param loadingOptions Options for loading Gaussian Splatting files.\r\n * @returns A promise resolving to the parsed SPZ data.\r\n */\r\nexport function ParseSpz(data: ArrayBuffer, scene: Scene, loadingOptions: SPLATLoadingOptions): Promise<IParsedPLY> {\r\n const ubuf = new Uint8Array(data);\r\n const ubufu32 = new Uint32Array(data.slice(0, 12)); // Only need ubufu32[0] to [2]\r\n // debug infos\r\n const splatCount = ubufu32[2];\r\n\r\n const shDegree = ubuf[12];\r\n const fractionalBits = ubuf[13];\r\n const flags = ubuf[14];\r\n const reserved = ubuf[15];\r\n const version = ubufu32[1];\r\n\r\n // check magic and version\r\n if (reserved || ubufu32[0] != 0x5053474e || (version != 2 && version != 3)) {\r\n // reserved must be 0\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Reject, data: buffer, hasVertexColors: false });\r\n });\r\n }\r\n\r\n const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32\r\n const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n\r\n const positionScale = 1.0 / (1 << fractionalBits);\r\n\r\n const int32View = new Int32Array(1);\r\n const uint8View = new Uint8Array(int32View.buffer);\r\n const read24bComponent = function (u8: Uint8Array, offset: number) {\r\n uint8View[0] = u8[offset + 0];\r\n uint8View[1] = u8[offset + 1];\r\n uint8View[2] = u8[offset + 2];\r\n uint8View[3] = u8[offset + 2] & 0x80 ? 0xff : 0x00;\r\n return int32View[0] * positionScale;\r\n };\r\n\r\n let byteOffset = 16;\r\n\r\n const position = new Float32Array(buffer);\r\n const scale = new Float32Array(buffer);\r\n const rgba = new Uint8ClampedArray(buffer);\r\n const rot = new Uint8ClampedArray(buffer);\r\n\r\n let coordinateSign = 1;\r\n let quaternionOffset = 0;\r\n if (!loadingOptions.flipY) {\r\n coordinateSign = -1;\r\n quaternionOffset = 255;\r\n }\r\n // positions\r\n for (let i = 0; i < splatCount; i++) {\r\n position[i * 8 + 0] = read24bComponent(ubuf, byteOffset + 0);\r\n position[i * 8 + 1] = coordinateSign * read24bComponent(ubuf, byteOffset + 3);\r\n position[i * 8 + 2] = coordinateSign * read24bComponent(ubuf, byteOffset + 6);\r\n byteOffset += 9;\r\n }\r\n\r\n // colors\r\n const shC0 = 0.282;\r\n for (let i = 0; i < splatCount; i++) {\r\n for (let component = 0; component < 3; component++) {\r\n const byteValue = ubuf[byteOffset + splatCount + i * 3 + component];\r\n // 0.15 is hard coded value from spz\r\n // Scale factor for DC color components. To convert to RGB, we should multiply by 0.282, but it can\r\n // be useful to represent base colors that are out of range if the higher spherical harmonics bands\r\n // bring them back into range so we multiply by a smaller value.\r\n const value = (byteValue - 127.5) / (0.15 * 255);\r\n rgba[i * 32 + 24 + component] = Scalar.Clamp((0.5 + shC0 * value) * 255, 0, 255);\r\n }\r\n\r\n rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i];\r\n }\r\n byteOffset += splatCount * 4;\r\n\r\n // scales\r\n for (let i = 0; i < splatCount; i++) {\r\n scale[i * 8 + 3 + 0] = Math.exp(ubuf[byteOffset + 0] / 16.0 - 10.0);\r\n scale[i * 8 + 3 + 1] = Math.exp(ubuf[byteOffset + 1] / 16.0 - 10.0);\r\n scale[i * 8 + 3 + 2] = Math.exp(ubuf[byteOffset + 2] / 16.0 - 10.0);\r\n byteOffset += 3;\r\n }\r\n\r\n // convert quaternion\r\n if (version >= 3) {\r\n /*\r\n In version 3, rotations are represented as the smallest three components of the normalized rotation quaternion, for optimal rotation accuracy.\r\n The largest component can be derived from the others and is not stored. Its index is stored on 2 bits\r\n and each of the smallest three components is encoded as a 10-bit signed integer.\r\n */\r\n const sqrt12 = Math.SQRT1_2;\r\n for (let i = 0; i < splatCount; i++) {\r\n const r = [ubuf[byteOffset + 0], ubuf[byteOffset + 1], ubuf[byteOffset + 2], ubuf[byteOffset + 3]];\r\n\r\n const comp = r[0] + (r[1] << 8) + (r[2] << 16) + (r[3] << 24);\r\n\r\n const cmask = (1 << 9) - 1;\r\n const rotation = [];\r\n const iLargest = comp >>> 30;\r\n let remaining = comp;\r\n let sumSquares = 0;\r\n\r\n for (let i = 3; i >= 0; --i) {\r\n if (i !== iLargest) {\r\n const mag = remaining & cmask;\r\n const negbit = (remaining >>> 9) & 0x1;\r\n remaining = remaining >>> 10;\r\n\r\n rotation[i] = sqrt12 * (mag / cmask);\r\n if (negbit === 1) {\r\n rotation[i] = -rotation[i];\r\n }\r\n\r\n // accumulate the sum of squares\r\n sumSquares += rotation[i] * rotation[i];\r\n }\r\n }\r\n\r\n const square = 1 - sumSquares;\r\n rotation[iLargest] = Math.sqrt(Math.max(square, 0));\r\n\r\n rotation[1] *= coordinateSign;\r\n rotation[2] *= coordinateSign;\r\n\r\n const shuffle = [3, 0, 1, 2]; // shuffle to match the order of the quaternion components in the splat file\r\n for (let j = 0; j < 4; j++) {\r\n rot[i * 32 + 28 + j] = Math.round(127.5 + rotation[shuffle[j]] * 127.5);\r\n }\r\n\r\n byteOffset += 4;\r\n }\r\n } else {\r\n /*\r\n In version 2, rotations are represented as the `(x, y, z)` components of the normalized rotation quaternion. The\r\n `w` component can be derived from the others and is not stored. Each component is encoded as an\r\n 8-bit signed integer.\r\n */\r\n for (let i = 0; i < splatCount; i++) {\r\n const x = ubuf[byteOffset + 0];\r\n const y = ubuf[byteOffset + 1] * coordinateSign + quaternionOffset;\r\n const z = ubuf[byteOffset + 2] * coordinateSign + quaternionOffset;\r\n const nx = x / 127.5 - 1;\r\n const ny = y / 127.5 - 1;\r\n const nz = z / 127.5 - 1;\r\n rot[i * 32 + 28 + 1] = x;\r\n rot[i * 32 + 28 + 2] = y;\r\n rot[i * 32 + 28 + 3] = z;\r\n const v = 1 - (nx * nx + ny * ny + nz * nz);\r\n rot[i * 32 + 28 + 0] = 127.5 + Math.sqrt(v < 0 ? 0 : v) * 127.5;\r\n\r\n byteOffset += 3;\r\n }\r\n }\r\n\r\n //SH\r\n if (shDegree) {\r\n // shVectorCount is : 3 for dim = 1, 8 for dim = 2 and 15 for dim = 3\r\n // number of vec3 vector needed per splat\r\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color\r\n // number of component values : 3 per vector3 (45)\r\n const shComponentCount = shVectorCount * 3;\r\n\r\n const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component\r\n let shIndexRead = byteOffset;\r\n\r\n // sh is an array of uint8array that will be used to create sh textures\r\n const sh: Uint8Array[] = [];\r\n\r\n const engine = scene.getEngine();\r\n const width = engine.getCaps().maxTextureSize;\r\n const height = Math.ceil(splatCount / width);\r\n // create array for the number of textures needed.\r\n for (let textureIndex = 0; textureIndex < textureCount; textureIndex++) {\r\n const texture = new Uint8Array(height * width * 4 * 4); // 4 components per texture, 4 sh per component\r\n sh.push(texture);\r\n }\r\n\r\n for (let i = 0; i < splatCount; i++) {\r\n for (let shIndexWrite = 0; shIndexWrite < shComponentCount; shIndexWrite++) {\r\n const shValue = ubuf[shIndexRead++];\r\n\r\n const textureIndex = Math.floor(shIndexWrite / 16);\r\n const shArray = sh[textureIndex];\r\n\r\n const byteIndexInTexture = shIndexWrite % 16; // [0..15]\r\n const offsetPerSplat = i * 16; // 16 sh values per texture per splat.\r\n shArray[byteIndexInTexture + offsetPerSplat] = shValue;\r\n }\r\n }\r\n\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false, sh: sh, trainedWithAntialiasing: !!flags });\r\n });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false, trainedWithAntialiasing: !!flags });\r\n });\r\n}\r\n"]}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@babylonjs/loaders",
|
3
|
-
"version": "8.30.
|
3
|
+
"version": "8.30.2",
|
4
4
|
"main": "index.js",
|
5
5
|
"module": "index.js",
|
6
6
|
"types": "index.d.ts",
|
@@ -18,10 +18,10 @@
|
|
18
18
|
"postcompile": "build-tools -c add-js-to-es6"
|
19
19
|
},
|
20
20
|
"devDependencies": {
|
21
|
-
"@babylonjs/core": "^8.30.
|
21
|
+
"@babylonjs/core": "^8.30.2",
|
22
22
|
"@dev/build-tools": "^1.0.0",
|
23
23
|
"@lts/loaders": "^1.0.0",
|
24
|
-
"babylonjs-gltf2interface": "^8.30.
|
24
|
+
"babylonjs-gltf2interface": "^8.30.2"
|
25
25
|
},
|
26
26
|
"peerDependencies": {
|
27
27
|
"@babylonjs/core": "^8.0.0",
|