@babylonjs/loaders 9.2.1 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OBJ/solidParser.js +1 -1
- package/OBJ/solidParser.js.map +1 -1
- package/SPLAT/sog.js +3 -3
- package/SPLAT/sog.js.map +1 -1
- package/SPLAT/splatDefs.d.ts +1 -0
- package/SPLAT/splatDefs.js.map +1 -1
- package/SPLAT/splatFileLoader.js +50 -23
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/SPLAT/splatLoadingOptions.d.ts +11 -0
- package/SPLAT/splatLoadingOptions.js.map +1 -1
- package/SPLAT/spz.d.ts +37 -3
- package/SPLAT/spz.js +175 -12
- package/SPLAT/spz.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js +5 -3
- package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js.map +1 -1
- package/package.json +3 -3
package/SPLAT/spz.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/promise-function-async */
|
|
2
2
|
import { Scalar } from "@babylonjs/core/Maths/math.scalar.js";
|
|
3
|
+
import { runCoroutineAsync, createYieldingScheduler } from "@babylonjs/core/Misc/coroutine.js";
|
|
4
|
+
import { _LoadScriptModuleAsync } from "@babylonjs/core/Misc/tools.internals.js";
|
|
5
|
+
const _SpzConversionBatchSize = 32768;
|
|
6
|
+
const _SH_C0 = 0.28209479177387814;
|
|
7
|
+
// Cached WASM module promise — initialized once, reused across all SPZ loads.
|
|
8
|
+
let _SpzModulePromise = null;
|
|
9
|
+
let _SpzModuleUrl = null;
|
|
3
10
|
/**
|
|
4
|
-
* Parses SPZ data and returns a promise resolving to an
|
|
11
|
+
* Parses SPZ data and returns a promise resolving to an IParsedSplat object.
|
|
5
12
|
* @param data The ArrayBuffer containing SPZ data.
|
|
6
13
|
* @param scene The Babylon.js scene.
|
|
7
|
-
* @param
|
|
14
|
+
* @param _loadingOptions Options for loading Gaussian Splatting files.
|
|
8
15
|
* @returns A promise resolving to the parsed SPZ data.
|
|
9
16
|
*/
|
|
10
|
-
export function ParseSpz(data, scene,
|
|
17
|
+
export function ParseSpz(data, scene, _loadingOptions) {
|
|
11
18
|
const ubuf = new Uint8Array(data);
|
|
12
19
|
const ubufu32 = new Uint32Array(data.slice(0, 12)); // Only need ubufu32[0] to [2]
|
|
13
20
|
// debug infos
|
|
@@ -18,10 +25,10 @@ export function ParseSpz(data, scene, loadingOptions) {
|
|
|
18
25
|
const reserved = ubuf[15];
|
|
19
26
|
const version = ubufu32[1];
|
|
20
27
|
// check magic and version
|
|
21
|
-
if (reserved || ubufu32[0] != 0x5053474e ||
|
|
28
|
+
if (reserved || ubufu32[0] != 0x5053474e || version < 2 || version > 4) {
|
|
22
29
|
// reserved must be 0
|
|
23
30
|
return new Promise((resolve) => {
|
|
24
|
-
resolve({ mode: 3 /* Mode.Reject */, data:
|
|
31
|
+
resolve({ mode: 3 /* Mode.Reject */, data: new ArrayBuffer(0), hasVertexColors: false });
|
|
25
32
|
});
|
|
26
33
|
}
|
|
27
34
|
const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32
|
|
@@ -49,7 +56,6 @@ export function ParseSpz(data, scene, loadingOptions) {
|
|
|
49
56
|
byteOffset += 9;
|
|
50
57
|
}
|
|
51
58
|
// colors
|
|
52
|
-
const shC0 = 0.282;
|
|
53
59
|
for (let i = 0; i < splatCount; i++) {
|
|
54
60
|
for (let component = 0; component < 3; component++) {
|
|
55
61
|
const byteValue = ubuf[byteOffset + splatCount + i * 3 + component];
|
|
@@ -58,7 +64,7 @@ export function ParseSpz(data, scene, loadingOptions) {
|
|
|
58
64
|
// be useful to represent base colors that are out of range if the higher spherical harmonics bands
|
|
59
65
|
// bring them back into range so we multiply by a smaller value.
|
|
60
66
|
const value = (byteValue - 127.5) / (0.15 * 255);
|
|
61
|
-
rgba[i * 32 + 24 + component] = Scalar.Clamp((0.5 +
|
|
67
|
+
rgba[i * 32 + 24 + component] = Scalar.Clamp((0.5 + _SH_C0 * value) * 255, 0, 255);
|
|
62
68
|
}
|
|
63
69
|
rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i];
|
|
64
70
|
}
|
|
@@ -129,12 +135,12 @@ export function ParseSpz(data, scene, loadingOptions) {
|
|
|
129
135
|
byteOffset += 3;
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
|
-
//SH
|
|
138
|
+
// SH
|
|
133
139
|
if (shDegree) {
|
|
134
|
-
// shVectorCount is : 3 for
|
|
135
|
-
// number of vec3
|
|
140
|
+
// shVectorCount is : 3 for degree 1, 8 for degree 2, 15 for degree 3, 24 for degree 4
|
|
141
|
+
// number of vec3 vectors needed per splat
|
|
136
142
|
const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color
|
|
137
|
-
// number of component values
|
|
143
|
+
// number of scalar component values: 3 per vec3
|
|
138
144
|
const shComponentCount = shVectorCount * 3;
|
|
139
145
|
const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component
|
|
140
146
|
let shIndexRead = byteOffset;
|
|
@@ -159,11 +165,168 @@ export function ParseSpz(data, scene, loadingOptions) {
|
|
|
159
165
|
}
|
|
160
166
|
}
|
|
161
167
|
return new Promise((resolve) => {
|
|
162
|
-
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, sh: sh, trainedWithAntialiasing: !!flags });
|
|
168
|
+
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, sh: sh, shDegree: shDegree, trainedWithAntialiasing: !!flags });
|
|
163
169
|
});
|
|
164
170
|
}
|
|
165
171
|
return new Promise((resolve) => {
|
|
166
172
|
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, trainedWithAntialiasing: !!flags });
|
|
167
173
|
});
|
|
168
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns the initialized spz WASM module loaded from the given URL, loading it on first call.
|
|
177
|
+
* @param url URL to the spz WASM ES module (its default export should be a factory function)
|
|
178
|
+
* @returns A promise resolving to the initialized spz WASM module
|
|
179
|
+
*/
|
|
180
|
+
export async function GetSpzModule(url) {
|
|
181
|
+
if (_SpzModulePromise && _SpzModuleUrl === url) {
|
|
182
|
+
return await _SpzModulePromise;
|
|
183
|
+
}
|
|
184
|
+
const spzModulePromise = _LoadScriptModuleAsync(`import createSpzModule from '${url}';
|
|
185
|
+
const module = await createSpzModule();
|
|
186
|
+
const returnedValue = module;`);
|
|
187
|
+
_SpzModuleUrl = url;
|
|
188
|
+
_SpzModulePromise = spzModulePromise;
|
|
189
|
+
return await spzModulePromise;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Converts a GaussianCloud object (from the spz WASM module) into the packed 32-byte-per-splat
|
|
193
|
+
* ArrayBuffer and SH texture arrays expected by GaussianSplattingMeshBase.updateData.
|
|
194
|
+
*
|
|
195
|
+
* Packed layout per splat (32 bytes):
|
|
196
|
+
* [0-11] position xyz (float32 x3)
|
|
197
|
+
* [12-23] scale xyz (float32 x3)
|
|
198
|
+
* [24-27] color RGBA (uint8 x4, colors in [0,255], alpha in [0,255])
|
|
199
|
+
* [28-31] quaternion wxyz (uint8 x4, encoded as q * 127.5 + 127.5)
|
|
200
|
+
*
|
|
201
|
+
* SH coefficients from the cloud (Float32, range ~[-1,1]) are encoded to bytes
|
|
202
|
+
* using the SPZ convention (load-spz.cc unquantizeSH): byte = coeff * 128 + 128.
|
|
203
|
+
*
|
|
204
|
+
* @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer
|
|
205
|
+
* @param scene The Babylon.js scene (used to query maxTextureSize for SH textures)
|
|
206
|
+
* @param useCoroutine If true, yields periodically to avoid blocking the main thread
|
|
207
|
+
* @returns A coroutine returning an IParsedSplat ready to be passed to updateData
|
|
208
|
+
*/
|
|
209
|
+
export function* ConvertSpzToSplat(cloud, scene, useCoroutine = false) {
|
|
210
|
+
const splatCount = cloud.numPoints;
|
|
211
|
+
const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32 bytes
|
|
212
|
+
const buffer = new ArrayBuffer(rowOutputLength * splatCount);
|
|
213
|
+
const fBuffer = new Float32Array(buffer);
|
|
214
|
+
const uBuffer = new Uint8Array(buffer);
|
|
215
|
+
const positions = cloud.positions;
|
|
216
|
+
const scales = cloud.scales;
|
|
217
|
+
const colors = cloud.colors;
|
|
218
|
+
const alphas = cloud.alphas;
|
|
219
|
+
const rotations = cloud.rotations;
|
|
220
|
+
// Build SH texture arrays upfront so both main and SH data can be written in a single pass
|
|
221
|
+
let sh = null;
|
|
222
|
+
const shDegree = cloud.shDegree;
|
|
223
|
+
let cloudSh = null;
|
|
224
|
+
let shComponentCount = 0;
|
|
225
|
+
let chunkStarts = null;
|
|
226
|
+
let chunkEnds = null;
|
|
227
|
+
let shArrays = null;
|
|
228
|
+
if (shDegree > 0 && cloud.sh.length > 0) {
|
|
229
|
+
const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;
|
|
230
|
+
shComponentCount = shVectorCount * 3;
|
|
231
|
+
const textureCount = Math.ceil(shComponentCount / 16);
|
|
232
|
+
const engine = scene.getEngine();
|
|
233
|
+
const width = engine.getCaps().maxTextureSize;
|
|
234
|
+
const height = Math.ceil(splatCount / width);
|
|
235
|
+
sh = [];
|
|
236
|
+
for (let t = 0; t < textureCount; t++) {
|
|
237
|
+
sh.push(new Uint8Array(height * width * 4 * 4));
|
|
238
|
+
}
|
|
239
|
+
// Precompute chunk start/end and hoist texture references out of the per-splat loop
|
|
240
|
+
chunkStarts = new Int32Array(textureCount);
|
|
241
|
+
chunkEnds = new Int32Array(textureCount);
|
|
242
|
+
for (let t = 0; t < textureCount; t++) {
|
|
243
|
+
chunkStarts[t] = t * 16;
|
|
244
|
+
chunkEnds[t] = Math.min((t + 1) * 16, shComponentCount);
|
|
245
|
+
}
|
|
246
|
+
shArrays = sh;
|
|
247
|
+
cloudSh = cloud.sh;
|
|
248
|
+
}
|
|
249
|
+
// Single pass: write packed splat data and SH textures together to halve iteration count
|
|
250
|
+
for (let i = 0; i < splatCount; i++) {
|
|
251
|
+
const fBase = i * 8;
|
|
252
|
+
const uBase = i * 32;
|
|
253
|
+
const p = i * 3;
|
|
254
|
+
const r = i * 4;
|
|
255
|
+
// Position (float32 x3, bytes 0-11)
|
|
256
|
+
fBuffer[fBase + 0] = positions[p + 0];
|
|
257
|
+
fBuffer[fBase + 1] = positions[p + 1];
|
|
258
|
+
fBuffer[fBase + 2] = positions[p + 2];
|
|
259
|
+
// Scale (float32 x3, bytes 12-23) — cloud scales are in log space, convert to linear
|
|
260
|
+
fBuffer[fBase + 3] = Math.exp(scales[p + 0]);
|
|
261
|
+
fBuffer[fBase + 4] = Math.exp(scales[p + 1]);
|
|
262
|
+
fBuffer[fBase + 5] = Math.exp(scales[p + 2]);
|
|
263
|
+
// Color RGB: cloud gives raw SH DC coefficients, convert to [0,255] display value
|
|
264
|
+
const c0 = (0.5 + _SH_C0 * colors[p + 0]) * 255;
|
|
265
|
+
const c1 = (0.5 + _SH_C0 * colors[p + 1]) * 255;
|
|
266
|
+
const c2 = (0.5 + _SH_C0 * colors[p + 2]) * 255;
|
|
267
|
+
uBuffer[uBase + 24] = c0 <= 0 ? 0 : c0 >= 255 ? 255 : (c0 + 0.5) | 0;
|
|
268
|
+
uBuffer[uBase + 25] = c1 <= 0 ? 0 : c1 >= 255 ? 255 : (c1 + 0.5) | 0;
|
|
269
|
+
uBuffer[uBase + 26] = c2 <= 0 ? 0 : c2 >= 255 ? 255 : (c2 + 0.5) | 0;
|
|
270
|
+
// Alpha: cloud gives raw logit opacity, apply sigmoid to get [0,255]
|
|
271
|
+
uBuffer[uBase + 27] = ((1.0 / (1.0 + Math.exp(-alphas[i]))) * 255 + 0.5) | 0;
|
|
272
|
+
// Rotation: cloud is xyzw, packed buffer expects wxyz
|
|
273
|
+
const rw = rotations[r + 3] * 127.5 + 127.5;
|
|
274
|
+
const rx = rotations[r + 0] * 127.5 + 127.5;
|
|
275
|
+
const ry = rotations[r + 1] * 127.5 + 127.5;
|
|
276
|
+
const rz = rotations[r + 2] * 127.5 + 127.5;
|
|
277
|
+
uBuffer[uBase + 28] = rw <= 0 ? 0 : rw >= 255 ? 255 : (rw + 0.5) | 0; // w
|
|
278
|
+
uBuffer[uBase + 29] = rx <= 0 ? 0 : rx >= 255 ? 255 : (rx + 0.5) | 0; // x
|
|
279
|
+
uBuffer[uBase + 30] = ry <= 0 ? 0 : ry >= 255 ? 255 : (ry + 0.5) | 0; // y
|
|
280
|
+
uBuffer[uBase + 31] = rz <= 0 ? 0 : rz >= 255 ? 255 : (rz + 0.5) | 0; // z
|
|
281
|
+
// SH: process all texture chunks for this splat in the same iteration
|
|
282
|
+
if (cloudSh && shArrays && chunkStarts && chunkEnds) {
|
|
283
|
+
const shSplatBase = i * shComponentCount;
|
|
284
|
+
const offsetPerSplat = i * 16;
|
|
285
|
+
for (let t = 0; t < shArrays.length; t++) {
|
|
286
|
+
const shT = shArrays[t];
|
|
287
|
+
const chunkStart = chunkStarts[t];
|
|
288
|
+
const chunkEnd = chunkEnds[t];
|
|
289
|
+
for (let j = chunkStart; j < chunkEnd; j++) {
|
|
290
|
+
const v = cloudSh[shSplatBase + j] * 128.0 + 128.0;
|
|
291
|
+
shT[offsetPerSplat + j - chunkStart] = v <= 0 ? 0 : v >= 255 ? 255 : (v + 0.5) | 0;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (i % _SpzConversionBatchSize === 0 && useCoroutine) {
|
|
296
|
+
yield;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// Extract safe-orbit-camera extension if present
|
|
300
|
+
let safeOrbitCameraRadiusMin;
|
|
301
|
+
let safeOrbitCameraElevationMinMax;
|
|
302
|
+
if (cloud.extensions) {
|
|
303
|
+
for (const ext of cloud.extensions) {
|
|
304
|
+
const safeOrbitExt = ext;
|
|
305
|
+
if (safeOrbitExt.safeOrbitRadiusMin !== undefined) {
|
|
306
|
+
safeOrbitCameraRadiusMin = safeOrbitExt.safeOrbitRadiusMin;
|
|
307
|
+
safeOrbitCameraElevationMinMax = [safeOrbitExt.safeOrbitElevationMin, safeOrbitExt.safeOrbitElevationMax];
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
mode: 0 /* Mode.Splat */,
|
|
314
|
+
data: buffer,
|
|
315
|
+
hasVertexColors: false,
|
|
316
|
+
sh: sh !== null ? sh : undefined,
|
|
317
|
+
shDegree: shDegree > 0 ? shDegree : undefined,
|
|
318
|
+
trainedWithAntialiasing: !!cloud.antialiased,
|
|
319
|
+
safeOrbitCameraRadiusMin,
|
|
320
|
+
safeOrbitCameraElevationMinMax,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Async version of ConvertSpzToSplat that yields periodically to avoid blocking the main thread.
|
|
325
|
+
* @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer
|
|
326
|
+
* @param scene The Babylon.js scene
|
|
327
|
+
* @returns A promise resolving to an IParsedSplat
|
|
328
|
+
*/
|
|
329
|
+
export async function ConvertSpzToSplatAsync(cloud, scene) {
|
|
330
|
+
return await runCoroutineAsync(ConvertSpzToSplat(cloud, scene, true), createYieldingScheduler());
|
|
331
|
+
}
|
|
169
332
|
//# sourceMappingURL=spz.js.map
|
package/SPLAT/spz.js.map
CHANGED
|
@@ -1 +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, type IParsedSplat } 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<IParsedSplat> {\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 // 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] = read24bComponent(ubuf, byteOffset + 3);\r\n position[i * 8 + 2] = 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 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];\r\n const z = ubuf[byteOffset + 2];\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"]}
|
|
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 { runCoroutineAsync, createYieldingScheduler, type Coroutine } from \"core/Misc/coroutine\";\r\nimport { _LoadScriptModuleAsync } from \"core/Misc/tools.internals\";\r\nimport { type SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { Mode, type IParsedSplat } from \"./splatDefs\";\r\nimport { type GaussianCloud, type SpzModule, type SpzExtensionSafeOrbitCameraAdobe } from \"@adobe/spz\";\r\n\r\nconst _SpzConversionBatchSize = 32768;\r\nconst _SH_C0 = 0.28209479177387814;\r\n\r\n// Cached WASM module promise — initialized once, reused across all SPZ loads.\r\nlet _SpzModulePromise: Promise<SpzModule> | null = null;\r\nlet _SpzModuleUrl: string | null = null;\r\n\r\n/**\r\n * Parses SPZ data and returns a promise resolving to an IParsedSplat 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<IParsedSplat> {\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 > 4) {\r\n // reserved must be 0\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Reject, data: new ArrayBuffer(0), 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 // 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] = read24bComponent(ubuf, byteOffset + 3);\r\n position[i * 8 + 2] = read24bComponent(ubuf, byteOffset + 6);\r\n byteOffset += 9;\r\n }\r\n\r\n // colors\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 + _SH_C0 * 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 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];\r\n const z = ubuf[byteOffset + 2];\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 degree 1, 8 for degree 2, 15 for degree 3, 24 for degree 4\r\n // number of vec3 vectors needed per splat\r\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color\r\n // number of scalar component values: 3 per vec3\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, shDegree: shDegree, 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\r\n/**\r\n * Returns the initialized spz WASM module loaded from the given URL, loading it on first call.\r\n * @param url URL to the spz WASM ES module (its default export should be a factory function)\r\n * @returns A promise resolving to the initialized spz WASM module\r\n */\r\nexport async function GetSpzModule(url: string): Promise<SpzModule> {\r\n if (_SpzModulePromise && _SpzModuleUrl === url) {\r\n return await _SpzModulePromise;\r\n }\r\n\r\n const spzModulePromise = _LoadScriptModuleAsync(\r\n `import createSpzModule from '${url}';\r\n const module = await createSpzModule();\r\n const returnedValue = module;`\r\n );\r\n\r\n _SpzModuleUrl = url;\r\n _SpzModulePromise = spzModulePromise;\r\n\r\n return await spzModulePromise;\r\n}\r\n\r\n/**\r\n * Converts a GaussianCloud object (from the spz WASM module) into the packed 32-byte-per-splat\r\n * ArrayBuffer and SH texture arrays expected by GaussianSplattingMeshBase.updateData.\r\n *\r\n * Packed layout per splat (32 bytes):\r\n * [0-11] position xyz (float32 x3)\r\n * [12-23] scale xyz (float32 x3)\r\n * [24-27] color RGBA (uint8 x4, colors in [0,255], alpha in [0,255])\r\n * [28-31] quaternion wxyz (uint8 x4, encoded as q * 127.5 + 127.5)\r\n *\r\n * SH coefficients from the cloud (Float32, range ~[-1,1]) are encoded to bytes\r\n * using the SPZ convention (load-spz.cc unquantizeSH): byte = coeff * 128 + 128.\r\n *\r\n * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer\r\n * @param scene The Babylon.js scene (used to query maxTextureSize for SH textures)\r\n * @param useCoroutine If true, yields periodically to avoid blocking the main thread\r\n * @returns A coroutine returning an IParsedSplat ready to be passed to updateData\r\n */\r\nexport function* ConvertSpzToSplat(cloud: GaussianCloud, scene: Scene, useCoroutine = false): Coroutine<IParsedSplat> {\r\n const splatCount: number = cloud.numPoints;\r\n const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32 bytes\r\n const buffer = new ArrayBuffer(rowOutputLength * splatCount);\r\n const fBuffer = new Float32Array(buffer);\r\n const uBuffer = new Uint8Array(buffer);\r\n\r\n const positions: Float32Array = cloud.positions;\r\n const scales: Float32Array = cloud.scales;\r\n const colors: Float32Array = cloud.colors;\r\n const alphas: Float32Array = cloud.alphas;\r\n const rotations: Float32Array = cloud.rotations;\r\n\r\n // Build SH texture arrays upfront so both main and SH data can be written in a single pass\r\n let sh: Uint8Array[] | null = null;\r\n const shDegree: number = cloud.shDegree;\r\n let cloudSh: Float32Array | null = null;\r\n let shComponentCount = 0;\r\n let chunkStarts: Int32Array | null = null;\r\n let chunkEnds: Int32Array | null = null;\r\n let shArrays: Uint8Array[] | null = null;\r\n\r\n if (shDegree > 0 && cloud.sh.length > 0) {\r\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\r\n shComponentCount = shVectorCount * 3;\r\n const textureCount = Math.ceil(shComponentCount / 16);\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 sh = [];\r\n for (let t = 0; t < textureCount; t++) {\r\n sh.push(new Uint8Array(height * width * 4 * 4));\r\n }\r\n\r\n // Precompute chunk start/end and hoist texture references out of the per-splat loop\r\n chunkStarts = new Int32Array(textureCount);\r\n chunkEnds = new Int32Array(textureCount);\r\n for (let t = 0; t < textureCount; t++) {\r\n chunkStarts[t] = t * 16;\r\n chunkEnds[t] = Math.min((t + 1) * 16, shComponentCount);\r\n }\r\n shArrays = sh;\r\n cloudSh = cloud.sh;\r\n }\r\n\r\n // Single pass: write packed splat data and SH textures together to halve iteration count\r\n for (let i = 0; i < splatCount; i++) {\r\n const fBase = i * 8;\r\n const uBase = i * 32;\r\n const p = i * 3;\r\n const r = i * 4;\r\n\r\n // Position (float32 x3, bytes 0-11)\r\n fBuffer[fBase + 0] = positions[p + 0];\r\n fBuffer[fBase + 1] = positions[p + 1];\r\n fBuffer[fBase + 2] = positions[p + 2];\r\n\r\n // Scale (float32 x3, bytes 12-23) — cloud scales are in log space, convert to linear\r\n fBuffer[fBase + 3] = Math.exp(scales[p + 0]);\r\n fBuffer[fBase + 4] = Math.exp(scales[p + 1]);\r\n fBuffer[fBase + 5] = Math.exp(scales[p + 2]);\r\n\r\n // Color RGB: cloud gives raw SH DC coefficients, convert to [0,255] display value\r\n const c0 = (0.5 + _SH_C0 * colors[p + 0]) * 255;\r\n const c1 = (0.5 + _SH_C0 * colors[p + 1]) * 255;\r\n const c2 = (0.5 + _SH_C0 * colors[p + 2]) * 255;\r\n uBuffer[uBase + 24] = c0 <= 0 ? 0 : c0 >= 255 ? 255 : (c0 + 0.5) | 0;\r\n uBuffer[uBase + 25] = c1 <= 0 ? 0 : c1 >= 255 ? 255 : (c1 + 0.5) | 0;\r\n uBuffer[uBase + 26] = c2 <= 0 ? 0 : c2 >= 255 ? 255 : (c2 + 0.5) | 0;\r\n // Alpha: cloud gives raw logit opacity, apply sigmoid to get [0,255]\r\n uBuffer[uBase + 27] = ((1.0 / (1.0 + Math.exp(-alphas[i]))) * 255 + 0.5) | 0;\r\n\r\n // Rotation: cloud is xyzw, packed buffer expects wxyz\r\n const rw = rotations[r + 3] * 127.5 + 127.5;\r\n const rx = rotations[r + 0] * 127.5 + 127.5;\r\n const ry = rotations[r + 1] * 127.5 + 127.5;\r\n const rz = rotations[r + 2] * 127.5 + 127.5;\r\n uBuffer[uBase + 28] = rw <= 0 ? 0 : rw >= 255 ? 255 : (rw + 0.5) | 0; // w\r\n uBuffer[uBase + 29] = rx <= 0 ? 0 : rx >= 255 ? 255 : (rx + 0.5) | 0; // x\r\n uBuffer[uBase + 30] = ry <= 0 ? 0 : ry >= 255 ? 255 : (ry + 0.5) | 0; // y\r\n uBuffer[uBase + 31] = rz <= 0 ? 0 : rz >= 255 ? 255 : (rz + 0.5) | 0; // z\r\n\r\n // SH: process all texture chunks for this splat in the same iteration\r\n if (cloudSh && shArrays && chunkStarts && chunkEnds) {\r\n const shSplatBase = i * shComponentCount;\r\n const offsetPerSplat = i * 16;\r\n for (let t = 0; t < shArrays.length; t++) {\r\n const shT = shArrays[t];\r\n const chunkStart = chunkStarts[t];\r\n const chunkEnd = chunkEnds[t];\r\n for (let j = chunkStart; j < chunkEnd; j++) {\r\n const v = cloudSh[shSplatBase + j] * 128.0 + 128.0;\r\n shT[offsetPerSplat + j - chunkStart] = v <= 0 ? 0 : v >= 255 ? 255 : (v + 0.5) | 0;\r\n }\r\n }\r\n }\r\n\r\n if (i % _SpzConversionBatchSize === 0 && useCoroutine) {\r\n yield;\r\n }\r\n }\r\n\r\n // Extract safe-orbit-camera extension if present\r\n let safeOrbitCameraRadiusMin: number | undefined;\r\n let safeOrbitCameraElevationMinMax: [number, number] | undefined;\r\n if (cloud.extensions) {\r\n for (const ext of cloud.extensions) {\r\n const safeOrbitExt = ext as SpzExtensionSafeOrbitCameraAdobe;\r\n if (safeOrbitExt.safeOrbitRadiusMin !== undefined) {\r\n safeOrbitCameraRadiusMin = safeOrbitExt.safeOrbitRadiusMin;\r\n safeOrbitCameraElevationMinMax = [safeOrbitExt.safeOrbitElevationMin, safeOrbitExt.safeOrbitElevationMax];\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n mode: Mode.Splat,\r\n data: buffer,\r\n hasVertexColors: false,\r\n sh: sh !== null ? sh : undefined,\r\n shDegree: shDegree > 0 ? shDegree : undefined,\r\n trainedWithAntialiasing: !!cloud.antialiased,\r\n safeOrbitCameraRadiusMin,\r\n safeOrbitCameraElevationMinMax,\r\n };\r\n}\r\n\r\n/**\r\n * Async version of ConvertSpzToSplat that yields periodically to avoid blocking the main thread.\r\n * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer\r\n * @param scene The Babylon.js scene\r\n * @returns A promise resolving to an IParsedSplat\r\n */\r\nexport async function ConvertSpzToSplatAsync(cloud: any, scene: Scene): Promise<IParsedSplat> {\r\n return await runCoroutineAsync(ConvertSpzToSplat(cloud, scene, true), createYieldingScheduler());\r\n}\r\n"]}
|
|
@@ -6,11 +6,13 @@ import { RichTypeAny } from "@babylonjs/core/FlowGraph/flowGraphRichTypes.js";
|
|
|
6
6
|
*/
|
|
7
7
|
export class FlowGraphGLTFDataProvider extends FlowGraphBlock {
|
|
8
8
|
constructor(config) {
|
|
9
|
-
super();
|
|
9
|
+
super(config);
|
|
10
10
|
const glTF = config.glTF;
|
|
11
|
-
|
|
11
|
+
// glTF may be undefined when the block is re-created from serialized data
|
|
12
|
+
// (e.g. in the Flow Graph Editor) where the live glTF parse tree is unavailable.
|
|
13
|
+
const animationGroups = glTF?.animations?.map((a) => a._babylonAnimationGroup) || [];
|
|
12
14
|
this.animationGroups = this.registerDataOutput("animationGroups", RichTypeAny, animationGroups);
|
|
13
|
-
const nodes = glTF
|
|
15
|
+
const nodes = glTF?.nodes?.map((n) => n._babylonTransformNode) || [];
|
|
14
16
|
this.nodes = this.registerDataOutput("nodes", RichTypeAny, nodes);
|
|
15
17
|
}
|
|
16
18
|
getClassName() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flowGraphGLTFDataProvider.js","sourceRoot":"","sources":["../../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAKlG,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAYhE;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,cAAc;IAazD,YAAY,MAAoD;QAC5D,KAAK,
|
|
1
|
+
{"version":3,"file":"flowGraphGLTFDataProvider.js","sourceRoot":"","sources":["../../../../../../../dev/loaders/src/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAKlG,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAYhE;;;GAGG;AACH,MAAM,OAAO,yBAA0B,SAAQ,cAAc;IAazD,YAAY,MAAoD;QAC5D,KAAK,CAAC,MAAM,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,0EAA0E;QAC1E,iFAAiF;QACjF,MAAM,eAAe,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB,CAAC,IAAI,EAAE,CAAC;QACrF,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,iBAAiB,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;QAChG,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;QACrE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACtE,CAAC;IAEe,YAAY;QACxB,OAAO,2BAA2B,CAAC;IACvC,CAAC;CACJ","sourcesContent":["import { type IFlowGraphBlockConfiguration, FlowGraphBlock } from \"core/FlowGraph/flowGraphBlock\";\nimport { type IGLTF } from \"../../glTFLoaderInterfaces\";\nimport { type FlowGraphDataConnection } from \"core/FlowGraph/flowGraphDataConnection\";\nimport { type AnimationGroup } from \"core/Animations/animationGroup\";\nimport { type TransformNode } from \"core/Meshes/transformNode\";\nimport { RichTypeAny } from \"core/FlowGraph/flowGraphRichTypes\";\n\n/**\n * a configuration interface for this block\n */\nexport interface IFlowGraphGLTFDataProviderBlockConfiguration extends IFlowGraphBlockConfiguration {\n /**\n * the glTF object to provide data from\n */\n glTF: IGLTF;\n}\n\n/**\n * a glTF-based FlowGraph block that provides arrays with babylon object, based on the glTF tree\n * Can be used, for example, to get animation index from a glTF animation\n */\nexport class FlowGraphGLTFDataProvider extends FlowGraphBlock {\n /**\n * Output: an array of animation groups\n * Corresponds directly to the glTF animations array\n */\n public readonly animationGroups: FlowGraphDataConnection<AnimationGroup[]>;\n\n /**\n * Output an array of (Transform) nodes\n * Corresponds directly to the glTF nodes array\n */\n public readonly nodes: FlowGraphDataConnection<TransformNode[]>;\n\n constructor(config: IFlowGraphGLTFDataProviderBlockConfiguration) {\n super(config);\n const glTF = config.glTF;\n // glTF may be undefined when the block is re-created from serialized data\n // (e.g. in the Flow Graph Editor) where the live glTF parse tree is unavailable.\n const animationGroups = glTF?.animations?.map((a) => a._babylonAnimationGroup) || [];\n this.animationGroups = this.registerDataOutput(\"animationGroups\", RichTypeAny, animationGroups);\n const nodes = glTF?.nodes?.map((n) => n._babylonTransformNode) || [];\n this.nodes = this.registerDataOutput(\"nodes\", RichTypeAny, nodes);\n }\n\n public override getClassName(): string {\n return \"FlowGraphGLTFDataProvider\";\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babylonjs/loaders",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0",
|
|
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": "9.
|
|
21
|
+
"@babylonjs/core": "9.3.0",
|
|
22
22
|
"@dev/build-tools": "^1.0.0",
|
|
23
23
|
"@dev/loaders": "^1.0.0",
|
|
24
|
-
"babylonjs-gltf2interface": "9.
|
|
24
|
+
"babylonjs-gltf2interface": "9.3.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@babylonjs/core": "^9.0.0",
|