@babylonjs/loaders 7.23.0 → 7.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OBJ/objFileLoader.d.ts +4 -5
- package/OBJ/objFileLoader.js +3 -4
- package/OBJ/objFileLoader.js.map +1 -1
- package/OBJ/objFileLoader.metadata.d.ts +4 -0
- package/OBJ/objFileLoader.metadata.js +5 -0
- package/OBJ/objFileLoader.metadata.js.map +1 -0
- package/SPLAT/index.d.ts +1 -0
- package/SPLAT/index.js +1 -0
- package/SPLAT/index.js.map +1 -1
- package/SPLAT/splatFileLoader.d.ts +36 -29
- package/SPLAT/splatFileLoader.js +354 -52
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/SPLAT/splatFileLoader.metadata.d.ts +11 -0
- package/SPLAT/splatFileLoader.metadata.js +10 -0
- package/SPLAT/splatFileLoader.metadata.js.map +1 -0
- package/SPLAT/splatLoadingOptions.d.ts +9 -0
- package/SPLAT/splatLoadingOptions.js +2 -0
- package/SPLAT/splatLoadingOptions.js.map +1 -0
- package/STL/stlFileLoader.d.ts +3 -4
- package/STL/stlFileLoader.js +3 -5
- package/STL/stlFileLoader.js.map +1 -1
- package/STL/stlFileLoader.metadata.d.ts +8 -0
- package/STL/stlFileLoader.metadata.js +8 -0
- package/STL/stlFileLoader.metadata.js.map +1 -0
- package/dynamic.d.ts +5 -0
- package/dynamic.js +48 -0
- package/dynamic.js.map +1 -0
- package/glTF/2.0/Extensions/EXT_lights_image_based.js +3 -1
- package/glTF/2.0/Extensions/EXT_lights_image_based.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +3 -1
- package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_meshopt_compression.js +3 -1
- package/glTF/2.0/Extensions/EXT_meshopt_compression.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_texture_avif.js +3 -1
- package/glTF/2.0/Extensions/EXT_texture_avif.js.map +1 -1
- package/glTF/2.0/Extensions/EXT_texture_webp.js +3 -1
- package/glTF/2.0/Extensions/EXT_texture_webp.js.map +1 -1
- package/glTF/2.0/Extensions/ExtrasAsMetadata.d.ts +1 -1
- package/glTF/2.0/Extensions/ExtrasAsMetadata.js +3 -2
- package/glTF/2.0/Extensions/ExtrasAsMetadata.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_animation_pointer.d.ts +1 -1
- package/glTF/2.0/Extensions/KHR_animation_pointer.js +3 -2
- package/glTF/2.0/Extensions/KHR_animation_pointer.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +3 -1
- package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity.d.ts +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity.js +3 -2
- package/glTF/2.0/Extensions/KHR_interactivity.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_lights_punctual.js +3 -1
- package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_dispersion.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_ior.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_iridescence.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_sheen.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_specular.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_transmission.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_unlit.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_variants.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_variants.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_volume.js +3 -1
- package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_mesh_quantization.d.ts +1 -1
- package/glTF/2.0/Extensions/KHR_mesh_quantization.js +3 -2
- package/glTF/2.0/Extensions/KHR_mesh_quantization.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_texture_basisu.js +3 -1
- package/glTF/2.0/Extensions/KHR_texture_basisu.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_texture_transform.js +3 -1
- package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.d.ts +1 -1
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.js +3 -2
- package/glTF/2.0/Extensions/KHR_xmp_json_ld.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_audio_emitter.js +3 -1
- package/glTF/2.0/Extensions/MSFT_audio_emitter.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_lod.js +3 -1
- package/glTF/2.0/Extensions/MSFT_lod.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js +3 -1
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.js +3 -1
- package/glTF/2.0/Extensions/MSFT_sRGBFactors.js.map +1 -1
- package/glTF/2.0/Extensions/dynamic.d.ts +4 -0
- package/glTF/2.0/Extensions/dynamic.js +136 -0
- package/glTF/2.0/Extensions/dynamic.js.map +1 -0
- package/glTF/2.0/glTFLoader.d.ts +6 -6
- package/glTF/2.0/glTFLoader.js +24 -28
- package/glTF/2.0/glTFLoader.js.map +1 -1
- package/glTF/2.0/glTFLoaderExtensionRegistry.d.ts +25 -0
- package/glTF/2.0/glTFLoaderExtensionRegistry.js +30 -0
- package/glTF/2.0/glTFLoaderExtensionRegistry.js.map +1 -0
- package/glTF/glTFFileLoader.d.ts +4 -6
- package/glTF/glTFFileLoader.js +9 -17
- package/glTF/glTFFileLoader.js.map +1 -1
- package/glTF/glTFFileLoader.metadata.d.ts +13 -0
- package/glTF/glTFFileLoader.metadata.js +18 -0
- package/glTF/glTFFileLoader.metadata.js.map +1 -0
- package/package.json +3 -3
package/SPLAT/splatFileLoader.js
CHANGED
@@ -1,50 +1,52 @@
|
|
1
1
|
import { registerSceneLoaderPlugin } from "@babylonjs/core/Loading/sceneLoader.js";
|
2
|
+
import { SPLATFileLoaderMetadata } from "./splatFileLoader.metadata.js";
|
2
3
|
import { GaussianSplattingMesh } from "@babylonjs/core/Meshes/GaussianSplatting/gaussianSplattingMesh.js";
|
3
|
-
|
4
|
-
|
4
|
+
import { AssetContainer } from "@babylonjs/core/assetContainer.js";
|
5
|
+
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
6
|
+
import { Logger } from "@babylonjs/core/Misc/logger.js";
|
7
|
+
import { Quaternion, Vector3 } from "@babylonjs/core/Maths/math.vector.js";
|
8
|
+
import { PointsCloudSystem } from "@babylonjs/core/Particles/pointsCloudSystem.js";
|
9
|
+
import { Color4 } from "@babylonjs/core/Maths/math.color.js";
|
10
|
+
import { VertexData } from "@babylonjs/core/Meshes/mesh.vertexData.js";
|
11
|
+
/**
|
12
|
+
* Indicator of the parsed ply buffer. A standard ready to use splat or an array of positions for a point cloud
|
13
|
+
*/
|
14
|
+
var Mode;
|
15
|
+
(function (Mode) {
|
16
|
+
Mode[Mode["Splat"] = 0] = "Splat";
|
17
|
+
Mode[Mode["PointCloud"] = 1] = "PointCloud";
|
18
|
+
Mode[Mode["Mesh"] = 2] = "Mesh";
|
19
|
+
})(Mode || (Mode = {}));
|
5
20
|
/**
|
6
21
|
* @experimental
|
7
22
|
* SPLAT file type loader.
|
8
23
|
* This is a babylon scene loader plugin.
|
9
24
|
*/
|
10
25
|
export class SPLATFileLoader {
|
11
|
-
//private _loadingOptions: SPLATLoadingOptions;
|
12
26
|
/**
|
13
27
|
* Creates loader for gaussian splatting files
|
28
|
+
* @param loadingOptions options for loading and parsing splat and PLY files.
|
14
29
|
*/
|
15
|
-
constructor() {
|
30
|
+
constructor(loadingOptions = SPLATFileLoader._DefaultLoadingOptions) {
|
16
31
|
/**
|
17
32
|
* Defines the name of the plugin.
|
18
33
|
*/
|
19
|
-
this.name =
|
34
|
+
this.name = SPLATFileLoaderMetadata.name;
|
35
|
+
this._assetContainer = null;
|
20
36
|
/**
|
21
37
|
* Defines the extensions the splat loader is able to load.
|
22
38
|
* force data to come in as an ArrayBuffer
|
23
39
|
*/
|
24
|
-
this.extensions =
|
25
|
-
|
26
|
-
".splat": { isBinary: true },
|
27
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
28
|
-
".ply": { isBinary: true },
|
29
|
-
};
|
40
|
+
this.extensions = SPLATFileLoaderMetadata.extensions;
|
41
|
+
this._loadingOptions = loadingOptions;
|
30
42
|
}
|
31
|
-
/**
|
32
|
-
|
33
|
-
|
34
|
-
*/
|
35
|
-
createPlugin() {
|
36
|
-
return new SPLATFileLoader();
|
37
|
-
}
|
38
|
-
/**
|
39
|
-
* If the data string can be loaded directly.
|
40
|
-
* @returns if the data can be loaded directly
|
41
|
-
*/
|
42
|
-
canDirectLoad() {
|
43
|
-
return false;
|
43
|
+
/** @internal */
|
44
|
+
createPlugin(options) {
|
45
|
+
return new SPLATFileLoader(options[SPLATFileLoaderMetadata.name]);
|
44
46
|
}
|
45
47
|
/**
|
46
48
|
* Imports from the loaded gaussian splatting data and adds them to the scene
|
47
|
-
* @param
|
49
|
+
* @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
|
48
50
|
* @param scene the scene the meshes should be added to
|
49
51
|
* @param data the gaussian splatting data to load
|
50
52
|
* @param rootUrl root url to load from
|
@@ -52,43 +54,343 @@ export class SPLATFileLoader {
|
|
52
54
|
* @param fileName Defines the name of the file to load
|
53
55
|
* @returns a promise containing the loaded meshes, particles, skeletons and animations
|
54
56
|
*/
|
55
|
-
async importMeshAsync(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
async importMeshAsync(meshesNames, scene, data, rootUrl, onProgress, fileName) {
|
58
|
+
return this._parse(meshesNames, scene, data, rootUrl).then((meshes) => {
|
59
|
+
return {
|
60
|
+
meshes: meshes,
|
61
|
+
particleSystems: [],
|
62
|
+
skeletons: [],
|
63
|
+
animationGroups: [],
|
64
|
+
transformNodes: [],
|
65
|
+
geometries: [],
|
66
|
+
lights: [],
|
67
|
+
spriteManagers: [],
|
68
|
+
};
|
69
|
+
});
|
70
|
+
}
|
71
|
+
static _BuildPointCloud(pointcloud, data) {
|
72
|
+
if (!data.byteLength) {
|
73
|
+
return false;
|
74
|
+
}
|
75
|
+
const uBuffer = new Uint8Array(data);
|
76
|
+
const fBuffer = new Float32Array(data);
|
77
|
+
// parsed array contains room for position(3floats), normal(3floats), color (4b), quantized quaternion (4b)
|
78
|
+
const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
|
79
|
+
const vertexCount = uBuffer.length / rowLength;
|
80
|
+
const pointcloudfunc = function (particle, i) {
|
81
|
+
const x = fBuffer[8 * i + 0];
|
82
|
+
const y = fBuffer[8 * i + 1];
|
83
|
+
const z = fBuffer[8 * i + 2];
|
84
|
+
particle.position = new Vector3(x, y, z);
|
85
|
+
const r = uBuffer[rowLength * i + 24 + 0] / 255;
|
86
|
+
const g = uBuffer[rowLength * i + 24 + 1] / 255;
|
87
|
+
const b = uBuffer[rowLength * i + 24 + 2] / 255;
|
88
|
+
particle.color = new Color4(r, g, b, 1);
|
67
89
|
};
|
90
|
+
pointcloud.addPoints(vertexCount, pointcloudfunc);
|
91
|
+
return true;
|
92
|
+
}
|
93
|
+
static _BuildMesh(scene, parsedPLY) {
|
94
|
+
const mesh = new Mesh("PLYMesh", scene);
|
95
|
+
const uBuffer = new Uint8Array(parsedPLY.data);
|
96
|
+
const fBuffer = new Float32Array(parsedPLY.data);
|
97
|
+
const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
|
98
|
+
const vertexCount = uBuffer.length / rowLength;
|
99
|
+
const positions = [];
|
100
|
+
const vertexData = new VertexData();
|
101
|
+
for (let i = 0; i < vertexCount; i++) {
|
102
|
+
const x = fBuffer[8 * i + 0];
|
103
|
+
const y = fBuffer[8 * i + 1];
|
104
|
+
const z = fBuffer[8 * i + 2];
|
105
|
+
positions.push(x, y, z);
|
106
|
+
}
|
107
|
+
if (parsedPLY.hasVertexColors) {
|
108
|
+
const colors = new Float32Array(vertexCount * 4);
|
109
|
+
for (let i = 0; i < vertexCount; i++) {
|
110
|
+
const r = uBuffer[rowLength * i + 24 + 0] / 255;
|
111
|
+
const g = uBuffer[rowLength * i + 24 + 1] / 255;
|
112
|
+
const b = uBuffer[rowLength * i + 24 + 2] / 255;
|
113
|
+
colors[i * 4 + 0] = r;
|
114
|
+
colors[i * 4 + 1] = g;
|
115
|
+
colors[i * 4 + 2] = b;
|
116
|
+
colors[i * 4 + 3] = 1;
|
117
|
+
}
|
118
|
+
vertexData.colors = colors;
|
119
|
+
}
|
120
|
+
vertexData.positions = positions;
|
121
|
+
vertexData.indices = parsedPLY.faces;
|
122
|
+
vertexData.applyToMesh(mesh);
|
123
|
+
return mesh;
|
124
|
+
}
|
125
|
+
_parse(meshesNames, scene, data, rootUrl) {
|
126
|
+
const babylonMeshesArray = []; //The mesh for babylon
|
127
|
+
const parsedPLY = SPLATFileLoader._ConvertPLYToSplat(data);
|
128
|
+
switch (parsedPLY.mode) {
|
129
|
+
case 0 /* Mode.Splat */:
|
130
|
+
{
|
131
|
+
const gaussianSplatting = new GaussianSplattingMesh("GaussianSplatting", null, scene, this._loadingOptions.keepInRam);
|
132
|
+
gaussianSplatting._parentContainer = this._assetContainer;
|
133
|
+
babylonMeshesArray.push(gaussianSplatting);
|
134
|
+
gaussianSplatting.loadDataAsync(parsedPLY.data);
|
135
|
+
}
|
136
|
+
break;
|
137
|
+
case 1 /* Mode.PointCloud */:
|
138
|
+
{
|
139
|
+
const pointcloud = new PointsCloudSystem("PointCloud", 1, scene);
|
140
|
+
if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {
|
141
|
+
return Promise.all([pointcloud.buildMeshAsync()]).then((mesh) => {
|
142
|
+
babylonMeshesArray.push(mesh[0]);
|
143
|
+
return babylonMeshesArray;
|
144
|
+
});
|
145
|
+
}
|
146
|
+
else {
|
147
|
+
pointcloud.dispose();
|
148
|
+
}
|
149
|
+
}
|
150
|
+
break;
|
151
|
+
case 2 /* Mode.Mesh */:
|
152
|
+
{
|
153
|
+
if (parsedPLY.faces) {
|
154
|
+
babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
throw new Error("PLY mesh doesn't contain face informations.");
|
158
|
+
}
|
159
|
+
}
|
160
|
+
break;
|
161
|
+
default:
|
162
|
+
throw new Error("Unsupported Splat mode");
|
163
|
+
}
|
164
|
+
return Promise.resolve(babylonMeshesArray);
|
68
165
|
}
|
69
166
|
/**
|
70
|
-
*
|
167
|
+
* Load into an asset container.
|
168
|
+
* @param scene The scene to load into
|
169
|
+
* @param data The data to import
|
170
|
+
* @param rootUrl The root url for scene and resources
|
171
|
+
* @returns The loaded asset container
|
172
|
+
*/
|
173
|
+
loadAssetContainerAsync(scene, data, rootUrl) {
|
174
|
+
const container = new AssetContainer(scene);
|
175
|
+
this._assetContainer = container;
|
176
|
+
return this.importMeshAsync(null, scene, data, rootUrl)
|
177
|
+
.then((result) => {
|
178
|
+
result.meshes.forEach((mesh) => container.meshes.push(mesh));
|
179
|
+
// mesh material will be null before 1st rendered frame.
|
180
|
+
this._assetContainer = null;
|
181
|
+
return container;
|
182
|
+
})
|
183
|
+
.catch((ex) => {
|
184
|
+
this._assetContainer = null;
|
185
|
+
throw ex;
|
186
|
+
});
|
187
|
+
}
|
188
|
+
/**
|
189
|
+
* Imports all objects from the loaded OBJ data and adds them to the scene
|
71
190
|
* @param scene the scene the objects should be added to
|
72
|
-
* @param data the
|
73
|
-
* @param
|
191
|
+
* @param data the OBJ data to load
|
192
|
+
* @param rootUrl root url to load from
|
74
193
|
* @returns a promise which completes when objects have been loaded to the scene
|
75
194
|
*/
|
76
|
-
loadAsync(scene, data,
|
77
|
-
|
78
|
-
return
|
195
|
+
loadAsync(scene, data, rootUrl) {
|
196
|
+
//Get the 3D model
|
197
|
+
return this.importMeshAsync(null, scene, data, rootUrl).then(() => {
|
198
|
+
// return void
|
199
|
+
});
|
79
200
|
}
|
80
|
-
// eslint-disable-next-line jsdoc/require-returns-check
|
81
201
|
/**
|
82
|
-
*
|
83
|
-
*
|
84
|
-
*
|
85
|
-
* @param
|
86
|
-
* @returns
|
202
|
+
* Code from https://github.com/dylanebert/gsplat.js/blob/main/src/loaders/PLYLoader.ts Under MIT license
|
203
|
+
* Converts a .ply data array buffer to splat
|
204
|
+
* if data array buffer is not ply, returns the original buffer
|
205
|
+
* @param data the .ply data to load
|
206
|
+
* @returns the loaded splat buffer
|
87
207
|
*/
|
88
|
-
|
89
|
-
|
208
|
+
static _ConvertPLYToSplat(data) {
|
209
|
+
const ubuf = new Uint8Array(data);
|
210
|
+
const header = new TextDecoder().decode(ubuf.slice(0, 1024 * 10));
|
211
|
+
const headerEnd = "end_header\n";
|
212
|
+
const headerEndIndex = header.indexOf(headerEnd);
|
213
|
+
if (headerEndIndex < 0 || !header) {
|
214
|
+
// standard splat
|
215
|
+
return { mode: 0 /* Mode.Splat */, data: data };
|
216
|
+
}
|
217
|
+
const vertexCount = parseInt(/element vertex (\d+)\n/.exec(header)[1]);
|
218
|
+
const faceElement = /element face (\d+)\n/.exec(header);
|
219
|
+
let faceCount = 0;
|
220
|
+
if (faceElement) {
|
221
|
+
faceCount = parseInt(faceElement[1]);
|
222
|
+
}
|
223
|
+
let rowOffset = 0;
|
224
|
+
const offsets = {
|
225
|
+
double: 8,
|
226
|
+
int: 4,
|
227
|
+
uint: 4,
|
228
|
+
float: 4,
|
229
|
+
short: 2,
|
230
|
+
ushort: 2,
|
231
|
+
uchar: 1,
|
232
|
+
list: 0,
|
233
|
+
};
|
234
|
+
const properties = [];
|
235
|
+
const filtered = header
|
236
|
+
.slice(0, headerEndIndex)
|
237
|
+
.split("\n")
|
238
|
+
.filter((k) => k.startsWith("property "));
|
239
|
+
for (const prop of filtered) {
|
240
|
+
const [, type, name] = prop.split(" ");
|
241
|
+
properties.push({ name, type, offset: rowOffset });
|
242
|
+
if (offsets[type]) {
|
243
|
+
rowOffset += offsets[type];
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
Logger.Warn(`Unsupported property type: ${type}.`);
|
247
|
+
}
|
248
|
+
}
|
249
|
+
const rowLength = 3 * 4 + 3 * 4 + 4 + 4;
|
250
|
+
const SH_C0 = 0.28209479177387814;
|
251
|
+
const dataView = new DataView(data, headerEndIndex + headerEnd.length);
|
252
|
+
const buffer = new ArrayBuffer(rowLength * vertexCount);
|
253
|
+
const q = new Quaternion();
|
254
|
+
for (let i = 0; i < vertexCount; i++) {
|
255
|
+
const position = new Float32Array(buffer, i * rowLength, 3);
|
256
|
+
const scale = new Float32Array(buffer, i * rowLength + 12, 3);
|
257
|
+
const rgba = new Uint8ClampedArray(buffer, i * rowLength + 24, 4);
|
258
|
+
const rot = new Uint8ClampedArray(buffer, i * rowLength + 28, 4);
|
259
|
+
let r0 = 255;
|
260
|
+
let r1 = 0;
|
261
|
+
let r2 = 0;
|
262
|
+
let r3 = 0;
|
263
|
+
for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) {
|
264
|
+
const property = properties[propertyIndex];
|
265
|
+
let value;
|
266
|
+
switch (property.type) {
|
267
|
+
case "float":
|
268
|
+
value = dataView.getFloat32(property.offset + i * rowOffset, true);
|
269
|
+
break;
|
270
|
+
case "int":
|
271
|
+
value = dataView.getInt32(property.offset + i * rowOffset, true);
|
272
|
+
break;
|
273
|
+
case "uint":
|
274
|
+
value = dataView.getUint32(property.offset + i * rowOffset, true);
|
275
|
+
break;
|
276
|
+
case "double":
|
277
|
+
value = dataView.getFloat64(property.offset + i * rowOffset, true);
|
278
|
+
break;
|
279
|
+
case "uchar":
|
280
|
+
value = dataView.getUint8(property.offset + i * rowOffset);
|
281
|
+
break;
|
282
|
+
default:
|
283
|
+
//throw new Error(`Unsupported property type: ${property.type}`);
|
284
|
+
continue;
|
285
|
+
}
|
286
|
+
switch (property.name) {
|
287
|
+
case "x":
|
288
|
+
position[0] = value;
|
289
|
+
break;
|
290
|
+
case "y":
|
291
|
+
position[1] = value;
|
292
|
+
break;
|
293
|
+
case "z":
|
294
|
+
position[2] = value;
|
295
|
+
break;
|
296
|
+
case "scale_0":
|
297
|
+
scale[0] = Math.exp(value);
|
298
|
+
break;
|
299
|
+
case "scale_1":
|
300
|
+
scale[1] = Math.exp(value);
|
301
|
+
break;
|
302
|
+
case "scale_2":
|
303
|
+
scale[2] = Math.exp(value);
|
304
|
+
break;
|
305
|
+
case "diffuse_red":
|
306
|
+
case "red":
|
307
|
+
rgba[0] = value;
|
308
|
+
break;
|
309
|
+
case "diffuse_green":
|
310
|
+
case "green":
|
311
|
+
rgba[1] = value;
|
312
|
+
break;
|
313
|
+
case "diffuse_blue":
|
314
|
+
case "blue":
|
315
|
+
rgba[2] = value;
|
316
|
+
break;
|
317
|
+
case "f_dc_0":
|
318
|
+
rgba[0] = (0.5 + SH_C0 * value) * 255;
|
319
|
+
break;
|
320
|
+
case "f_dc_1":
|
321
|
+
rgba[1] = (0.5 + SH_C0 * value) * 255;
|
322
|
+
break;
|
323
|
+
case "f_dc_2":
|
324
|
+
rgba[2] = (0.5 + SH_C0 * value) * 255;
|
325
|
+
break;
|
326
|
+
case "f_dc_3":
|
327
|
+
rgba[3] = (0.5 + SH_C0 * value) * 255;
|
328
|
+
break;
|
329
|
+
case "opacity":
|
330
|
+
rgba[3] = (1 / (1 + Math.exp(-value))) * 255;
|
331
|
+
break;
|
332
|
+
case "rot_0":
|
333
|
+
r0 = value;
|
334
|
+
break;
|
335
|
+
case "rot_1":
|
336
|
+
r1 = value;
|
337
|
+
break;
|
338
|
+
case "rot_2":
|
339
|
+
r2 = value;
|
340
|
+
break;
|
341
|
+
case "rot_3":
|
342
|
+
r3 = value;
|
343
|
+
break;
|
344
|
+
}
|
345
|
+
}
|
346
|
+
q.set(r1, r2, r3, r0);
|
347
|
+
q.normalize();
|
348
|
+
rot[0] = q.w * 128 + 128;
|
349
|
+
rot[1] = q.x * 128 + 128;
|
350
|
+
rot[2] = q.y * 128 + 128;
|
351
|
+
rot[3] = q.z * 128 + 128;
|
352
|
+
}
|
353
|
+
// faces
|
354
|
+
const faces = [];
|
355
|
+
if (faceCount) {
|
356
|
+
let offset = rowOffset * vertexCount;
|
357
|
+
for (let i = 0; i < faceCount; i++) {
|
358
|
+
const faceVertexCount = dataView.getUint8(offset);
|
359
|
+
if (faceVertexCount != 3) {
|
360
|
+
continue; // only support triangles
|
361
|
+
}
|
362
|
+
offset += 1;
|
363
|
+
for (let j = 0; j < faceVertexCount; j++) {
|
364
|
+
const vertexIndex = dataView.getUint32(offset + (2 - j) * 4, true); // change face winding
|
365
|
+
faces.push(vertexIndex);
|
366
|
+
}
|
367
|
+
offset += 12;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
// count available properties. if all necessary are present then it's a splat. Otherwise, it's a point cloud
|
371
|
+
// if faces are found, then it's a standard mesh
|
372
|
+
let propertyCount = 0;
|
373
|
+
let propertyColorCount = 0;
|
374
|
+
const splatProperties = ["x", "y", "z", "scale_0", "scale_1", "scale_2", "opacity", "rot_0", "rot_1", "rot_2", "rot_3"];
|
375
|
+
const splatColorProperties = ["red", "green", "blue", "f_dc_0", "f_dc_1", "f_dc_2"];
|
376
|
+
for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) {
|
377
|
+
const property = properties[propertyIndex];
|
378
|
+
if (splatProperties.includes(property.name)) {
|
379
|
+
propertyCount++;
|
380
|
+
}
|
381
|
+
if (splatColorProperties.includes(property.name)) {
|
382
|
+
propertyColorCount++;
|
383
|
+
}
|
384
|
+
}
|
385
|
+
const hasMandatoryProperties = propertyCount == splatProperties.length && propertyColorCount == 3;
|
386
|
+
const currentMode = faceCount ? 2 /* Mode.Mesh */ : hasMandatoryProperties ? 0 /* Mode.Splat */ : 1 /* Mode.PointCloud */;
|
387
|
+
// parsed ready ready to be used as a splat
|
388
|
+
return { mode: currentMode, data: buffer, faces: faces, hasVertexColors: !!propertyColorCount };
|
90
389
|
}
|
91
390
|
}
|
92
|
-
|
391
|
+
SPLATFileLoader._DefaultLoadingOptions = {
|
392
|
+
keepInRam: false,
|
393
|
+
};
|
394
|
+
// Add this loader into the register plugin
|
93
395
|
registerSceneLoaderPlugin(new SPLATFileLoader());
|
94
396
|
//# sourceMappingURL=splatFileLoader.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"splatFileLoader.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatFileLoader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,yBAAyB,EAAE,+CAAiC;AACrE,OAAO,EAAE,qBAAqB,EAAE,0EAA4D;AAI5F,gEAAgE;AAChE,MAAM,YAAY,GAAG,OAAO,CAAC;AAY7B;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAiBxB,+CAA+C;IAC/C;;OAEG;IACH;QApBA;;WAEG;QACa,SAAI,GAAG,YAAY,CAAC;QAEpC;;;WAGG;QACa,eAAU,GAAG;YACzB,gEAAgE;YAChE,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC5B,gEAAgE;YAChE,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;SACmB,CAAC;IAMnC,CAAC;IAEhB;;;OAGG;IACH,YAAY;QACR,OAAO,IAAI,eAAe,EAAE,CAAC;IACjC,CAAC;IAED;;;OAGG;IACI,aAAa;QAChB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,eAAe,CACxB,YAAiB,EACjB,KAAY,EACZ,IAAS,EACT,OAAe,EACf,UAAuD,EACvD,QAAiB;QAEjB,MAAM,iBAAiB,GAAG,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACtF,MAAM,iBAAiB,CAAC,aAAa,CAAC,OAAO,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO;YACH,MAAM,EAAE,CAAC,iBAAiB,CAAC;YAC3B,eAAe,EAAE,EAAE;YACnB,SAAS,EAAE,EAAE;YACb,eAAe,EAAE,EAAE;YACnB,cAAc,EAAE,EAAE;YAClB,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,EAAE;YACV,cAAc,EAAE,EAAE;SACrB,CAAC;IACN,CAAC;IAED;;;;;;OAMG;IACI,SAAS,CAAC,KAAY,EAAE,IAAS,EAAE,QAAgB;QACtD,MAAM,iBAAiB,GAAG,IAAI,qBAAqB,CAAC,mBAAmB,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACtF,OAAO,iBAAiB,CAAC,aAAa,CAAC,qBAAqB,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,uDAAuD;IACvD;;;;;;OAMG;IACI,uBAAuB,CAAC,MAAa,EAAE,KAAa,EAAE,QAAgB;QACzE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC9F,CAAC;CACJ;AAED,0CAA0C;AAC1C,yBAAyB,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC","sourcesContent":["import type {\r\n ISceneLoaderPluginAsync,\r\n ISceneLoaderPluginFactory,\r\n ISceneLoaderPlugin,\r\n ISceneLoaderAsyncResult,\r\n ISceneLoaderPluginExtensions,\r\n ISceneLoaderProgressEvent,\r\n} from \"core/Loading/sceneLoader\";\r\nimport { registerSceneLoaderPlugin } from \"core/Loading/sceneLoader\";\r\nimport { GaussianSplattingMesh } from \"core/Meshes/GaussianSplatting/gaussianSplattingMesh\";\r\nimport type { AssetContainer } from \"core/assetContainer\";\r\nimport type { Scene } from \"core/scene\";\r\n\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nconst PLUGIN_SPLAT = \"splat\";\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 [PLUGIN_SPLAT]: {};\r\n }\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 = PLUGIN_SPLAT;\r\n\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 = {\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\r\n //private _loadingOptions: SPLATLoadingOptions;\r\n /**\r\n * Creates loader for gaussian splatting files\r\n */\r\n constructor() {}\r\n\r\n /**\r\n * Instantiates a gaussian splatting file loader plugin.\r\n * @returns the created plugin\r\n */\r\n createPlugin(): ISceneLoaderPluginAsync | ISceneLoaderPlugin {\r\n return new SPLATFileLoader();\r\n }\r\n\r\n /**\r\n * If the data string can be loaded directly.\r\n * @returns if the data can be loaded directly\r\n */\r\n public canDirectLoad(): boolean {\r\n return false;\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 const gaussianSplatting = new GaussianSplattingMesh(\"GaussianSplatting\", null, scene);\r\n await gaussianSplatting.loadFileAsync(rootUrl + (fileName ?? \"\"));\r\n return {\r\n meshes: [gaussianSplatting],\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 * Imports all objects from the loaded gaussian splatting data and adds them to the scene\r\n * @param scene the scene the objects 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 * @returns a promise which completes when objects have been loaded to the scene\r\n */\r\n public loadAsync(scene: Scene, data: any, _rootUrl: string): Promise<void> {\r\n const gaussianSplatting = new GaussianSplattingMesh(\"GaussianSplatting\", null, scene);\r\n return gaussianSplatting.loadDataAsync(GaussianSplattingMesh.ConvertPLYToSplat(data));\r\n }\r\n\r\n // eslint-disable-next-line jsdoc/require-returns-check\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 throw new Error(\"loadAssetContainerAsync not implemented for Gaussian Splatting loading\");\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 { Quaternion, 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 const babylonMeshesArray: Array<Mesh> = []; //The mesh for babylon\r\n const parsedPLY = SPLATFileLoader._ConvertPLYToSplat(data as ArrayBuffer);\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.loadDataAsync(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 Promise.resolve(babylonMeshesArray);\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): 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 { mode: Mode.Splat, data: data };\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 let rowOffset = 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 const properties: PlyProperty[] = [];\r\n const filtered = header\r\n .slice(0, headerEndIndex)\r\n .split(\"\\n\")\r\n .filter((k) => k.startsWith(\"property \"));\r\n for (const prop of filtered) {\r\n const [, type, name] = prop.split(\" \");\r\n properties.push({ name, type, offset: rowOffset });\r\n if (offsets[type]) {\r\n rowOffset += offsets[type];\r\n } else {\r\n Logger.Warn(`Unsupported property type: ${type}.`);\r\n }\r\n }\r\n\r\n const rowLength = 3 * 4 + 3 * 4 + 4 + 4;\r\n const SH_C0 = 0.28209479177387814;\r\n\r\n const dataView = new DataView(data, headerEndIndex + headerEnd.length);\r\n const buffer = new ArrayBuffer(rowLength * vertexCount);\r\n const q = new Quaternion();\r\n\r\n for (let i = 0; i < vertexCount; i++) {\r\n const position = new Float32Array(buffer, i * rowLength, 3);\r\n const scale = new Float32Array(buffer, i * rowLength + 12, 3);\r\n const rgba = new Uint8ClampedArray(buffer, i * rowLength + 24, 4);\r\n const rot = new Uint8ClampedArray(buffer, i * rowLength + 28, 4);\r\n\r\n let r0: number = 255;\r\n let r1: number = 0;\r\n let r2: number = 0;\r\n let r3: number = 0;\r\n\r\n for (let propertyIndex = 0; propertyIndex < properties.length; propertyIndex++) {\r\n const property = properties[propertyIndex];\r\n let value;\r\n switch (property.type) {\r\n case \"float\":\r\n value = dataView.getFloat32(property.offset + i * rowOffset, true);\r\n break;\r\n case \"int\":\r\n value = dataView.getInt32(property.offset + i * rowOffset, true);\r\n break;\r\n case \"uint\":\r\n value = dataView.getUint32(property.offset + i * rowOffset, true);\r\n break;\r\n case \"double\":\r\n value = dataView.getFloat64(property.offset + i * rowOffset, true);\r\n break;\r\n case \"uchar\":\r\n value = dataView.getUint8(property.offset + i * rowOffset);\r\n break;\r\n default:\r\n //throw new Error(`Unsupported property type: ${property.type}`);\r\n continue;\r\n }\r\n\r\n switch (property.name) {\r\n case \"x\":\r\n position[0] = value;\r\n break;\r\n case \"y\":\r\n position[1] = value;\r\n break;\r\n case \"z\":\r\n position[2] = value;\r\n break;\r\n case \"scale_0\":\r\n scale[0] = Math.exp(value);\r\n break;\r\n case \"scale_1\":\r\n scale[1] = Math.exp(value);\r\n break;\r\n case \"scale_2\":\r\n scale[2] = Math.exp(value);\r\n break;\r\n case \"diffuse_red\":\r\n case \"red\":\r\n rgba[0] = value;\r\n break;\r\n case \"diffuse_green\":\r\n case \"green\":\r\n rgba[1] = value;\r\n break;\r\n case \"diffuse_blue\":\r\n case \"blue\":\r\n rgba[2] = value;\r\n break;\r\n case \"f_dc_0\":\r\n rgba[0] = (0.5 + SH_C0 * value) * 255;\r\n break;\r\n case \"f_dc_1\":\r\n rgba[1] = (0.5 + SH_C0 * value) * 255;\r\n break;\r\n case \"f_dc_2\":\r\n rgba[2] = (0.5 + SH_C0 * value) * 255;\r\n break;\r\n case \"f_dc_3\":\r\n rgba[3] = (0.5 + SH_C0 * value) * 255;\r\n break;\r\n case \"opacity\":\r\n rgba[3] = (1 / (1 + Math.exp(-value))) * 255;\r\n break;\r\n case \"rot_0\":\r\n r0 = value;\r\n break;\r\n case \"rot_1\":\r\n r1 = value;\r\n break;\r\n case \"rot_2\":\r\n r2 = value;\r\n break;\r\n case \"rot_3\":\r\n r3 = value;\r\n break;\r\n }\r\n }\r\n\r\n q.set(r1, r2, r3, r0);\r\n q.normalize();\r\n rot[0] = q.w * 128 + 128;\r\n rot[1] = q.x * 128 + 128;\r\n rot[2] = q.y * 128 + 128;\r\n rot[3] = q.z * 128 + 128;\r\n }\r\n\r\n // faces\r\n const faces = [];\r\n if (faceCount) {\r\n let offset = rowOffset * vertexCount;\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 // 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 < properties.length; propertyIndex++) {\r\n const property = properties[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 { mode: currentMode, data: buffer, faces: faces, hasVertexColors: !!propertyColorCount };\r\n }\r\n}\r\n\r\n// Add this loader into the register plugin\r\nregisterSceneLoaderPlugin(new SPLATFileLoader());\r\n"]}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export const SPLATFileLoaderMetadata = {
|
2
|
+
name: "splat",
|
3
|
+
extensions: {
|
4
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
5
|
+
".splat": { isBinary: true },
|
6
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
7
|
+
".ply": { isBinary: true },
|
8
|
+
},
|
9
|
+
};
|
10
|
+
//# sourceMappingURL=splatFileLoader.metadata.js.map
|
@@ -0,0 +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"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"splatLoadingOptions.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/splatLoadingOptions.ts"],"names":[],"mappings":"","sourcesContent":["/**\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"]}
|
package/STL/stlFileLoader.d.ts
CHANGED
@@ -3,13 +3,13 @@ import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
|
|
3
3
|
import type { ISceneLoaderPlugin } from "@babylonjs/core/Loading/sceneLoader.js";
|
4
4
|
import { AssetContainer } from "@babylonjs/core/assetContainer.js";
|
5
5
|
import type { Scene } from "@babylonjs/core/scene.js";
|
6
|
-
|
6
|
+
import { STLFileLoaderMetadata } from "./stlFileLoader.metadata";
|
7
7
|
declare module "@babylonjs/core/Loading/sceneLoader.js" {
|
8
8
|
interface SceneLoaderPluginOptions {
|
9
9
|
/**
|
10
10
|
* Defines options for the stl loader.
|
11
11
|
*/
|
12
|
-
[
|
12
|
+
[STLFileLoaderMetadata.name]: {};
|
13
13
|
}
|
14
14
|
}
|
15
15
|
/**
|
@@ -28,7 +28,7 @@ export declare class STLFileLoader implements ISceneLoaderPlugin {
|
|
28
28
|
/**
|
29
29
|
* Defines the name of the plugin.
|
30
30
|
*/
|
31
|
-
readonly name
|
31
|
+
readonly name: "stl";
|
32
32
|
/**
|
33
33
|
* Defines the extensions the stl loader is able to load.
|
34
34
|
* force data to come in as an ArrayBuffer
|
@@ -75,4 +75,3 @@ export declare class STLFileLoader implements ISceneLoaderPlugin {
|
|
75
75
|
private _parseBinary;
|
76
76
|
private _parseASCII;
|
77
77
|
}
|
78
|
-
export {};
|
package/STL/stlFileLoader.js
CHANGED
@@ -3,7 +3,7 @@ import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
|
|
3
3
|
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
4
4
|
import { registerSceneLoaderPlugin } from "@babylonjs/core/Loading/sceneLoader.js";
|
5
5
|
import { AssetContainer } from "@babylonjs/core/assetContainer.js";
|
6
|
-
|
6
|
+
import { STLFileLoaderMetadata } from "./stlFileLoader.metadata.js";
|
7
7
|
/**
|
8
8
|
* STL file type loader.
|
9
9
|
* This is a babylon scene loader plugin.
|
@@ -21,15 +21,13 @@ export class STLFileLoader {
|
|
21
21
|
/**
|
22
22
|
* Defines the name of the plugin.
|
23
23
|
*/
|
24
|
-
this.name =
|
24
|
+
this.name = STLFileLoaderMetadata.name;
|
25
25
|
/**
|
26
26
|
* Defines the extensions the stl loader is able to load.
|
27
27
|
* force data to come in as an ArrayBuffer
|
28
28
|
* we'll convert to string if it looks like it's an ASCII .stl
|
29
29
|
*/
|
30
|
-
this.extensions =
|
31
|
-
".stl": { isBinary: true },
|
32
|
-
};
|
30
|
+
this.extensions = STLFileLoaderMetadata.extensions;
|
33
31
|
}
|
34
32
|
/**
|
35
33
|
* Import meshes into a scene.
|