@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.
@@ -16,6 +16,7 @@ export interface IParsedSplat {
16
16
  faces?: number[];
17
17
  hasVertexColors?: boolean;
18
18
  sh?: Uint8Array[];
19
+ shDegree?: number;
19
20
  trainedWithAntialiasing?: boolean;
20
21
  compressed?: boolean;
21
22
  rawSplat?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"splatDefs.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatDefs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAkB,IAKjB;AALD,WAAkB,IAAI;IAClB,iCAAS,CAAA;IACT,2CAAc,CAAA;IACd,+BAAQ,CAAA;IACR,mCAAU,CAAA;AACd,CAAC,EALiB,IAAI,KAAJ,IAAI,QAKrB","sourcesContent":["/**\r\n * Indicator of the parsed ply buffer. A standard ready to use splat or an array of positions for a point cloud\r\n */\r\nexport const enum Mode {\r\n Splat = 0,\r\n PointCloud = 1,\r\n Mesh = 2,\r\n Reject = 3,\r\n}\r\n\r\n/**\r\n * A parsed buffer and how to use it\r\n */\r\nexport interface IParsedSplat {\r\n data: ArrayBuffer;\r\n mode: Mode;\r\n faces?: number[];\r\n hasVertexColors?: boolean;\r\n sh?: Uint8Array[];\r\n trainedWithAntialiasing?: boolean;\r\n compressed?: boolean;\r\n rawSplat?: boolean;\r\n safeOrbitCameraRadiusMin?: number;\r\n safeOrbitCameraElevationMinMax?: [number, number];\r\n upAxis?: \"X\" | \"Y\" | \"Z\";\r\n chirality?: \"LeftHanded\" | \"RightHanded\";\r\n}\r\n"]}
1
+ {"version":3,"file":"splatDefs.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatDefs.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAkB,IAKjB;AALD,WAAkB,IAAI;IAClB,iCAAS,CAAA;IACT,2CAAc,CAAA;IACd,+BAAQ,CAAA;IACR,mCAAU,CAAA;AACd,CAAC,EALiB,IAAI,KAAJ,IAAI,QAKrB","sourcesContent":["/**\r\n * Indicator of the parsed ply buffer. A standard ready to use splat or an array of positions for a point cloud\r\n */\r\nexport const enum Mode {\r\n Splat = 0,\r\n PointCloud = 1,\r\n Mesh = 2,\r\n Reject = 3,\r\n}\r\n\r\n/**\r\n * A parsed buffer and how to use it\r\n */\r\nexport interface IParsedSplat {\r\n data: ArrayBuffer;\r\n mode: Mode;\r\n faces?: number[];\r\n hasVertexColors?: boolean;\r\n sh?: Uint8Array[];\r\n shDegree?: number;\r\n trainedWithAntialiasing?: boolean;\r\n compressed?: boolean;\r\n rawSplat?: boolean;\r\n safeOrbitCameraRadiusMin?: number;\r\n safeOrbitCameraElevationMinMax?: [number, number];\r\n upAxis?: \"X\" | \"Y\" | \"Z\";\r\n chirality?: \"LeftHanded\" | \"RightHanded\";\r\n}\r\n"]}
@@ -10,7 +10,7 @@ import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
10
10
  import { PointsCloudSystem } from "@babylonjs/core/Particles/pointsCloudSystem.js";
11
11
  import { Color4 } from "@babylonjs/core/Maths/math.color.js";
12
12
  import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData.js";
13
- import { ParseSpz } from "./spz.js";
13
+ import { ConvertSpzToSplatAsync, GetSpzModule, ParseSpz } from "./spz.js";
14
14
  import { ParseSogMeta } from "./sog.js";
15
15
  import { Tools } from "@babylonjs/core/Misc/tools.js";
16
16
  /**
@@ -147,7 +147,7 @@ export class SPLATFileLoader {
147
147
  const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
148
148
  gaussianSplatting._parentContainer = this._assetContainer;
149
149
  babylonMeshesArray.push(gaussianSplatting);
150
- gaussianSplatting.updateData(parsedSOG.data, parsedSOG.sh, { flipY: false });
150
+ gaussianSplatting.updateData(parsedSOG.data, parsedSOG.sh, { flipY: false }, undefined, parsedSOG.shDegree);
151
151
  gaussianSplatting.scaling.y *= -1;
152
152
  gaussianSplatting.computeWorldMatrix(true);
153
153
  scene._blockEntityCollection = false;
@@ -198,7 +198,7 @@ export class SPLATFileLoader {
198
198
  const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
199
199
  gaussianSplatting._parentContainer = this._assetContainer;
200
200
  babylonMeshesArray.push(gaussianSplatting);
201
- gaussianSplatting.updateData(parsedPLY.data, parsedPLY.sh, { flipY: false });
201
+ gaussianSplatting.updateData(parsedPLY.data, parsedPLY.sh, { flipY: false }, undefined, parsedPLY.shDegree);
202
202
  gaussianSplatting.scaling.y *= -1.0;
203
203
  if (parsedPLY.chirality === "RightHanded") {
204
204
  gaussianSplatting.scaling.y *= -1.0;
@@ -249,13 +249,45 @@ export class SPLATFileLoader {
249
249
  resolve(babylonMeshesArray);
250
250
  });
251
251
  };
252
- // Check for gzip magic bytes (SPZ format) before attempting decompression
252
+ // Check for gzip magic bytes to detect SPZ format
253
253
  if (u8[0] !== 0x1f || u8[1] !== 0x8b) {
254
254
  return new Promise((resolve) => {
255
255
  handlePLY(resolve);
256
256
  });
257
257
  }
258
- // Use GZip DecompressionStream for SPZ files
258
+ const applyParsedSPZ = (parsedSPZ, resolve) => {
259
+ scene._blockEntityCollection = !!this._assetContainer;
260
+ const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
261
+ if (parsedSPZ.trainedWithAntialiasing) {
262
+ const gsMaterial = gaussianSplatting.material;
263
+ gsMaterial.kernelSize = 0.1;
264
+ gsMaterial.compensation = true;
265
+ }
266
+ gaussianSplatting._parentContainer = this._assetContainer;
267
+ babylonMeshesArray.push(gaussianSplatting);
268
+ gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh, { flipY: false }, undefined, parsedSPZ.shDegree);
269
+ if (!this._loadingOptions.flipY) {
270
+ gaussianSplatting.scaling.y *= -1.0;
271
+ gaussianSplatting.computeWorldMatrix(true);
272
+ }
273
+ scene._blockEntityCollection = false;
274
+ this.applyAutoCameraLimits(parsedSPZ, scene);
275
+ resolve(babylonMeshesArray);
276
+ };
277
+ if (this._loadingOptions.spzLibraryUrl) {
278
+ // WASM path: load spz module from URL, pass raw gzip data directly
279
+ // eslint-disable-next-line github/no-then
280
+ return GetSpzModule(this._loadingOptions.spzLibraryUrl).then((spz) => {
281
+ const cloud = spz.loadSpzFromBuffer(new Uint8Array(data), { to: spz.CoordinateSystem.RUB });
282
+ // eslint-disable-next-line github/no-then
283
+ return ConvertSpzToSplatAsync(cloud, scene).then((parsedSPZ) => {
284
+ return new Promise((resolve) => {
285
+ applyParsedSPZ(parsedSPZ, resolve);
286
+ });
287
+ });
288
+ });
289
+ }
290
+ // Manual path: decompress gzip, then parse with the built-in SPZ parser
259
291
  const readableStream = new ReadableStream({
260
292
  start(controller) {
261
293
  controller.enqueue(new Uint8Array(data));
@@ -271,23 +303,7 @@ export class SPLATFileLoader {
271
303
  .then((buffer) => {
272
304
  // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then
273
305
  ParseSpz(buffer, scene, this._loadingOptions).then((parsedSPZ) => {
274
- scene._blockEntityCollection = !!this._assetContainer;
275
- const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
276
- if (parsedSPZ.trainedWithAntialiasing) {
277
- const gsMaterial = gaussianSplatting.material;
278
- gsMaterial.kernelSize = 0.1;
279
- gsMaterial.compensation = true;
280
- }
281
- gaussianSplatting._parentContainer = this._assetContainer;
282
- babylonMeshesArray.push(gaussianSplatting);
283
- gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh, { flipY: false });
284
- if (!this._loadingOptions.flipY) {
285
- gaussianSplatting.scaling.y *= -1.0;
286
- gaussianSplatting.computeWorldMatrix(true);
287
- }
288
- scene._blockEntityCollection = false;
289
- this.applyAutoCameraLimits(parsedSPZ, scene);
290
- resolve(babylonMeshesArray);
306
+ applyParsedSPZ(parsedSPZ, resolve);
291
307
  });
292
308
  })
293
309
  // eslint-disable-next-line github/no-then
@@ -494,7 +510,16 @@ export class SPLATFileLoader {
494
510
  // early exit for chunked/quantized ply
495
511
  if (chunkCount) {
496
512
  return await new Promise((resolve) => {
497
- resolve({ mode: 0 /* Mode.Splat */, data: splatsData.buffer, sh: splatsData.sh, faces: faces, hasVertexColors: false, compressed: true, rawSplat: false });
513
+ resolve({
514
+ mode: 0 /* Mode.Splat */,
515
+ data: splatsData.buffer,
516
+ sh: splatsData.sh,
517
+ shDegree: splatsData.shDegree,
518
+ faces: faces,
519
+ hasVertexColors: false,
520
+ compressed: true,
521
+ rawSplat: false,
522
+ });
498
523
  });
