@myned-ai/gsplat-flame-avatar-renderer 1.0.5 → 1.0.7

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.
Files changed (58) hide show
  1. package/README.md +160 -32
  2. package/dist/gsplat-flame-avatar-renderer.cjs.js +3510 -749
  3. package/dist/gsplat-flame-avatar-renderer.cjs.min.js +2 -0
  4. package/dist/gsplat-flame-avatar-renderer.cjs.min.js.map +1 -0
  5. package/dist/gsplat-flame-avatar-renderer.esm.js +3471 -751
  6. package/dist/gsplat-flame-avatar-renderer.esm.min.js +2 -0
  7. package/dist/gsplat-flame-avatar-renderer.esm.min.js.map +1 -0
  8. package/package.json +14 -7
  9. package/dist/gsplat-flame-avatar-renderer.cjs.js.map +0 -1
  10. package/dist/gsplat-flame-avatar-renderer.esm.js.map +0 -1
  11. package/src/api/index.js +0 -7
  12. package/src/buffers/SplatBuffer.js +0 -1394
  13. package/src/buffers/SplatBufferGenerator.js +0 -41
  14. package/src/buffers/SplatPartitioner.js +0 -110
  15. package/src/buffers/UncompressedSplatArray.js +0 -106
  16. package/src/buffers/index.js +0 -11
  17. package/src/core/SplatGeometry.js +0 -48
  18. package/src/core/SplatMesh.js +0 -2620
  19. package/src/core/SplatScene.js +0 -43
  20. package/src/core/SplatTree.js +0 -200
  21. package/src/core/Viewer.js +0 -2895
  22. package/src/core/index.js +0 -13
  23. package/src/enums/EngineConstants.js +0 -58
  24. package/src/enums/LogLevel.js +0 -13
  25. package/src/enums/RenderMode.js +0 -11
  26. package/src/enums/SceneFormat.js +0 -21
  27. package/src/enums/SceneRevealMode.js +0 -11
  28. package/src/enums/SplatRenderMode.js +0 -10
  29. package/src/enums/index.js +0 -13
  30. package/src/flame/FlameAnimator.js +0 -271
  31. package/src/flame/FlameConstants.js +0 -21
  32. package/src/flame/FlameTextureManager.js +0 -293
  33. package/src/flame/index.js +0 -22
  34. package/src/flame/utils.js +0 -50
  35. package/src/index.js +0 -39
  36. package/src/loaders/DirectLoadError.js +0 -14
  37. package/src/loaders/INRIAV1PlyParser.js +0 -223
  38. package/src/loaders/PlyLoader.js +0 -261
  39. package/src/loaders/PlyParser.js +0 -19
  40. package/src/loaders/PlyParserUtils.js +0 -311
  41. package/src/loaders/index.js +0 -13
  42. package/src/materials/SplatMaterial.js +0 -1065
  43. package/src/materials/SplatMaterial2D.js +0 -358
  44. package/src/materials/SplatMaterial3D.js +0 -278
  45. package/src/materials/index.js +0 -11
  46. package/src/raycaster/Hit.js +0 -37
  47. package/src/raycaster/Ray.js +0 -123
  48. package/src/raycaster/Raycaster.js +0 -175
  49. package/src/raycaster/index.js +0 -10
  50. package/src/renderer/AnimationManager.js +0 -574
  51. package/src/renderer/AppConstants.js +0 -101
  52. package/src/renderer/GaussianSplatRenderer.js +0 -695
  53. package/src/renderer/index.js +0 -24
  54. package/src/utils/LoaderUtils.js +0 -65
  55. package/src/utils/Util.js +0 -375
  56. package/src/utils/index.js +0 -9
  57. package/src/worker/SortWorker.js +0 -284
  58. package/src/worker/index.js +0 -8
