@myned-ai/gsplat-flame-avatar-renderer 1.0.2 → 1.0.4

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 (66) hide show
  1. package/README.md +1 -21
  2. package/dist/gsplat-flame-avatar-renderer.cjs.js +12875 -0
  3. package/dist/{gsplat-flame-avatar-renderer.umd.js.map → gsplat-flame-avatar-renderer.cjs.js.map} +1 -1
  4. package/dist/gsplat-flame-avatar-renderer.esm.js +1 -1
  5. package/package.json +5 -3
  6. package/src/api/index.js +7 -0
  7. package/src/buffers/SplatBuffer.js +1394 -0
  8. package/src/buffers/SplatBufferGenerator.js +41 -0
  9. package/src/buffers/SplatPartitioner.js +110 -0
  10. package/src/buffers/UncompressedSplatArray.js +106 -0
  11. package/src/buffers/index.js +11 -0
  12. package/src/core/SplatGeometry.js +48 -0
  13. package/src/core/SplatMesh.js +2620 -0
  14. package/src/core/SplatScene.js +43 -0
  15. package/src/core/SplatTree.js +200 -0
  16. package/src/core/Viewer.js +2895 -0
  17. package/src/core/index.js +13 -0
  18. package/src/enums/EngineConstants.js +58 -0
  19. package/src/enums/LogLevel.js +13 -0
  20. package/src/enums/RenderMode.js +11 -0
  21. package/src/enums/SceneFormat.js +21 -0
  22. package/src/enums/SceneRevealMode.js +11 -0
  23. package/src/enums/SplatRenderMode.js +10 -0
  24. package/src/enums/index.js +13 -0
  25. package/src/flame/FlameAnimator.js +271 -0
  26. package/src/flame/FlameConstants.js +21 -0
  27. package/src/flame/FlameTextureManager.js +293 -0
  28. package/src/flame/index.js +22 -0
  29. package/src/flame/utils.js +50 -0
  30. package/src/index.js +39 -0
  31. package/src/loaders/DirectLoadError.js +14 -0
  32. package/src/loaders/INRIAV1PlyParser.js +223 -0
  33. package/src/loaders/PlyLoader.js +261 -0
  34. package/src/loaders/PlyParser.js +19 -0
  35. package/src/loaders/PlyParserUtils.js +311 -0
  36. package/src/loaders/index.js +13 -0
  37. package/src/materials/SplatMaterial.js +1065 -0
  38. package/src/materials/SplatMaterial2D.js +358 -0
  39. package/src/materials/SplatMaterial3D.js +278 -0
  40. package/src/materials/index.js +11 -0
  41. package/src/raycaster/Hit.js +37 -0
  42. package/src/raycaster/Ray.js +123 -0
  43. package/src/raycaster/Raycaster.js +175 -0
  44. package/src/raycaster/index.js +10 -0
  45. package/src/renderer/AnimationManager.js +574 -0
  46. package/src/renderer/AppConstants.js +101 -0
  47. package/src/renderer/GaussianSplatRenderer.js +695 -0
  48. package/src/renderer/index.js +24 -0
  49. package/src/utils/LoaderUtils.js +65 -0
  50. package/src/utils/Util.js +375 -0
  51. package/src/utils/index.js +9 -0
  52. package/src/worker/SortWorker.js +284 -0
  53. package/src/worker/index.js +8 -0
  54. package/dist/gsplat-flame-avatar-renderer.esm.min.js +0 -2
  55. package/dist/gsplat-flame-avatar-renderer.esm.min.js.map +0 -1
  56. package/dist/gsplat-flame-avatar-renderer.umd.js +0 -12876
  57. package/dist/gsplat-flame-avatar-renderer.umd.min.js +0 -2
  58. package/dist/gsplat-flame-avatar-renderer.umd.min.js.map +0 -1
  59. package/dist/gsplat-flame-avatar.esm.js +0 -12755
  60. package/dist/gsplat-flame-avatar.esm.js.map +0 -1
  61. package/dist/gsplat-flame-avatar.esm.min.js +0 -2
  62. package/dist/gsplat-flame-avatar.esm.min.js.map +0 -1
  63. package/dist/gsplat-flame-avatar.umd.js +0 -12876
  64. package/dist/gsplat-flame-avatar.umd.js.map +0 -1
  65. package/dist/gsplat-flame-avatar.umd.min.js +0 -2
  66. package/dist/gsplat-flame-avatar.umd.min.js.map +0 -1
