@babylonjs/loaders 9.12.0 → 9.12.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.
Files changed (77) hide show
  1. package/FBX/fbxFileLoader.d.ts +194 -0
  2. package/FBX/fbxFileLoader.js +2440 -0
  3. package/FBX/fbxFileLoader.js.map +1 -0
  4. package/FBX/fbxFileLoader.metadata.d.ts +11 -0
  5. package/FBX/fbxFileLoader.metadata.js +11 -0
  6. package/FBX/fbxFileLoader.metadata.js.map +1 -0
  7. package/FBX/index.d.ts +3 -0
  8. package/FBX/index.js +3 -0
  9. package/FBX/index.js.map +1 -0
  10. package/FBX/interpreter/animation.d.ts +122 -0
  11. package/FBX/interpreter/animation.js +648 -0
  12. package/FBX/interpreter/animation.js.map +1 -0
  13. package/FBX/interpreter/blendShapes.d.ts +44 -0
  14. package/FBX/interpreter/blendShapes.js +192 -0
  15. package/FBX/interpreter/blendShapes.js.map +1 -0
  16. package/FBX/interpreter/connections.d.ts +95 -0
  17. package/FBX/interpreter/connections.js +233 -0
  18. package/FBX/interpreter/connections.js.map +1 -0
  19. package/FBX/interpreter/fbxInterpreter.d.ts +149 -0
  20. package/FBX/interpreter/fbxInterpreter.js +496 -0
  21. package/FBX/interpreter/fbxInterpreter.js.map +1 -0
  22. package/FBX/interpreter/geometry.d.ts +55 -0
  23. package/FBX/interpreter/geometry.js +573 -0
  24. package/FBX/interpreter/geometry.js.map +1 -0
  25. package/FBX/interpreter/materials.d.ts +50 -0
  26. package/FBX/interpreter/materials.js +144 -0
  27. package/FBX/interpreter/materials.js.map +1 -0
  28. package/FBX/interpreter/propertyTemplates.d.ts +22 -0
  29. package/FBX/interpreter/propertyTemplates.js +125 -0
  30. package/FBX/interpreter/propertyTemplates.js.map +1 -0
  31. package/FBX/interpreter/rig.d.ts +20 -0
  32. package/FBX/interpreter/rig.js +259 -0
  33. package/FBX/interpreter/rig.js.map +1 -0
  34. package/FBX/interpreter/sceneDiagnostics.d.ts +14 -0
  35. package/FBX/interpreter/sceneDiagnostics.js +55 -0
  36. package/FBX/interpreter/sceneDiagnostics.js.map +1 -0
  37. package/FBX/interpreter/skeleton.d.ts +93 -0
  38. package/FBX/interpreter/skeleton.js +515 -0
  39. package/FBX/interpreter/skeleton.js.map +1 -0
  40. package/FBX/interpreter/transform.d.ts +21 -0
  41. package/FBX/interpreter/transform.js +92 -0
  42. package/FBX/interpreter/transform.js.map +1 -0
  43. package/FBX/parsers/fbxAsciiParser.d.ts +5 -0
  44. package/FBX/parsers/fbxAsciiParser.js +330 -0
  45. package/FBX/parsers/fbxAsciiParser.js.map +1 -0
  46. package/FBX/parsers/fbxBinaryParser.d.ts +6 -0
  47. package/FBX/parsers/fbxBinaryParser.js +255 -0
  48. package/FBX/parsers/fbxBinaryParser.js.map +1 -0
  49. package/FBX/parsers/zlibInflate.d.ts +7 -0
  50. package/FBX/parsers/zlibInflate.js +350 -0
  51. package/FBX/parsers/zlibInflate.js.map +1 -0
  52. package/FBX/types/fbxTypes.d.ts +54 -0
  53. package/FBX/types/fbxTypes.js +66 -0
  54. package/FBX/types/fbxTypes.js.map +1 -0
  55. package/SPLAT/gaussianSplattingStream.d.ts +341 -0
  56. package/SPLAT/gaussianSplattingStream.js +976 -0
  57. package/SPLAT/gaussianSplattingStream.js.map +1 -0
  58. package/SPLAT/gaussianSplattingWorkBuffer.d.ts +51 -0
  59. package/SPLAT/gaussianSplattingWorkBuffer.js +159 -0
  60. package/SPLAT/gaussianSplattingWorkBuffer.js.map +1 -0
  61. package/SPLAT/gaussianSplattingWorkBufferShaders.d.ts +25 -0
  62. package/SPLAT/gaussianSplattingWorkBufferShaders.js +255 -0
  63. package/SPLAT/gaussianSplattingWorkBufferShaders.js.map +1 -0
  64. package/SPLAT/index.d.ts +1 -0
  65. package/SPLAT/index.js +1 -0
  66. package/SPLAT/index.js.map +1 -1
  67. package/SPLAT/sog.js +18 -16
  68. package/SPLAT/sog.js.map +1 -1
  69. package/SPLAT/splatFileLoader.d.ts +8 -0
  70. package/SPLAT/splatFileLoader.js +49 -0
  71. package/SPLAT/splatFileLoader.js.map +1 -1
  72. package/dynamic.js +9 -0
  73. package/dynamic.js.map +1 -1
  74. package/index.d.ts +1 -0
  75. package/index.js +1 -0
  76. package/index.js.map +1 -1
  77. package/package.json +3 -3