499
524
  }
500
525
  // count available properties. if all necessary are present then it's a splat. Otherwise, it's a point cloud
@@ -521,6 +546,7 @@ export class SPLATFileLoader {
521
546
  mode: currentMode,
522
547
  data: splatsData.buffer,
523
548
  sh: splatsData.sh,
549
+ shDegree: splatsData.shDegree,
524
550
  faces: faces,
525
551
  hasVertexColors: !!propertyColorCount,
526
552
  compressed: false,
@@ -533,6 +559,7 @@ export class SPLATFileLoader {
533
559
  SPLATFileLoader._DefaultLoadingOptions = {
534
560
  keepInRam: false,
535
561
  flipY: false,
562
+ spzLibraryUrl: typeof WebAssembly === "object" ? "https://unpkg.com/@adobe/spz@0.2.0/dist/spz.js" : undefined,
536
563
  };
537
564
  // Add this loader into the register plugin
538
565
  RegisterSceneLoaderPlugin(new SPLATFileLoader());
@@ -1 +1 @@
1
- {"version":3,"file":"splatFileLoader.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/promise-function-async*/\r\n/* eslint-disable @typescript-eslint/naming-convention */\r\nimport {\r\n type ISceneLoaderPluginAsync,\r\n type ISceneLoaderPluginFactory,\r\n type ISceneLoaderAsyncResult,\r\n type ISceneLoaderProgressEvent,\r\n type SceneLoaderPluginOptions,\r\n RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { SPLATFileLoaderMetadata } from \"./splatFileLoader.metadata\";\r\nimport { GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { Vector3 } from \"core/Maths/math.vector\";\r\nimport { PointsCloudSystem } from \"core/Particles/pointsCloudSystem\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { type SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { type GaussianSplattingMaterial } from \"core/Materials/GaussianSplatting/gaussianSplattingMaterial\";\r\nimport { ParseSpz } from \"./spz\";\r\nimport { Mode, type IParsedSplat } from \"./splatDefs\";\r\nimport { ParseSogMeta, type SOGRootData } from \"./sog\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { type ArcRotateCamera } from \"core/Cameras/arcRotateCamera\";\r\n\r\ndeclare module \"core/Loading/sceneLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface SceneLoaderPluginOptions {\r\n /**\r\n * Defines options for the splat loader.\r\n */\r\n [SPLATFileLoaderMetadata.name]: Partial<SPLATLoadingOptions>;\r\n }\r\n}\r\n\r\n// FFlate access\r\ndeclare const fflate: any;\r\n\r\n/**\r\n * @experimental\r\n * SPLAT file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n /**\r\n * Defines the name of the plugin.\r\n */\r\n public readonly name = SPLATFileLoaderMetadata.name;\r\n\r\n private _assetContainer: Nullable<AssetContainer> = null;\r\n\r\n private readonly _loadingOptions: Readonly<SPLATLoadingOptions>;\r\n /**\r\n * Defines the extensions the splat loader is able to load.\r\n * force data to come in as an ArrayBuffer\r\n */\r\n public readonly extensions = SPLATFileLoaderMetadata.extensions;\r\n\r\n /**\r\n * Creates loader for gaussian splatting files\r\n * @param loadingOptions options for loading and parsing splat and PLY files.\r\n */\r\n constructor(loadingOptions: Partial<Readonly<SPLATLoadingOptions>> = SPLATFileLoader._DefaultLoadingOptions) {\r\n this._loadingOptions = loadingOptions;\r\n }\r\n\r\n private static readonly _DefaultLoadingOptions = {\r\n keepInRam: false,\r\n flipY: false,\r\n } as const satisfies SPLATLoadingOptions;\r\n\r\n /** @internal */\r\n createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\r\n return new SPLATFileLoader(options[SPLATFileLoaderMetadata.name]);\r\n }\r\n\r\n /**\r\n * Imports from the loaded gaussian splatting data and adds them to the scene\r\n * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n * @param scene the scene the meshes should be added to\r\n * @param data the gaussian splatting data to load\r\n * @param rootUrl root url to load from\r\n * @param _onProgress callback called while file is loading\r\n * @param _fileName Defines the name of the file to load\r\n * @returns a promise containing the loaded meshes, particles, skeletons and animations\r\n */\r\n public async importMeshAsync(\r\n meshesNames: any,\r\n scene: Scene,\r\n data: any,\r\n rootUrl: string,\r\n _onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n _fileName?: string\r\n ): Promise<ISceneLoaderAsyncResult> {\r\n // eslint-disable-next-line github/no-then\r\n return await this._parseAsync(meshesNames, scene, data, rootUrl).then((meshes) => {\r\n return {\r\n meshes: meshes,\r\n particleSystems: [],\r\n skeletons: [],\r\n animationGroups: [],\r\n transformNodes: [],\r\n geometries: [],\r\n lights: [],\r\n spriteManagers: [],\r\n };\r\n });\r\n }\r\n\r\n private static _BuildPointCloud(pointcloud: PointsCloudSystem, data: ArrayBuffer): boolean {\r\n if (!data.byteLength) {\r\n return false;\r\n }\r\n const uBuffer = new Uint8Array(data);\r\n const fBuffer = new Float32Array(data);\r\n\r\n // parsed array contains room for position(3floats), normal(3floats), color (4b), quantized quaternion (4b)\r\n const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n const vertexCount = uBuffer.length / rowLength;\r\n\r\n const pointcloudfunc = function (particle: any, i: number) {\r\n const x = fBuffer[8 * i + 0];\r\n const y = fBuffer[8 * i + 1];\r\n const z = fBuffer[8 * i + 2];\r\n particle.position = new Vector3(x, y, z);\r\n\r\n const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n particle.color = new Color4(r, g, b, 1);\r\n };\r\n\r\n pointcloud.addPoints(vertexCount, pointcloudfunc);\r\n return true;\r\n }\r\n\r\n private static _BuildMesh(scene: Scene, parsedPLY: IParsedSplat): Mesh {\r\n const mesh = new Mesh(\"PLYMesh\", scene);\r\n\r\n const uBuffer = new Uint8Array(parsedPLY.data);\r\n const fBuffer = new Float32Array(parsedPLY.data);\r\n\r\n const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n const vertexCount = uBuffer.length / rowLength;\r\n\r\n const positions = [];\r\n\r\n const vertexData = new VertexData();\r\n for (let i = 0; i < vertexCount; i++) {\r\n const x = fBuffer[8 * i + 0];\r\n const y = fBuffer[8 * i + 1];\r\n const z = fBuffer[8 * i + 2];\r\n positions.push(x, y, z);\r\n }\r\n\r\n if (parsedPLY.hasVertexColors) {\r\n const colors = new Float32Array(vertexCount * 4);\r\n for (let i = 0; i < vertexCount; i++) {\r\n const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n colors[i * 4 + 0] = r;\r\n colors[i * 4 + 1] = g;\r\n colors[i * 4 + 2] = b;\r\n colors[i * 4 + 3] = 1;\r\n }\r\n vertexData.colors = colors;\r\n }\r\n\r\n vertexData.positions = positions;\r\n vertexData.indices = parsedPLY.faces!;\r\n\r\n vertexData.applyToMesh(mesh);\r\n return mesh;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax, @typescript-eslint/naming-convention\r\n private async _unzipWithFFlateAsync(data: Uint8Array): Promise<Map<string, Uint8Array>> {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n let fflate = this._loadingOptions.fflate as typeof import(\"fflate\");\r\n // ensure fflate is loaded\r\n if (!fflate) {\r\n if (typeof (window as any).fflate === \"undefined\") {\r\n await Tools.LoadScriptAsync(this._loadingOptions.deflateURL ?? \"https://unpkg.com/fflate/umd/index.js\");\r\n }\r\n fflate = (window as any).fflate as typeof fflate;\r\n }\r\n\r\n const { unzipSync } = fflate;\r\n\r\n const unzipped = unzipSync(data) as Record<string, Uint8Array>; // { [filename: string]: Uint8Array }\r\n\r\n const files = new Map<string, Uint8Array>();\r\n for (const [name, content] of Object.entries(unzipped)) {\r\n files.set(name, content);\r\n }\r\n return files;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n private _parseAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string): Promise<Array<AbstractMesh>> {\r\n const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n\r\n const makeGSFromParsedSOG = (parsedSOG: IParsedSplat) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedSOG.data, parsedSOG.sh, { flipY: false });\r\n gaussianSplatting.scaling.y *= -1;\r\n gaussianSplatting.computeWorldMatrix(true);\r\n scene._blockEntityCollection = false;\r\n };\r\n\r\n // check if data is json string\r\n if (typeof data === \"string\") {\r\n const dataSOG = JSON.parse(data) as SOGRootData;\r\n if (dataSOG && dataSOG.means && dataSOG.scales && dataSOG.quats && dataSOG.sh0) {\r\n return new Promise((resolve) => {\r\n ParseSogMeta(dataSOG, rootUrl, scene)\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n .then((parsedSOG) => {\r\n makeGSFromParsedSOG(parsedSOG);\r\n resolve(babylonMeshesArray);\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n throw new Error(\"Failed to parse SOG data.\");\r\n });\r\n });\r\n }\r\n }\r\n\r\n const u8 = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\r\n // ZIP signature check for SOG\r\n if (u8[0] === 0x50 && u8[1] === 0x4b) {\r\n return new Promise((resolve) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n this._unzipWithFFlateAsync(u8).then((files) => {\r\n ParseSogMeta(files, rootUrl, scene)\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n .then((parsedSOG) => {\r\n makeGSFromParsedSOG(parsedSOG);\r\n resolve(babylonMeshesArray);\r\n }) // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n throw new Error(\"Failed to parse SOG zip data.\");\r\n });\r\n });\r\n });\r\n }\r\n\r\n const handlePLY = (resolve: (value: AbstractMesh[]) => void) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer).then(async (parsedPLY) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n switch (parsedPLY.mode) {\r\n case Mode.Splat:\r\n {\r\n const gaussianSplatting =\r\n this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedPLY.data, parsedPLY.sh, { flipY: false });\r\n gaussianSplatting.scaling.y *= -1.0;\r\n\r\n if (parsedPLY.chirality === \"RightHanded\") {\r\n gaussianSplatting.scaling.y *= -1.0;\r\n }\r\n\r\n switch (parsedPLY.upAxis) {\r\n case \"X\":\r\n gaussianSplatting.rotation = new Vector3(0, 0, Math.PI / 2);\r\n break;\r\n case \"Y\":\r\n gaussianSplatting.rotation = new Vector3(0, 0, Math.PI);\r\n break;\r\n case \"Z\":\r\n gaussianSplatting.rotation = new Vector3(-Math.PI / 2, Math.PI, 0);\r\n break;\r\n }\r\n gaussianSplatting.computeWorldMatrix(true);\r\n }\r\n break;\r\n case Mode.PointCloud:\r\n {\r\n const pointcloud = new PointsCloudSystem(\"PointCloud\", 1, scene);\r\n if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {\r\n // eslint-disable-next-line github/no-then\r\n await pointcloud.buildMeshAsync().then((mesh) => {\r\n babylonMeshesArray.push(mesh);\r\n });\r\n } else {\r\n pointcloud.dispose();\r\n }\r\n }\r\n break;\r\n case Mode.Mesh:\r\n {\r\n if (parsedPLY.faces) {\r\n babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));\r\n } else {\r\n throw new Error(\"PLY mesh doesn't contain face informations.\");\r\n }\r\n }\r\n break;\r\n default:\r\n throw new Error(\"Unsupported Splat mode\");\r\n }\r\n scene._blockEntityCollection = false;\r\n this.applyAutoCameraLimits(parsedPLY, scene);\r\n resolve(babylonMeshesArray);\r\n });\r\n };\r\n\r\n // Check for gzip magic bytes (SPZ format) before attempting decompression\r\n if (u8[0] !== 0x1f || u8[1] !== 0x8b) {\r\n return new Promise((resolve) => {\r\n handlePLY(resolve);\r\n });\r\n }\r\n\r\n // Use GZip DecompressionStream for SPZ files\r\n const readableStream = new ReadableStream({\r\n start(controller) {\r\n controller.enqueue(new Uint8Array(data));\r\n controller.close();\r\n },\r\n });\r\n const decompressionStream = new DecompressionStream(\"gzip\");\r\n const decompressedStream = readableStream.pipeThrough(decompressionStream);\r\n\r\n return new Promise((resolve) => {\r\n new Response(decompressedStream)\r\n .arrayBuffer()\r\n // eslint-disable-next-line github/no-then\r\n .then((buffer) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n ParseSpz(buffer, scene, this._loadingOptions).then((parsedSPZ) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n const gaussianSplatting =\r\n this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n if (parsedSPZ.trainedWithAntialiasing) {\r\n const gsMaterial = gaussianSplatting.material as GaussianSplattingMaterial;\r\n gsMaterial.kernelSize = 0.1;\r\n gsMaterial.compensation = true;\r\n }\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh, { flipY: false });\r\n if (!this._loadingOptions.flipY) {\r\n gaussianSplatting.scaling.y *= -1.0;\r\n gaussianSplatting.computeWorldMatrix(true);\r\n }\r\n scene._blockEntityCollection = false;\r\n this.applyAutoCameraLimits(parsedSPZ, scene);\r\n resolve(babylonMeshesArray);\r\n });\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n handlePLY(resolve);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Applies camera limits based on parsed meta data\r\n * @param meta parsed splat meta data\r\n * @param scene\r\n */\r\n private applyAutoCameraLimits(meta: IParsedSplat, scene: Scene): void {\r\n if (this._loadingOptions.disableAutoCameraLimits) {\r\n return;\r\n }\r\n if ((meta.safeOrbitCameraRadiusMin !== undefined || meta.safeOrbitCameraElevationMinMax !== undefined) && scene.activeCamera?.getClassName() === \"ArcRotateCamera\") {\r\n const arcCam = scene.activeCamera as ArcRotateCamera;\r\n if (meta.safeOrbitCameraElevationMinMax) {\r\n arcCam.lowerBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[1];\r\n arcCam.upperBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[0];\r\n }\r\n\r\n if (meta.safeOrbitCameraRadiusMin) {\r\n arcCam.lowerRadiusLimit = meta.safeOrbitCameraRadiusMin;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Load into an asset container.\r\n * @param scene The scene to load into\r\n * @param data The data to import\r\n * @param rootUrl The root url for scene and resources\r\n * @returns The loaded asset container\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string): Promise<AssetContainer> {\r\n const container = new AssetContainer(scene);\r\n this._assetContainer = container;\r\n\r\n return (\r\n this.importMeshAsync(null, scene, data, rootUrl)\r\n // eslint-disable-next-line github/no-then\r\n .then((result) => {\r\n for (const mesh of result.meshes) {\r\n container.meshes.push(mesh);\r\n }\r\n // mesh material will be null before 1st rendered frame.\r\n this._assetContainer = null;\r\n return container;\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch((ex) => {\r\n this._assetContainer = null;\r\n throw ex;\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Imports all objects from the loaded OBJ data and adds them to the scene\r\n * @param scene the scene the objects should be added to\r\n * @param data the OBJ data to load\r\n * @param rootUrl root url to load from\r\n * @returns a promise which completes when objects have been loaded to the scene\r\n */\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n public loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void> {\r\n //Get the 3D model\r\n // eslint-disable-next-line github/no-then\r\n return this.importMeshAsync(null, scene, data, rootUrl).then(() => {\r\n // return void\r\n });\r\n }\r\n\r\n /**\r\n * Code from https://github.com/dylanebert/gsplat.js/blob/main/src/loaders/PLYLoader.ts Under MIT license\r\n * Converts a .ply data array buffer to splat\r\n * if data array buffer is not ply, returns the original buffer\r\n * @param data the .ply data to load\r\n * @returns the loaded splat buffer\r\n */\r\n private static _ConvertPLYToSplat(data: ArrayBuffer): Promise<IParsedSplat> {\r\n const ubuf = new Uint8Array(data);\r\n const header = new TextDecoder().decode(ubuf.slice(0, 1024 * 10));\r\n const headerEnd = \"end_header\\n\";\r\n const headerEndIndex = header.indexOf(headerEnd);\r\n if (headerEndIndex < 0 || !header) {\r\n // standard splat\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: data, rawSplat: true });\r\n });\r\n }\r\n\r\n const vertexCount = parseInt(/element vertex (\\d+)\\n/.exec(header)![1]);\r\n const faceElement = /element face (\\d+)\\n/.exec(header);\r\n let faceCount = 0;\r\n if (faceElement) {\r\n faceCount = parseInt(faceElement[1]);\r\n }\r\n const chunkElement = /element chunk (\\d+)\\n/.exec(header);\r\n let chunkCount = 0;\r\n if (chunkElement) {\r\n chunkCount = parseInt(chunkElement[1]);\r\n }\r\n\r\n let rowVertexOffset = 0;\r\n let rowChunkOffset = 0;\r\n const offsets: Record<string, number> = {\r\n double: 8,\r\n int: 4,\r\n uint: 4,\r\n float: 4,\r\n short: 2,\r\n ushort: 2,\r\n uchar: 1,\r\n list: 0,\r\n };\r\n\r\n type PlyProperty = {\r\n name: string;\r\n type: string;\r\n offset: number;\r\n };\r\n\r\n const ElementMode: Record<string, number> = {\r\n Vertex: 0,\r\n Chunk: 1,\r\n SH: 2,\r\n Float_Tuple: 3,\r\n Float: 4,\r\n Uchar: 5,\r\n };\r\n\r\n let chunkMode = ElementMode.Chunk;\r\n const vertexProperties: PlyProperty[] = [];\r\n const chunkProperties: PlyProperty[] = [];\r\n const filtered = header.slice(0, headerEndIndex).split(\"\\n\");\r\n const metaData: Partial<IParsedSplat> = {};\r\n for (const prop of filtered) {\r\n if (prop.startsWith(\"property \")) {\r\n const [, type, name] = prop.split(\" \");\r\n\r\n if (chunkMode == ElementMode.Chunk) {\r\n chunkProperties.push({ name, type, offset: rowChunkOffset });\r\n rowChunkOffset += offsets[type];\r\n } else if (chunkMode == ElementMode.Vertex) {\r\n vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n rowVertexOffset += offsets[type];\r\n } else if (chunkMode == ElementMode.SH) {\r\n vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n } else if (chunkMode == ElementMode.Float_Tuple) {\r\n const view = new DataView(data, rowChunkOffset, offsets.float * 2);\r\n metaData.safeOrbitCameraElevationMinMax = [view.getFloat32(0, true), view.getFloat32(4, true)];\r\n } else if (chunkMode == ElementMode.Float) {\r\n const view = new DataView(data, rowChunkOffset, offsets.float);\r\n metaData.safeOrbitCameraRadiusMin = view.getFloat32(0, true);\r\n } else if (chunkMode == ElementMode.Uchar) {\r\n const view = new DataView(data, rowChunkOffset, offsets.uchar);\r\n if (name == \"up_axis\") {\r\n metaData.upAxis = view.getUint8(0) == 0 ? \"X\" : view.getUint8(0) == 1 ? \"Y\" : \"Z\";\r\n } else if (name == \"chirality\") {\r\n metaData.chirality = view.getUint8(0) == 0 ? \"LeftHanded\" : \"RightHanded\";\r\n }\r\n }\r\n\r\n if (!offsets[type]) {\r\n Logger.Warn(`Unsupported property type: ${type}.`);\r\n }\r\n } else if (prop.startsWith(\"element \")) {\r\n const [, type] = prop.split(\" \");\r\n if (type == \"chunk\") {\r\n chunkMode = ElementMode.Chunk;\r\n } else if (type == \"vertex\") {\r\n chunkMode = ElementMode.Vertex;\r\n } else if (type == \"sh\") {\r\n chunkMode = ElementMode.SH;\r\n } else if (type == \"safe_orbit_camera_elevation_min_max_radians\") {\r\n chunkMode = ElementMode.Float_Tuple;\r\n } else if (type == \"safe_orbit_camera_radius_min\") {\r\n chunkMode = ElementMode.Float;\r\n } else if (type == \"up_axis\" || type == \"chirality\") {\r\n chunkMode = ElementMode.Uchar;\r\n }\r\n }\r\n }\r\n\r\n const rowVertexLength = rowVertexOffset;\r\n const rowChunkLength = rowChunkOffset;\r\n\r\n // eslint-disable-next-line github/no-then\r\n return (GaussianSplattingMesh.ConvertPLYWithSHToSplatAsync(data) as any).then(async (splatsData: any) => {\r\n const dataView = new DataView(data, headerEndIndex + headerEnd.length);\r\n let offset = rowChunkLength * chunkCount + rowVertexLength * vertexCount;\r\n // faces\r\n const faces: number[] = [];\r\n if (faceCount) {\r\n for (let i = 0; i < faceCount; i++) {\r\n const faceVertexCount = dataView.getUint8(offset);\r\n if (faceVertexCount != 3) {\r\n continue; // only support triangles\r\n }\r\n offset += 1;\r\n\r\n for (let j = 0; j < faceVertexCount; j++) {\r\n const vertexIndex = dataView.getUint32(offset + (2 - j) * 4, true); // change face winding\r\n faces.push(vertexIndex);\r\n }\r\n offset += 12;\r\n }\r\n }\r\n\r\n // early exit for chunked/quantized ply\r\n if (chunkCount) {\r\n return await new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: splatsData.buffer, sh: splatsData.sh, faces: faces, hasVertexColors: false, compressed: true, rawSplat: false });\r\n });\r\n }\r\n // count available properties. if all necessary are present then it's a splat. Otherwise, it's a point cloud\r\n // if faces are found, then it's a standard mesh\r\n let propertyCount = 0;\r\n let propertyColorCount = 0;\r\n const splatProperties = [\"x\", \"y\", \"z\", \"scale_0\", \"scale_1\", \"scale_2\", \"opacity\", \"rot_0\", \"rot_1\", \"rot_2\", \"rot_3\"];\r\n const splatColorProperties = [\"red\", \"green\", \"blue\", \"f_dc_0\", \"f_dc_1\", \"f_dc_2\"];\r\n for (let propertyIndex = 0; propertyIndex < vertexProperties.length; propertyIndex++) {\r\n const property = vertexProperties[propertyIndex];\r\n if (splatProperties.includes(property.name)) {\r\n propertyCount++;\r\n }\r\n if (splatColorProperties.includes(property.name)) {\r\n propertyColorCount++;\r\n }\r\n }\r\n const hasMandatoryProperties = propertyCount == splatProperties.length && propertyColorCount == 3;\r\n const currentMode = faceCount ? Mode.Mesh : hasMandatoryProperties ? Mode.Splat : Mode.PointCloud;\r\n // parsed ready ready to be used as a splat\r\n return await new Promise((resolve) => {\r\n resolve({\r\n ...metaData,\r\n mode: currentMode,\r\n data: splatsData.buffer,\r\n sh: splatsData.sh,\r\n faces: faces,\r\n hasVertexColors: !!propertyColorCount,\r\n compressed: false,\r\n rawSplat: false,\r\n });\r\n });\r\n });\r\n }\r\n}\r\n\r\n// Add this loader into the register plugin\r\nRegisterSceneLoaderPlugin(new SPLATFileLoader());\r\n"]}
1
+ {"version":3,"file":"splatFileLoader.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/promise-function-async*/\r\n/* eslint-disable @typescript-eslint/naming-convention */\r\nimport {\r\n type ISceneLoaderPluginAsync,\r\n type ISceneLoaderPluginFactory,\r\n type ISceneLoaderAsyncResult,\r\n type ISceneLoaderProgressEvent,\r\n type SceneLoaderPluginOptions,\r\n RegisterSceneLoaderPlugin,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { SPLATFileLoaderMetadata } from \"./splatFileLoader.metadata\";\r\nimport { GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\nimport { AssetContainer } from \"core/assetContainer\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type AbstractMesh } from \"core/Meshes/abstractMesh\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { Logger } from \"core/Misc/logger\";\r\nimport { Vector3 } from \"core/Maths/math.vector\";\r\nimport { PointsCloudSystem } from \"core/Particles/pointsCloudSystem\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { type SPLATLoadingOptions } from \"./splatLoadingOptions\";\r\nimport { type GaussianSplattingMaterial } from \"core/Materials/GaussianSplatting/gaussianSplattingMaterial\";\r\nimport { ConvertSpzToSplatAsync, GetSpzModule, ParseSpz } from \"./spz\";\r\nimport { Mode, type IParsedSplat } from \"./splatDefs\";\r\nimport { ParseSogMeta, type SOGRootData } from \"./sog\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { type ArcRotateCamera } from \"core/Cameras/arcRotateCamera\";\r\n\r\ndeclare module \"core/Loading/sceneLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc, @typescript-eslint/naming-convention\r\n export interface SceneLoaderPluginOptions {\r\n /**\r\n * Defines options for the splat loader.\r\n */\r\n [SPLATFileLoaderMetadata.name]: Partial<SPLATLoadingOptions>;\r\n }\r\n}\r\n\r\n// FFlate access\r\ndeclare const fflate: any;\r\n\r\n/**\r\n * @experimental\r\n * SPLAT file type loader.\r\n * This is a babylon scene loader plugin.\r\n */\r\nexport class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {\r\n /**\r\n * Defines the name of the plugin.\r\n */\r\n public readonly name = SPLATFileLoaderMetadata.name;\r\n\r\n private _assetContainer: Nullable<AssetContainer> = null;\r\n\r\n private readonly _loadingOptions: Readonly<SPLATLoadingOptions>;\r\n /**\r\n * Defines the extensions the splat loader is able to load.\r\n * force data to come in as an ArrayBuffer\r\n */\r\n public readonly extensions = SPLATFileLoaderMetadata.extensions;\r\n\r\n /**\r\n * Creates loader for gaussian splatting files\r\n * @param loadingOptions options for loading and parsing splat and PLY files.\r\n */\r\n constructor(loadingOptions: Partial<Readonly<SPLATLoadingOptions>> = SPLATFileLoader._DefaultLoadingOptions) {\r\n this._loadingOptions = loadingOptions;\r\n }\r\n\r\n private static readonly _DefaultLoadingOptions = {\r\n keepInRam: false,\r\n flipY: false,\r\n spzLibraryUrl: typeof WebAssembly === \"object\" ? \"https://unpkg.com/@adobe/spz@0.2.0/dist/spz.js\" : undefined,\r\n } as const satisfies SPLATLoadingOptions;\r\n\r\n /** @internal */\r\n createPlugin(options: SceneLoaderPluginOptions): ISceneLoaderPluginAsync {\r\n return new SPLATFileLoader(options[SPLATFileLoaderMetadata.name]);\r\n }\r\n\r\n /**\r\n * Imports from the loaded gaussian splatting data and adds them to the scene\r\n * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file\r\n * @param scene the scene the meshes should be added to\r\n * @param data the gaussian splatting data to load\r\n * @param rootUrl root url to load from\r\n * @param _onProgress callback called while file is loading\r\n * @param _fileName Defines the name of the file to load\r\n * @returns a promise containing the loaded meshes, particles, skeletons and animations\r\n */\r\n public async importMeshAsync(\r\n meshesNames: any,\r\n scene: Scene,\r\n data: any,\r\n rootUrl: string,\r\n _onProgress?: (event: ISceneLoaderProgressEvent) => void,\r\n _fileName?: string\r\n ): Promise<ISceneLoaderAsyncResult> {\r\n // eslint-disable-next-line github/no-then\r\n return await this._parseAsync(meshesNames, scene, data, rootUrl).then((meshes) => {\r\n return {\r\n meshes: meshes,\r\n particleSystems: [],\r\n skeletons: [],\r\n animationGroups: [],\r\n transformNodes: [],\r\n geometries: [],\r\n lights: [],\r\n spriteManagers: [],\r\n };\r\n });\r\n }\r\n\r\n private static _BuildPointCloud(pointcloud: PointsCloudSystem, data: ArrayBuffer): boolean {\r\n if (!data.byteLength) {\r\n return false;\r\n }\r\n const uBuffer = new Uint8Array(data);\r\n const fBuffer = new Float32Array(data);\r\n\r\n // parsed array contains room for position(3floats), normal(3floats), color (4b), quantized quaternion (4b)\r\n const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n const vertexCount = uBuffer.length / rowLength;\r\n\r\n const pointcloudfunc = function (particle: any, i: number) {\r\n const x = fBuffer[8 * i + 0];\r\n const y = fBuffer[8 * i + 1];\r\n const z = fBuffer[8 * i + 2];\r\n particle.position = new Vector3(x, y, z);\r\n\r\n const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n particle.color = new Color4(r, g, b, 1);\r\n };\r\n\r\n pointcloud.addPoints(vertexCount, pointcloudfunc);\r\n return true;\r\n }\r\n\r\n private static _BuildMesh(scene: Scene, parsedPLY: IParsedSplat): Mesh {\r\n const mesh = new Mesh(\"PLYMesh\", scene);\r\n\r\n const uBuffer = new Uint8Array(parsedPLY.data);\r\n const fBuffer = new Float32Array(parsedPLY.data);\r\n\r\n const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n const vertexCount = uBuffer.length / rowLength;\r\n\r\n const positions = [];\r\n\r\n const vertexData = new VertexData();\r\n for (let i = 0; i < vertexCount; i++) {\r\n const x = fBuffer[8 * i + 0];\r\n const y = fBuffer[8 * i + 1];\r\n const z = fBuffer[8 * i + 2];\r\n positions.push(x, y, z);\r\n }\r\n\r\n if (parsedPLY.hasVertexColors) {\r\n const colors = new Float32Array(vertexCount * 4);\r\n for (let i = 0; i < vertexCount; i++) {\r\n const r = uBuffer[rowLength * i + 24 + 0] / 255;\r\n const g = uBuffer[rowLength * i + 24 + 1] / 255;\r\n const b = uBuffer[rowLength * i + 24 + 2] / 255;\r\n colors[i * 4 + 0] = r;\r\n colors[i * 4 + 1] = g;\r\n colors[i * 4 + 2] = b;\r\n colors[i * 4 + 3] = 1;\r\n }\r\n vertexData.colors = colors;\r\n }\r\n\r\n vertexData.positions = positions;\r\n vertexData.indices = parsedPLY.faces!;\r\n\r\n vertexData.applyToMesh(mesh);\r\n return mesh;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax, @typescript-eslint/naming-convention\r\n private async _unzipWithFFlateAsync(data: Uint8Array): Promise<Map<string, Uint8Array>> {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n let fflate = this._loadingOptions.fflate as typeof import(\"fflate\");\r\n // ensure fflate is loaded\r\n if (!fflate) {\r\n if (typeof (window as any).fflate === \"undefined\") {\r\n await Tools.LoadScriptAsync(this._loadingOptions.deflateURL ?? \"https://unpkg.com/fflate/umd/index.js\");\r\n }\r\n fflate = (window as any).fflate as typeof fflate;\r\n }\r\n\r\n const { unzipSync } = fflate;\r\n\r\n const unzipped = unzipSync(data) as Record<string, Uint8Array>; // { [filename: string]: Uint8Array }\r\n\r\n const files = new Map<string, Uint8Array>();\r\n for (const [name, content] of Object.entries(unzipped)) {\r\n files.set(name, content);\r\n }\r\n return files;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n private _parseAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string): Promise<Array<AbstractMesh>> {\r\n const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n\r\n const makeGSFromParsedSOG = (parsedSOG: IParsedSplat) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedSOG.data, parsedSOG.sh, { flipY: false }, undefined, parsedSOG.shDegree);\r\n gaussianSplatting.scaling.y *= -1;\r\n gaussianSplatting.computeWorldMatrix(true);\r\n scene._blockEntityCollection = false;\r\n };\r\n\r\n // check if data is json string\r\n if (typeof data === \"string\") {\r\n const dataSOG = JSON.parse(data) as SOGRootData;\r\n if (dataSOG && dataSOG.means && dataSOG.scales && dataSOG.quats && dataSOG.sh0) {\r\n return new Promise((resolve) => {\r\n ParseSogMeta(dataSOG, rootUrl, scene)\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n .then((parsedSOG) => {\r\n makeGSFromParsedSOG(parsedSOG);\r\n resolve(babylonMeshesArray);\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n throw new Error(\"Failed to parse SOG data.\");\r\n });\r\n });\r\n }\r\n }\r\n\r\n const u8 = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\r\n // ZIP signature check for SOG\r\n if (u8[0] === 0x50 && u8[1] === 0x4b) {\r\n return new Promise((resolve) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n this._unzipWithFFlateAsync(u8).then((files) => {\r\n ParseSogMeta(files, rootUrl, scene)\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n .then((parsedSOG) => {\r\n makeGSFromParsedSOG(parsedSOG);\r\n resolve(babylonMeshesArray);\r\n }) // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n throw new Error(\"Failed to parse SOG zip data.\");\r\n });\r\n });\r\n });\r\n }\r\n\r\n const handlePLY = (resolve: (value: AbstractMesh[]) => void) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer).then(async (parsedPLY) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n switch (parsedPLY.mode) {\r\n case Mode.Splat:\r\n {\r\n const gaussianSplatting =\r\n this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedPLY.data, parsedPLY.sh, { flipY: false }, undefined, parsedPLY.shDegree);\r\n gaussianSplatting.scaling.y *= -1.0;\r\n\r\n if (parsedPLY.chirality === \"RightHanded\") {\r\n gaussianSplatting.scaling.y *= -1.0;\r\n }\r\n\r\n switch (parsedPLY.upAxis) {\r\n case \"X\":\r\n gaussianSplatting.rotation = new Vector3(0, 0, Math.PI / 2);\r\n break;\r\n case \"Y\":\r\n gaussianSplatting.rotation = new Vector3(0, 0, Math.PI);\r\n break;\r\n case \"Z\":\r\n gaussianSplatting.rotation = new Vector3(-Math.PI / 2, Math.PI, 0);\r\n break;\r\n }\r\n gaussianSplatting.computeWorldMatrix(true);\r\n }\r\n break;\r\n case Mode.PointCloud:\r\n {\r\n const pointcloud = new PointsCloudSystem(\"PointCloud\", 1, scene);\r\n if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {\r\n // eslint-disable-next-line github/no-then\r\n await pointcloud.buildMeshAsync().then((mesh) => {\r\n babylonMeshesArray.push(mesh);\r\n });\r\n } else {\r\n pointcloud.dispose();\r\n }\r\n }\r\n break;\r\n case Mode.Mesh:\r\n {\r\n if (parsedPLY.faces) {\r\n babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));\r\n } else {\r\n throw new Error(\"PLY mesh doesn't contain face informations.\");\r\n }\r\n }\r\n break;\r\n default:\r\n throw new Error(\"Unsupported Splat mode\");\r\n }\r\n scene._blockEntityCollection = false;\r\n this.applyAutoCameraLimits(parsedPLY, scene);\r\n resolve(babylonMeshesArray);\r\n });\r\n };\r\n\r\n // Check for gzip magic bytes to detect SPZ format\r\n if (u8[0] !== 0x1f || u8[1] !== 0x8b) {\r\n return new Promise((resolve) => {\r\n handlePLY(resolve);\r\n });\r\n }\r\n\r\n const applyParsedSPZ = (parsedSPZ: IParsedSplat, resolve: (meshes: typeof babylonMeshesArray) => void) => {\r\n scene._blockEntityCollection = !!this._assetContainer;\r\n const gaussianSplatting = this._loadingOptions.gaussianSplattingMesh ?? new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n if (parsedSPZ.trainedWithAntialiasing) {\r\n const gsMaterial = gaussianSplatting.material as GaussianSplattingMaterial;\r\n gsMaterial.kernelSize = 0.1;\r\n gsMaterial.compensation = true;\r\n }\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh, { flipY: false }, undefined, parsedSPZ.shDegree);\r\n if (!this._loadingOptions.flipY) {\r\n gaussianSplatting.scaling.y *= -1.0;\r\n gaussianSplatting.computeWorldMatrix(true);\r\n }\r\n scene._blockEntityCollection = false;\r\n this.applyAutoCameraLimits(parsedSPZ, scene);\r\n resolve(babylonMeshesArray);\r\n };\r\n\r\n if (this._loadingOptions.spzLibraryUrl) {\r\n // WASM path: load spz module from URL, pass raw gzip data directly\r\n // eslint-disable-next-line github/no-then\r\n return GetSpzModule(this._loadingOptions.spzLibraryUrl).then((spz) => {\r\n const cloud = spz.loadSpzFromBuffer(new Uint8Array(data), { to: spz.CoordinateSystem.RUB });\r\n // eslint-disable-next-line github/no-then\r\n return ConvertSpzToSplatAsync(cloud, scene).then((parsedSPZ) => {\r\n return new Promise<AbstractMesh[]>((resolve) => {\r\n applyParsedSPZ(parsedSPZ, resolve);\r\n });\r\n });\r\n });\r\n }\r\n\r\n // Manual path: decompress gzip, then parse with the built-in SPZ parser\r\n const readableStream = new ReadableStream({\r\n start(controller) {\r\n controller.enqueue(new Uint8Array(data));\r\n controller.close();\r\n },\r\n });\r\n const decompressionStream = new DecompressionStream(\"gzip\");\r\n const decompressedStream = readableStream.pipeThrough(decompressionStream);\r\n\r\n return new Promise((resolve) => {\r\n new Response(decompressedStream)\r\n .arrayBuffer()\r\n // eslint-disable-next-line github/no-then\r\n .then((buffer) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises, github/no-then\r\n ParseSpz(buffer, scene, this._loadingOptions).then((parsedSPZ) => {\r\n applyParsedSPZ(parsedSPZ, resolve);\r\n });\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch(() => {\r\n handlePLY(resolve);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Applies camera limits based on parsed meta data\r\n * @param meta parsed splat meta data\r\n * @param scene\r\n */\r\n private applyAutoCameraLimits(meta: IParsedSplat, scene: Scene): void {\r\n if (this._loadingOptions.disableAutoCameraLimits) {\r\n return;\r\n }\r\n if ((meta.safeOrbitCameraRadiusMin !== undefined || meta.safeOrbitCameraElevationMinMax !== undefined) && scene.activeCamera?.getClassName() === \"ArcRotateCamera\") {\r\n const arcCam = scene.activeCamera as ArcRotateCamera;\r\n if (meta.safeOrbitCameraElevationMinMax) {\r\n arcCam.lowerBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[1];\r\n arcCam.upperBetaLimit = Math.PI * 0.5 - meta.safeOrbitCameraElevationMinMax[0];\r\n }\r\n\r\n if (meta.safeOrbitCameraRadiusMin) {\r\n arcCam.lowerRadiusLimit = meta.safeOrbitCameraRadiusMin;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Load into an asset container.\r\n * @param scene The scene to load into\r\n * @param data The data to import\r\n * @param rootUrl The root url for scene and resources\r\n * @returns The loaded asset container\r\n */\r\n // eslint-disable-next-line no-restricted-syntax\r\n public loadAssetContainerAsync(scene: Scene, data: string, rootUrl: string): Promise<AssetContainer> {\r\n const container = new AssetContainer(scene);\r\n this._assetContainer = container;\r\n\r\n return (\r\n this.importMeshAsync(null, scene, data, rootUrl)\r\n // eslint-disable-next-line github/no-then\r\n .then((result) => {\r\n for (const mesh of result.meshes) {\r\n container.meshes.push(mesh);\r\n }\r\n // mesh material will be null before 1st rendered frame.\r\n this._assetContainer = null;\r\n return container;\r\n })\r\n // eslint-disable-next-line github/no-then\r\n .catch((ex) => {\r\n this._assetContainer = null;\r\n throw ex;\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Imports all objects from the loaded OBJ data and adds them to the scene\r\n * @param scene the scene the objects should be added to\r\n * @param data the OBJ data to load\r\n * @param rootUrl root url to load from\r\n * @returns a promise which completes when objects have been loaded to the scene\r\n */\r\n // eslint-disable-next-line @typescript-eslint/promise-function-async, no-restricted-syntax\r\n public loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void> {\r\n //Get the 3D model\r\n // eslint-disable-next-line github/no-then\r\n return this.importMeshAsync(null, scene, data, rootUrl).then(() => {\r\n // return void\r\n });\r\n }\r\n\r\n /**\r\n * Code from https://github.com/dylanebert/gsplat.js/blob/main/src/loaders/PLYLoader.ts Under MIT license\r\n * Converts a .ply data array buffer to splat\r\n * if data array buffer is not ply, returns the original buffer\r\n * @param data the .ply data to load\r\n * @returns the loaded splat buffer\r\n */\r\n private static _ConvertPLYToSplat(data: ArrayBuffer): Promise<IParsedSplat> {\r\n const ubuf = new Uint8Array(data);\r\n const header = new TextDecoder().decode(ubuf.slice(0, 1024 * 10));\r\n const headerEnd = \"end_header\\n\";\r\n const headerEndIndex = header.indexOf(headerEnd);\r\n if (headerEndIndex < 0 || !header) {\r\n // standard splat\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: data, rawSplat: true });\r\n });\r\n }\r\n\r\n const vertexCount = parseInt(/element vertex (\\d+)\\n/.exec(header)![1]);\r\n const faceElement = /element face (\\d+)\\n/.exec(header);\r\n let faceCount = 0;\r\n if (faceElement) {\r\n faceCount = parseInt(faceElement[1]);\r\n }\r\n const chunkElement = /element chunk (\\d+)\\n/.exec(header);\r\n let chunkCount = 0;\r\n if (chunkElement) {\r\n chunkCount = parseInt(chunkElement[1]);\r\n }\r\n\r\n let rowVertexOffset = 0;\r\n let rowChunkOffset = 0;\r\n const offsets: Record<string, number> = {\r\n double: 8,\r\n int: 4,\r\n uint: 4,\r\n float: 4,\r\n short: 2,\r\n ushort: 2,\r\n uchar: 1,\r\n list: 0,\r\n };\r\n\r\n type PlyProperty = {\r\n name: string;\r\n type: string;\r\n offset: number;\r\n };\r\n\r\n const ElementMode: Record<string, number> = {\r\n Vertex: 0,\r\n Chunk: 1,\r\n SH: 2,\r\n Float_Tuple: 3,\r\n Float: 4,\r\n Uchar: 5,\r\n };\r\n\r\n let chunkMode = ElementMode.Chunk;\r\n const vertexProperties: PlyProperty[] = [];\r\n const chunkProperties: PlyProperty[] = [];\r\n const filtered = header.slice(0, headerEndIndex).split(\"\\n\");\r\n const metaData: Partial<IParsedSplat> = {};\r\n for (const prop of filtered) {\r\n if (prop.startsWith(\"property \")) {\r\n const [, type, name] = prop.split(\" \");\r\n\r\n if (chunkMode == ElementMode.Chunk) {\r\n chunkProperties.push({ name, type, offset: rowChunkOffset });\r\n rowChunkOffset += offsets[type];\r\n } else if (chunkMode == ElementMode.Vertex) {\r\n vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n rowVertexOffset += offsets[type];\r\n } else if (chunkMode == ElementMode.SH) {\r\n vertexProperties.push({ name, type, offset: rowVertexOffset });\r\n } else if (chunkMode == ElementMode.Float_Tuple) {\r\n const view = new DataView(data, rowChunkOffset, offsets.float * 2);\r\n metaData.safeOrbitCameraElevationMinMax = [view.getFloat32(0, true), view.getFloat32(4, true)];\r\n } else if (chunkMode == ElementMode.Float) {\r\n const view = new DataView(data, rowChunkOffset, offsets.float);\r\n metaData.safeOrbitCameraRadiusMin = view.getFloat32(0, true);\r\n } else if (chunkMode == ElementMode.Uchar) {\r\n const view = new DataView(data, rowChunkOffset, offsets.uchar);\r\n if (name == \"up_axis\") {\r\n metaData.upAxis = view.getUint8(0) == 0 ? \"X\" : view.getUint8(0) == 1 ? \"Y\" : \"Z\";\r\n } else if (name == \"chirality\") {\r\n metaData.chirality = view.getUint8(0) == 0 ? \"LeftHanded\" : \"RightHanded\";\r\n }\r\n }\r\n\r\n if (!offsets[type]) {\r\n Logger.Warn(`Unsupported property type: ${type}.`);\r\n }\r\n } else if (prop.startsWith(\"element \")) {\r\n const [, type] = prop.split(\" \");\r\n if (type == \"chunk\") {\r\n chunkMode = ElementMode.Chunk;\r\n } else if (type == \"vertex\") {\r\n chunkMode = ElementMode.Vertex;\r\n } else if (type == \"sh\") {\r\n chunkMode = ElementMode.SH;\r\n } else if (type == \"safe_orbit_camera_elevation_min_max_radians\") {\r\n chunkMode = ElementMode.Float_Tuple;\r\n } else if (type == \"safe_orbit_camera_radius_min\") {\r\n chunkMode = ElementMode.Float;\r\n } else if (type == \"up_axis\" || type == \"chirality\") {\r\n chunkMode = ElementMode.Uchar;\r\n }\r\n }\r\n }\r\n\r\n const rowVertexLength = rowVertexOffset;\r\n const rowChunkLength = rowChunkOffset;\r\n\r\n // eslint-disable-next-line github/no-then\r\n return (GaussianSplattingMesh.ConvertPLYWithSHToSplatAsync(data) as any).then(async (splatsData: any) => {\r\n const dataView = new DataView(data, headerEndIndex + headerEnd.length);\r\n let offset = rowChunkLength * chunkCount + rowVertexLength * vertexCount;\r\n // faces\r\n const faces: number[] = [];\r\n if (faceCount) {\r\n for (let i = 0; i < faceCount; i++) {\r\n const faceVertexCount = dataView.getUint8(offset);\r\n if (faceVertexCount != 3) {\r\n continue; // only support triangles\r\n }\r\n offset += 1;\r\n\r\n for (let j = 0; j < faceVertexCount; j++) {\r\n const vertexIndex = dataView.getUint32(offset + (2 - j) * 4, true); // change face winding\r\n faces.push(vertexIndex);\r\n }\r\n offset += 12;\r\n }\r\n }\r\n\r\n // early exit for chunked/quantized ply\r\n if (chunkCount) {\r\n return await new Promise((resolve) => {\r\n resolve({\r\n mode: Mode.Splat,\r\n data: splatsData.buffer,\r\n sh: splatsData.sh,\r\n shDegree: splatsData.shDegree,\r\n faces: faces,\r\n hasVertexColors: false,\r\n compressed: true,\r\n rawSplat: false,\r\n });\r\n });\r\n }\r\n // count available properties. if all necessary are present then it's a splat. Otherwise, it's a point cloud\r\n // if faces are found, then it's a standard mesh\r\n let propertyCount = 0;\r\n let propertyColorCount = 0;\r\n const splatProperties = [\"x\", \"y\", \"z\", \"scale_0\", \"scale_1\", \"scale_2\", \"opacity\", \"rot_0\", \"rot_1\", \"rot_2\", \"rot_3\"];\r\n const splatColorProperties = [\"red\", \"green\", \"blue\", \"f_dc_0\", \"f_dc_1\", \"f_dc_2\"];\r\n for (let propertyIndex = 0; propertyIndex < vertexProperties.length; propertyIndex++) {\r\n const property = vertexProperties[propertyIndex];\r\n if (splatProperties.includes(property.name)) {\r\n propertyCount++;\r\n }\r\n if (splatColorProperties.includes(property.name)) {\r\n propertyColorCount++;\r\n }\r\n }\r\n const hasMandatoryProperties = propertyCount == splatProperties.length && propertyColorCount == 3;\r\n const currentMode = faceCount ? Mode.Mesh : hasMandatoryProperties ? Mode.Splat : Mode.PointCloud;\r\n // parsed ready ready to be used as a splat\r\n return await new Promise((resolve) => {\r\n resolve({\r\n ...metaData,\r\n mode: currentMode,\r\n data: splatsData.buffer,\r\n sh: splatsData.sh,\r\n shDegree: splatsData.shDegree,\r\n faces: faces,\r\n hasVertexColors: !!propertyColorCount,\r\n compressed: false,\r\n rawSplat: false,\r\n });\r\n });\r\n });\r\n }\r\n}\r\n\r\n// Add this loader into the register plugin\r\nRegisterSceneLoaderPlugin(new SPLATFileLoader());\r\n"]}
@@ -30,4 +30,15 @@ export type SPLATLoadingOptions = {
30
30
  * Mesh that will be used to load data instead of creating a new one
31
31
  */
32
32
  gaussianSplattingMesh?: GaussianSplattingMesh;
33
+ /**
34
+ * URL to load the spz WASM ES module from (e.g. the \@adobe/spz package).
35
+ * When provided, the WASM-based SPZ loader is used, which supports extra features
36
+ * such as antialiasing metadata, and vendor-specific extensions such as safe-orbit
37
+ * camera limits.
38
+ * Defaults to the \@adobe/spz unpkg URL when WebAssembly is supported, and undefined otherwise.
39
+ * Set to undefined to force the built-in manual SPZ parser regardless of WebAssembly support.
40
+ * @example Setting the URL directly on the loader options
41
+ * spzLibraryUrl: "https://unpkg.com/\@adobe/spz\@0.2.0/dist/spz.js"
42
+ */
43
+ spzLibraryUrl?: string;
33
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"splatLoadingOptions.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatLoadingOptions.ts"],"names":[],"mappings":"","sourcesContent":["import { type GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\n\r\n/**\r\n * Options for loading Gaussian Splatting and PLY files\r\n */\r\nexport type SPLATLoadingOptions = {\r\n /**\r\n * Defines if buffers should be kept in memory for editing purposes\r\n */\r\n keepInRam?: boolean;\r\n /**\r\n * Spatial Y Flip for splat position and orientation\r\n */\r\n flipY?: boolean;\r\n /**\r\n * URL to load fflate from. If null or undefined, will load from unpkg.com\r\n * (https://unpkg.com/fflate/umd/index.js)\r\n */\r\n deflateURL?: string;\r\n /**\r\n * Instance of [fflate](https://github.com/101arrowz/fflate) to avoid\r\n * dynamically loading of the lib to global if needed, useful for bundler users.\r\n * @example import * as fflate from 'fflate';\r\n */\r\n fflate?: unknown;\r\n\r\n /**\r\n * Disable automatic camera limits from being applied if they exist in the splat file\r\n */\r\n disableAutoCameraLimits?: boolean;\r\n\r\n /**\r\n * Mesh that will be used to load data instead of creating a new one\r\n */\r\n gaussianSplattingMesh?: GaussianSplattingMesh;\r\n};\r\n"]}
1
+ {"version":3,"file":"splatLoadingOptions.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatLoadingOptions.ts"],"names":[],"mappings":"","sourcesContent":["import { type GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\n\r\n/**\r\n * Options for loading Gaussian Splatting and PLY files\r\n */\r\nexport type SPLATLoadingOptions = {\r\n /**\r\n * Defines if buffers should be kept in memory for editing purposes\r\n */\r\n keepInRam?: boolean;\r\n /**\r\n * Spatial Y Flip for splat position and orientation\r\n */\r\n flipY?: boolean;\r\n /**\r\n * URL to load fflate from. If null or undefined, will load from unpkg.com\r\n * (https://unpkg.com/fflate/umd/index.js)\r\n */\r\n deflateURL?: string;\r\n /**\r\n * Instance of [fflate](https://github.com/101arrowz/fflate) to avoid\r\n * dynamically loading of the lib to global if needed, useful for bundler users.\r\n * @example import * as fflate from 'fflate';\r\n */\r\n fflate?: unknown;\r\n\r\n /**\r\n * Disable automatic camera limits from being applied if they exist in the splat file\r\n */\r\n disableAutoCameraLimits?: boolean;\r\n\r\n /**\r\n * Mesh that will be used to load data instead of creating a new one\r\n */\r\n gaussianSplattingMesh?: GaussianSplattingMesh;\r\n\r\n /**\r\n * URL to load the spz WASM ES module from (e.g. the \\@adobe/spz package).\r\n * When provided, the WASM-based SPZ loader is used, which supports extra features\r\n * such as antialiasing metadata, and vendor-specific extensions such as safe-orbit\r\n * camera limits.\r\n * Defaults to the \\@adobe/spz unpkg URL when WebAssembly is supported, and undefined otherwise.\r\n * Set to undefined to force the built-in manual SPZ parser regardless of WebAssembly support.\r\n * @example Setting the URL directly on the loader options\r\n * spzLibraryUrl: \"https://unpkg.com/\\@adobe/spz\\@0.2.0/dist/spz.js\"\r\n */\r\n spzLibraryUrl?: string;\r\n};\r\n"]}
package/SPLAT/spz.d.ts CHANGED
@@ -1,11 +1,45 @@
1
1
  import { type Scene } from "@babylonjs/core/scene.js";
