@babylonjs/loaders 9.26.0 → 9.26.2

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 (129) hide show
  1. package/FBX/fbxConstraintBehavior.d.ts +188 -0
  2. package/FBX/fbxConstraintBehavior.js +532 -0
  3. package/FBX/fbxConstraintBehavior.js.map +1 -0
  4. package/FBX/fbxFileLoader.pure.d.ts +175 -6
  5. package/FBX/fbxFileLoader.pure.js +1521 -286
  6. package/FBX/fbxFileLoader.pure.js.map +1 -1
  7. package/FBX/index.d.ts +4 -1
  8. package/FBX/index.js +1 -0
  9. package/FBX/index.js.map +1 -1
  10. package/FBX/interpreter/animation.d.ts +73 -33
  11. package/FBX/interpreter/animation.js +620 -223
  12. package/FBX/interpreter/animation.js.map +1 -1
  13. package/FBX/interpreter/animationCurve.d.ts +91 -0
  14. package/FBX/interpreter/animationCurve.js +623 -0
  15. package/FBX/interpreter/animationCurve.js.map +1 -0
  16. package/FBX/interpreter/blendShapes.js +9 -18
  17. package/FBX/interpreter/blendShapes.js.map +1 -1
  18. package/FBX/interpreter/connections.d.ts +1 -1
  19. package/FBX/interpreter/connections.js +173 -34
  20. package/FBX/interpreter/connections.js.map +1 -1
  21. package/FBX/interpreter/constraints.d.ts +68 -0
  22. package/FBX/interpreter/constraints.js +143 -0
  23. package/FBX/interpreter/constraints.js.map +1 -0
  24. package/FBX/interpreter/fbxInterpreter.d.ts +89 -4
  25. package/FBX/interpreter/fbxInterpreter.js +474 -122
  26. package/FBX/interpreter/fbxInterpreter.js.map +1 -1
  27. package/FBX/interpreter/geometry.d.ts +1 -1
  28. package/FBX/interpreter/geometry.js +150 -92
  29. package/FBX/interpreter/geometry.js.map +1 -1
  30. package/FBX/interpreter/legacyDocument.d.ts +11 -0
  31. package/FBX/interpreter/legacyDocument.js +425 -0
  32. package/FBX/interpreter/legacyDocument.js.map +1 -0
  33. package/FBX/interpreter/materialModel.d.ts +71 -0
  34. package/FBX/interpreter/materialModel.js +622 -0
  35. package/FBX/interpreter/materialModel.js.map +1 -0
  36. package/FBX/interpreter/materials.d.ts +13 -1
  37. package/FBX/interpreter/materials.js +88 -5
  38. package/FBX/interpreter/materials.js.map +1 -1
  39. package/FBX/interpreter/nodeTransform.d.ts +32 -0
  40. package/FBX/interpreter/nodeTransform.js +54 -0
  41. package/FBX/interpreter/nodeTransform.js.map +1 -0
  42. package/FBX/interpreter/nurbs.d.ts +99 -0
  43. package/FBX/interpreter/nurbs.js +627 -0
  44. package/FBX/interpreter/nurbs.js.map +1 -0
  45. package/FBX/interpreter/propertyTemplates.d.ts +23 -0
  46. package/FBX/interpreter/propertyTemplates.js +109 -2
  47. package/FBX/interpreter/propertyTemplates.js.map +1 -1
  48. package/FBX/interpreter/rig.js +16 -0
  49. package/FBX/interpreter/rig.js.map +1 -1
  50. package/FBX/interpreter/sceneDiagnostics.js +28 -3
  51. package/FBX/interpreter/sceneDiagnostics.js.map +1 -1
  52. package/FBX/interpreter/skeleton.d.ts +4 -18
  53. package/FBX/interpreter/skeleton.js +16 -94
  54. package/FBX/interpreter/skeleton.js.map +1 -1
  55. package/FBX/parsers/fbxAsciiParser.js +119 -9
  56. package/FBX/parsers/fbxAsciiParser.js.map +1 -1
  57. package/FBX/parsers/fbxBinaryParser.js +74 -22
  58. package/FBX/parsers/fbxBinaryParser.js.map +1 -1
  59. package/FBX/pure.d.ts +1 -0
  60. package/FBX/pure.js +1 -0
  61. package/FBX/pure.js.map +1 -1
  62. package/FBX/types/fbxTypes.d.ts +18 -2
  63. package/FBX/types/fbxTypes.js +40 -12
  64. package/FBX/types/fbxTypes.js.map +1 -1
  65. package/SPLAT/gaussianSplattingStream.d.ts +79 -25
  66. package/SPLAT/gaussianSplattingStream.js +320 -95
  67. package/SPLAT/gaussianSplattingStream.js.map +1 -1
  68. package/USD/usdCommandProtocol.d.ts +20 -4
  69. package/USD/usdCommandProtocol.js +25 -3
  70. package/USD/usdCommandProtocol.js.map +1 -1
  71. package/USD/usdFileLoader.pure.js +2 -0
  72. package/USD/usdFileLoader.pure.js.map +1 -1
  73. package/USD/usdSceneMaterializer.js +430 -92
  74. package/USD/usdSceneMaterializer.js.map +1 -1
  75. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.d.ts +110 -3
  76. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js +468 -74
  77. package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js.map +1 -1
  78. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.d.ts +47 -0
  79. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.js +68 -0
  80. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphEventReferenceBlock.js.map +1 -0
  81. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.d.ts +2 -2
  82. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js +1 -1
  83. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphGLTFDataProvider.js.map +1 -1
  84. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.d.ts +24 -0
  85. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.js +38 -0
  86. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphObjectReferenceBlock.js.map +1 -0
  87. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.d.ts +41 -0
  88. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.js +63 -0
  89. package/glTF/2.0/Extensions/KHR_interactivity/flowGraphUnsupportedInteractivityBlock.js.map +1 -0
  90. package/glTF/2.0/Extensions/KHR_interactivity/index.d.ts +5 -0
  91. package/glTF/2.0/Extensions/KHR_interactivity/index.js +5 -0
  92. package/glTF/2.0/Extensions/KHR_interactivity/index.js.map +1 -1
  93. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.d.ts +112 -0
  94. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js +773 -0
  95. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphModel.js.map +1 -0
  96. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.d.ts +18 -10
  97. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js +299 -54
  98. package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js.map +1 -1
  99. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.d.ts +2 -1
  100. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js +7 -2
  101. package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js.map +1 -1
  102. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.d.ts +24 -0
  103. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.js +89 -0
  104. package/glTF/2.0/Extensions/KHR_interactivity/interactivityNodeState.js.map +1 -0
  105. package/glTF/2.0/Extensions/KHR_interactivity/pure.d.ts +5 -0
  106. package/glTF/2.0/Extensions/KHR_interactivity/pure.js +5 -0
  107. package/glTF/2.0/Extensions/KHR_interactivity/pure.js.map +1 -1
  108. package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +55 -1
  109. package/glTF/2.0/Extensions/KHR_interactivity.pure.js +124 -76
  110. package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -1
  111. package/glTF/2.0/Extensions/KHR_interactivity.types.d.ts +18 -1
  112. package/glTF/2.0/Extensions/KHR_interactivity.types.js.map +1 -1
  113. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.d.ts +2 -0
  114. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js +114 -56
  115. package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js.map +1 -1
  116. package/glTF/2.0/Extensions/KHR_node_selectability.pure.d.ts +2 -0
  117. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js +80 -35
  118. package/glTF/2.0/Extensions/KHR_node_selectability.pure.js.map +1 -1
  119. package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js +3 -2
  120. package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js.map +1 -1
  121. package/glTF/2.0/Extensions/objectModelMapping.d.ts +4 -2
  122. package/glTF/2.0/Extensions/objectModelMapping.js +33 -4
  123. package/glTF/2.0/Extensions/objectModelMapping.js.map +1 -1
  124. package/glTF/2.0/glTFLoader.pure.d.ts +1 -1
  125. package/glTF/2.0/glTFLoader.pure.js +9 -4
  126. package/glTF/2.0/glTFLoader.pure.js.map +1 -1
  127. package/glTF/2.0/glTFLoaderExtension.d.ts +2 -1
  128. package/glTF/2.0/glTFLoaderExtension.js.map +1 -1
  129. package/package.json +3 -3