@@ -0,0 +1,233 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */
2
+ import { cleanFBXName, findDocumentNode, getPropertyValue, getSafeFBXObjectId } from "../types/fbxTypes.js";
3
+ /**
4
+ * Build a connection graph from a parsed FBX document.
5
+ * Maps object IDs to their FBXNode and resolves parent-child relationships.
6
+ */
7
+ export function resolveConnections(doc) {
8
+ const objects = new Map();
9
+ const objectEntries = [];
10
+ const childrenOf = new Map();
11
+ const parentOf = new Map();
12
+ const connections = [];
13
+ const connectionEntries = [];
14
+ const diagnostics = [];
15
+ const legacyIds = new Map();
16
+ const syntheticLegacyIds = new Map();
17
+ let nextLegacyId = -1;
18
+ const getLegacyId = (name) => {
19
+ let id = legacyIds.get(name);
20
+ if (id === undefined) {
21
+ id = nextLegacyId--;
22
+ legacyIds.set(name, id);
23
+ }
24
+ return id;
25
+ };
26
+ const getSyntheticLegacyId = (role, name) => {
27
+ let idsByName = syntheticLegacyIds.get(role);
28
+ if (!idsByName) {
29
+ idsByName = new Map();
30
+ syntheticLegacyIds.set(role, idsByName);
31
+ }
32
+ let id = idsByName.get(name);
33
+ if (id === undefined) {
34
+ id = nextLegacyId--;
35
+ idsByName.set(name, id);
36
+ }
37
+ return id;
38
+ };
39
+ // Build object map from Objects section
40
+ const objectsNode = findDocumentNode(doc, "Objects");
41
+ if (objectsNode) {
42
+ for (const obj of objectsNode.children) {
43
+ const idProp = obj.properties[0];
44
+ if (idProp) {
45
+ const id = toObjectNumber(idProp.value);
46
+ if (id !== undefined) {
47
+ objects.set(id, obj);
48
+ objectEntries.push({ id, node: obj, source: "Objects", synthetic: false });
49
+ }
50
+ else if (typeof idProp.value === "string") {
51
+ const legacyName = cleanFBXName(idProp.value);
52
+ const id = getLegacyId(legacyName);
53
+ const normalized = normalizeLegacyObject(obj, id);
54
+ objects.set(id, normalized);
55
+ objectEntries.push({ id, node: normalized, source: "Objects", legacyName, synthetic: false });
56
+ if (obj.name === "Model" && getPropertyValue(obj, 1) === "Mesh") {
57
+ const geometryId = getSyntheticLegacyId("Geometry", legacyName);
58
+ const geometry = createLegacyGeometry(obj, geometryId);
59
+ objects.set(geometryId, geometry);
60
+ objectEntries.push({ id: geometryId, node: geometry, source: "legacySyntheticGeometry", legacyName, synthetic: true });
61
+ addConnection(connections, childrenOf, parentOf, diagnostics, "OO", geometryId, id);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ // Parse connections
68
+ const connectionsNode = findDocumentNode(doc, "Connections");
69
+ if (connectionsNode) {
70
+ for (const c of connectionsNode.children) {
71
+ if (c.name !== "C" && c.name !== "Connect") {
72
+ continue;
73
+ }
74
+ const connectionIndex = connectionEntries.length;
75
+ const type = getPropertyValue(c, 0);
76
+ const childIdRaw = c.properties[1]?.value;
77
+ const parentIdRaw = c.properties[2]?.value;
78
+ const entry = {
79
+ source: c.name,
80
+ rawType: type,
81
+ accepted: false,
82
+ };
83
+ connectionEntries.push(entry);
84
+ if (type !== "OO" && type !== "OP") {
85
+ const childId = childIdRaw === undefined ? undefined : toObjectId(childIdRaw, legacyIds);
86
+ const parentId = parentIdRaw === undefined ? undefined : toObjectId(parentIdRaw, legacyIds);
87
+ diagnostics.push({
88
+ reason: "unsupported-connection-type",
89
+ message: `Unsupported FBX connection type '${type ?? ""}' was not added to the graph.`,
90
+ connectionIndex,
91
+ type,
92
+ childId,
93
+ parentId,
94
+ });
95
+ continue;
96
+ }
97
+ if (childIdRaw === undefined || parentIdRaw === undefined) {
98
+ diagnostics.push({
99
+ reason: "missing-connection-endpoint",
100
+ message: "FBX connection is missing a child or parent endpoint.",
101
+ connectionIndex,
102
+ type,
103
+ });
104
+ continue;
105
+ }
106
+ const childId = toObjectId(childIdRaw, legacyIds);
107
+ const parentId = toObjectId(parentIdRaw, legacyIds);
108
+ if (childId === undefined || parentId === undefined) {
109
+ diagnostics.push({
110
+ reason: "unresolved-legacy-endpoint",
111
+ message: "FBX connection references a legacy string endpoint that is not present in the object table.",
112
+ connectionIndex,
113
+ type,
114
+ });
115
+ continue;
116
+ }
117
+ const propertyName = type === "OP" && c.properties.length > 3 ? getPropertyValue(c, 3) : undefined;
118
+ entry.childId = childId;
119
+ entry.parentId = parentId;
120
+ entry.propertyName = propertyName;
121
+ if (childId === parentId) {
122
+ diagnostics.push({
123
+ reason: "self-loop",
124
+ message: "FBX connection references the same object as child and parent.",
125
+ connectionIndex,
126
+ type,
127
+ childId,
128
+ parentId,
129
+ propertyName,
130
+ });
131
+ }
132
+ if (!objects.has(childId)) {
133
+ diagnostics.push({
134
+ reason: "unresolved-object-reference",
135
+ message: "FBX connection child ID is not present in the object table.",
136
+ connectionIndex,
137
+ type,
138
+ childId,
139
+ parentId,
140
+ propertyName,
141
+ });
142
+ }
143
+ if (parentId !== 0 && !objects.has(parentId)) {
144
+ diagnostics.push({
145
+ reason: "unresolved-object-reference",
146
+ message: "FBX connection parent ID is not present in the object table.",
147
+ connectionIndex,
148
+ type,
149
+ childId,
150
+ parentId,
151
+ propertyName,
152
+ });
153
+ }
154
+ addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex);
155
+ entry.accepted = true;
156
+ }
157
+ }
158
+ return { objects, objectEntries, childrenOf, parentOf, connections, connectionEntries, diagnostics };
159
+ }
160
+ /** Get all child objects of a given parent ID, optionally filtered by node name */
161
+ export function getChildren(map, parentId, nodeName) {
162
+ const children = map.childrenOf.get(parentId) ?? [];
163
+ const result = [];
164
+ for (const child of children) {
165
+ const node = map.objects.get(child.id);
166
+ if (node && (!nodeName || node.name === nodeName)) {
167
+ result.push({ id: child.id, node, propertyName: child.propertyName });
168
+ }
169
+ }
170
+ return result;
171
+ }
172
+ function toObjectNumber(value) {
173
+ return getSafeFBXObjectId(value);
174
+ }
175
+ function toObjectId(value, legacyIds) {
176
+ const numericId = toObjectNumber(value);
177
+ if (numericId !== undefined) {
178
+ return numericId;
179
+ }
180
+ if (typeof value !== "string") {
181
+ return undefined;
182
+ }
183
+ const legacyName = cleanFBXName(value);
184
+ if (legacyName === "Scene") {
185
+ return 0;
186
+ }
187
+ return legacyIds.get(legacyName);
188
+ }
189
+ function addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex) {
190
+ connections.push({ type, childId, parentId, propertyName });
191
+ if (!childrenOf.has(parentId)) {
192
+ childrenOf.set(parentId, []);
193
+ }
194
+ childrenOf.get(parentId).push({ id: childId, propertyName });
195
+ const existingParent = parentOf.get(childId);
196
+ if (existingParent) {
197
+ diagnostics.push({
198
+ reason: "duplicate-parent",
199
+ message: "FBX object has multiple parents; preserving the existing last-parent behavior.",
200
+ connectionIndex,
201
+ type,
202
+ childId,
203
+ parentId,
204
+ propertyName,
205
+ });
206
+ }
207
+ parentOf.set(childId, { id: parentId, propertyName });
208
+ }
209
+ function normalizeLegacyObject(node, id) {
210
+ const name = cleanFBXName(getPropertyValue(node, 0) ?? node.name);
211
+ const subType = getPropertyValue(node, 1) ?? "";
212
+ return {
213
+ ...node,
214
+ properties: [
215
+ { type: "int64", value: id },
216
+ { type: "string", value: name },
217
+ { type: "string", value: subType },
218
+ ],
219
+ };
220
+ }
221
+ function createLegacyGeometry(modelNode, geometryId) {
222
+ const name = cleanFBXName(getPropertyValue(modelNode, 0) ?? "Geometry");
223
+ return {
224
+ name: "Geometry",
225
+ properties: [
226
+ { type: "int64", value: geometryId },
227
+ { type: "string", value: name },
228
+ { type: "string", value: "Mesh" },
229
+ ],
230
+ children: modelNode.children,
231
+ };
232
+ }
233
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../../../dev/loaders/src/FBX/interpreter/connections.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention, jsdoc/require-param, jsdoc/require-returns */\r\nimport { type FBXDocument, type FBXNode, cleanFBXName, findDocumentNode, getPropertyValue, getSafeFBXObjectId } from \"../types/fbxTypes\";\r\n\r\n/** Connection type: OO = object-to-object, OP = object-to-property */\r\nexport type ConnectionType = \"OO\" | \"OP\";\r\n\r\n/** A resolved FBX object connection. */\r\nexport interface FBXConnection {\r\n /** Connection type. */\r\n type: ConnectionType;\r\n /** Child object ID. */\r\n childId: number;\r\n /** Parent object ID. */\r\n parentId: number;\r\n /** For OP connections, the property name on the parent (e.g. \"DiffuseColor\") */\r\n propertyName?: string;\r\n}\r\n\r\n/** Object table entry used by the FBX connection graph. */\r\nexport interface FBXObjectEntry {\r\n /** Object ID. */\r\n id: number;\r\n /** Object node. */\r\n node: FBXNode;\r\n /** Source of the object entry. */\r\n source: \"Objects\" | \"legacySyntheticGeometry\";\r\n /** Legacy string object name, when applicable. */\r\n legacyName?: string;\r\n /** True if the object was synthesized for legacy compatibility. */\r\n synthetic: boolean;\r\n}\r\n\r\n/** Raw connection-table entry and import status. */\r\nexport interface FBXConnectionEntry {\r\n /** Source node name. */\r\n source: \"C\" | \"Connect\";\r\n /** Raw connection type. */\r\n rawType?: string;\r\n /** Child object ID, when resolved. */\r\n childId?: number;\r\n /** Parent object ID, when resolved. */\r\n parentId?: number;\r\n /** OP connection property name, when present. */\r\n propertyName?: string;\r\n /** True if the connection was accepted into the resolved graph. */\r\n accepted: boolean;\r\n}\r\n\r\n/** Reason a connection produced a diagnostic. */\r\nexport type FBXConnectionDiagnosticReason =\r\n | \"unsupported-connection-type\"\r\n | \"missing-connection-endpoint\"\r\n | \"unresolved-legacy-endpoint\"\r\n | \"unresolved-object-reference\"\r\n | \"duplicate-parent\"\r\n | \"self-loop\";\r\n\r\n/** Recoverable connection graph issue. */\r\nexport interface FBXConnectionDiagnostic {\r\n /** Diagnostic reason. */\r\n reason: FBXConnectionDiagnosticReason;\r\n /** Human-readable diagnostic message. */\r\n message: string;\r\n /** Connection-table index associated with the diagnostic, if applicable. */\r\n connectionIndex?: number;\r\n /** Connection type associated with the diagnostic, if applicable. */\r\n type?: string;\r\n /** Child object ID associated with the diagnostic, if applicable. */\r\n childId?: number;\r\n /** Parent object ID associated with the diagnostic, if applicable. */\r\n parentId?: number;\r\n /** OP connection property name associated with the diagnostic, if applicable. */\r\n propertyName?: string;\r\n}\r\n\r\n/** Resolved FBX object and connection graph. */\r\nexport interface FBXObjectMap {\r\n /** All objects by their unique ID */\r\n objects: Map<number, FBXNode>;\r\n /** Object table entries, including synthetic compatibility objects */\r\n objectEntries: FBXObjectEntry[];\r\n /** Children of each object ID */\r\n childrenOf: Map<number, { id: number; propertyName?: string }[]>;\r\n /** Parent of each object ID */\r\n parentOf: Map<number, { id: number; propertyName?: string }>;\r\n /** Raw connection list */\r\n connections: FBXConnection[];\r\n /** Raw connection-table entries and whether they were accepted into the graph */\r\n connectionEntries: FBXConnectionEntry[];\r\n /** Unsupported or suspicious connection shapes encountered while preserving graph behavior */\r\n diagnostics: FBXConnectionDiagnostic[];\r\n}\r\n\r\n/**\r\n * Build a connection graph from a parsed FBX document.\r\n * Maps object IDs to their FBXNode and resolves parent-child relationships.\r\n */\r\nexport function resolveConnections(doc: FBXDocument): FBXObjectMap {\r\n const objects = new Map<number, FBXNode>();\r\n const objectEntries: FBXObjectEntry[] = [];\r\n const childrenOf = new Map<number, { id: number; propertyName?: string }[]>();\r\n const parentOf = new Map<number, { id: number; propertyName?: string }>();\r\n const connections: FBXConnection[] = [];\r\n const connectionEntries: FBXConnectionEntry[] = [];\r\n const diagnostics: FBXConnectionDiagnostic[] = [];\r\n const legacyIds = new Map<string, number>();\r\n const syntheticLegacyIds = new Map<string, Map<string, number>>();\r\n let nextLegacyId = -1;\r\n\r\n const getLegacyId = (name: string): number => {\r\n let id = legacyIds.get(name);\r\n if (id === undefined) {\r\n id = nextLegacyId--;\r\n legacyIds.set(name, id);\r\n }\r\n return id;\r\n };\r\n\r\n const getSyntheticLegacyId = (role: string, name: string): number => {\r\n let idsByName = syntheticLegacyIds.get(role);\r\n if (!idsByName) {\r\n idsByName = new Map();\r\n syntheticLegacyIds.set(role, idsByName);\r\n }\r\n\r\n let id = idsByName.get(name);\r\n if (id === undefined) {\r\n id = nextLegacyId--;\r\n idsByName.set(name, id);\r\n }\r\n return id;\r\n };\r\n\r\n // Build object map from Objects section\r\n const objectsNode = findDocumentNode(doc, \"Objects\");\r\n if (objectsNode) {\r\n for (const obj of objectsNode.children) {\r\n const idProp = obj.properties[0];\r\n if (idProp) {\r\n const id = toObjectNumber(idProp.value);\r\n if (id !== undefined) {\r\n objects.set(id, obj);\r\n objectEntries.push({ id, node: obj, source: \"Objects\", synthetic: false });\r\n } else if (typeof idProp.value === \"string\") {\r\n const legacyName = cleanFBXName(idProp.value);\r\n const id = getLegacyId(legacyName);\r\n const normalized = normalizeLegacyObject(obj, id);\r\n objects.set(id, normalized);\r\n objectEntries.push({ id, node: normalized, source: \"Objects\", legacyName, synthetic: false });\r\n\r\n if (obj.name === \"Model\" && getPropertyValue<string>(obj, 1) === \"Mesh\") {\r\n const geometryId = getSyntheticLegacyId(\"Geometry\", legacyName);\r\n const geometry = createLegacyGeometry(obj, geometryId);\r\n objects.set(geometryId, geometry);\r\n objectEntries.push({ id: geometryId, node: geometry, source: \"legacySyntheticGeometry\", legacyName, synthetic: true });\r\n addConnection(connections, childrenOf, parentOf, diagnostics, \"OO\", geometryId, id);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Parse connections\r\n const connectionsNode = findDocumentNode(doc, \"Connections\");\r\n if (connectionsNode) {\r\n for (const c of connectionsNode.children) {\r\n if (c.name !== \"C\" && c.name !== \"Connect\") {\r\n continue;\r\n }\r\n\r\n const connectionIndex = connectionEntries.length;\r\n const type = getPropertyValue<string>(c, 0);\r\n const childIdRaw = c.properties[1]?.value;\r\n const parentIdRaw = c.properties[2]?.value;\r\n const entry: FBXConnectionEntry = {\r\n source: c.name,\r\n rawType: type,\r\n accepted: false,\r\n };\r\n connectionEntries.push(entry);\r\n\r\n if (type !== \"OO\" && type !== \"OP\") {\r\n const childId = childIdRaw === undefined ? undefined : toObjectId(childIdRaw, legacyIds);\r\n const parentId = parentIdRaw === undefined ? undefined : toObjectId(parentIdRaw, legacyIds);\r\n diagnostics.push({\r\n reason: \"unsupported-connection-type\",\r\n message: `Unsupported FBX connection type '${type ?? \"\"}' was not added to the graph.`,\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n });\r\n continue;\r\n }\r\n\r\n if (childIdRaw === undefined || parentIdRaw === undefined) {\r\n diagnostics.push({\r\n reason: \"missing-connection-endpoint\",\r\n message: \"FBX connection is missing a child or parent endpoint.\",\r\n connectionIndex,\r\n type,\r\n });\r\n continue;\r\n }\r\n\r\n const childId = toObjectId(childIdRaw, legacyIds);\r\n const parentId = toObjectId(parentIdRaw, legacyIds);\r\n if (childId === undefined || parentId === undefined) {\r\n diagnostics.push({\r\n reason: \"unresolved-legacy-endpoint\",\r\n message: \"FBX connection references a legacy string endpoint that is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n });\r\n continue;\r\n }\r\n\r\n const propertyName = type === \"OP\" && c.properties.length > 3 ? getPropertyValue<string>(c, 3) : undefined;\r\n\r\n entry.childId = childId;\r\n entry.parentId = parentId;\r\n entry.propertyName = propertyName;\r\n\r\n if (childId === parentId) {\r\n diagnostics.push({\r\n reason: \"self-loop\",\r\n message: \"FBX connection references the same object as child and parent.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n if (!objects.has(childId)) {\r\n diagnostics.push({\r\n reason: \"unresolved-object-reference\",\r\n message: \"FBX connection child ID is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n if (parentId !== 0 && !objects.has(parentId)) {\r\n diagnostics.push({\r\n reason: \"unresolved-object-reference\",\r\n message: \"FBX connection parent ID is not present in the object table.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n\r\n addConnection(connections, childrenOf, parentOf, diagnostics, type, childId, parentId, propertyName, connectionIndex);\r\n entry.accepted = true;\r\n }\r\n }\r\n\r\n return { objects, objectEntries, childrenOf, parentOf, connections, connectionEntries, diagnostics };\r\n}\r\n\r\n/** Get all child objects of a given parent ID, optionally filtered by node name */\r\nexport function getChildren(map: FBXObjectMap, parentId: number, nodeName?: string): { id: number; node: FBXNode; propertyName?: string }[] {\r\n const children = map.childrenOf.get(parentId) ?? [];\r\n const result: { id: number; node: FBXNode; propertyName?: string }[] = [];\r\n\r\n for (const child of children) {\r\n const node = map.objects.get(child.id);\r\n if (node && (!nodeName || node.name === nodeName)) {\r\n result.push({ id: child.id, node, propertyName: child.propertyName });\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction toObjectNumber(value: unknown): number | undefined {\r\n return getSafeFBXObjectId(value);\r\n}\r\n\r\nfunction toObjectId(value: unknown, legacyIds: Map<string, number>): number | undefined {\r\n const numericId = toObjectNumber(value);\r\n if (numericId !== undefined) {\r\n return numericId;\r\n }\r\n if (typeof value !== \"string\") {\r\n return undefined;\r\n }\r\n const legacyName = cleanFBXName(value);\r\n if (legacyName === \"Scene\") {\r\n return 0;\r\n }\r\n return legacyIds.get(legacyName);\r\n}\r\n\r\nfunction addConnection(\r\n connections: FBXConnection[],\r\n childrenOf: Map<number, { id: number; propertyName?: string }[]>,\r\n parentOf: Map<number, { id: number; propertyName?: string }>,\r\n diagnostics: FBXConnectionDiagnostic[],\r\n type: ConnectionType,\r\n childId: number,\r\n parentId: number,\r\n propertyName?: string,\r\n connectionIndex?: number\r\n): void {\r\n connections.push({ type, childId, parentId, propertyName });\r\n\r\n if (!childrenOf.has(parentId)) {\r\n childrenOf.set(parentId, []);\r\n }\r\n childrenOf.get(parentId)!.push({ id: childId, propertyName });\r\n const existingParent = parentOf.get(childId);\r\n if (existingParent) {\r\n diagnostics.push({\r\n reason: \"duplicate-parent\",\r\n message: \"FBX object has multiple parents; preserving the existing last-parent behavior.\",\r\n connectionIndex,\r\n type,\r\n childId,\r\n parentId,\r\n propertyName,\r\n });\r\n }\r\n parentOf.set(childId, { id: parentId, propertyName });\r\n}\r\n\r\nfunction normalizeLegacyObject(node: FBXNode, id: number): FBXNode {\r\n const name = cleanFBXName(getPropertyValue<string>(node, 0) ?? node.name);\r\n const subType = getPropertyValue<string>(node, 1) ?? \"\";\r\n return {\r\n ...node,\r\n properties: [\r\n { type: \"int64\", value: id },\r\n { type: \"string\", value: name },\r\n { type: \"string\", value: subType },\r\n ],\r\n };\r\n}\r\n\r\nfunction createLegacyGeometry(modelNode: FBXNode, geometryId: number): FBXNode {\r\n const name = cleanFBXName(getPropertyValue<string>(modelNode, 0) ?? \"Geometry\");\r\n return {\r\n name: \"Geometry\",\r\n properties: [\r\n { type: \"int64\", value: geometryId },\r\n { type: \"string\", value: name },\r\n { type: \"string\", value: \"Mesh\" },\r\n ],\r\n children: modelNode.children,\r\n };\r\n}\r\n"]}
@@ -0,0 +1,149 @@
1
+ import { type FBXDocument } from "../types/fbxTypes.js";
2
+ import { type FBXGeometryData } from "./geometry.js";
3
+ import { type FBXMaterialData } from "./materials.js";
4
+ import { type FBXSkinData } from "./skeleton.js";
5
+ import { type FBXRigData } from "./rig.js";
6
+ import { type FBXAnimationStackData } from "./animation.js";
7
+ import { type FBXBlendShapeData } from "./blendShapes.js";
8
+ import { type FBXSceneDiagnostic } from "./sceneDiagnostics.js";
9
+ /** Represents a model (transform node) in the FBX scene */
10
+ export interface FBXModelData {
11
+ id: number;
12
+ name: string;
13
+ subType: string;
14
+ /** Geometry attached to this model (if it's a Mesh type) */
15
+ geometry?: FBXGeometryData;
16
+ /** Materials assigned to this model */
17
+ materials: FBXMaterialData[];
18
+ /** Child models */
19
+ children: FBXModelData[];
20
+ /** Transform properties */
21
+ translation: [number, number, number];
22
+ rotation: [number, number, number];
23
+ scale: [number, number, number];
24
+ /** PreRotation (applied before Lcl Rotation, in degrees) */
25
+ preRotation: [number, number, number];
26
+ /** PostRotation (applied after Lcl Rotation, inverted, in degrees) */
27
+ postRotation: [number, number, number];
28
+ /** RotationPivot — point around which rotation occurs */
29
+ rotationPivot: [number, number, number];
30
+ /** ScalingPivot — point around which scaling occurs */
31
+ scalingPivot: [number, number, number];
32
+ /** RotationOffset — translation after rotation pivot */
33
+ rotationOffset: [number, number, number];
34
+ /** ScalingOffset — translation after scaling pivot */
35
+ scalingOffset: [number, number, number];
36
+ /** Geometric transforms — applied to geometry only, do not affect children */
37
+ geometricTranslation: [number, number, number];
38
+ geometricRotation: [number, number, number];
39
+ geometricScaling: [number, number, number];
40
+ /** Rotation order: 0=XYZ, 1=XZY, 2=YZX, 3=YXZ, 4=ZXY, 5=ZYX */
41
+ rotationOrder: number;
42
+ /** FBX transform inheritance mode. 0=RrSs, 1=RSrs, 2=Rrs */
43
+ inheritType: number;
44
+ /** Whether backface culling is disabled ("CullingOff") */
45
+ cullingOff: boolean;
46
+ /** User-defined custom properties from Properties70 */
47
+ customProperties?: Record<string, string | number | boolean>;
48
+ /** Recoverable model import diagnostics */
49
+ diagnostics: string[];
50
+ }
51
+ /** Camera data extracted from FBX */
52
+ export interface FBXCameraData {
53
+ /** Model ID this camera is attached to */
54
+ modelId: number;
55
+ /** Camera name */
56
+ name: string;
57
+ /** Field of view in degrees */
58
+ fieldOfView: number;
59
+ /** Near clip plane */
60
+ nearPlane: number;
61
+ /** Far clip plane */
62
+ farPlane: number;
63
+ /** Aspect ratio (width/height), 0 = use viewport */
64
+ aspectRatio: number;
65
+ /** Projection type */
66
+ projectionType: "perspective" | "orthographic";
67
+ /** Focal length in millimeters when present */
68
+ focalLength?: number;
69
+ /** Filmback width in inches when present */
70
+ filmWidth?: number;
71
+ /** Filmback height in inches when present */
72
+ filmHeight?: number;
73
+ /** Orthographic zoom/height when present */
74
+ orthoZoom?: number;
75
+ /** Camera roll in degrees when present */
76
+ roll?: number;
77
+ /** Known unsupported or unrecognized camera properties */
78
+ unknownProperties: string[];
79
+ /** Recoverable camera import diagnostics */
80
+ diagnostics: string[];
81
+ }
82
+ /** Light data extracted from FBX */
83
+ export interface FBXLightData {
84
+ /** Model ID this light is attached to */
85
+ modelId: number;
86
+ /** Light name */
87
+ name: string;
88
+ /** Light type: 0=Point, 1=Directional, 2=Spot */
89
+ lightType: number;
90
+ /** Color [r,g,b] 0-1 */
91
+ color: [number, number, number];
92
+ /** Intensity multiplier */
93
+ intensity: number;
94
+ /** Cone angle in degrees (for spot lights) */
95
+ coneAngle: number;
96
+ /** Decay type: 0=None, 1=Linear, 2=Quadratic */
97
+ decayType: number;
98
+ /** Inner cone angle in degrees for spot lights */
99
+ innerAngle?: number;
100
+ /** Outer cone angle in degrees for spot lights */
101
+ outerAngle?: number;
102
+ /** Distance at which FBX attenuation starts; preserved as metadata */
103
+ decayStart?: number;
104
+ /** Whether FBX near attenuation is enabled */
105
+ enableNearAttenuation?: boolean;
106
+ /** Whether FBX far attenuation is enabled */
107
+ enableFarAttenuation?: boolean;
108
+ /** Whether the source light requested shadow casting */
109
+ castShadows?: boolean;
110
+ /** Known unsupported or unrecognized light properties */
111
+ unknownProperties: string[];
112
+ /** Recoverable light import diagnostics */
113
+ diagnostics: string[];
114
+ }
115
+ /** Result of interpreting an FBX document */
116
+ export interface FBXSceneData {
117
+ /** All root-level models */
118
+ rootModels: FBXModelData[];
119
+ /** All geometries in the scene */
120
+ geometries: FBXGeometryData[];
121
+ /** All materials in the scene */
122
+ materials: FBXMaterialData[];
123
+ /** Skin deformers (skeletons + vertex weights) */
124
+ skins: FBXSkinData[];
125
+ /** Resolved deformation rigs shared by one or more skins */
126
+ rigs: FBXRigData[];
127
+ /** Blend shape deformers (morph targets) */
128
+ blendShapes: FBXBlendShapeData[];
129
+ /** Animation stacks (clips) */
130
+ animations: FBXAnimationStackData[];
131
+ /** Cameras */
132
+ cameras: FBXCameraData[];
133
+ /** Lights */
134
+ lights: FBXLightData[];
135
+ /** Scene-level unsupported feature diagnostics */
136
+ diagnostics: FBXSceneDiagnostic[];
137
+ /** Global settings */
138
+ upAxis: number;
139
+ upAxisSign: number;
140
+ frontAxis: number;
141
+ frontAxisSign: number;
142
+ coordAxis: number;
143
+ coordAxisSign: number;
144
+ unitScaleFactor: number;
145
+ }
146
+ /**
147
+ * Interpret a parsed FBX document into scene data.
148
+ */
149
+ export declare function interpretFBX(doc: FBXDocument): FBXSceneData;