2
+ import { type Coroutine } from "@babylonjs/core/Misc/coroutine.js";
2
3
  import { type SPLATLoadingOptions } from "./splatLoadingOptions.js";
3
4
  import { type IParsedSplat } from "./splatDefs.js";
5
+ import { type GaussianCloud, type SpzModule } from "@adobe/spz";
4
6
  /**
5
- * Parses SPZ data and returns a promise resolving to an IParsedPLY object.
7
+ * Parses SPZ data and returns a promise resolving to an IParsedSplat object.
6
8
  * @param data The ArrayBuffer containing SPZ data.
7
9
  * @param scene The Babylon.js scene.
8
- * @param loadingOptions Options for loading Gaussian Splatting files.
10
+ * @param _loadingOptions Options for loading Gaussian Splatting files.
9
11
  * @returns A promise resolving to the parsed SPZ data.
10
12
  */
11
- export declare function ParseSpz(data: ArrayBuffer, scene: Scene, loadingOptions: SPLATLoadingOptions): Promise<IParsedSplat>;
13
+ export declare function ParseSpz(data: ArrayBuffer, scene: Scene, _loadingOptions: SPLATLoadingOptions): Promise<IParsedSplat>;
14
+ /**
15
+ * Returns the initialized spz WASM module loaded from the given URL, loading it on first call.
16
+ * @param url URL to the spz WASM ES module (its default export should be a factory function)
17
+ * @returns A promise resolving to the initialized spz WASM module
18
+ */
19
+ export declare function GetSpzModule(url: string): Promise<SpzModule>;
20
+ /**
21
+ * Converts a GaussianCloud object (from the spz WASM module) into the packed 32-byte-per-splat
22
+ * ArrayBuffer and SH texture arrays expected by GaussianSplattingMeshBase.updateData.
23
+ *
24
+ * Packed layout per splat (32 bytes):
25
+ * [0-11] position xyz (float32 x3)
26
+ * [12-23] scale xyz (float32 x3)
27
+ * [24-27] color RGBA (uint8 x4, colors in [0,255], alpha in [0,255])
28
+ * [28-31] quaternion wxyz (uint8 x4, encoded as q * 127.5 + 127.5)
29
+ *
30
+ * SH coefficients from the cloud (Float32, range ~[-1,1]) are encoded to bytes
31
+ * using the SPZ convention (load-spz.cc unquantizeSH): byte = coeff * 128 + 128.
32
+ *
33
+ * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer
34
+ * @param scene The Babylon.js scene (used to query maxTextureSize for SH textures)
35
+ * @param useCoroutine If true, yields periodically to avoid blocking the main thread
36
+ * @returns A coroutine returning an IParsedSplat ready to be passed to updateData
37
+ */
38
+ export declare function ConvertSpzToSplat(cloud: GaussianCloud, scene: Scene, useCoroutine?: boolean): Coroutine<IParsedSplat>;
39
+ /**
40
+ * Async version of ConvertSpzToSplat that yields periodically to avoid blocking the main thread.
41
+ * @param cloud The GaussianCloud returned by spz.loadSpzFromBuffer
42
+ * @param scene The Babylon.js scene
43
+ * @returns A promise resolving to an IParsedSplat
44
+ */
45
+ export declare function ConvertSpzToSplatAsync(cloud: any, scene: Scene): Promise<IParsedSplat>;