@@ -0,0 +1,532 @@
1
+ import { Matrix, Quaternion, Vector3 } from "@babylonjs/core/Maths/math.vector.pure.js";
2
+ import { eulerToMatrixXYZ } from "./interpreter/transform.js";
3
+ const DEG2RAD = Math.PI / 180;
4
+ /** Scratch objects shared by every solve; the solver runs on one thread, one constraint at a time. */
5
+ const Scratch = {
6
+ invRoot: new Matrix(),
7
+ parent: new Matrix(),
8
+ invParent: new Matrix(),
9
+ world: new Matrix(),
10
+ local: new Matrix(),
11
+ mA: new Matrix(),
12
+ mB: new Matrix(),
13
+ mC: new Matrix(),
14
+ mD: new Matrix(),
15
+ position: new Vector3(),
16
+ scale: new Vector3(),
17
+ translation: new Vector3(),
18
+ decomposedScale: new Vector3(),
19
+ localValue: new Vector3(),
20
+ up: new Vector3(),
21
+ forward: new Vector3(),
22
+ origin: new Vector3(),
23
+ axisA: new Vector3(),
24
+ axisB: new Vector3(),
25
+ axisC: new Vector3(),
26
+ eulerA: new Vector3(),
27
+ eulerB: new Vector3(),
28
+ rotation: new Quaternion(),
29
+ decomposedRotation: new Quaternion(),
30
+ result: new Quaternion(),
31
+ };
32
+ const Solvers = new WeakMap();
33
+ /**
34
+ * Solves every FBX constraint of a scene once per frame, in dependency order, from the scene's animation phase
35
+ * observers (`beginFrame` before animations, `solve` after them). Created on demand by the first
36
+ * `FBXConstraintBehavior` attached in the scene and removed with the last one.
37
+ */
38
+ export class FBXConstraintSolver {
39
+ constructor(scene) {
40
+ this._behaviors = [];
41
+ this._ordered = [];
42
+ this._cyclic = [];
43
+ this._dirty = false;
44
+ this._beforeAnimations = null;
45
+ this._afterAnimations = null;
46
+ this._scene = scene;
47
+ }
48
+ /**
49
+ * Solver of a scene, if any constraint behavior is attached in it.
50
+ * @param scene - Scene to look up
51
+ * @returns The solver, or undefined
52
+ */
53
+ static Get(scene) {
54
+ return Solvers.get(scene);
55
+ }
56
+ /**
57
+ * Solver of a scene, created when missing.
58
+ * @param scene - Scene to look up
59
+ * @returns The solver
60
+ */
61
+ static GetOrCreate(scene) {
62
+ let solver = Solvers.get(scene);
63
+ if (!solver) {
64
+ solver = new FBXConstraintSolver(scene);
65
+ Solvers.set(scene, solver);
66
+ }
67
+ return solver;
68
+ }
69
+ /** Registered behaviors in solve order (a target's constraint before the constraints that read it). */
70
+ get constraints() {
71
+ this._ensureOrder();
72
+ return this._ordered;
73
+ }
74
+ /**
75
+ * Behaviors that take part in a dependency cycle (A targets B while B targets A). They are solved after all
76
+ * acyclic constraints, in registration order, so each sees the other's result from the previous solve.
77
+ */
78
+ get cyclicConstraints() {
79
+ this._ensureOrder();
80
+ return this._cyclic;
81
+ }
82
+ /**
83
+ * Adds a behavior to the solve set.
84
+ * @param behavior - Behavior to add
85
+ */
86
+ register(behavior) {
87
+ if (this._behaviors.indexOf(behavior) >= 0) {
88
+ return;
89
+ }
90
+ this._behaviors.push(behavior);
91
+ this._dirty = true;
92
+ if (!this._beforeAnimations) {
93
+ this._beforeAnimations = this._scene.onBeforeAnimationsObservable.add(() => this.beginFrame());
94
+ this._afterAnimations = this._scene.onAfterAnimationsObservable.add(() => this.solve());
95
+ }
96
+ }
97
+ /**
98
+ * Removes a behavior from the solve set; the solver disposes itself with the last one.
99
+ * @param behavior - Behavior to remove
100
+ */
101
+ unregister(behavior) {
102
+ const index = this._behaviors.indexOf(behavior);
103
+ if (index < 0) {
104
+ return;
105
+ }
106
+ this._behaviors.splice(index, 1);
107
+ this._dirty = true;
108
+ if (this._behaviors.length === 0) {
109
+ this._scene.onBeforeAnimationsObservable.remove(this._beforeAnimations);
110
+ this._scene.onAfterAnimationsObservable.remove(this._afterAnimations);
111
+ this._beforeAnimations = null;
112
+ this._afterAnimations = null;
113
+ Solvers.delete(this._scene);
114
+ }
115
+ }
116
+ /** Marks the solve order stale, e.g. after re-parenting a constrained node. */
117
+ invalidateOrder() {
118
+ this._dirty = true;
119
+ }
120
+ /**
121
+ * Start of a frame, before animations run: every constrained node gets its unconstrained transform back, so
122
+ * that animation either overwrites it or leaves it untouched.
123
+ */
124
+ beginFrame() {
125
+ for (const behavior of this._behaviors) {
126
+ behavior.restoreBase();
127
+ }
128
+ }
129
+ /**
130
+ * End of the animation phase: takes every constrained node's current transform as its unconstrained value,
131
+ * then solves every registered constraint once, in dependency order.
132
+ */
133
+ solve() {
134
+ this._ensureOrder();
135
+ for (const behavior of this._behaviors) {
136
+ behavior.captureBase();
137
+ }
138
+ for (const behavior of this._ordered) {
139
+ behavior.evaluate();
140
+ }
141
+ }
142
+ _ensureOrder() {
143
+ if (!this._dirty) {
144
+ return;
145
+ }
146
+ this._dirty = false;
147
+ const behaviors = this._behaviors;
148
+ const count = behaviors.length;
149
+ // dependencies[i] lists the behaviors that must be solved before behaviors[i]
150
+ const dependencies = behaviors.map(() => []);
151
+ for (let i = 0; i < count; i++) {
152
+ const reads = behaviors[i].dependencyNodes();
153
+ for (let j = 0; j < count; j++) {
154
+ if (i === j) {
155
+ continue;
156
+ }
157
+ const driven = behaviors[j].attachedNode;
158
+ if (driven && reads.some((node) => FBXConstraintSolver._IsAncestorOrSelf(driven, node))) {
159
+ dependencies[i].push(j);
160
+ }
161
+ }
162
+ }
163
+ // Kahn's algorithm; whatever is left when no free behavior remains sits on a cycle.
164
+ const remaining = dependencies.map((deps) => deps.length);
165
+ const done = behaviors.map(() => false);
166
+ const ordered = [];
167
+ let progressed = true;
168
+ while (progressed) {
169
+ progressed = false;
170
+ for (let i = 0; i < count; i++) {
171
+ if (done[i] || remaining[i] > 0) {
172
+ continue;
173
+ }
174
+ done[i] = true;
175
+ ordered.push(behaviors[i]);
176
+ progressed = true;
177
+ for (let k = 0; k < count; k++) {
178
+ if (!done[k] && dependencies[k].indexOf(i) >= 0) {
179
+ remaining[k]--;
180
+ }
181
+ }
182
+ }
183
+ }
184
+ const cyclic = [];
185
+ for (let i = 0; i < count; i++) {
186
+ if (!done[i]) {
187
+ cyclic.push(behaviors[i]);
188
+ ordered.push(behaviors[i]);
189
+ }
190
+ }
191
+ this._ordered = ordered;
192
+ this._cyclic = cyclic;
193
+ }
194
+ static _IsAncestorOrSelf(ancestor, node) {
195
+ let current = node;
196
+ while (current) {
197
+ if (current === ancestor) {
198
+ return true;
199
+ }
200
+ current = current.parent;
201
+ }
202
+ return false;
203
+ }
204
+ }
205
+ /** Babylon behavior evaluating an FBX aim, parent, position, rotation or scale constraint. */
206
+ export class FBXConstraintBehavior {
207
+ /**
208
+ * Creates the behavior.
209
+ * @param constraint - Constraint data extracted from the file
210
+ * @param _options - Resolved targets and scene information
211
+ */
212
+ constructor(
213
+ /** Constraint data extracted from the file */
214
+ constraint, _options) {
215
+ this.constraint = constraint;
216
+ this._options = _options;
217
+ /** Node the behavior is attached to */
218
+ this.attachedNode = null;
219
+ /** Set to false to pause the constraint without detaching it */
220
+ this.enabled = true;
221
+ /** Unconstrained transform of the current frame (what animation produced), blended towards the constraint's result. */
222
+ this._base = { position: new Vector3(), rotation: new Quaternion(), scaling: new Vector3() };
223
+ this._hasBase = false;
224
+ this.name = `fbxConstraint:${constraint.name}`;
225
+ this._offsetTranslation = new Vector3(constraint.offsetTranslation[0], constraint.offsetTranslation[1], constraint.offsetTranslation[2]);
226
+ this._offsetRotation = eulerToMatrixXYZ(constraint.offsetRotation[0] * DEG2RAD, constraint.offsetRotation[1] * DEG2RAD, constraint.offsetRotation[2] * DEG2RAD);
227
+ this._offsetScale = new Vector3(constraint.offsetScale[0], constraint.offsetScale[1], constraint.offsetScale[2]);
228
+ const localBasis = new Matrix();
229
+ this._localBasisTransposed = FBXConstraintBehavior._OrthonormalBasisToRef(new Vector3(constraint.aimVector[0], constraint.aimVector[1], constraint.aimVector[2]), new Vector3(constraint.upVector[0], constraint.upVector[1], constraint.upVector[2]), localBasis)
230
+ ? localBasis.transpose()
231
+ : null;
232
+ }
233
+ /** Nothing to initialize */
234
+ init() { }
235
+ /**
236
+ * Registers the behavior with the scene's solver, takes the node's current transform as the unconstrained
237
+ * value and solves the constraint once.
238
+ * @param target - Node to constrain
239
+ */
240
+ attach(target) {
241
+ this.attachedNode = target;
242
+ FBXConstraintSolver.GetOrCreate(target.getScene()).register(this);
243
+ this.captureBase();
244
+ this.evaluate();
245
+ }
246
+ /** Unregisters the behavior; the node keeps its last solved transform. */
247
+ detach() {
248
+ if (this.attachedNode) {
249
+ FBXConstraintSolver.Get(this.attachedNode.getScene())?.unregister(this);
250
+ }
251
+ this.attachedNode = null;
252
+ this._hasBase = false;
253
+ }
254
+ /**
255
+ * Takes the node's current transform as the unconstrained value the next solve blends from. The solver calls
256
+ * this after the scene's animations ran; call it yourself after writing a transform by hand.
257
+ */
258
+ captureBase() {
259
+ const node = this.attachedNode;
260
+ if (!node) {
261
+ return;
262
+ }
263
+ if (!node.rotationQuaternion) {
264
+ node.rotationQuaternion = Quaternion.FromEulerVector(node.rotation);
265
+ }
266
+ this._base.position.copyFrom(node.position);
267
+ this._base.rotation.copyFrom(node.rotationQuaternion);
268
+ this._base.scaling.copyFrom(node.scaling);
269
+ this._hasBase = true;
270
+ }
271
+ /**
272
+ * Writes the unconstrained transform back to the node. The solver calls this before the scene's animations
273
+ * run, so a node nothing animates keeps its unconstrained value between frames instead of the solved one.
274
+ */
275
+ restoreBase() {
276
+ const node = this.attachedNode;
277
+ if (!node || !this._hasBase) {
278
+ return;
279
+ }
280
+ node.position.copyFrom(this._base.position);
281
+ node.rotationQuaternion.copyFrom(this._base.rotation);
282
+ node.scaling.copyFrom(this._base.scaling);
283
+ }
284
+ /**
285
+ * Nodes whose world transform the solve reads: the targets, the up node and the constrained node's parent.
286
+ * @returns The nodes, used by the solver to order constraints
287
+ */
288
+ dependencyNodes() {
289
+ const nodes = this._options.targets.map((t) => t.node);
290
+ nodes.push(this._options.upNode);
291
+ nodes.push(this.attachedNode ? this.attachedNode.parent : null);
292
+ return nodes;
293
+ }
294
+ /**
295
+ * Solves the constraint from the captured unconstrained transform and writes the node's local transform.
296
+ * Blends are relative to the value captured by `captureBase`, not to whatever the node holds now.
297
+ */
298
+ evaluate() {
299
+ const node = this.attachedNode;
300
+ const c = this.constraint;
301
+ if (!node || !this.enabled || !c.active || c.weight <= 0 || this._options.targets.length === 0) {
302
+ return;
303
+ }
304
+ if (!this._hasBase) {
305
+ this.captureBase();
306
+ }
307
+ this._options.root.computeWorldMatrix(true).invertToRef(Scratch.invRoot);
308
+ const parent = node.parent;
309
+ if (parent && typeof parent.computeWorldMatrix === "function") {
310
+ this._fbxWorld(parent, Scratch.parent);
311
+ }
312
+ else {
313
+ Matrix.IdentityToRef(Scratch.parent);
314
+ }
315
+ Scratch.parent.invertToRef(Scratch.invParent);
316
+ switch (c.type) {
317
+ case "position":
318
+ this._solvePosition(node);
319
+ break;
320
+ case "rotation":
321
+ this._solveRotation(node);
322
+ break;
323
+ case "scale":
324
+ this._solveScale(node);
325
+ break;
326
+ case "parent":
327
+ this._solveParent(node);
328
+ break;
329
+ case "aim":
330
+ this._solveAim(node);
331
+ break;
332
+ default:
333
+ break;
334
+ }
335
+ }
336
+ /**
337
+ * World matrix of a node relative to the asset root (FBX space).
338
+ * @param node - node to evaluate
339
+ * @param out - matrix receiving the result
340
+ * @returns `out`
341
+ */
342
+ _fbxWorld(node, out) {
343
+ node.computeWorldMatrix(true).multiplyToRef(Scratch.invRoot, out);
344
+ return out;
345
+ }
346
+ /**
347
+ * Weighted blend of the targets' world transforms (relative to the root).
348
+ * @param position - Receives the blended translation
349
+ * @param rotation - Receives the blended rotation
350
+ * @param scale - Receives the blended scale
351
+ * @returns The total target weight, 0 when no target contributes
352
+ */
353
+ _blendTargets(position, rotation, scale) {
354
+ position.set(0, 0, 0);
355
+ scale.set(0, 0, 0);
356
+ rotation.set(0, 0, 0, 1);
357
+ let total = 0;
358
+ for (const target of this._options.targets) {
359
+ if (target.weight <= 0) {
360
+ continue;
361
+ }
362
+ target.offset.multiplyToRef(this._fbxWorld(target.node, Scratch.world), Scratch.local);
363
+ Scratch.local.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
364
+ const next = total + target.weight;
365
+ position.addInPlace(Scratch.translation.scaleInPlace(target.weight));
366
+ scale.addInPlace(Scratch.decomposedScale.scaleInPlace(target.weight));
367
+ if (total === 0) {
368
+ rotation.copyFrom(Scratch.decomposedRotation);
369
+ }
370
+ else {
371
+ Quaternion.SlerpToRef(rotation, Scratch.decomposedRotation, target.weight / next, rotation);
372
+ }
373
+ total = next;
374
+ }
375
+ if (total > 0) {
376
+ position.scaleInPlace(1 / total);
377
+ scale.scaleInPlace(1 / total);
378
+ }
379
+ return total;
380
+ }
381
+ _applyWeighted(base, desired, mask, out) {
382
+ const w = this.constraint.weight;
383
+ out.set(mask[0] ? base.x + (desired.x - base.x) * w : base.x, mask[1] ? base.y + (desired.y - base.y) * w : base.y, mask[2] ? base.z + (desired.z - base.z) * w : base.z);
384
+ }
385
+ _applyRotation(node, desiredLocal, mask) {
386
+ const base = this._base.rotation;
387
+ const result = Scratch.result;
388
+ result.copyFrom(desiredLocal);
389
+ if (!(mask[0] && mask[1] && mask[2])) {
390
+ base.toEulerAnglesToRef(Scratch.eulerA);
391
+ desiredLocal.toEulerAnglesToRef(Scratch.eulerB);
392
+ Quaternion.FromEulerAnglesToRef(mask[0] ? Scratch.eulerB.x : Scratch.eulerA.x, mask[1] ? Scratch.eulerB.y : Scratch.eulerA.y, mask[2] ? Scratch.eulerB.z : Scratch.eulerA.z, result);
393
+ }
394
+ if (this.constraint.weight < 1) {
395
+ Quaternion.SlerpToRef(base, result, this.constraint.weight, result);
396
+ }
397
+ node.rotationQuaternion.copyFrom(result);
398
+ }
399
+ _writePosition(node, desiredLocal) {
400
+ this._applyWeighted(this._base.position, desiredLocal, this.constraint.affectTranslation, node.position);
401
+ }
402
+ _writeScaling(node, desiredLocal) {
403
+ this._applyWeighted(this._base.scaling, desiredLocal, this.constraint.affectScale, node.scaling);
404
+ }
405
+ _solvePosition(node) {
406
+ if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {
407
+ return;
408
+ }
409
+ Vector3.TransformCoordinatesToRef(Scratch.position, Scratch.invParent, Scratch.localValue);
410
+ Scratch.localValue.addInPlace(this._offsetTranslation);
411
+ this._writePosition(node, Scratch.localValue);
412
+ }
413
+ _solveRotation(node) {
414
+ if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {
415
+ return;
416
+ }
417
+ Matrix.FromQuaternionToRef(Scratch.rotation, Scratch.mA);
418
+ this._offsetRotation.multiplyToRef(Scratch.mA, Scratch.mB);
419
+ Scratch.mB.multiplyToRef(Scratch.invParent, Scratch.mC);
420
+ Scratch.mC.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
421
+ this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);
422
+ }
423
+ _solveScale(node) {
424
+ if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {
425
+ return;
426
+ }
427
+ Scratch.parent.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
428
+ const parentScale = Scratch.decomposedScale;
429
+ const scale = Scratch.scale;
430
+ Scratch.localValue.set((parentScale.x !== 0 ? scale.x / parentScale.x : scale.x) * this._offsetScale.x, (parentScale.y !== 0 ? scale.y / parentScale.y : scale.y) * this._offsetScale.y, (parentScale.z !== 0 ? scale.z / parentScale.z : scale.z) * this._offsetScale.z);
431
+ this._writeScaling(node, Scratch.localValue);
432
+ }
433
+ _solveParent(node) {
434
+ if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {
435
+ return;
436
+ }
437
+ Matrix.ComposeToRef(Scratch.scale, Scratch.rotation, Scratch.position, Scratch.mA);
438
+ Scratch.mA.multiplyToRef(Scratch.invParent, Scratch.mB);
439
+ Scratch.mB.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
440
+ this._writePosition(node, Scratch.translation);
441
+ this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);
442
+ this._writeScaling(node, Scratch.decomposedScale);
443
+ }
444
+ _solveAim(node) {
445
+ const c = this.constraint;
446
+ if (!this._localBasisTransposed || this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {
447
+ return;
448
+ }
449
+ // The node's own world position (after animation) is the origin of the aim.
450
+ const nodeWorld = this._fbxWorld(node, Scratch.world);
451
+ nodeWorld.getTranslationToRef(Scratch.origin);
452
+ Scratch.position.subtractToRef(Scratch.origin, Scratch.forward);
453
+ if (Scratch.forward.lengthSquared() < 1e-20) {
454
+ return;
455
+ }
456
+ Scratch.forward.normalize();
457
+ // Up direction in world space
458
+ const up = Scratch.up;
459
+ switch (c.worldUpType) {
460
+ case 1: // aim the up vector at the up node
461
+ if (this._options.upNode) {
462
+ this._fbxWorld(this._options.upNode, Scratch.local).getTranslationToRef(up);
463
+ up.subtractInPlace(Scratch.origin);
464
+ }
465
+ else {
466
+ up.copyFrom(this._options.sceneUp);
467
+ }
468
+ break;
469
+ case 2: // copy the up vector from the up node's orientation
470
+ if (this._options.upNode) {
471
+ this._fbxWorld(this._options.upNode, Scratch.local).decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
472
+ up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);
473
+ up.rotateByQuaternionToRef(Scratch.decomposedRotation, up);
474
+ }
475
+ else {
476
+ up.copyFrom(this._options.sceneUp);
477
+ }
478
+ break;
479
+ case 3: // explicit world vector
480
+ up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);
481
+ break;
482
+ case 4: // none: keep the current roll by using the node's current up
483
+ Scratch.localValue.set(c.upVector[0], c.upVector[1], c.upVector[2]);
484
+ Vector3.TransformNormalToRef(Scratch.localValue, nodeWorld, up);
485
+ break;
486
+ default: // scene up
487
+ up.copyFrom(this._options.sceneUp);
488
+ break;
489
+ }
490
+ if (up.lengthSquared() < 1e-20 || Math.abs(Vector3.Dot(up.normalizeToRef(Scratch.localValue), Scratch.forward)) > 0.9999) {
491
+ // Degenerate up: pick any perpendicular vector
492
+ if (Math.abs(Scratch.forward.y) < 0.9) {
493
+ up.set(0, 1, 0);
494
+ }
495
+ else {
496
+ up.set(1, 0, 0);
497
+ }
498
+ }
499
+ // World basis (forward, up, side); the local basis (aimVector, upVector, side) is fixed per constraint.
500
+ if (!FBXConstraintBehavior._OrthonormalBasisToRef(Scratch.forward, up, Scratch.mA)) {
501
+ return;
502
+ }
503
+ // rotation R with R(localBasis) = worldBasis: R = localBasis^T * worldBasis (row-vector convention)
504
+ this._localBasisTransposed.multiplyToRef(Scratch.mA, Scratch.mB);
505
+ this._offsetRotation.multiplyToRef(Scratch.mB, Scratch.mC);
506
+ Scratch.mC.multiplyToRef(Scratch.invParent, Scratch.mD);
507
+ Scratch.mD.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);
508
+ this._applyRotation(node, Scratch.decomposedRotation, c.affectRotation);
509
+ }
510
+ /**
511
+ * Builds a rotation matrix whose rows are `first`, `second` made orthogonal to it, and their cross product.
512
+ * @param first - primary axis
513
+ * @param second - secondary axis
514
+ * @param out - matrix receiving the basis
515
+ * @returns false when the axes are parallel or degenerate (`out` is then unchanged)
516
+ */
517
+ static _OrthonormalBasisToRef(first, second, out) {
518
+ const a = Scratch.axisA;
519
+ const b = Scratch.axisB;
520
+ const cr = Scratch.axisC;
521
+ first.normalizeToRef(a);
522
+ second.subtractToRef(a.scaleToRef(Vector3.Dot(a, second), b), b);
523
+ if (a.lengthSquared() < 1e-20 || b.lengthSquared() < 1e-20) {
524
+ return false;
525
+ }
526
+ b.normalize();
527
+ Vector3.CrossToRef(a, b, cr);
528
+ Matrix.FromValuesToRef(a.x, a.y, a.z, 0, b.x, b.y, b.z, 0, cr.x, cr.y, cr.z, 0, 0, 0, 0, 1, out);
529
+ return true;
530
+ }
531
+ }
532
+ //# sourceMappingURL=fbxConstraintBehavior.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fbxConstraintBehavior.js","sourceRoot":"","sources":["../../../../dev/loaders/src/FBX/fbxConstraintBehavior.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/naming-convention */\n/**\n * Runtime evaluation of FBX constraints. An `FBXConstraintBehavior` is attached to each constrained node; all\n * behaviors of a scene register with one `FBXConstraintSolver`, which solves them in dependency order (a constraint\n * whose target or parent is driven by another constraint is solved after it) and reuses scratch objects, so solving\n * allocates nothing per frame.\n *\n * The solver brackets the scene's animation phase: before animations run it writes each node's unconstrained\n * transform back, after they ran it captures the result as the new unconstrained transform and solves. A partial\n * weight therefore always blends from what animation (or nothing) produced this frame, never from the previous\n * solve's output, so a 50% weight stays a 50% blend instead of converging on the target.\n *\n * All maths happen in FBX space, i.e. relative to the loader's root node, so the handedness conversion applied\n * at the root never enters the solve.\n */\nimport { type Behavior } from \"core/Behaviors/behavior\";\nimport { type Nullable } from \"core/types\";\nimport { type Node } from \"core/node\";\nimport { type Observer } from \"core/Misc/observable\";\nimport { type Scene } from \"core/scene\";\nimport { Matrix, Quaternion, Vector3 } from \"core/Maths/math.vector.pure\";\nimport { type TransformNode } from \"core/Meshes/transformNode.pure\";\nimport { type FBXConstraintData } from \"./interpreter/constraints\";\nimport { eulerToMatrixXYZ } from \"./interpreter/transform\";\n\nconst DEG2RAD = Math.PI / 180;\n\n/** Resolved target of a constraint. */\nexport interface FBXConstraintBehaviorTarget {\n /** Target node */\n node: TransformNode;\n /** Normalized target weight (0..1) */\n weight: number;\n /** Offset matrix for parent constraints (in the target's space) */\n offset: Matrix;\n}\n\n/** Options resolved by the loader when creating the behavior. */\nexport interface FBXConstraintBehaviorOptions {\n /** Root of the loaded asset; world matrices are made relative to it */\n root: TransformNode;\n /** Resolved targets of the constraint, in file order */\n targets: FBXConstraintBehaviorTarget[];\n /** World up object of an aim constraint, when it has one */\n upNode: Nullable<TransformNode>;\n /** Scene up axis in FBX space */\n sceneUp: Vector3;\n}\n\n/** Scratch objects shared by every solve; the solver runs on one thread, one constraint at a time. */\nconst Scratch = {\n invRoot: new Matrix(),\n parent: new Matrix(),\n invParent: new Matrix(),\n world: new Matrix(),\n local: new Matrix(),\n mA: new Matrix(),\n mB: new Matrix(),\n mC: new Matrix(),\n mD: new Matrix(),\n position: new Vector3(),\n scale: new Vector3(),\n translation: new Vector3(),\n decomposedScale: new Vector3(),\n localValue: new Vector3(),\n up: new Vector3(),\n forward: new Vector3(),\n origin: new Vector3(),\n axisA: new Vector3(),\n axisB: new Vector3(),\n axisC: new Vector3(),\n eulerA: new Vector3(),\n eulerB: new Vector3(),\n rotation: new Quaternion(),\n decomposedRotation: new Quaternion(),\n result: new Quaternion(),\n};\n\nconst Solvers = new WeakMap<Scene, FBXConstraintSolver>();\n\n/**\n * Solves every FBX constraint of a scene once per frame, in dependency order, from the scene's animation phase\n * observers (`beginFrame` before animations, `solve` after them). Created on demand by the first\n * `FBXConstraintBehavior` attached in the scene and removed with the last one.\n */\nexport class FBXConstraintSolver {\n private readonly _scene: Scene;\n private readonly _behaviors: FBXConstraintBehavior[] = [];\n private _ordered: FBXConstraintBehavior[] = [];\n private _cyclic: FBXConstraintBehavior[] = [];\n private _dirty = false;\n private _beforeAnimations: Nullable<Observer<Scene>> = null;\n private _afterAnimations: Nullable<Observer<Scene>> = null;\n\n private constructor(scene: Scene) {\n this._scene = scene;\n }\n\n /**\n * Solver of a scene, if any constraint behavior is attached in it.\n * @param scene - Scene to look up\n * @returns The solver, or undefined\n */\n public static Get(scene: Scene): FBXConstraintSolver | undefined {\n return Solvers.get(scene);\n }\n\n /**\n * Solver of a scene, created when missing.\n * @param scene - Scene to look up\n * @returns The solver\n */\n public static GetOrCreate(scene: Scene): FBXConstraintSolver {\n let solver = Solvers.get(scene);\n if (!solver) {\n solver = new FBXConstraintSolver(scene);\n Solvers.set(scene, solver);\n }\n return solver;\n }\n\n /** Registered behaviors in solve order (a target's constraint before the constraints that read it). */\n public get constraints(): readonly FBXConstraintBehavior[] {\n this._ensureOrder();\n return this._ordered;\n }\n\n /**\n * Behaviors that take part in a dependency cycle (A targets B while B targets A). They are solved after all\n * acyclic constraints, in registration order, so each sees the other's result from the previous solve.\n */\n public get cyclicConstraints(): readonly FBXConstraintBehavior[] {\n this._ensureOrder();\n return this._cyclic;\n }\n\n /**\n * Adds a behavior to the solve set.\n * @param behavior - Behavior to add\n */\n public register(behavior: FBXConstraintBehavior): void {\n if (this._behaviors.indexOf(behavior) >= 0) {\n return;\n }\n this._behaviors.push(behavior);\n this._dirty = true;\n if (!this._beforeAnimations) {\n this._beforeAnimations = this._scene.onBeforeAnimationsObservable.add(() => this.beginFrame());\n this._afterAnimations = this._scene.onAfterAnimationsObservable.add(() => this.solve());\n }\n }\n\n /**\n * Removes a behavior from the solve set; the solver disposes itself with the last one.\n * @param behavior - Behavior to remove\n */\n public unregister(behavior: FBXConstraintBehavior): void {\n const index = this._behaviors.indexOf(behavior);\n if (index < 0) {\n return;\n }\n this._behaviors.splice(index, 1);\n this._dirty = true;\n if (this._behaviors.length === 0) {\n this._scene.onBeforeAnimationsObservable.remove(this._beforeAnimations);\n this._scene.onAfterAnimationsObservable.remove(this._afterAnimations);\n this._beforeAnimations = null;\n this._afterAnimations = null;\n Solvers.delete(this._scene);\n }\n }\n\n /** Marks the solve order stale, e.g. after re-parenting a constrained node. */\n public invalidateOrder(): void {\n this._dirty = true;\n }\n\n /**\n * Start of a frame, before animations run: every constrained node gets its unconstrained transform back, so\n * that animation either overwrites it or leaves it untouched.\n */\n public beginFrame(): void {\n for (const behavior of this._behaviors) {\n behavior.restoreBase();\n }\n }\n\n /**\n * End of the animation phase: takes every constrained node's current transform as its unconstrained value,\n * then solves every registered constraint once, in dependency order.\n */\n public solve(): void {\n this._ensureOrder();\n for (const behavior of this._behaviors) {\n behavior.captureBase();\n }\n for (const behavior of this._ordered) {\n behavior.evaluate();\n }\n }\n\n private _ensureOrder(): void {\n if (!this._dirty) {\n return;\n }\n this._dirty = false;\n const behaviors = this._behaviors;\n const count = behaviors.length;\n // dependencies[i] lists the behaviors that must be solved before behaviors[i]\n const dependencies: number[][] = behaviors.map(() => []);\n for (let i = 0; i < count; i++) {\n const reads = behaviors[i].dependencyNodes();\n for (let j = 0; j < count; j++) {\n if (i === j) {\n continue;\n }\n const driven = behaviors[j].attachedNode;\n if (driven && reads.some((node) => FBXConstraintSolver._IsAncestorOrSelf(driven, node))) {\n dependencies[i].push(j);\n }\n }\n }\n // Kahn's algorithm; whatever is left when no free behavior remains sits on a cycle.\n const remaining = dependencies.map((deps) => deps.length);\n const done = behaviors.map(() => false);\n const ordered: FBXConstraintBehavior[] = [];\n let progressed = true;\n while (progressed) {\n progressed = false;\n for (let i = 0; i < count; i++) {\n if (done[i] || remaining[i] > 0) {\n continue;\n }\n done[i] = true;\n ordered.push(behaviors[i]);\n progressed = true;\n for (let k = 0; k < count; k++) {\n if (!done[k] && dependencies[k].indexOf(i) >= 0) {\n remaining[k]--;\n }\n }\n }\n }\n const cyclic: FBXConstraintBehavior[] = [];\n for (let i = 0; i < count; i++) {\n if (!done[i]) {\n cyclic.push(behaviors[i]);\n ordered.push(behaviors[i]);\n }\n }\n this._ordered = ordered;\n this._cyclic = cyclic;\n }\n\n private static _IsAncestorOrSelf(ancestor: TransformNode, node: Nullable<Node>): boolean {\n let current: Nullable<Node> = node;\n while (current) {\n if (current === ancestor) {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n}\n\n/** Babylon behavior evaluating an FBX aim, parent, position, rotation or scale constraint. */\nexport class FBXConstraintBehavior implements Behavior<TransformNode> {\n /** Behavior name (`fbxConstraint:` followed by the constraint name) */\n public readonly name: string;\n /** Node the behavior is attached to */\n public attachedNode: Nullable<TransformNode> = null;\n /** Set to false to pause the constraint without detaching it */\n public enabled = true;\n\n private readonly _offsetTranslation: Vector3;\n private readonly _offsetRotation: Matrix;\n private readonly _offsetScale: Vector3;\n private readonly _localBasisTransposed: Nullable<Matrix>;\n /** Unconstrained transform of the current frame (what animation produced), blended towards the constraint's result. */\n private readonly _base = { position: new Vector3(), rotation: new Quaternion(), scaling: new Vector3() };\n private _hasBase = false;\n\n /**\n * Creates the behavior.\n * @param constraint - Constraint data extracted from the file\n * @param _options - Resolved targets and scene information\n */\n public constructor(\n /** Constraint data extracted from the file */\n public readonly constraint: FBXConstraintData,\n private readonly _options: FBXConstraintBehaviorOptions\n ) {\n this.name = `fbxConstraint:${constraint.name}`;\n this._offsetTranslation = new Vector3(constraint.offsetTranslation[0], constraint.offsetTranslation[1], constraint.offsetTranslation[2]);\n this._offsetRotation = eulerToMatrixXYZ(constraint.offsetRotation[0] * DEG2RAD, constraint.offsetRotation[1] * DEG2RAD, constraint.offsetRotation[2] * DEG2RAD);\n this._offsetScale = new Vector3(constraint.offsetScale[0], constraint.offsetScale[1], constraint.offsetScale[2]);\n const localBasis = new Matrix();\n this._localBasisTransposed = FBXConstraintBehavior._OrthonormalBasisToRef(\n new Vector3(constraint.aimVector[0], constraint.aimVector[1], constraint.aimVector[2]),\n new Vector3(constraint.upVector[0], constraint.upVector[1], constraint.upVector[2]),\n localBasis\n )\n ? localBasis.transpose()\n : null;\n }\n\n /** Nothing to initialize */\n public init(): void {}\n\n /**\n * Registers the behavior with the scene's solver, takes the node's current transform as the unconstrained\n * value and solves the constraint once.\n * @param target - Node to constrain\n */\n public attach(target: TransformNode): void {\n this.attachedNode = target;\n FBXConstraintSolver.GetOrCreate(target.getScene()).register(this);\n this.captureBase();\n this.evaluate();\n }\n\n /** Unregisters the behavior; the node keeps its last solved transform. */\n public detach(): void {\n if (this.attachedNode) {\n FBXConstraintSolver.Get(this.attachedNode.getScene())?.unregister(this);\n }\n this.attachedNode = null;\n this._hasBase = false;\n }\n\n /**\n * Takes the node's current transform as the unconstrained value the next solve blends from. The solver calls\n * this after the scene's animations ran; call it yourself after writing a transform by hand.\n */\n public captureBase(): void {\n const node = this.attachedNode;\n if (!node) {\n return;\n }\n if (!node.rotationQuaternion) {\n node.rotationQuaternion = Quaternion.FromEulerVector(node.rotation);\n }\n this._base.position.copyFrom(node.position);\n this._base.rotation.copyFrom(node.rotationQuaternion);\n this._base.scaling.copyFrom(node.scaling);\n this._hasBase = true;\n }\n\n /**\n * Writes the unconstrained transform back to the node. The solver calls this before the scene's animations\n * run, so a node nothing animates keeps its unconstrained value between frames instead of the solved one.\n */\n public restoreBase(): void {\n const node = this.attachedNode;\n if (!node || !this._hasBase) {\n return;\n }\n node.position.copyFrom(this._base.position);\n node.rotationQuaternion!.copyFrom(this._base.rotation);\n node.scaling.copyFrom(this._base.scaling);\n }\n\n /**\n * Nodes whose world transform the solve reads: the targets, the up node and the constrained node's parent.\n * @returns The nodes, used by the solver to order constraints\n */\n public dependencyNodes(): Nullable<Node>[] {\n const nodes: Nullable<Node>[] = this._options.targets.map((t) => t.node);\n nodes.push(this._options.upNode);\n nodes.push(this.attachedNode ? this.attachedNode.parent : null);\n return nodes;\n }\n\n /**\n * Solves the constraint from the captured unconstrained transform and writes the node's local transform.\n * Blends are relative to the value captured by `captureBase`, not to whatever the node holds now.\n */\n public evaluate(): void {\n const node = this.attachedNode;\n const c = this.constraint;\n if (!node || !this.enabled || !c.active || c.weight <= 0 || this._options.targets.length === 0) {\n return;\n }\n if (!this._hasBase) {\n this.captureBase();\n }\n this._options.root.computeWorldMatrix(true).invertToRef(Scratch.invRoot);\n const parent = node.parent as Nullable<TransformNode>;\n if (parent && typeof parent.computeWorldMatrix === \"function\") {\n this._fbxWorld(parent, Scratch.parent);\n } else {\n Matrix.IdentityToRef(Scratch.parent);\n }\n Scratch.parent.invertToRef(Scratch.invParent);\n\n switch (c.type) {\n case \"position\":\n this._solvePosition(node);\n break;\n case \"rotation\":\n this._solveRotation(node);\n break;\n case \"scale\":\n this._solveScale(node);\n break;\n case \"parent\":\n this._solveParent(node);\n break;\n case \"aim\":\n this._solveAim(node);\n break;\n default:\n break;\n }\n }\n\n /**\n * World matrix of a node relative to the asset root (FBX space).\n * @param node - node to evaluate\n * @param out - matrix receiving the result\n * @returns `out`\n */\n private _fbxWorld(node: TransformNode, out: Matrix): Matrix {\n node.computeWorldMatrix(true).multiplyToRef(Scratch.invRoot, out);\n return out;\n }\n\n /**\n * Weighted blend of the targets' world transforms (relative to the root).\n * @param position - Receives the blended translation\n * @param rotation - Receives the blended rotation\n * @param scale - Receives the blended scale\n * @returns The total target weight, 0 when no target contributes\n */\n private _blendTargets(position: Vector3, rotation: Quaternion, scale: Vector3): number {\n position.set(0, 0, 0);\n scale.set(0, 0, 0);\n rotation.set(0, 0, 0, 1);\n let total = 0;\n for (const target of this._options.targets) {\n if (target.weight <= 0) {\n continue;\n }\n target.offset.multiplyToRef(this._fbxWorld(target.node, Scratch.world), Scratch.local);\n Scratch.local.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n const next = total + target.weight;\n position.addInPlace(Scratch.translation.scaleInPlace(target.weight));\n scale.addInPlace(Scratch.decomposedScale.scaleInPlace(target.weight));\n if (total === 0) {\n rotation.copyFrom(Scratch.decomposedRotation);\n } else {\n Quaternion.SlerpToRef(rotation, Scratch.decomposedRotation, target.weight / next, rotation);\n }\n total = next;\n }\n if (total > 0) {\n position.scaleInPlace(1 / total);\n scale.scaleInPlace(1 / total);\n }\n return total;\n }\n\n private _applyWeighted(base: Vector3, desired: Vector3, mask: readonly boolean[], out: Vector3): void {\n const w = this.constraint.weight;\n out.set(mask[0] ? base.x + (desired.x - base.x) * w : base.x, mask[1] ? base.y + (desired.y - base.y) * w : base.y, mask[2] ? base.z + (desired.z - base.z) * w : base.z);\n }\n\n private _applyRotation(node: TransformNode, desiredLocal: Quaternion, mask: readonly boolean[]): void {\n const base = this._base.rotation;\n const result = Scratch.result;\n result.copyFrom(desiredLocal);\n if (!(mask[0] && mask[1] && mask[2])) {\n base.toEulerAnglesToRef(Scratch.eulerA);\n desiredLocal.toEulerAnglesToRef(Scratch.eulerB);\n Quaternion.FromEulerAnglesToRef(\n mask[0] ? Scratch.eulerB.x : Scratch.eulerA.x,\n mask[1] ? Scratch.eulerB.y : Scratch.eulerA.y,\n mask[2] ? Scratch.eulerB.z : Scratch.eulerA.z,\n result\n );\n }\n if (this.constraint.weight < 1) {\n Quaternion.SlerpToRef(base, result, this.constraint.weight, result);\n }\n node.rotationQuaternion!.copyFrom(result);\n }\n\n private _writePosition(node: TransformNode, desiredLocal: Vector3): void {\n this._applyWeighted(this._base.position, desiredLocal, this.constraint.affectTranslation, node.position);\n }\n\n private _writeScaling(node: TransformNode, desiredLocal: Vector3): void {\n this._applyWeighted(this._base.scaling, desiredLocal, this.constraint.affectScale, node.scaling);\n }\n\n private _solvePosition(node: TransformNode): void {\n if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n return;\n }\n Vector3.TransformCoordinatesToRef(Scratch.position, Scratch.invParent, Scratch.localValue);\n Scratch.localValue.addInPlace(this._offsetTranslation);\n this._writePosition(node, Scratch.localValue);\n }\n\n private _solveRotation(node: TransformNode): void {\n if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n return;\n }\n Matrix.FromQuaternionToRef(Scratch.rotation, Scratch.mA);\n this._offsetRotation.multiplyToRef(Scratch.mA, Scratch.mB);\n Scratch.mB.multiplyToRef(Scratch.invParent, Scratch.mC);\n Scratch.mC.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);\n }\n\n private _solveScale(node: TransformNode): void {\n if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n return;\n }\n Scratch.parent.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n const parentScale = Scratch.decomposedScale;\n const scale = Scratch.scale;\n Scratch.localValue.set(\n (parentScale.x !== 0 ? scale.x / parentScale.x : scale.x) * this._offsetScale.x,\n (parentScale.y !== 0 ? scale.y / parentScale.y : scale.y) * this._offsetScale.y,\n (parentScale.z !== 0 ? scale.z / parentScale.z : scale.z) * this._offsetScale.z\n );\n this._writeScaling(node, Scratch.localValue);\n }\n\n private _solveParent(node: TransformNode): void {\n if (this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n return;\n }\n Matrix.ComposeToRef(Scratch.scale, Scratch.rotation, Scratch.position, Scratch.mA);\n Scratch.mA.multiplyToRef(Scratch.invParent, Scratch.mB);\n Scratch.mB.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n this._writePosition(node, Scratch.translation);\n this._applyRotation(node, Scratch.decomposedRotation, this.constraint.affectRotation);\n this._writeScaling(node, Scratch.decomposedScale);\n }\n\n private _solveAim(node: TransformNode): void {\n const c = this.constraint;\n if (!this._localBasisTransposed || this._blendTargets(Scratch.position, Scratch.rotation, Scratch.scale) === 0) {\n return;\n }\n // The node's own world position (after animation) is the origin of the aim.\n const nodeWorld = this._fbxWorld(node, Scratch.world);\n nodeWorld.getTranslationToRef(Scratch.origin);\n Scratch.position.subtractToRef(Scratch.origin, Scratch.forward);\n if (Scratch.forward.lengthSquared() < 1e-20) {\n return;\n }\n Scratch.forward.normalize();\n\n // Up direction in world space\n const up = Scratch.up;\n switch (c.worldUpType) {\n case 1: // aim the up vector at the up node\n if (this._options.upNode) {\n this._fbxWorld(this._options.upNode, Scratch.local).getTranslationToRef(up);\n up.subtractInPlace(Scratch.origin);\n } else {\n up.copyFrom(this._options.sceneUp);\n }\n break;\n case 2: // copy the up vector from the up node's orientation\n if (this._options.upNode) {\n this._fbxWorld(this._options.upNode, Scratch.local).decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);\n up.rotateByQuaternionToRef(Scratch.decomposedRotation, up);\n } else {\n up.copyFrom(this._options.sceneUp);\n }\n break;\n case 3: // explicit world vector\n up.set(c.worldUpVector[0], c.worldUpVector[1], c.worldUpVector[2]);\n break;\n case 4: // none: keep the current roll by using the node's current up\n Scratch.localValue.set(c.upVector[0], c.upVector[1], c.upVector[2]);\n Vector3.TransformNormalToRef(Scratch.localValue, nodeWorld, up);\n break;\n default: // scene up\n up.copyFrom(this._options.sceneUp);\n break;\n }\n if (up.lengthSquared() < 1e-20 || Math.abs(Vector3.Dot(up.normalizeToRef(Scratch.localValue), Scratch.forward)) > 0.9999) {\n // Degenerate up: pick any perpendicular vector\n if (Math.abs(Scratch.forward.y) < 0.9) {\n up.set(0, 1, 0);\n } else {\n up.set(1, 0, 0);\n }\n }\n\n // World basis (forward, up, side); the local basis (aimVector, upVector, side) is fixed per constraint.\n if (!FBXConstraintBehavior._OrthonormalBasisToRef(Scratch.forward, up, Scratch.mA)) {\n return;\n }\n // rotation R with R(localBasis) = worldBasis: R = localBasis^T * worldBasis (row-vector convention)\n this._localBasisTransposed.multiplyToRef(Scratch.mA, Scratch.mB);\n this._offsetRotation.multiplyToRef(Scratch.mB, Scratch.mC);\n Scratch.mC.multiplyToRef(Scratch.invParent, Scratch.mD);\n Scratch.mD.decompose(Scratch.decomposedScale, Scratch.decomposedRotation, Scratch.translation);\n this._applyRotation(node, Scratch.decomposedRotation, c.affectRotation);\n }\n\n /**\n * Builds a rotation matrix whose rows are `first`, `second` made orthogonal to it, and their cross product.\n * @param first - primary axis\n * @param second - secondary axis\n * @param out - matrix receiving the basis\n * @returns false when the axes are parallel or degenerate (`out` is then unchanged)\n */\n private static _OrthonormalBasisToRef(first: Vector3, second: Vector3, out: Matrix): boolean {\n const a = Scratch.axisA;\n const b = Scratch.axisB;\n const cr = Scratch.axisC;\n first.normalizeToRef(a);\n second.subtractToRef(a.scaleToRef(Vector3.Dot(a, second), b), b);\n if (a.lengthSquared() < 1e-20 || b.lengthSquared() < 1e-20) {\n return false;\n }\n b.normalize();\n Vector3.CrossToRef(a, b, cr);\n Matrix.FromValuesToRef(a.x, a.y, a.z, 0, b.x, b.y, b.z, 0, cr.x, cr.y, cr.z, 0, 0, 0, 0, 1, out);\n return true;\n }\n}\n"]}