From b766ac48d5a4d3da194bc2838465538d3c4952e4 Mon Sep 17 00:00:00 2001 From: Popov72 Date: Sat, 28 Feb 2026 15:24:47 +0100 Subject: [PATCH 1/2] Fix regression --- .../dev/core/src/Animations/animatorAvatar.ts | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/dev/core/src/Animations/animatorAvatar.ts b/packages/dev/core/src/Animations/animatorAvatar.ts index 3b20221f2ca..367adee2863 100644 --- a/packages/dev/core/src/Animations/animatorAvatar.ts +++ b/packages/dev/core/src/Animations/animatorAvatar.ts @@ -89,7 +89,7 @@ export interface IRetargetOptions { mapNodeNames?: Map; } -type TransformNodeNameToNode = Map; +type TransformNodeNameToNode = Map; /** * Represents an animator avatar that manages meshes, skeletons and morph target managers for a hierarchical transform node and mesh structure. @@ -158,14 +158,11 @@ export class AnimatorAvatar { this._collectMesh(rootNode); } - rootNode - .getChildMeshes(false, (node) => { - const mesh = node as AbstractMesh; - return mesh.getTotalVertices() > 0; - }) - .forEach((mesh) => { + rootNode.getChildMeshes(false).forEach((mesh) => { + if (mesh.getTotalVertices() > 0) { this._collectMesh(mesh); - }); + } + }); this._computeBoneWorldMatrices(); } @@ -282,6 +279,7 @@ export class AnimatorAvatar { position: tn.position.clone(), scaling: tn.scaling.clone(), quaternion: tn.rotationQuaternion.clone(), + rotation: tn.rotation.clone(), }, }); } @@ -339,9 +337,9 @@ export class AnimatorAvatar { Logger.Warn( `RetargetAnimationGroup - Avatar '${this.name}', AnimationGroup '${animationGroup.name}': "${sourceTransformNodeName}" bone not found in any skeleton of avatar: animation removed.` ); - animationGroup.targetedAnimations.splice(i, 1); - i--; } + animationGroup.targetedAnimations.splice(i, 1); + i--; break; } @@ -465,6 +463,7 @@ export class AnimatorAvatar { private _computeBoneWorldMatrices() { this.skeletons.forEach((skeleton) => { + skeleton.returnToRest(); skeleton.prepare(true); skeleton.bones.forEach((bone) => { @@ -842,9 +841,13 @@ export class AnimatorAvatar { sourceTransformNodeNameToNode.forEach((data) => { const { node, initialTransformations } = data; - node.position = initialTransformations.position; - node.scaling = initialTransformations.scaling; - node.rotationQuaternion = initialTransformations.quaternion; + node.position.copyFrom(initialTransformations.position); + node.scaling.copyFrom(initialTransformations.scaling); + if (node.rotationQuaternion) { + node.rotationQuaternion.copyFrom(initialTransformations.quaternion); + } else { + node.rotation.copyFrom(initialTransformations.rotation); + } node.computeWorldMatrix(true); }); } From 78fb168ccf7e7bf52804ef192303d80732b05c2b Mon Sep 17 00:00:00 2001 From: Popov72 Date: Sat, 28 Feb 2026 15:47:34 +0100 Subject: [PATCH 2/2] Fix quaternion usage --- .../dev/core/src/Animations/animatorAvatar.ts | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/dev/core/src/Animations/animatorAvatar.ts b/packages/dev/core/src/Animations/animatorAvatar.ts index 367adee2863..e8f7b851c6b 100644 --- a/packages/dev/core/src/Animations/animatorAvatar.ts +++ b/packages/dev/core/src/Animations/animatorAvatar.ts @@ -89,7 +89,7 @@ export interface IRetargetOptions { mapNodeNames?: Map; } -type TransformNodeNameToNode = Map; +type TransformNodeNameToNode = Map; /** * Represents an animator avatar that manages meshes, skeletons and morph target managers for a hierarchical transform node and mesh structure. @@ -163,8 +163,6 @@ export class AnimatorAvatar { this._collectMesh(mesh); } }); - - this._computeBoneWorldMatrices(); } private _collectMesh(mesh: AbstractMesh) { @@ -268,20 +266,20 @@ export class AnimatorAvatar { lstSourceTransformNodes.add(tn); - if (!tn.rotationQuaternion) { - tn.rotationQuaternion = Quaternion.FromEulerAngles(tn.rotation.x, tn.rotation.y, tn.rotation.z); - tn.rotation.setAll(0); - } - sourceTransformNodeNameToNode.set(mapNodeNames.get(tn.name) ?? tn.name, { node: tn, initialTransformations: { position: tn.position.clone(), scaling: tn.scaling.clone(), - quaternion: tn.rotationQuaternion.clone(), + quaternion: tn.rotationQuaternion?.clone(), rotation: tn.rotation.clone(), }, }); + + if (!tn.rotationQuaternion) { + tn.rotationQuaternion = Quaternion.FromEulerAngles(tn.rotation.x, tn.rotation.y, tn.rotation.z); + tn.rotation.setAll(0); + } } } @@ -843,8 +841,8 @@ export class AnimatorAvatar { const { node, initialTransformations } = data; node.position.copyFrom(initialTransformations.position); node.scaling.copyFrom(initialTransformations.scaling); - if (node.rotationQuaternion) { - node.rotationQuaternion.copyFrom(initialTransformations.quaternion); + if (initialTransformations.quaternion) { + node.rotationQuaternion!.copyFrom(initialTransformations.quaternion); } else { node.rotation.copyFrom(initialTransformations.rotation); }