@myned-ai/gsplat-flame-avatar-renderer 1.0.6 → 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.
- package/README.md +30 -0
- package/dist/gsplat-flame-avatar-renderer.cjs.js +38 -33
- package/dist/gsplat-flame-avatar-renderer.cjs.min.js +1 -1
- package/dist/gsplat-flame-avatar-renderer.cjs.min.js.map +1 -1
- package/dist/gsplat-flame-avatar-renderer.esm.js +38 -33
- package/dist/gsplat-flame-avatar-renderer.esm.min.js +1 -1
- package/dist/gsplat-flame-avatar-renderer.esm.min.js.map +1 -1
- package/package.json +5 -2
- package/src/api/index.js +0 -7
- package/src/buffers/SplatBuffer.js +0 -1394
- package/src/buffers/SplatBufferGenerator.js +0 -41
- package/src/buffers/SplatPartitioner.js +0 -110
- package/src/buffers/UncompressedSplatArray.js +0 -106
- package/src/buffers/index.js +0 -11
- package/src/core/SplatGeometry.js +0 -48
- package/src/core/SplatMesh.js +0 -2627
- package/src/core/SplatScene.js +0 -43
- package/src/core/SplatTree.js +0 -200
- package/src/core/Viewer.js +0 -2746
- package/src/core/index.js +0 -13
- package/src/enums/EngineConstants.js +0 -58
- package/src/enums/LogLevel.js +0 -13
- package/src/enums/RenderMode.js +0 -11
- package/src/enums/SceneFormat.js +0 -21
- package/src/enums/SceneRevealMode.js +0 -11
- package/src/enums/SplatRenderMode.js +0 -10
- package/src/enums/index.js +0 -13
- package/src/errors/ApplicationError.js +0 -185
- package/src/errors/index.js +0 -17
- package/src/flame/FlameAnimator.js +0 -496
- package/src/flame/FlameConstants.js +0 -21
- package/src/flame/FlameTextureManager.js +0 -293
- package/src/flame/index.js +0 -22
- package/src/flame/utils.js +0 -50
- package/src/index.js +0 -39
- package/src/loaders/DirectLoadError.js +0 -14
- package/src/loaders/INRIAV1PlyParser.js +0 -223
- package/src/loaders/PlyLoader.js +0 -519
- package/src/loaders/PlyParser.js +0 -19
- package/src/loaders/PlyParserUtils.js +0 -311
- package/src/loaders/index.js +0 -13
- package/src/materials/SplatMaterial.js +0 -1068
- package/src/materials/SplatMaterial2D.js +0 -358
- package/src/materials/SplatMaterial3D.js +0 -323
- package/src/materials/index.js +0 -11
- package/src/raycaster/Hit.js +0 -37
- package/src/raycaster/Ray.js +0 -123
- package/src/raycaster/Raycaster.js +0 -175
- package/src/raycaster/index.js +0 -10
- package/src/renderer/AnimationManager.js +0 -577
- package/src/renderer/AppConstants.js +0 -101
- package/src/renderer/GaussianSplatRenderer.js +0 -1146
- package/src/renderer/index.js +0 -24
- package/src/utils/BlobUrlManager.js +0 -294
- package/src/utils/EventEmitter.js +0 -349
- package/src/utils/LoaderUtils.js +0 -66
- package/src/utils/Logger.js +0 -171
- package/src/utils/ObjectPool.js +0 -248
- package/src/utils/RenderLoop.js +0 -306
- package/src/utils/Util.js +0 -416
- package/src/utils/ValidationUtils.js +0 -331
- package/src/utils/index.js +0 -18
- package/src/worker/SortWorker.js +0 -284
- package/src/worker/index.js +0 -8
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PlyParserUtils and related constants
|
|
3
|
-
*
|
|
4
|
-
* Derived from @mkkellogg/gaussian-splats-3d (MIT License)
|
|
5
|
-
* https://github.com/mkkellogg/GaussianSplats3D
|
|
6
|
-
*
|
|
7
|
-
* Simplified for FLAME avatar - only supports INRIAV1 format.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// Ply format types (simplified - FLAME uses INRIAV1)
|
|
11
|
-
export const PlyFormat = {
|
|
12
|
-
'INRIAV1': 0
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// Field size IDs
|
|
16
|
-
export const FieldSizeIdDouble = 0;
|
|
17
|
-
export const FieldSizeIdInt = 1;
|
|
18
|
-
export const FieldSizeIdUInt = 2;
|
|
19
|
-
export const FieldSizeIdFloat = 3;
|
|
20
|
-
export const FieldSizeIdShort = 4;
|
|
21
|
-
export const FieldSizeIdUShort = 5;
|
|
22
|
-
export const FieldSizeIdUChar = 6;
|
|
23
|
-
|
|
24
|
-
export const FieldSizeStringMap = {
|
|
25
|
-
'double': FieldSizeIdDouble,
|
|
26
|
-
'int': FieldSizeIdInt,
|
|
27
|
-
'uint': FieldSizeIdUInt,
|
|
28
|
-
'float': FieldSizeIdFloat,
|
|
29
|
-
'short': FieldSizeIdShort,
|
|
30
|
-
'ushort': FieldSizeIdUShort,
|
|
31
|
-
'uchar': FieldSizeIdUChar,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const FieldSize = {
|
|
35
|
-
[FieldSizeIdDouble]: 8,
|
|
36
|
-
[FieldSizeIdInt]: 4,
|
|
37
|
-
[FieldSizeIdUInt]: 4,
|
|
38
|
-
[FieldSizeIdFloat]: 4,
|
|
39
|
-
[FieldSizeIdShort]: 2,
|
|
40
|
-
[FieldSizeIdUShort]: 2,
|
|
41
|
-
[FieldSizeIdUChar]: 1,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export class PlyParserUtils {
|
|
45
|
-
|
|
46
|
-
static HeaderEndToken = 'end_header';
|
|
47
|
-
|
|
48
|
-
constructor() {
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
decodeSectionHeader(headerLines, fieldNameIdMap, headerStartLine = 0) {
|
|
52
|
-
|
|
53
|
-
const extractedLines = [];
|
|
54
|
-
|
|
55
|
-
let processingSection = false;
|
|
56
|
-
let headerEndLine = -1;
|
|
57
|
-
let vertexCount = 0;
|
|
58
|
-
let endOfHeader = false;
|
|
59
|
-
let sectionName = null;
|
|
60
|
-
|
|
61
|
-
const fieldIds = [];
|
|
62
|
-
const fieldTypes = [];
|
|
63
|
-
const allFieldNames = [];
|
|
64
|
-
const usedFieldNames = [];
|
|
65
|
-
const fieldTypesByName = {};
|
|
66
|
-
|
|
67
|
-
for (let i = headerStartLine; i < headerLines.length; i++) {
|
|
68
|
-
const line = headerLines[i].trim();
|
|
69
|
-
if (line.startsWith('element')) {
|
|
70
|
-
if (processingSection) {
|
|
71
|
-
headerEndLine--;
|
|
72
|
-
break;
|
|
73
|
-
} else {
|
|
74
|
-
processingSection = true;
|
|
75
|
-
headerStartLine = i;
|
|
76
|
-
headerEndLine = i;
|
|
77
|
-
const lineComponents = line.split(' ');
|
|
78
|
-
let validComponents = 0;
|
|
79
|
-
for (let lineComponent of lineComponents) {
|
|
80
|
-
const trimmedComponent = lineComponent.trim();
|
|
81
|
-
if (trimmedComponent.length > 0) {
|
|
82
|
-
validComponents++;
|
|
83
|
-
if (validComponents === 2) {
|
|
84
|
-
sectionName = trimmedComponent;
|
|
85
|
-
} else if (validComponents === 3) {
|
|
86
|
-
vertexCount = parseInt(trimmedComponent);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
} else if (line.startsWith('property')) {
|
|
92
|
-
const fieldMatch = line.match(/(\w+)\s+(\w+)\s+(\w+)/);
|
|
93
|
-
if (fieldMatch) {
|
|
94
|
-
const fieldTypeStr = fieldMatch[2];
|
|
95
|
-
const fieldName = fieldMatch[3];
|
|
96
|
-
allFieldNames.push(fieldName);
|
|
97
|
-
const fieldId = fieldNameIdMap[fieldName];
|
|
98
|
-
fieldTypesByName[fieldName] = fieldTypeStr;
|
|
99
|
-
const fieldType = FieldSizeStringMap[fieldTypeStr];
|
|
100
|
-
if (fieldId !== undefined) {
|
|
101
|
-
usedFieldNames.push(fieldName);
|
|
102
|
-
fieldIds.push(fieldId);
|
|
103
|
-
fieldTypes[fieldId] = fieldType;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (line === PlyParserUtils.HeaderEndToken) {
|
|
108
|
-
endOfHeader = true;
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
if (processingSection) {
|
|
112
|
-
extractedLines.push(line);
|
|
113
|
-
headerEndLine++;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const fieldOffsets = [];
|
|
118
|
-
let bytesPerVertex = 0;
|
|
119
|
-
for (let fieldName of allFieldNames) {
|
|
120
|
-
const fieldType = fieldTypesByName[fieldName];
|
|
121
|
-
if (Object.hasOwn(fieldTypesByName, fieldName)) {
|
|
122
|
-
const fieldId = fieldNameIdMap[fieldName];
|
|
123
|
-
if (fieldId !== undefined) {
|
|
124
|
-
fieldOffsets[fieldId] = bytesPerVertex;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
bytesPerVertex += FieldSize[FieldSizeStringMap[fieldType]];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const sphericalHarmonics = this.decodeSphericalHarmonicsFromSectionHeader(allFieldNames, fieldNameIdMap);
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
'headerLines': extractedLines,
|
|
134
|
-
'headerStartLine': headerStartLine,
|
|
135
|
-
'headerEndLine': headerEndLine,
|
|
136
|
-
'fieldTypes': fieldTypes,
|
|
137
|
-
'fieldIds': fieldIds,
|
|
138
|
-
'fieldOffsets': fieldOffsets,
|
|
139
|
-
'bytesPerVertex': bytesPerVertex,
|
|
140
|
-
'vertexCount': vertexCount,
|
|
141
|
-
'dataSizeBytes': bytesPerVertex * vertexCount,
|
|
142
|
-
'endOfHeader': endOfHeader,
|
|
143
|
-
'sectionName': sectionName,
|
|
144
|
-
'sphericalHarmonicsDegree': sphericalHarmonics.degree,
|
|
145
|
-
'sphericalHarmonicsCoefficientsPerChannel': sphericalHarmonics.coefficientsPerChannel,
|
|
146
|
-
'sphericalHarmonicsDegree1Fields': sphericalHarmonics.degree1Fields,
|
|
147
|
-
'sphericalHarmonicsDegree2Fields': sphericalHarmonics.degree2Fields
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
decodeSphericalHarmonicsFromSectionHeader(fieldNames, fieldNameIdMap) {
|
|
152
|
-
let sphericalHarmonicsFieldCount = 0;
|
|
153
|
-
let coefficientsPerChannel = 0;
|
|
154
|
-
for (let fieldName of fieldNames) {
|
|
155
|
-
if (fieldName.startsWith('f_rest')) sphericalHarmonicsFieldCount++;
|
|
156
|
-
}
|
|
157
|
-
coefficientsPerChannel = sphericalHarmonicsFieldCount / 3;
|
|
158
|
-
let degree = 0;
|
|
159
|
-
if (coefficientsPerChannel >= 3) degree = 1;
|
|
160
|
-
if (coefficientsPerChannel >= 8) degree = 2;
|
|
161
|
-
|
|
162
|
-
let degree1Fields = [];
|
|
163
|
-
let degree2Fields = [];
|
|
164
|
-
|
|
165
|
-
for (let rgb = 0; rgb < 3; rgb++) {
|
|
166
|
-
if (degree >= 1) {
|
|
167
|
-
for (let i = 0; i < 3; i++) {
|
|
168
|
-
degree1Fields.push(fieldNameIdMap['f_rest_' + (i + coefficientsPerChannel * rgb)]);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (degree >= 2) {
|
|
172
|
-
for (let i = 0; i < 5; i++) {
|
|
173
|
-
degree2Fields.push(fieldNameIdMap['f_rest_' + (i + coefficientsPerChannel * rgb + 3)]);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
'degree': degree,
|
|
180
|
-
'coefficientsPerChannel': coefficientsPerChannel,
|
|
181
|
-
'degree1Fields': degree1Fields,
|
|
182
|
-
'degree2Fields': degree2Fields
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
static getHeaderSectionNames(headerLines) {
|
|
187
|
-
const sectionNames = [];
|
|
188
|
-
for (let headerLine of headerLines) {
|
|
189
|
-
if (headerLine.startsWith('element')) {
|
|
190
|
-
const lineComponents = headerLine.split(' ');
|
|
191
|
-
let validComponents = 0;
|
|
192
|
-
for (let lineComponent of lineComponents) {
|
|
193
|
-
const trimmedComponent = lineComponent.trim();
|
|
194
|
-
if (trimmedComponent.length > 0) {
|
|
195
|
-
validComponents++;
|
|
196
|
-
if (validComponents === 2) {
|
|
197
|
-
sectionNames.push(trimmedComponent);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return sectionNames;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
static checkTextForEndHeader(endHeaderTestText) {
|
|
207
|
-
if (endHeaderTestText.includes(PlyParserUtils.HeaderEndToken)) {
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
static checkBufferForEndHeader(buffer, searchOfset, chunkSize, decoder) {
|
|
214
|
-
const endHeaderTestChunk = new Uint8Array(buffer, Math.max(0, searchOfset - chunkSize), chunkSize);
|
|
215
|
-
const endHeaderTestText = decoder.decode(endHeaderTestChunk);
|
|
216
|
-
return PlyParserUtils.checkTextForEndHeader(endHeaderTestText);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
static extractHeaderFromBufferToText(plyBuffer) {
|
|
220
|
-
const decoder = new TextDecoder();
|
|
221
|
-
let headerOffset = 0;
|
|
222
|
-
let headerText = '';
|
|
223
|
-
const readChunkSize = 100;
|
|
224
|
-
|
|
225
|
-
while (true) {
|
|
226
|
-
if (headerOffset + readChunkSize >= plyBuffer.byteLength) {
|
|
227
|
-
throw new Error('End of file reached while searching for end of header');
|
|
228
|
-
}
|
|
229
|
-
const headerChunk = new Uint8Array(plyBuffer, headerOffset, readChunkSize);
|
|
230
|
-
headerText += decoder.decode(headerChunk);
|
|
231
|
-
headerOffset += readChunkSize;
|
|
232
|
-
|
|
233
|
-
if (PlyParserUtils.checkBufferForEndHeader(plyBuffer, headerOffset, readChunkSize * 2, decoder)) {
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return headerText;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
readHeaderFromBuffer(plyBuffer) {
|
|
242
|
-
const decoder = new TextDecoder();
|
|
243
|
-
let headerOffset = 0;
|
|
244
|
-
let headerText = '';
|
|
245
|
-
const readChunkSize = 100;
|
|
246
|
-
|
|
247
|
-
while (true) {
|
|
248
|
-
if (headerOffset + readChunkSize >= plyBuffer.byteLength) {
|
|
249
|
-
throw new Error('End of file reached while searching for end of header');
|
|
250
|
-
}
|
|
251
|
-
const headerChunk = new Uint8Array(plyBuffer, headerOffset, readChunkSize);
|
|
252
|
-
headerText += decoder.decode(headerChunk);
|
|
253
|
-
headerOffset += readChunkSize;
|
|
254
|
-
|
|
255
|
-
if (PlyParserUtils.checkBufferForEndHeader(plyBuffer, headerOffset, readChunkSize * 2, decoder)) {
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return headerText;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
static convertHeaderTextToLines(headerText) {
|
|
264
|
-
const headerLines = headerText.split('\n');
|
|
265
|
-
const prunedLines = [];
|
|
266
|
-
for (let i = 0; i < headerLines.length; i++) {
|
|
267
|
-
const line = headerLines[i].trim();
|
|
268
|
-
prunedLines.push(line);
|
|
269
|
-
if (line === PlyParserUtils.HeaderEndToken) {
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return prunedLines;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
static determineHeaderFormatFromHeaderText(_headerText) {
|
|
277
|
-
// Simplified - FLAME avatars always use INRIAV1 format
|
|
278
|
-
return PlyFormat.INRIAV1;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
static determineHeaderFormatFromPlyBuffer(plyBuffer) {
|
|
282
|
-
const headertText = PlyParserUtils.extractHeaderFromBufferToText(plyBuffer);
|
|
283
|
-
return PlyParserUtils.determineHeaderFormatFromHeaderText(headertText);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
static readVertex(vertexData, header, row, dataOffset, fieldsToRead, rawVertex, normalize = true) {
|
|
287
|
-
const offset = row * header.bytesPerVertex + dataOffset;
|
|
288
|
-
const fieldOffsets = header.fieldOffsets;
|
|
289
|
-
const fieldTypes = header.fieldTypes;
|
|
290
|
-
for (let fieldId of fieldsToRead) {
|
|
291
|
-
const fieldType = fieldTypes[fieldId];
|
|
292
|
-
if (fieldType === FieldSizeIdFloat) {
|
|
293
|
-
rawVertex[fieldId] = vertexData.getFloat32(offset + fieldOffsets[fieldId], true);
|
|
294
|
-
} else if (fieldType === FieldSizeIdShort) {
|
|
295
|
-
rawVertex[fieldId] = vertexData.getInt16(offset + fieldOffsets[fieldId], true);
|
|
296
|
-
} else if (fieldType === FieldSizeIdUShort) {
|
|
297
|
-
rawVertex[fieldId] = vertexData.getUint16(offset + fieldOffsets[fieldId], true);
|
|
298
|
-
} else if (fieldType === FieldSizeIdInt) {
|
|
299
|
-
rawVertex[fieldId] = vertexData.getInt32(offset + fieldOffsets[fieldId], true);
|
|
300
|
-
} else if (fieldType === FieldSizeIdUInt) {
|
|
301
|
-
rawVertex[fieldId] = vertexData.getUint32(offset + fieldOffsets[fieldId], true);
|
|
302
|
-
} else if (fieldType === FieldSizeIdUChar) {
|
|
303
|
-
if (normalize) {
|
|
304
|
-
rawVertex[fieldId] = vertexData.getUint8(offset + fieldOffsets[fieldId]) / 255.0;
|
|
305
|
-
} else {
|
|
306
|
-
rawVertex[fieldId] = vertexData.getUint8(offset + fieldOffsets[fieldId]);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
package/src/loaders/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gsplat-flame-avatar - Loaders Module
|
|
3
|
-
* File format loaders for PLY (INRIAV1 format).
|
|
4
|
-
*
|
|
5
|
-
* Derived from @mkkellogg/gaussian-splats-3d (MIT License)
|
|
6
|
-
* Simplified for FLAME avatar usage.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export { PlyLoader } from './PlyLoader.js';
|
|
10
|
-
export { PlyParser } from './PlyParser.js';
|
|
11
|
-
export { PlyParserUtils, PlyFormat, FieldSize, FieldSizeStringMap } from './PlyParserUtils.js';
|
|
12
|
-
export { INRIAV1PlyParser } from './INRIAV1PlyParser.js';
|
|
13
|
-
export { DirectLoadError } from './DirectLoadError.js';
|