@@ -0,0 +1,13 @@
1
+ /**
2
+ * gsplat-flame-avatar - Core Module
3
+ * Core rendering engine components.
4
+ *
5
+ * Based on @mkkellogg/gaussian-splats-3d (MIT License)
6
+ * Extended with FLAME avatar support.
7
+ */
8
+
9
+ export { SplatGeometry } from './SplatGeometry.js';
10
+ export { SplatMesh } from './SplatMesh.js';
11
+ export { SplatScene } from './SplatScene.js';
12
+ export { SplatTree } from './SplatTree.js';
13
+ export { Viewer } from './Viewer.js';
@@ -0,0 +1,58 @@
1
+ /**
2
+ * EngineConstants
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ *
7
+ * Core constants for Gaussian Splat rendering.
8
+ */
9
+
10
+ export class Constants {
11
+ static DefaultSplatSortDistanceMapPrecision = 16;
12
+ static MemoryPageSize = 65536;
13
+ static BytesPerFloat = 4;
14
+ static BytesPerInt = 4;
15
+ static MaxScenes = 32;
16
+ static ProgressiveLoadSectionSize = 262144;
17
+ static ProgressiveLoadSectionDelayDuration = 15;
18
+ static SphericalHarmonics8BitCompressionRange = 3;
19
+ }
20
+
21
+ export const DefaultSphericalHarmonics8BitCompressionRange = Constants.SphericalHarmonics8BitCompressionRange;
22
+
23
+ // SplatMesh constants
24
+ export const COVARIANCES_ELEMENTS_PER_SPLAT = 6;
25
+ export const CENTER_COLORS_ELEMENTS_PER_SPLAT = 4;
26
+
27
+ export const COVARIANCES_ELEMENTS_PER_TEXEL_STORED = 4;
28
+ export const COVARIANCES_ELEMENTS_PER_TEXEL_ALLOCATED = 4;
29
+ export const COVARIANCES_ELEMENTS_PER_TEXEL_COMPRESSED_STORED = 6;
30
+ export const COVARIANCES_ELEMENTS_PER_TEXEL_COMPRESSED_ALLOCATED = 8;
31
+ export const SCALES_ROTATIONS_ELEMENTS_PER_TEXEL = 4;
32
+ export const CENTER_COLORS_ELEMENTS_PER_TEXEL = 4;
33
+ export const SCENE_INDEXES_ELEMENTS_PER_TEXEL = 1;
34
+
35
+ export const SCENE_FADEIN_RATE_FAST = 0.012;
36
+ export const SCENE_FADEIN_RATE_GRADUAL = 0.003;
37
+
38
+ // Viewer constants
39
+ export const THREE_CAMERA_FOV = 50;
40
+ export const MINIMUM_DISTANCE_TO_NEW_FOCAL_POINT = 0.5;
41
+ export const CONSECUTIVE_RENDERED_FRAMES_FOR_FPS_CALCULATION = 60;
42
+ export const MIN_SPLAT_COUNT_TO_SHOW_SPLAT_TREE_LOADING_SPINNER = 1500000;
43
+ export const FOCUS_MARKER_FADE_IN_SPEED = 0.4;
44
+ export const FOCUS_MARKER_FADE_OUT_SPEED = 0.12;
45
+
46
+ // Internal load types for loaders
47
+ export const InternalLoadType = {
48
+ DirectToSplatBuffer: 0,
49
+ DirectToSplatArray: 1,
50
+ DownloadBeforeProcessing: 2
51
+ };
52
+
53
+ // Loader status
54
+ export const LoaderStatus = {
55
+ 'Downloading': 0,
56
+ 'Processing': 1,
57
+ 'Done': 2
58
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Log level enumeration for controlling verbosity
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ */
7
+ export const LogLevel = {
8
+ None: 0,
9
+ Error: 1,
10
+ Warning: 2,
11
+ Info: 3,
12
+ Debug: 4
13
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Render mode enumeration
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ */
7
+ export const RenderMode = {
8
+ Always: 0,
9
+ OnChange: 1,
10
+ Never: 2
11
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Scene format enumeration for supported file types
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ *
7
+ * Simplified for FLAME avatar usage - only PLY format is supported.
8
+ */
9
+ export const SceneFormat = {
10
+ 'Ply': 0
11
+ };
12
+
13
+ /**
14
+ * Determine scene format from file path
15
+ * @param {string} path - File path
16
+ * @returns {number|null} Scene format or null if unknown
17
+ */
18
+ export const sceneFormatFromPath = (path) => {
19
+ if (path.endsWith('.ply')) return SceneFormat.Ply;
20
+ return null;
21
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Scene reveal mode enumeration
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ */
7
+ export const SceneRevealMode = {
8
+ Default: 0,
9
+ Gradual: 1,
10
+ Instant: 2
11
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Splat render mode enumeration
3
+ *
4
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
5
+ * https://github.com/mkkellogg/GaussianSplats3D
6
+ */
7
+ export const SplatRenderMode = {
8
+ ThreeD: 0,
9
+ TwoD: 1
10
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * gsplat-flame-avatar - Enums Module
3
+ * Constants and enumerations for rendering configuration.
4
+ *
5
+ * Derived from @mkkellogg/gaussian-splats-3d (MIT License)
6
+ */
7
+
8
+ export * from './LogLevel.js';
9
+ export * from './RenderMode.js';
10
+ export * from './SceneFormat.js';
11
+ export * from './SceneRevealMode.js';
12
+ export * from './SplatRenderMode.js';
13
+ export * from './EngineConstants.js';
@@ -0,0 +1,271 @@
1
+ /**
2
+ * FlameAnimator
3
+ *
4
+ * Derived from gaussian-splat-renderer-for-lam
5
+ *
6
+ * Handles FLAME model animation and skeleton updates:
7
+ * - Bone rotation from FLAME parameters
8
+ * - Blendshape weight updates
9
+ * - Skeleton synchronization with gaussian splat mesh
10
+ */
11
+
12
+ import {
13
+ Vector3,
14
+ Quaternion,
15
+ Matrix4,
16
+ Bone,
17
+ Skeleton
18
+ } from 'three';
19
+
20
+ import { FlameTextureManager } from './FlameTextureManager.js';
21
+
22
+ /**
23
+ * FlameAnimator - Manages FLAME parametric head model animation
24
+ */
25
+ export class FlameAnimator {
26
+ constructor() {
27
+ this.skeleton = null;
28
+ this.bones = null;
29
+ this.flameParams = null;
30
+ this.lbsWeight = null;
31
+ this.frame = 0;
32
+ this.totalFrames = 0;
33
+ this.useFlame = true;
34
+ this.avatarMesh = null;
35
+ this.gaussianSplatCount = 0;
36
+ }
37
+
38
+ /**
39
+ * Initialize with FLAME parameters and LBS weights
40
+ * @param {object} flameParams - FLAME animation parameters
41
+ * @param {object} boneTree - Skeleton hierarchy data
42
+ * @param {Array} lbsWeight - LBS weights for each vertex
43
+ * @param {THREE.SkinnedMesh} avatarMesh - The FLAME avatar mesh
44
+ */
45
+ initialize(flameParams, boneTree, lbsWeight, avatarMesh) {
46
+ this.flameParams = flameParams;
47
+ this.lbsWeight = lbsWeight;
48
+ this.avatarMesh = avatarMesh;
49
+
50
+ if (flameParams && flameParams.rotation) {
51
+ this.totalFrames = flameParams.rotation.length;
52
+ }
53
+
54
+ this.gaussianSplatCount = avatarMesh.geometry.attributes.position.count;
55
+
56
+ // Build skeleton from bone tree
57
+ this.buildSkeleton(boneTree);
58
+ }
59
+
60
+ /**
61
+ * Build skeleton from bone tree data
62
+ * @param {object} boneTree - Skeleton hierarchy definition
63
+ */
64
+ buildSkeleton(boneTree) {
65
+ if (!boneTree) return;
66
+
67
+ this.bones = [];
68
+ const boneInverses = [];
69
+
70
+ // Create bones from tree structure
71
+ const createBone = (boneData, parentBone = null) => {
72
+ const bone = new Bone();
73
+ bone.name = boneData.name || `bone_${this.bones.length}`;
74
+
75
+ if (boneData.position) {
76
+ bone.position.fromArray(boneData.position);
77
+ }
78
+ if (boneData.rotation) {
79
+ bone.rotation.fromArray(boneData.rotation);
80
+ }
81
+ if (boneData.scale) {
82
+ bone.scale.fromArray(boneData.scale);
83
+ }
84
+
85
+ if (parentBone) {
86
+ parentBone.add(bone);
87
+ }
88
+
89
+ this.bones.push(bone);
90
+
91
+ // Create inverse bind matrix
92
+ const inverseMatrix = new Matrix4();
93
+ if (boneData.inverseBindMatrix) {
94
+ inverseMatrix.fromArray(boneData.inverseBindMatrix);
95
+ } else {
96
+ bone.updateMatrixWorld(true);
97
+ inverseMatrix.copy(bone.matrixWorld).invert();
98
+ }
99
+ boneInverses.push(inverseMatrix);
100
+
101
+ // Process children
102
+ if (boneData.children) {
103
+ boneData.children.forEach(child => createBone(child, bone));
104
+ }
105
+ };
106
+
107
+ // If boneTree is array, create bones directly
108
+ if (Array.isArray(boneTree)) {
109
+ boneTree.forEach((boneData, index) => {
110
+ const bone = new Bone();
111
+ bone.name = boneData.name || `bone_${index}`;
112
+
113
+ if (boneData.position) {
114
+ bone.position.fromArray(boneData.position);
115
+ }
116
+
117
+ this.bones.push(bone);
118
+
119
+ const inverseMatrix = new Matrix4();
120
+ if (boneData.inverseBindMatrix) {
121
+ inverseMatrix.fromArray(boneData.inverseBindMatrix);
122
+ }
123
+ boneInverses.push(inverseMatrix);
124
+ });
125
+
126
+ // Set up hierarchy (FLAME: root -> neck -> jaw, eyes)
127
+ if (this.bones.length >= 5) {
128
+ this.bones[0].add(this.bones[1]); // root -> neck
129
+ this.bones[1].add(this.bones[2]); // neck -> jaw
130
+ this.bones[1].add(this.bones[3]); // neck -> leftEye
131
+ this.bones[1].add(this.bones[4]); // neck -> rightEye
132
+ }
133
+ } else if (boneTree.root) {
134
+ createBone(boneTree.root);
135
+ }
136
+
137
+ // Create skeleton
138
+ this.skeleton = new Skeleton(this.bones, boneInverses);
139
+ }
140
+
141
+ /**
142
+ * Set bone rotation from axis-angle or quaternion
143
+ * @param {THREE.Bone} bone - Target bone
144
+ * @param {Array} angles - Rotation values
145
+ * @param {boolean} isQuat - Whether angles are quaternion
146
+ */
147
+ setBoneRotation(bone, angles, isQuat = false) {
148
+ let quaternion;
149
+
150
+ if (isQuat) {
151
+ quaternion = new Quaternion(angles[0], angles[1], angles[2], angles[3]);
152
+ } else {
153
+ // Axis-angle representation
154
+ const value = new Vector3(angles[0], angles[1], angles[2]);
155
+ const angleInRadians = value.length();
156
+ const axis = value.normalize();
157
+ quaternion = new Quaternion().setFromAxisAngle(axis, angleInRadians);
158
+ }
159
+
160
+ bone.quaternion.copy(quaternion);
161
+ bone.updateMatrixWorld(true);
162
+ }
163
+
164
+ /**
165
+ * Update FLAME bones from current frame parameters
166
+ */
167
+ updateFlameBones() {
168
+ if (!this.flameParams || !this.skeleton) return {};
169
+
170
+ const frame = this.frame;
171
+ const bsWeight = this.flameParams['expr'][frame];
172
+
173
+ // Root bone rotation
174
+ const rootAngle = this.flameParams['rotation'][frame];
175
+ this.setBoneRotation(this.skeleton.bones[0], rootAngle);
176
+
177
+ // Neck rotation
178
+ const neckAngle = this.flameParams['neck_pose'][frame];
179
+ this.setBoneRotation(this.skeleton.bones[1], neckAngle);
180
+
181
+ // Jaw rotation
182
+ const jawAngle = this.flameParams['jaw_pose'][frame];
183
+ this.setBoneRotation(this.skeleton.bones[2], jawAngle);
184
+
185
+ // Eyes rotation (combined in eyes_pose array)
186
+ const eyesAngle = this.flameParams['eyes_pose'][frame];
187
+ this.setBoneRotation(this.skeleton.bones[3], eyesAngle);
188
+ this.setBoneRotation(this.skeleton.bones[4], [eyesAngle[3], eyesAngle[4], eyesAngle[5]]);
189
+
190
+ // Update skeleton matrices
191
+ this.skeleton.update();
192
+
193
+ // Get updated bone matrices
194
+ const numBones = 5;
195
+ const bonesMatrix = FlameTextureManager.getUpdatedBoneMatrices(this.skeleton, numBones);
196
+
197
+ return {
198
+ bsWeight,
199
+ bonesMatrix,
200
+ bonesNum: numBones,
201
+ bonesWeight: this.lbsWeight
202
+ };
203
+ }
204
+
205
+ /**
206
+ * Run morph update - main animation loop function
207
+ * @param {SplatMesh} splatMesh - The gaussian splat mesh to update
208
+ */
209
+ runMorphUpdate(splatMesh) {
210
+ const morphedMesh = new Float32Array(
211
+ this.avatarMesh.geometry.attributes.position.array
212
+ );
213
+
214
+ splatMesh.gaussianSplatCount = this.gaussianSplatCount;
215
+ splatMesh.bonesNum = 5;
216
+
217
+ if (this.useFlame) {
218
+ const updateData = this.updateFlameBones();
219
+ splatMesh.bsWeight = updateData.bsWeight;
220
+ splatMesh.bonesMatrix = updateData.bonesMatrix;
221
+ splatMesh.bonesNum = updateData.bonesNum;
222
+ splatMesh.bonesWeight = updateData.bonesWeight;
223
+ }
224
+
225
+ splatMesh.morphedMesh = morphedMesh;
226
+
227
+ // Update textures
228
+ const splatNum = splatMesh.morphedMesh.length / 3;
229
+ if (splatMesh.splatDataTextures && splatMesh.splatDataTextures['flameModel']) {
230
+ splatMesh.updateTextureAfterBSAndSkeleton(0, splatNum - 1, this.useFlame);
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Set current animation frame
236
+ * @param {number} frame - Frame number
237
+ */
238
+ setFrame(frame) {
239
+ this.frame = frame % this.totalFrames;
240
+ }
241
+
242
+ /**
243
+ * Advance to next frame
244
+ */
245
+ nextFrame() {
246
+ this.frame = (this.frame + 1) % this.totalFrames;
247
+ }
248
+
249
+ /**
250
+ * Get skeleton for external use
251
+ */
252
+ getSkeleton() {
253
+ return this.skeleton;
254
+ }
255
+
256
+ /**
257
+ * Get current frame number
258
+ */
259
+ getFrame() {
260
+ return this.frame;
261
+ }
262
+
263
+ /**
264
+ * Get total frame count
265
+ */
266
+ getTotalFrames() {
267
+ return this.totalFrames;
268
+ }
269
+ }
270
+
271
+ export default FlameAnimator;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * FlameConstants
3
+ *
4
+ * Derived from gaussian-splat-renderer-for-lam
5
+ * FLAME-specific constants for parametric head model.
6
+ *
7
+ * Note: General engine constants (MaxScenes, etc.) are in enums/EngineConstants.js
8
+ */
9
+
10
+ export const Constants = {
11
+ // FLAME model constants
12
+ FlameBonesCount: 5, // root, neck, jaw, leftEye, rightEye
13
+ DefaultBlendshapeCount: 52, // ARKit blendshapes
14
+
15
+ // Texture sizes for FLAME data
16
+ FlameModelTextureSize: { width: 4096, height: 2048 },
17
+ BoneTextureSize: { width: 4, height: 32 },
18
+ BoneWeightTextureSize: { width: 512, height: 512 }
19
+ };
20
+
21
+ export default Constants;