@babylonjs/loaders 7.37.0 → 7.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SPLAT/splatFileLoader.d.ts +4 -0
- package/SPLAT/splatFileLoader.js +169 -38
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/SPLAT/splatFileLoader.metadata.d.ts +3 -0
- package/SPLAT/splatFileLoader.metadata.js +2 -0
- package/SPLAT/splatFileLoader.metadata.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_variants.d.ts +38 -18
- package/glTF/2.0/Extensions/KHR_materials_variants.js +50 -26
- package/glTF/2.0/Extensions/KHR_materials_variants.js.map +1 -1
- package/glTF/2.0/glTFLoader.js +2 -21
- package/glTF/2.0/glTFLoader.js.map +1 -1
- package/package.json +3 -3
|
@@ -34,6 +34,9 @@ export declare class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneL
|
|
|
34
34
|
readonly ".ply": {
|
|
35
35
|
readonly isBinary: true;
|
|
36
36
|
};
|
|
37
|
+
readonly ".spz": {
|
|
38
|
+
readonly isBinary: true;
|
|
39
|
+
};
|
|
37
40
|
};
|
|
38
41
|
/**
|
|
39
42
|
* Creates loader for gaussian splatting files
|
|
@@ -56,6 +59,7 @@ export declare class SPLATFileLoader implements ISceneLoaderPluginAsync, ISceneL
|
|
|
56
59
|
importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
|
|
57
60
|
private static _BuildPointCloud;
|
|
58
61
|
private static _BuildMesh;
|
|
62
|
+
private _parseSPZ;
|
|
59
63
|
private _parse;
|
|
60
64
|
/**
|
|
61
65
|
* Load into an asset container.
|
package/SPLAT/splatFileLoader.js
CHANGED
|
@@ -16,6 +16,7 @@ var Mode;
|
|
|
16
16
|
Mode[Mode["Splat"] = 0] = "Splat";
|
|
17
17
|
Mode[Mode["PointCloud"] = 1] = "PointCloud";
|
|
18
18
|
Mode[Mode["Mesh"] = 2] = "Mesh";
|
|
19
|
+
Mode[Mode["Reject"] = 3] = "Reject";
|
|
19
20
|
})(Mode || (Mode = {}));
|
|
20
21
|
/**
|
|
21
22
|
* @experimental
|
|
@@ -122,46 +123,176 @@ export class SPLATFileLoader {
|
|
|
122
123
|
vertexData.applyToMesh(mesh);
|
|
123
124
|
return mesh;
|
|
124
125
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
126
|
+
_parseSPZ(data, scene) {
|
|
127
|
+
const ubuf = new Uint8Array(data);
|
|
128
|
+
const ubufu32 = new Uint32Array(data);
|
|
129
|
+
// debug infos
|
|
130
|
+
//Logger.Log(`SPZ version ${ubufu32[1]}`);
|
|
131
|
+
//Logger.Log(`num points ${ubufu32[2]}`);
|
|
132
|
+
const splatCount = ubufu32[2];
|
|
133
|
+
const shDegree = ubuf[12];
|
|
134
|
+
const fractionalBits = ubuf[13];
|
|
135
|
+
//const flags = ubuf[14];
|
|
136
|
+
const reserved = ubuf[15];
|
|
137
|
+
// check magic and version
|
|
138
|
+
if (reserved || ubufu32[0] != 0x5053474e || ubufu32[1] != 2) {
|
|
139
|
+
// reserved must be 0
|
|
140
|
+
return new Promise((resolve) => {
|
|
141
|
+
resolve({ mode: 3 /* Mode.Reject */, data: buffer, hasVertexColors: false });
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const rowOutputLength = 3 * 4 + 3 * 4 + 4 + 4; // 32
|
|
145
|
+
const buffer = new ArrayBuffer(rowOutputLength * splatCount);
|
|
146
|
+
const positionScale = 1.0 / (1 << fractionalBits);
|
|
147
|
+
const int32View = new Int32Array(1);
|
|
148
|
+
const uint8View = new Uint8Array(int32View.buffer);
|
|
149
|
+
const read24bComponent = function (u8, offset) {
|
|
150
|
+
uint8View[0] = u8[offset + 0];
|
|
151
|
+
uint8View[1] = u8[offset + 1];
|
|
152
|
+
uint8View[2] = u8[offset + 2];
|
|
153
|
+
uint8View[3] = u8[offset + 2] & 0x80 ? 0xff : 0x00;
|
|
154
|
+
return int32View[0] * positionScale;
|
|
155
|
+
};
|
|
156
|
+
let byteOffset = 16;
|
|
157
|
+
const position = new Float32Array(buffer);
|
|
158
|
+
const scale = new Float32Array(buffer);
|
|
159
|
+
const rgba = new Uint8ClampedArray(buffer);
|
|
160
|
+
const rot = new Uint8ClampedArray(buffer);
|
|
161
|
+
// positions
|
|
162
|
+
for (let i = 0; i < splatCount; i++) {
|
|
163
|
+
position[i * 8 + 0] = read24bComponent(ubuf, byteOffset + 0);
|
|
164
|
+
position[i * 8 + 1] = -read24bComponent(ubuf, byteOffset + 3);
|
|
165
|
+
position[i * 8 + 2] = read24bComponent(ubuf, byteOffset + 6);
|
|
166
|
+
byteOffset += 9;
|
|
167
|
+
}
|
|
168
|
+
// colors
|
|
169
|
+
for (let i = 0; i < splatCount; i++) {
|
|
170
|
+
rgba[i * 32 + 24 + 0] = ubuf[byteOffset + splatCount + i * 3 + 0];
|
|
171
|
+
rgba[i * 32 + 24 + 1] = ubuf[byteOffset + splatCount + i * 3 + 1];
|
|
172
|
+
rgba[i * 32 + 24 + 2] = ubuf[byteOffset + splatCount + i * 3 + 2];
|
|
173
|
+
rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i];
|
|
174
|
+
}
|
|
175
|
+
byteOffset += splatCount * 4;
|
|
176
|
+
// scales
|
|
177
|
+
for (let i = 0; i < splatCount; i++) {
|
|
178
|
+
scale[i * 8 + 3 + 0] = Math.exp(ubuf[byteOffset + 0] / 16.0 - 10.0);
|
|
179
|
+
scale[i * 8 + 3 + 1] = Math.exp(ubuf[byteOffset + 1] / 16.0 - 10.0);
|
|
180
|
+
scale[i * 8 + 3 + 2] = Math.exp(ubuf[byteOffset + 2] / 16.0 - 10.0);
|
|
181
|
+
byteOffset += 3;
|
|
182
|
+
}
|
|
183
|
+
// rotations
|
|
184
|
+
for (let i = 0; i < splatCount; i++) {
|
|
185
|
+
const x = ubuf[byteOffset + 0];
|
|
186
|
+
const y = ubuf[byteOffset + 1];
|
|
187
|
+
const z = ubuf[byteOffset + 2];
|
|
188
|
+
const nx = x / 127.5 - 1;
|
|
189
|
+
const ny = y / 127.5 - 1;
|
|
190
|
+
const nz = z / 127.5 - 1;
|
|
191
|
+
rot[i * 32 + 28 + 1] = x;
|
|
192
|
+
rot[i * 32 + 28 + 2] = y;
|
|
193
|
+
rot[i * 32 + 28 + 3] = z;
|
|
194
|
+
rot[i * 32 + 28 + 0] = (1 - Math.sqrt(nx * nx + ny * ny + nz * nz)) * 127.5 + 127.5;
|
|
195
|
+
byteOffset += 3;
|
|
196
|
+
}
|
|
197
|
+
//SH
|
|
198
|
+
if (shDegree) {
|
|
199
|
+
// shVectorCount is : 3 for dim = 1, 8 for dim = 2 and 15 for dim = 3
|
|
200
|
+
// number of vec3 vector needed per splat
|
|
201
|
+
const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1; // minus 1 because sh0 is color
|
|
202
|
+
// number of component values : 3 per vector3 (45)
|
|
203
|
+
const shComponentCount = shVectorCount * 3;
|
|
204
|
+
const textureCount = Math.ceil(shComponentCount / 16); // 4 components can be stored per texture, 4 sh per component
|
|
205
|
+
let shIndexRead = byteOffset;
|
|
206
|
+
// sh is an array of uint8array that will be used to create sh textures
|
|
207
|
+
const sh = [];
|
|
208
|
+
const engine = scene.getEngine();
|
|
209
|
+
const width = engine.getCaps().maxTextureSize;
|
|
210
|
+
const height = Math.ceil(splatCount / width);
|
|
211
|
+
// create array for the number of textures needed.
|
|
212
|
+
for (let textureIndex = 0; textureIndex < textureCount; textureIndex++) {
|
|
213
|
+
const texture = new Uint8Array(height * width * 4 * 4); // 4 components per texture, 4 sh per component
|
|
214
|
+
sh.push(texture);
|
|
215
|
+
}
|
|
216
|
+
for (let i = 0; i < splatCount; i++) {
|
|
217
|
+
for (let shIndexWrite = 0; shIndexWrite < shComponentCount; shIndexWrite++) {
|
|
218
|
+
const shValue = ubuf[shIndexRead++];
|
|
219
|
+
const textureIndex = Math.floor(shIndexWrite / 16);
|
|
220
|
+
const shArray = sh[textureIndex];
|
|
221
|
+
const byteIndexInTexture = shIndexWrite % 16; // [0..15]
|
|
222
|
+
const offsetPerSplat = i * 16; // 16 sh values per texture per splat.
|
|
223
|
+
shArray[byteIndexInTexture + offsetPerSplat] = shValue;
|
|
224
|
+
}
|
|
163
225
|
}
|
|
164
226
|
return new Promise((resolve) => {
|
|
227
|
+
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false, sh: sh });
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return new Promise((resolve) => {
|
|
231
|
+
resolve({ mode: 0 /* Mode.Splat */, data: buffer, hasVertexColors: false });
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
_parse(meshesNames, scene, data, rootUrl) {
|
|
235
|
+
const babylonMeshesArray = []; //The mesh for babylon
|
|
236
|
+
const readableStream = new ReadableStream({
|
|
237
|
+
start(controller) {
|
|
238
|
+
controller.enqueue(new Uint8Array(data)); // Enqueue the ArrayBuffer as a Uint8Array
|
|
239
|
+
controller.close();
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
// Use GZip DecompressionStream
|
|
243
|
+
const decompressionStream = new DecompressionStream("gzip");
|
|
244
|
+
const decompressedStream = readableStream.pipeThrough(decompressionStream);
|
|
245
|
+
return new Promise((resolve) => {
|
|
246
|
+
new Response(decompressedStream)
|
|
247
|
+
.arrayBuffer()
|
|
248
|
+
.then((buffer) => {
|
|
249
|
+
this._parseSPZ(buffer, scene).then((parsedSPZ) => {
|
|
250
|
+
const gaussianSplatting = new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
|
|
251
|
+
gaussianSplatting._parentContainer = this._assetContainer;
|
|
252
|
+
babylonMeshesArray.push(gaussianSplatting);
|
|
253
|
+
gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh);
|
|
254
|
+
});
|
|
255
|
+
resolve(babylonMeshesArray);
|
|
256
|
+
})
|
|
257
|
+
.catch(() => {
|
|
258
|
+
// Catch any decompression errors
|
|
259
|
+
SPLATFileLoader._ConvertPLYToSplat(data).then(async (parsedPLY) => {
|
|
260
|
+
switch (parsedPLY.mode) {
|
|
261
|
+
case 0 /* Mode.Splat */:
|
|
262
|
+
{
|
|
263
|
+
const gaussianSplatting = new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
|
|
264
|
+
gaussianSplatting._parentContainer = this._assetContainer;
|
|
265
|
+
babylonMeshesArray.push(gaussianSplatting);
|
|
266
|
+
gaussianSplatting.updateData(parsedPLY.data);
|
|
267
|
+
}
|
|
268
|
+
break;
|
|
269
|
+
case 1 /* Mode.PointCloud */:
|
|
270
|
+
{
|
|
271
|
+
const pointcloud = new PointsCloudSystem("PointCloud", 1, scene);
|
|
272
|
+
if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {
|
|
273
|
+
await pointcloud.buildMeshAsync().then((mesh) => {
|
|
274
|
+
babylonMeshesArray.push(mesh);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
pointcloud.dispose();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
break;
|
|
282
|
+
case 2 /* Mode.Mesh */:
|
|
283
|
+
{
|
|
284
|
+
if (parsedPLY.faces) {
|
|
285
|
+
babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
throw new Error("PLY mesh doesn't contain face informations.");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
default:
|
|
293
|
+
throw new Error("Unsupported Splat mode");
|
|
294
|
+
}
|
|
295
|
+
});
|
|
165
296
|
resolve(babylonMeshesArray);
|
|
166
297
|
});
|
|
167
298
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"splatFileLoader.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ISceneLoaderPluginAsync, ISceneLoaderPluginFactory, ISceneLoaderAsyncResult, ISceneLoaderProgressEvent, SceneLoaderPluginOptions } from \"core/Loading/sceneLoader\";\r\nimport { registerSceneLoaderPlugin } 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\n\r\ndeclare module \"core/Loading/sceneLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc\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/**\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\nconst enum Mode {\r\n Splat = 0,\r\n PointCloud = 1,\r\n Mesh = 2,\r\n}\r\n\r\n/**\r\n * A parsed buffer and how to use it\r\n */\r\ninterface ParsedPLY {\r\n data: ArrayBuffer;\r\n mode: Mode;\r\n faces?: number[];\r\n hasVertexColors?: boolean;\r\n}\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 } 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 return this._parse(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: ParsedPLY): 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 private _parse(meshesNames: any, scene: Scene, data: any, rootUrl: string): Promise<Array<AbstractMesh>> {\r\n return SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer).then(async (parsedPLY) => {\r\n const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n switch (parsedPLY.mode) {\r\n case Mode.Splat:\r\n {\r\n const gaussianSplatting = new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n await gaussianSplatting.updateDataAsync(parsedPLY.data);\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 return Promise.all([pointcloud.buildMeshAsync()]).then((mesh) => {\r\n babylonMeshesArray.push(mesh[0]);\r\n return babylonMeshesArray;\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 return new Promise((resolve) => {\r\n resolve(babylonMeshesArray);\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 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 this.importMeshAsync(null, scene, data, rootUrl)\r\n .then((result) => {\r\n result.meshes.forEach((mesh) => container.meshes.push(mesh));\r\n // mesh material will be null before 1st rendered frame.\r\n this._assetContainer = null;\r\n return container;\r\n })\r\n .catch((ex) => {\r\n this._assetContainer = null;\r\n throw ex;\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 public loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void> {\r\n //Get the 3D model\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<ParsedPLY> {\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 });\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 enum ElementMode {\r\n Vertex = 0,\r\n Chunk = 1,\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 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 }\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 }\r\n }\r\n }\r\n\r\n const rowVertexLength = rowVertexOffset;\r\n const rowChunkLength = rowChunkOffset;\r\n\r\n return GaussianSplattingMesh.ConvertPLYToSplatAsync(data).then((buffer) => {\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 new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: buffer, faces: faces, hasVertexColors: 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 new Promise((resolve) => {\r\n resolve({ mode: currentMode, data: buffer, faces: faces, hasVertexColors: !!propertyColorCount });\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":["import type { ISceneLoaderPluginAsync, ISceneLoaderPluginFactory, ISceneLoaderAsyncResult, ISceneLoaderProgressEvent, SceneLoaderPluginOptions } from \"core/Loading/sceneLoader\";\r\nimport { registerSceneLoaderPlugin } 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\n\r\ndeclare module \"core/Loading/sceneLoader\" {\r\n // eslint-disable-next-line jsdoc/require-jsdoc\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/**\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\nconst 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\ninterface ParsedPLY {\r\n data: ArrayBuffer;\r\n mode: Mode;\r\n faces?: number[];\r\n hasVertexColors?: boolean;\r\n sh?: Uint8Array[];\r\n}\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 } 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 return this._parse(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: ParsedPLY): 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 private _parseSPZ(data: ArrayBuffer, scene: Scene): Promise<ParsedPLY> {\r\n const ubuf = new Uint8Array(data);\r\n const ubufu32 = new Uint32Array(data);\r\n // debug infos\r\n //Logger.Log(`SPZ version ${ubufu32[1]}`);\r\n //Logger.Log(`num points ${ubufu32[2]}`);\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\r\n // check magic and version\r\n if (reserved || ubufu32[0] != 0x5053474e || ubufu32[1] != 2) {\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 for (let i = 0; i < splatCount; i++) {\r\n rgba[i * 32 + 24 + 0] = ubuf[byteOffset + splatCount + i * 3 + 0];\r\n rgba[i * 32 + 24 + 1] = ubuf[byteOffset + splatCount + i * 3 + 1];\r\n rgba[i * 32 + 24 + 2] = ubuf[byteOffset + splatCount + i * 3 + 2];\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 // rotations\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 rot[i * 32 + 28 + 0] = (1 - Math.sqrt(nx * nx + ny * ny + nz * nz)) * 127.5 + 127.5;\r\n byteOffset += 3;\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 });\r\n });\r\n }\r\n\r\n return new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: buffer, hasVertexColors: false });\r\n });\r\n }\r\n\r\n private _parse(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 readableStream = new ReadableStream({\r\n start(controller) {\r\n controller.enqueue(new Uint8Array(data)); // Enqueue the ArrayBuffer as a Uint8Array\r\n controller.close();\r\n },\r\n });\r\n\r\n // Use GZip DecompressionStream\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 .then((buffer) => {\r\n this._parseSPZ(buffer, scene).then((parsedSPZ) => {\r\n const gaussianSplatting = new GaussianSplattingMesh(\"GaussianSplatting\", null, scene, this._loadingOptions.keepInRam);\r\n gaussianSplatting._parentContainer = this._assetContainer;\r\n babylonMeshesArray.push(gaussianSplatting);\r\n gaussianSplatting.updateData(parsedSPZ.data, parsedSPZ.sh);\r\n });\r\n resolve(babylonMeshesArray);\r\n })\r\n .catch(() => {\r\n // Catch any decompression errors\r\n SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer).then(async (parsedPLY) => {\r\n switch (parsedPLY.mode) {\r\n case Mode.Splat:\r\n {\r\n const gaussianSplatting = 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);\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 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 });\r\n resolve(babylonMeshesArray);\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 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 this.importMeshAsync(null, scene, data, rootUrl)\r\n .then((result) => {\r\n result.meshes.forEach((mesh) => container.meshes.push(mesh));\r\n // mesh material will be null before 1st rendered frame.\r\n this._assetContainer = null;\r\n return container;\r\n })\r\n .catch((ex) => {\r\n this._assetContainer = null;\r\n throw ex;\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 public loadAsync(scene: Scene, data: string, rootUrl: string): Promise<void> {\r\n //Get the 3D model\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<ParsedPLY> {\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 });\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 enum ElementMode {\r\n Vertex = 0,\r\n Chunk = 1,\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 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 }\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 }\r\n }\r\n }\r\n\r\n const rowVertexLength = rowVertexOffset;\r\n const rowChunkLength = rowChunkOffset;\r\n\r\n return GaussianSplattingMesh.ConvertPLYToSplatAsync(data).then((buffer) => {\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 new Promise((resolve) => {\r\n resolve({ mode: Mode.Splat, data: buffer, faces: faces, hasVertexColors: 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 new Promise((resolve) => {\r\n resolve({ mode: currentMode, data: buffer, faces: faces, hasVertexColors: !!propertyColorCount });\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"]}
|
|
@@ -5,6 +5,8 @@ export const SPLATFileLoaderMetadata = {
|
|
|
5
5
|
".splat": { isBinary: true },
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
7
7
|
".ply": { isBinary: true },
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
|
+
".spz": { isBinary: true },
|
|
8
10
|
},
|
|
9
11
|
};
|
|
10
12
|
//# sourceMappingURL=splatFileLoader.metadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"splatFileLoader.metadata.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.metadata.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACnC,IAAI,EAAE,OAAO;IAEb,UAAU,EAAE;QACR,gEAAgE;QAChE,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5B,gEAAgE;QAChE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;KACmB;CACN,CAAC","sourcesContent":["// eslint-disable-next-line import/no-internal-modules\r\nimport type { ISceneLoaderPluginExtensions, ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const SPLATFileLoaderMetadata = {\r\n name: \"splat\",\r\n\r\n extensions: {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \".splat\": { isBinary: true },\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \".ply\": { isBinary: true },\r\n } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n"]}
|
|
1
|
+
{"version":3,"file":"splatFileLoader.metadata.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.metadata.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACnC,IAAI,EAAE,OAAO;IAEb,UAAU,EAAE;QACR,gEAAgE;QAChE,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5B,gEAAgE;QAChE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC1B,gEAAgE;QAChE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;KACmB;CACN,CAAC","sourcesContent":["// eslint-disable-next-line import/no-internal-modules\r\nimport type { ISceneLoaderPluginExtensions, ISceneLoaderPluginMetadata } from \"core/index\";\r\n\r\nexport const SPLATFileLoaderMetadata = {\r\n name: \"splat\",\r\n\r\n extensions: {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \".splat\": { isBinary: true },\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \".ply\": { isBinary: true },\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \".spz\": { isBinary: true },\r\n } as const satisfies ISceneLoaderPluginExtensions,\r\n} as const satisfies ISceneLoaderPluginMetadata;\r\n"]}
|
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
import type { Nullable } from "@babylonjs/core/types.js";
|
|
2
2
|
import type { IGLTFLoaderExtension } from "../glTFLoaderExtension";
|
|
3
3
|
import { GLTFLoader } from "../glTFLoader";
|
|
4
|
-
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
|
5
4
|
import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
|
|
6
5
|
import type { INode, IMeshPrimitive, IMesh } from "../glTFLoaderInterfaces";
|
|
6
|
+
import type { TransformNode } from "@babylonjs/core/Meshes/transformNode.js";
|
|
7
|
+
import type { MaterialVariantsController } from "../../glTFFileLoader";
|
|
8
|
+
export { MaterialVariantsController };
|
|
7
9
|
declare module "../../glTFFileLoader" {
|
|
10
|
+
type MaterialVariantsController = {
|
|
11
|
+
/**
|
|
12
|
+
* The list of available variant names for this asset.
|
|
13
|
+
*/
|
|
14
|
+
readonly variants: readonly string[];
|
|
15
|
+
/**
|
|
16
|
+
* Gets or sets the selected variant.
|
|
17
|
+
*/
|
|
18
|
+
selectedVariant: string;
|
|
19
|
+
};
|
|
8
20
|
interface GLTFLoaderExtensionOptions {
|
|
9
21
|
/**
|
|
10
22
|
* Defines options for the KHR_materials_variants extension.
|
|
11
23
|
*/
|
|
12
|
-
["KHR_materials_variants"]: {
|
|
24
|
+
["KHR_materials_variants"]: Partial<{
|
|
25
|
+
/**
|
|
26
|
+
* Defines a callback that will be called if material variants are loaded.
|
|
27
|
+
* @experimental
|
|
28
|
+
*/
|
|
29
|
+
onLoaded: (controller: MaterialVariantsController) => void;
|
|
30
|
+
}>;
|
|
13
31
|
}
|
|
14
32
|
}
|
|
15
33
|
/**
|
|
@@ -34,53 +52,55 @@ export declare class KHR_materials_variants implements IGLTFLoaderExtension {
|
|
|
34
52
|
dispose(): void;
|
|
35
53
|
/**
|
|
36
54
|
* Gets the list of available variant names for this asset.
|
|
37
|
-
* @param
|
|
55
|
+
* @param rootNode The glTF root node
|
|
38
56
|
* @returns the list of all the variant names for this model
|
|
39
57
|
*/
|
|
40
|
-
static GetAvailableVariants(
|
|
58
|
+
static GetAvailableVariants(rootNode: TransformNode): string[];
|
|
41
59
|
/**
|
|
42
60
|
* Gets the list of available variant names for this asset.
|
|
43
|
-
* @param
|
|
61
|
+
* @param rootNode The glTF root node
|
|
44
62
|
* @returns the list of all the variant names for this model
|
|
45
63
|
*/
|
|
46
|
-
getAvailableVariants(
|
|
64
|
+
getAvailableVariants(rootNode: TransformNode): string[];
|
|
47
65
|
/**
|
|
48
66
|
* Select a variant given a variant name or a list of variant names.
|
|
49
|
-
* @param
|
|
67
|
+
* @param rootNode The glTF root node
|
|
50
68
|
* @param variantName The variant name(s) to select.
|
|
51
69
|
*/
|
|
52
|
-
static SelectVariant(
|
|
70
|
+
static SelectVariant(rootNode: TransformNode, variantName: string | string[]): void;
|
|
53
71
|
/**
|
|
54
72
|
* Select a variant given a variant name or a list of variant names.
|
|
55
|
-
* @param
|
|
73
|
+
* @param rootNode The glTF root node
|
|
56
74
|
* @param variantName The variant name(s) to select.
|
|
57
75
|
*/
|
|
58
|
-
selectVariant(
|
|
76
|
+
selectVariant(rootNode: TransformNode, variantName: string | string[]): void;
|
|
59
77
|
/**
|
|
60
78
|
* Reset back to the original before selecting a variant.
|
|
61
|
-
* @param
|
|
79
|
+
* @param rootNode The glTF root node
|
|
62
80
|
*/
|
|
63
|
-
static Reset(
|
|
81
|
+
static Reset(rootNode: TransformNode): void;
|
|
64
82
|
/**
|
|
65
83
|
* Reset back to the original before selecting a variant.
|
|
66
|
-
* @param
|
|
84
|
+
* @param rootNode The glTF root node
|
|
67
85
|
*/
|
|
68
|
-
reset(
|
|
86
|
+
reset(rootNode: TransformNode): void;
|
|
69
87
|
/**
|
|
70
88
|
* Gets the last selected variant name(s) or null if original.
|
|
71
|
-
* @param
|
|
89
|
+
* @param rootNode The glTF root node
|
|
72
90
|
* @returns The selected variant name(s).
|
|
73
91
|
*/
|
|
74
|
-
static GetLastSelectedVariant(
|
|
92
|
+
static GetLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]>;
|
|
75
93
|
/**
|
|
76
94
|
* Gets the last selected variant name(s) or null if original.
|
|
77
|
-
* @param
|
|
95
|
+
* @param rootNode The glTF root node
|
|
78
96
|
* @returns The selected variant name(s).
|
|
79
97
|
*/
|
|
80
|
-
getLastSelectedVariant(
|
|
98
|
+
getLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]>;
|
|
81
99
|
private static _GetExtensionMetadata;
|
|
82
100
|
/** @internal */
|
|
83
101
|
onLoading(): void;
|
|
102
|
+
/** @internal */
|
|
103
|
+
onReady(): void;
|
|
84
104
|
/**
|
|
85
105
|
* @internal
|
|
86
106
|
*/
|