@@ -1,293 +0,0 @@
1
- /**
2
- * FlameTextureManager
3
- *
4
- * Derived from gaussian-splat-renderer-for-lam
5
- *
6
- * Manages GPU textures for FLAME parametric head model:
7
- * - Blendshape morph target data textures
8
- * - Bone matrix textures for skeleton animation
9
- * - LBS weight textures for skinning
10
- */
11
-
12
- import {
13
- Vector2,
14
- DataTexture,
15
- RGBAIntegerFormat,
16
- UnsignedIntType
17
- } from 'three';
18
-
19
- import { uintEncodedFloat } from './utils.js';
20
-
21
- /**
22
- * Build the FLAME model texture containing blendshape positions
23
- * @param {THREE.SkinnedMesh} flameModel - The FLAME mesh with morph targets
24
- * @param {THREE.ShaderMaterial} material - The splat material to update uniforms
25
- * @param {number} gaussianSplatCount - Number of gaussian splats
26
- * @returns {object} Texture data object
27
- */
28
- export function buildModelTexture(flameModel, material, gaussianSplatCount) {
29
- const flameModelTexSize = new Vector2(4096, 2048);
30
-
31
- const shapedMesh = flameModel.geometry.attributes.position.array;
32
- let shapedMeshArray = [];
33
- const pointNum = shapedMesh.length / 3;
34
- const bsLength = flameModel.geometry.morphAttributes.position.length;
35
-
36
- // Sort morph targets by dictionary order
37
- const morphTargetNames = Object.keys(flameModel.morphTargetDictionary);
38
- morphTargetNames.forEach((name) => {
39
- const originalIndex = flameModel.morphTargetDictionary[name];
40
- const bsMesh = flameModel.geometry.morphAttributes.position[originalIndex];
41
- shapedMeshArray = shapedMeshArray.concat(Array.from(bsMesh.array));
42
- });
43
-
44
- // Add base mesh positions
45
- shapedMeshArray = shapedMeshArray.concat(Array.from(shapedMesh));
46
-
47
- // Create texture data
48
- const flameModelData = new Float32Array(flameModelTexSize.x * flameModelTexSize.y * 4);
49
- const flameModelDataInt = new Uint32Array(flameModelTexSize.x * flameModelTexSize.y * 4);
50
-
51
- for (let c = 0; c < pointNum * (bsLength + 1); c++) {
52
- flameModelData[c * 4 + 0] = shapedMeshArray[c * 3 + 0];
53
- flameModelData[c * 4 + 1] = shapedMeshArray[c * 3 + 1];
54
- flameModelData[c * 4 + 2] = shapedMeshArray[c * 3 + 2];
55
-
56
- flameModelDataInt[c * 4 + 0] = uintEncodedFloat(flameModelData[c * 4 + 0]);
57
- flameModelDataInt[c * 4 + 1] = uintEncodedFloat(flameModelData[c * 4 + 1]);
58
- flameModelDataInt[c * 4 + 2] = uintEncodedFloat(flameModelData[c * 4 + 2]);
59
- }
60
-
61
- const flameModelTex = new DataTexture(
62
- flameModelDataInt,
63
- flameModelTexSize.x,
64
- flameModelTexSize.y,
65
- RGBAIntegerFormat,
66
- UnsignedIntType
67
- );
68
- flameModelTex.internalFormat = 'RGBA32UI';
69
- flameModelTex.needsUpdate = true;
70
-
71
- // Update material uniforms
72
- material.uniforms.flameModelTexture.value = flameModelTex;
73
- material.uniforms.flameModelTextureSize.value.copy(flameModelTexSize);
74
- material.uniforms.gaussianSplatCount.value = gaussianSplatCount;
75
- material.uniformsNeedUpdate = true;
76
-
77
- return {
78
- data: flameModelDataInt,
79
- texture: flameModelTex,
80
- size: flameModelTexSize,
81
- baseData: { flameModelPos: flameModelData }
82
- };
83
- }
84
-
85
- /**
86
- * Build bone matrix texture for skeleton animation
87
- * @param {Float32Array} bonesMatrix - Flattened bone matrices
88
- * @param {number} bonesNum - Number of bones
89
- * @param {object} bsWeight - Blendshape weights object
90
- * @param {object} morphTargetDictionary - Maps blendshape names to indices
91
- * @param {THREE.SkinnedMesh} flameModel - The FLAME mesh
92
- * @param {THREE.ShaderMaterial} material - The splat material
93
- * @param {boolean} useFlameModel - Use FLAME mode
94
- * @returns {object} Texture data object
95
- */
96
- export function buildBoneMatrixTexture(
97
- bonesMatrix,
98
- bonesNum,
99
- bsWeight,
100
- morphTargetDictionary,
101
- flameModel,
102
- material,
103
- useFlameModel
104
- ) {
105
- if (!bsWeight) return null;
106
-
107
- // bonesNum + expressionBSNum / 4 = 30, so texture height is 32
108
- const boneTextureSize = new Vector2(4, 32);
109
- const boneMatrixTextureData = new Float32Array(bonesMatrix);
110
- const boneMatrixTextureDataInt = new Uint32Array(boneTextureSize.x * boneTextureSize.y * 4);
111
-
112
- if (useFlameModel) {
113
- // Encode bone matrices
114
- for (let c = 0; c < bonesNum * 16; c++) {
115
- boneMatrixTextureDataInt[c] = uintEncodedFloat(boneMatrixTextureData[c]);
116
- }
117
-
118
- // Set skeleton uniforms
119
- if (flameModel && flameModel.skeleton) {
120
- material.uniforms.boneTexture0.value = flameModel.skeleton.boneTexture;
121
- material.uniforms.bindMatrix.value = flameModel.bindMatrix;
122
- material.uniforms.bindMatrixInverse.value = flameModel.bindMatrixInverse;
123
- }
124
- }
125
-
126
- // Encode blendshape weights
127
- for (const key in bsWeight) {
128
- if (Object.hasOwn(bsWeight, key)) {
129
- const value = bsWeight[key];
130
- const idx = morphTargetDictionary[key];
131
- boneMatrixTextureDataInt[idx + bonesNum * 16] = uintEncodedFloat(value);
132
- }
133
- }
134
-
135
- const boneMatrixTex = new DataTexture(
136
- boneMatrixTextureDataInt,
137
- boneTextureSize.x,
138
- boneTextureSize.y,
139
- RGBAIntegerFormat,
140
- UnsignedIntType
141
- );
142
- boneMatrixTex.internalFormat = 'RGBA32UI';
143
- boneMatrixTex.needsUpdate = true;
144
-
145
- material.uniforms.boneTexture.value = boneMatrixTex;
146
- material.uniforms.boneTextureSize.value.copy(boneTextureSize);
147
- material.uniformsNeedUpdate = true;
148
-
149
- return {
150
- data: boneMatrixTextureDataInt,
151
- texture: boneMatrixTex,
152
- size: boneTextureSize,
153
- baseData: { boneMatrix: boneMatrixTextureDataInt }
154
- };
155
- }
156
-
157
- /**
158
- * Update bone matrix texture with new animation data
159
- * @param {object} splatDataTextures - Texture data storage
160
- * @param {Float32Array} bonesMatrix - Updated bone matrices
161
- * @param {number} bonesNum - Number of bones
162
- * @param {object} bsWeight - Updated blendshape weights
163
- * @param {object} morphTargetDictionary - Blendshape name to index map
164
- * @param {THREE.SkinnedMesh} flameModel - The FLAME mesh
165
- * @param {THREE.ShaderMaterial} material - The splat material
166
- * @param {boolean} updateFlameBoneMatrix - Whether to update bone matrices
167
- */
168
- export function updateBoneMatrixTexture(
169
- splatDataTextures,
170
- bonesMatrix,
171
- bonesNum,
172
- bsWeight,
173
- morphTargetDictionary,
174
- flameModel,
175
- material,
176
- updateFlameBoneMatrix = false
177
- ) {
178
- if (!bsWeight || !morphTargetDictionary) return;
179
-
180
- if (updateFlameBoneMatrix) {
181
- const boneMatrixTextureData = new Float32Array(bonesMatrix);
182
- for (let c = 0; c < bonesNum * 16; c++) {
183
- splatDataTextures.baseData['boneMatrix'][c] = uintEncodedFloat(boneMatrixTextureData[c]);
184
- }
185
- }
186
-
187
- // Update blendshape weights
188
- for (const key in bsWeight) {
189
- if (Object.hasOwn(bsWeight, key)) {
190
- const value = bsWeight[key];
191
- const idx = morphTargetDictionary[key];
192
- splatDataTextures.baseData['boneMatrix'][idx + bonesNum * 16] = uintEncodedFloat(value);
193
- }
194
- }
195
-
196
- // Update texture data
197
- splatDataTextures['boneMatrix']['texture'].data = splatDataTextures.baseData['boneMatrix'];
198
- splatDataTextures['boneMatrix']['texture'].needsUpdate = true;
199
- material.uniforms.boneTexture.value = splatDataTextures['boneMatrix']['texture'];
200
-
201
- // Update skeleton uniforms
202
- if (flameModel.skeleton) {
203
- material.uniforms.boneTexture0.value = flameModel.skeleton.boneTexture;
204
- material.uniforms.bindMatrix.value = flameModel.bindMatrix;
205
- material.uniforms.bindMatrixInverse.value = flameModel.bindMatrixInverse;
206
- }
207
-
208
- material.uniformsNeedUpdate = true;
209
- }
210
-
211
- /**
212
- * Build LBS weight texture for skin deformation
213
- * @param {THREE.SkinnedMesh} flameModel - The FLAME mesh
214
- * @param {Array} bonesWeight - Per-vertex bone weights array
215
- * @param {THREE.ShaderMaterial} material - The splat material
216
- * @returns {object} Texture data object
217
- */
218
- export function buildBoneWeightTexture(flameModel, bonesWeight, material) {
219
- const shapedMesh = flameModel.geometry.attributes.position.array;
220
- const pointNum = shapedMesh.length / 3;
221
-
222
- const boneWeightTextureSize = new Vector2(512, 512);
223
- const boneWeightTextureData = new Float32Array(boneWeightTextureSize.x * boneWeightTextureSize.y * 4);
224
- const boneWeightTextureDataInt = new Uint32Array(boneWeightTextureSize.x * boneWeightTextureSize.y * 4);
225
-
226
- for (let i = 0; i < pointNum; i++) {
227
- // Store 5 bone weights per vertex (2 texels)
228
- boneWeightTextureData[i * 8 + 0] = bonesWeight[i][0];
229
- boneWeightTextureData[i * 8 + 1] = bonesWeight[i][1];
230
- boneWeightTextureData[i * 8 + 2] = bonesWeight[i][2];
231
- boneWeightTextureData[i * 8 + 3] = bonesWeight[i][3];
232
- boneWeightTextureData[i * 8 + 4] = bonesWeight[i][4];
233
-
234
- boneWeightTextureDataInt[i * 8 + 0] = uintEncodedFloat(bonesWeight[i][0]);
235
- boneWeightTextureDataInt[i * 8 + 1] = uintEncodedFloat(bonesWeight[i][1]);
236
- boneWeightTextureDataInt[i * 8 + 2] = uintEncodedFloat(bonesWeight[i][2]);
237
- boneWeightTextureDataInt[i * 8 + 3] = uintEncodedFloat(bonesWeight[i][3]);
238
- boneWeightTextureDataInt[i * 8 + 4] = uintEncodedFloat(bonesWeight[i][4]);
239
- }
240
-
241
- const boneWeightTex = new DataTexture(
242
- boneWeightTextureDataInt,
243
- boneWeightTextureSize.x,
244
- boneWeightTextureSize.y,
245
- RGBAIntegerFormat,
246
- UnsignedIntType
247
- );
248
- boneWeightTex.internalFormat = 'RGBA32UI';
249
- boneWeightTex.needsUpdate = true;
250
-
251
- material.uniforms.boneWeightTexture.value = boneWeightTex;
252
- material.uniforms.boneWeightTextureSize.value.copy(boneWeightTextureSize);
253
- material.uniformsNeedUpdate = true;
254
-
255
- return {
256
- data: boneWeightTextureDataInt,
257
- texture: boneWeightTex,
258
- size: boneWeightTextureSize,
259
- baseData: { boneWeight: boneWeightTextureDataInt }
260
- };
261
- }
262
-
263
- /**
264
- * Get updated bone matrices from skeleton
265
- * @param {THREE.Skeleton} skeleton - The skeleton to read matrices from
266
- * @param {number} boneNum - Number of bones
267
- * @returns {Float32Array} Flattened bone matrices
268
- */
269
- export function getUpdatedBoneMatrices(skeleton, boneNum) {
270
- const updatedBoneMatrices = [];
271
-
272
- for (let j = 0; j < boneNum; j++) {
273
- const boneMatrix = skeleton.bones[j].matrixWorld.clone()
274
- .multiply(skeleton.boneInverses[j].clone());
275
-
276
- const elements = boneMatrix.elements;
277
- for (let i = 0; i < elements.length; i++) {
278
- updatedBoneMatrices.push(elements[i]);
279
- }
280
- }
281
-
282
- return new Float32Array(updatedBoneMatrices);
283
- }
284
-
285
- export const FlameTextureManager = {
286
- buildModelTexture,
287
- buildBoneMatrixTexture,
288
- updateBoneMatrixTexture,
289
- buildBoneWeightTexture,
290
- getUpdatedBoneMatrices
291
- };
292
-
293
- export default FlameTextureManager;
@@ -1,22 +0,0 @@
1
- /**
2
- * gsplat-flame-avatar - FLAME Module
3
- * Modified GaussianSplats3D components with FLAME parametric head model support
4
- */
5
-
6
- // FLAME-specific Constants (exported as FlameConstants to avoid conflict)
7
- export { Constants as FlameConstants } from './FlameConstants.js';
8
-
9
- // Texture Constants (not duplicated elsewhere)
10
- export { TextureConstants } from './utils.js';
11
-
12
- // FLAME support
13
- export {
14
- FlameTextureManager,
15
- buildModelTexture,
16
- buildBoneMatrixTexture,
17
- updateBoneMatrixTexture,
18
- buildBoneWeightTexture,
19
- getUpdatedBoneMatrices
20
- } from './FlameTextureManager.js';
21
-
22
- export { FlameAnimator } from './FlameAnimator.js';
@@ -1,50 +0,0 @@
1
- /**
2
- * FLAME Utility Functions
3
- *
4
- * Derived from gaussian-splat-renderer-for-lam
5
- * Contains encoding functions and helpers for GPU texture data.
6
- */
7
-
8
- /**
9
- * Encode float as uint32 for GPU texture storage
10
- * Uses Float32Array/Int32Array view trick to reinterpret float bits as integer
11
- */
12
- export const uintEncodedFloat = (function() {
13
- const floatView = new Float32Array(1);
14
- const int32View = new Int32Array(floatView.buffer);
15
-
16
- return function(f) {
17
- floatView[0] = f;
18
- return int32View[0];
19
- };
20
- })();
21
-
22
- /**
23
- * Convert RGBA values to a single integer
24
- */
25
- export const rgbaToInteger = function(r, g, b, a) {
26
- return r + (g << 8) + (b << 16) + (a << 24);
27
- };
28
-
29
- /**
30
- * Convert RGBA array at offset to a single integer
31
- */
32
- export const rgbaArrayToInteger = function(arr, offset) {
33
- return arr[offset] + (arr[offset + 1] << 8) + (arr[offset + 2] << 16) + (arr[offset + 3] << 24);
34
- };
35
-
36
- /**
37
- * Constants for texture data layout
38
- */
39
- export const TextureConstants = {
40
- CENTER_COLORS_ELEMENTS_PER_TEXEL: 4,
41
- CENTER_COLORS_ELEMENTS_PER_SPLAT: 4,
42
- COVARIANCES_ELEMENTS_PER_TEXEL_STORED: 2,
43
- COVARIANCES_ELEMENTS_PER_TEXEL_ALLOCATED: 4,
44
- COVARIANCES_ELEMENTS_PER_TEXEL_COMPRESSED_STORED: 2,
45
- COVARIANCES_ELEMENTS_PER_TEXEL_COMPRESSED_ALLOCATED: 4,
46
- COVARIANCES_ELEMENTS_PER_SPLAT: 6,
47
- SCALES_ROTATIONS_ELEMENTS_PER_TEXEL: 4,
48
- SCENE_INDEXES_ELEMENTS_PER_TEXEL: 1,
49
- MAX_TEXTURE_TEXELS: 4096 * 4096
50
- };
package/src/index.js DELETED
@@ -1,39 +0,0 @@
1
- /**
2
- * gsplat-flame-avatar
3
- *
4
- * A specialized Gaussian Splatting library with FLAME parametric head model support.
5
- * Built on Three.js for real-time facial animation of Gaussian Splat avatars.
6
- *
7
- * Based on @mkkellogg/gaussian-splats-3d (MIT License)
8
- * Extended with FLAME integration from gaussian-splat-renderer-for-lam
9
- */
10
-
11
- // Enums
12
- export * from './enums/index.js';
13
-
14
- // Utils
15
- export * from './utils/index.js';
16
-
17
- // Api
18
- export * from './api/index.js';
19
-
20
- // Renderer (GaussianSplatRenderer, AnimationManager, state classes)
21
- export * from './renderer/index.js';
22
-
23
- // Buffers
24
- export * from './buffers/index.js';
25
-
26
- // Core (Viewer, SplatMesh, etc.)
27
- export * from './core/index.js';
28
-
29
- // Loaders
30
- export * from './loaders/index.js';
31
-
32
- // Materials
33
- export * from './materials/index.js';
34
-
35
- // Raycaster
36
- export * from './raycaster/index.js';
37
-
38
- // FLAME support
39
- export * from './flame/index.js';
@@ -1,14 +0,0 @@
1
- /**
2
- * DirectLoadError
3
- *
4
- * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
- * https://github.com/mkkellogg/GaussianSplats3D
6
- *
7
- * Minor enhancement: Added this.name property for better error identification.
8
- */
9
- export class DirectLoadError extends Error {
10
- constructor(msg) {
11
- super(msg);
12
- this.name = 'DirectLoadError';
13
- }
14
- }
@@ -1,223 +0,0 @@
1
- /**
2
- * INRIAV1PlyParser
3
- *
4
- * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
- * https://github.com/mkkellogg/GaussianSplats3D
6
- *
7
- * Import paths adjusted for gsplat-flame-avatar package structure.
8
- */
9
-
10
- import { Quaternion } from 'three';
11
- import { UncompressedSplatArray } from '../buffers/UncompressedSplatArray.js';
12
- import { SplatBuffer } from '../buffers/SplatBuffer.js';
13
- import { PlyParserUtils } from './PlyParserUtils.js';
14
- import { clamp } from '../utils/Util.js';
15
-
16
- const BaseFieldNamesToRead = ['scale_0', 'scale_1', 'scale_2', 'rot_0', 'rot_1', 'rot_2', 'rot_3', 'x', 'y', 'z',
17
- 'f_dc_0', 'f_dc_1', 'f_dc_2', 'opacity', 'red', 'green', 'blue', 'f_rest_0'];
18
-
19
- const BaseFieldsToReadIndexes = BaseFieldNamesToRead.map((e, i) => i);
20
-
21
- const [
22
- SCALE_0, SCALE_1, SCALE_2, ROT_0, ROT_1, ROT_2, ROT_3, X, Y, Z, F_DC_0, F_DC_1, F_DC_2, OPACITY, RED, GREEN, BLUE, F_REST_0
23
- ] = BaseFieldsToReadIndexes;
24
-
25
- export class INRIAV1PlyParser {
26
-
27
- constructor() {
28
- this.plyParserutils = new PlyParserUtils();
29
- }
30
-
31
- decodeHeaderLines(headerLines) {
32
-
33
- let shLineCount = 0;
34
- headerLines.forEach((line) => {
35
- if (line.includes('f_rest_')) shLineCount++;
36
- });
37
-
38
- let shFieldsToReadCount = 0;
39
- if (shLineCount >= 45) {
40
- shFieldsToReadCount = 45;
41
- } else if (shLineCount >= 24) {
42
- shFieldsToReadCount = 24;
43
- } else if (shLineCount >= 9) {
44
- shFieldsToReadCount = 9;
45
- }
46
-
47
- const shFieldIndexesToMap = Array.from(Array(Math.max(shFieldsToReadCount - 1, 0)));
48
- let shRemainingFieldNamesToRead = shFieldIndexesToMap.map((element, index) => `f_rest_${index + 1}`);
49
-
50
- const fieldNamesToRead = [...BaseFieldNamesToRead, ...shRemainingFieldNamesToRead];
51
- const fieldsToReadIndexes = fieldNamesToRead.map((e, i) => i);
52
-
53
- const fieldNameIdMap = fieldsToReadIndexes.reduce((acc, element) => {
54
- acc[fieldNamesToRead[element]] = element;
55
- return acc;
56
- }, {});
57
- const header = this.plyParserutils.decodeSectionHeader(headerLines, fieldNameIdMap, 0);
58
- header.splatCount = header.vertexCount;
59
- header.bytesPerSplat = header.bytesPerVertex;
60
- header.fieldsToReadIndexes = fieldsToReadIndexes;
61
- return header;
62
- }
63
-
64
- decodeHeaderText(headerText) {
65
- const headerLines = PlyParserUtils.convertHeaderTextToLines(headerText);
66
- const header = this.decodeHeaderLines(headerLines);
67
- header.headerText = headerText;
68
- header.headerSizeBytes = headerText.indexOf(PlyParserUtils.HeaderEndToken) + PlyParserUtils.HeaderEndToken.length + 1;
69
- return header;
70
- }
71
-
72
- decodeHeaderFromBuffer(plyBuffer) {
73
- const headerText = this.plyParserutils.readHeaderFromBuffer(plyBuffer);
74
- return this.decodeHeaderText(headerText);
75
- }
76
-
77
- findSplatData(plyBuffer, header) {
78
- return new DataView(plyBuffer, header.headerSizeBytes);
79
- }
80
-
81
- parseToUncompressedSplatBufferSection(header, fromSplat, toSplat, splatData, splatDataOffset,
82
- toBuffer, toOffset, outSphericalHarmonicsDegree = 0) {
83
- outSphericalHarmonicsDegree = Math.min(outSphericalHarmonicsDegree, header.sphericalHarmonicsDegree);
84
- const outBytesPerSplat = SplatBuffer.CompressionLevels[0].SphericalHarmonicsDegrees[outSphericalHarmonicsDegree].BytesPerSplat;
85
-
86
- for (let i = fromSplat; i <= toSplat; i++) {
87
- const parsedSplat = INRIAV1PlyParser.parseToUncompressedSplat(splatData, i, header,
88
- splatDataOffset, outSphericalHarmonicsDegree);
89
- const outBase = i * outBytesPerSplat + toOffset;
90
- SplatBuffer.writeSplatDataToSectionBuffer(parsedSplat, toBuffer, outBase, 0, outSphericalHarmonicsDegree);
91
- }
92
- }
93
-
94
- parseToUncompressedSplatArraySection(header, fromSplat, toSplat, splatData, splatDataOffset,
95
- splatArray, outSphericalHarmonicsDegree = 0) {
96
- outSphericalHarmonicsDegree = Math.min(outSphericalHarmonicsDegree, header.sphericalHarmonicsDegree);
97
- for (let i = fromSplat; i <= toSplat; i++) {
98
- const parsedSplat = INRIAV1PlyParser.parseToUncompressedSplat(splatData, i, header,
99
- splatDataOffset, outSphericalHarmonicsDegree);
100
- splatArray.addSplat(parsedSplat);
101
- }
102
- }
103
-
104
- decodeSectionSplatData(sectionSplatData, splatCount, sectionHeader, outSphericalHarmonicsDegree) {
105
- outSphericalHarmonicsDegree = Math.min(outSphericalHarmonicsDegree, sectionHeader.sphericalHarmonicsDegree);
106
- const splatArray = new UncompressedSplatArray(outSphericalHarmonicsDegree);
107
- for (let row = 0; row < splatCount; row++) {
108
- const newSplat = INRIAV1PlyParser.parseToUncompressedSplat(sectionSplatData, row, sectionHeader,
109
- 0, outSphericalHarmonicsDegree);
110
- splatArray.addSplat(newSplat);
111
- }
112
- return splatArray;
113
- }
114
-
115
- static parseToUncompressedSplat = function() {
116
-
117
- let rawSplat = [];
118
- const tempRotation = new Quaternion();
119
-
120
- const OFFSET_X = UncompressedSplatArray.OFFSET.X;
121
- const OFFSET_Y = UncompressedSplatArray.OFFSET.Y;
122
- const OFFSET_Z = UncompressedSplatArray.OFFSET.Z;
123
-
124
- const OFFSET_SCALE0 = UncompressedSplatArray.OFFSET.SCALE0;
125
- const OFFSET_SCALE1 = UncompressedSplatArray.OFFSET.SCALE1;
126
- const OFFSET_SCALE2 = UncompressedSplatArray.OFFSET.SCALE2;
127
-
128
- const OFFSET_ROTATION0 = UncompressedSplatArray.OFFSET.ROTATION0;
129
- const OFFSET_ROTATION1 = UncompressedSplatArray.OFFSET.ROTATION1;
130
- const OFFSET_ROTATION2 = UncompressedSplatArray.OFFSET.ROTATION2;
131
- const OFFSET_ROTATION3 = UncompressedSplatArray.OFFSET.ROTATION3;
132
-
133
- const OFFSET_FDC0 = UncompressedSplatArray.OFFSET.FDC0;
134
- const OFFSET_FDC1 = UncompressedSplatArray.OFFSET.FDC1;
135
- const OFFSET_FDC2 = UncompressedSplatArray.OFFSET.FDC2;
136
- const OFFSET_OPACITY = UncompressedSplatArray.OFFSET.OPACITY;
137
-
138
- const OFFSET_FRC = [];
139
-
140
- for (let i = 0; i < 45; i++) {
141
- OFFSET_FRC[i] = UncompressedSplatArray.OFFSET.FRC0 + i;
142
- }
143
-
144
- return function(splatData, row, header, splatDataOffset = 0, outSphericalHarmonicsDegree = 0) {
145
- outSphericalHarmonicsDegree = Math.min(outSphericalHarmonicsDegree, header.sphericalHarmonicsDegree);
146
- INRIAV1PlyParser.readSplat(splatData, header, row, splatDataOffset, rawSplat);
147
- const newSplat = UncompressedSplatArray.createSplat(outSphericalHarmonicsDegree);
148
- if (rawSplat[SCALE_0] !== undefined) {
149
- newSplat[OFFSET_SCALE0] = Math.exp(rawSplat[SCALE_0]);
150
- newSplat[OFFSET_SCALE1] = Math.exp(rawSplat[SCALE_1]);
151
- newSplat[OFFSET_SCALE2] = Math.exp(rawSplat[SCALE_2]);
152
- } else {
153
- newSplat[OFFSET_SCALE0] = 0.01;
154
- newSplat[OFFSET_SCALE1] = 0.01;
155
- newSplat[OFFSET_SCALE2] = 0.01;
156
- }
157
-
158
- if (rawSplat[F_DC_0] !== undefined) {
159
- const SH_C0 = 0.28209479177387814;
160
- newSplat[OFFSET_FDC0] = rawSplat[F_DC_0] * 255;
161
- newSplat[OFFSET_FDC1] = rawSplat[F_DC_1] * 255;
162
- newSplat[OFFSET_FDC2] = rawSplat[F_DC_2] * 255;
163
- } else if (rawSplat[RED] !== undefined) {
164
- newSplat[OFFSET_FDC0] = rawSplat[RED] * 255;
165
- newSplat[OFFSET_FDC1] = rawSplat[GREEN] * 255;
166
- newSplat[OFFSET_FDC2] = rawSplat[BLUE] * 255;
167
- } else {
168
- newSplat[OFFSET_FDC0] = 0;
169
- newSplat[OFFSET_FDC1] = 0;
170
- newSplat[OFFSET_FDC2] = 0;
171
- }
172
-
173
- if (rawSplat[OPACITY] !== undefined) {
174
- newSplat[OFFSET_OPACITY] = (1 / (1 + Math.exp(-rawSplat[OPACITY]))) * 255;
175
- }
176
-
177
- newSplat[OFFSET_FDC0] = clamp(Math.floor(newSplat[OFFSET_FDC0]), 0, 255);
178
- newSplat[OFFSET_FDC1] = clamp(Math.floor(newSplat[OFFSET_FDC1]), 0, 255);
179
- newSplat[OFFSET_FDC2] = clamp(Math.floor(newSplat[OFFSET_FDC2]), 0, 255);
180
- newSplat[OFFSET_OPACITY] = clamp(Math.floor(newSplat[OFFSET_OPACITY]), 0, 255);
181
-
182
- if (outSphericalHarmonicsDegree >= 1) {
183
- if (rawSplat[F_REST_0] !== undefined) {
184
- for (let i = 0; i < 9; i++) {
185
- newSplat[OFFSET_FRC[i]] = rawSplat[header.sphericalHarmonicsDegree1Fields[i]];
186
- }
187
- if (outSphericalHarmonicsDegree >= 2) {
188
- for (let i = 0; i < 15; i++) {
189
- newSplat[OFFSET_FRC[9 + i]] = rawSplat[header.sphericalHarmonicsDegree2Fields[i]];
190
- }
191
- }
192
- }
193
- }
194
-
195
- tempRotation.set(rawSplat[ROT_0], rawSplat[ROT_1], rawSplat[ROT_2], rawSplat[ROT_3]);
196
- tempRotation.normalize();
197
-
198
- newSplat[OFFSET_ROTATION0] = tempRotation.x;
199
- newSplat[OFFSET_ROTATION1] = tempRotation.y;
200
- newSplat[OFFSET_ROTATION2] = tempRotation.z;
201
- newSplat[OFFSET_ROTATION3] = tempRotation.w;
202
-
203
- newSplat[OFFSET_X] = rawSplat[X];
204
- newSplat[OFFSET_Y] = rawSplat[Y];
205
- newSplat[OFFSET_Z] = rawSplat[Z];
206
-
207
- return newSplat;
208
- };
209
-
210
- }();
211
-
212
- static readSplat(splatData, header, row, dataOffset, rawSplat) {
213
- return PlyParserUtils.readVertex(splatData, header, row, dataOffset, header.fieldsToReadIndexes, rawSplat, true);
214
- }
215
-
216
- parseToUncompressedSplatArray(plyBuffer, outSphericalHarmonicsDegree = 0) {
217
- const header = this.decodeHeaderFromBuffer(plyBuffer);
218
- const splatCount = header.splatCount;
219
- const splatData = this.findSplatData(plyBuffer, header);
220
- const splatArray = this.decodeSectionSplatData(splatData, splatCount, header, outSphericalHarmonicsDegree);
221
- return splatArray;
222
- }
223
- }