@sage-rsc/talking-head-react 1.4.7 → 1.4.9
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/dist/index.cjs +2 -2
- package/dist/index.js +766 -780
- package/package.json +1 -1
- package/src/lib/talkinghead.mjs +39 -38
package/package.json
CHANGED
package/src/lib/talkinghead.mjs
CHANGED
|
@@ -1667,55 +1667,66 @@ class TalkingHead {
|
|
|
1667
1667
|
const tempEuler = new THREE.Euler();
|
|
1668
1668
|
const tempQuaternion = new THREE.Quaternion();
|
|
1669
1669
|
|
|
1670
|
+
// Check if FBX animation is playing - if so, be even more aggressive
|
|
1671
|
+
const isFBXPlaying = this.mixer && this.currentFBXAction && this.currentFBXAction.isRunning();
|
|
1672
|
+
|
|
1670
1673
|
// Research-based relaxed shoulder rotation values
|
|
1671
|
-
// Natural relaxed shoulders: X rotation ~0.
|
|
1674
|
+
// Natural relaxed shoulders: X rotation ~0.4-0.5 radians
|
|
1672
1675
|
// High/stiff shoulders: X rotation ~1.5-1.8 radians
|
|
1673
|
-
// We
|
|
1674
|
-
const targetX = 0.
|
|
1675
|
-
const maxX = 0.
|
|
1676
|
+
// We ALWAYS clamp to relaxed position, especially during FBX animations
|
|
1677
|
+
const targetX = 0.5; // Target X rotation for relaxed, natural shoulders (radians)
|
|
1678
|
+
const maxX = 0.6; // Maximum allowed X rotation - very strict
|
|
1676
1679
|
|
|
1677
1680
|
// Adjust left shoulder bone directly
|
|
1678
1681
|
if (leftShoulderBone.quaternion) {
|
|
1679
1682
|
tempEuler.setFromQuaternion(leftShoulderBone.quaternion, 'XYZ');
|
|
1680
|
-
const originalX = tempEuler.x;
|
|
1681
1683
|
|
|
1682
|
-
//
|
|
1684
|
+
// ALWAYS clamp X rotation to relaxed position (no threshold check)
|
|
1685
|
+
// During FBX animations, be even more aggressive
|
|
1683
1686
|
if (tempEuler.x > maxX) {
|
|
1684
|
-
// Force to target relaxed position
|
|
1687
|
+
// Force to target relaxed position immediately
|
|
1685
1688
|
tempEuler.x = targetX;
|
|
1686
1689
|
} else if (tempEuler.x > targetX) {
|
|
1687
|
-
//
|
|
1688
|
-
|
|
1690
|
+
// If slightly above target, reduce aggressively
|
|
1691
|
+
if (isFBXPlaying) {
|
|
1692
|
+
// During FBX animations, force to target immediately
|
|
1693
|
+
tempEuler.x = targetX;
|
|
1694
|
+
} else {
|
|
1695
|
+
// Otherwise, reduce smoothly but still aggressively
|
|
1696
|
+
tempEuler.x = targetX + (tempEuler.x - targetX) * 0.1;
|
|
1697
|
+
}
|
|
1689
1698
|
}
|
|
1690
1699
|
|
|
1691
|
-
//
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
leftShoulderBone.updateMatrixWorld(true);
|
|
1696
|
-
}
|
|
1700
|
+
// Always apply the adjustment (no change detection)
|
|
1701
|
+
tempQuaternion.setFromEuler(tempEuler, 'XYZ');
|
|
1702
|
+
leftShoulderBone.quaternion.copy(tempQuaternion);
|
|
1703
|
+
leftShoulderBone.updateMatrixWorld(true);
|
|
1697
1704
|
}
|
|
1698
1705
|
|
|
1699
1706
|
// Adjust right shoulder bone directly
|
|
1700
1707
|
if (rightShoulderBone.quaternion) {
|
|
1701
1708
|
tempEuler.setFromQuaternion(rightShoulderBone.quaternion, 'XYZ');
|
|
1702
|
-
const originalX = tempEuler.x;
|
|
1703
1709
|
|
|
1704
|
-
//
|
|
1710
|
+
// ALWAYS clamp X rotation to relaxed position (no threshold check)
|
|
1711
|
+
// During FBX animations, be even more aggressive
|
|
1705
1712
|
if (tempEuler.x > maxX) {
|
|
1706
|
-
// Force to target relaxed position
|
|
1713
|
+
// Force to target relaxed position immediately
|
|
1707
1714
|
tempEuler.x = targetX;
|
|
1708
1715
|
} else if (tempEuler.x > targetX) {
|
|
1709
|
-
//
|
|
1710
|
-
|
|
1716
|
+
// If slightly above target, reduce aggressively
|
|
1717
|
+
if (isFBXPlaying) {
|
|
1718
|
+
// During FBX animations, force to target immediately
|
|
1719
|
+
tempEuler.x = targetX;
|
|
1720
|
+
} else {
|
|
1721
|
+
// Otherwise, reduce smoothly but still aggressively
|
|
1722
|
+
tempEuler.x = targetX + (tempEuler.x - targetX) * 0.1;
|
|
1723
|
+
}
|
|
1711
1724
|
}
|
|
1712
1725
|
|
|
1713
|
-
//
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
rightShoulderBone.updateMatrixWorld(true);
|
|
1718
|
-
}
|
|
1726
|
+
// Always apply the adjustment (no change detection)
|
|
1727
|
+
tempQuaternion.setFromEuler(tempEuler, 'XYZ');
|
|
1728
|
+
rightShoulderBone.quaternion.copy(tempQuaternion);
|
|
1729
|
+
rightShoulderBone.updateMatrixWorld(true);
|
|
1719
1730
|
}
|
|
1720
1731
|
}
|
|
1721
1732
|
|
|
@@ -5760,7 +5771,6 @@ class TalkingHead {
|
|
|
5760
5771
|
// Filter and map animation tracks
|
|
5761
5772
|
const mappedTracks = [];
|
|
5762
5773
|
const unmappedBones = new Set();
|
|
5763
|
-
let filteredShoulderTracks = 0;
|
|
5764
5774
|
anim.tracks.forEach(track => {
|
|
5765
5775
|
// Remove mixamorig prefix first
|
|
5766
5776
|
let trackName = track.name.replaceAll('mixamorig', '');
|
|
@@ -5771,13 +5781,8 @@ class TalkingHead {
|
|
|
5771
5781
|
// Map bone name to avatar skeleton
|
|
5772
5782
|
const mappedBoneName = mapBoneName(fbxBoneName);
|
|
5773
5783
|
|
|
5774
|
-
//
|
|
5775
|
-
|
|
5776
|
-
if (property === 'quaternion' || property === 'rotation') {
|
|
5777
|
-
filteredShoulderTracks++;
|
|
5778
|
-
return; // Skip this track - don't add it to mappedTracks
|
|
5779
|
-
}
|
|
5780
|
-
}
|
|
5784
|
+
// Note: We allow shoulder rotation tracks to play so arms position correctly
|
|
5785
|
+
// The shoulder adjustment function will override them after animation updates
|
|
5781
5786
|
|
|
5782
5787
|
if (mappedBoneName && property) {
|
|
5783
5788
|
// Create new track with mapped bone name
|
|
@@ -5806,10 +5811,6 @@ class TalkingHead {
|
|
|
5806
5811
|
}
|
|
5807
5812
|
});
|
|
5808
5813
|
|
|
5809
|
-
if (filteredShoulderTracks > 0) {
|
|
5810
|
-
console.log(`✓ Filtered out ${filteredShoulderTracks} shoulder rotation track(s) to prevent high shoulders`);
|
|
5811
|
-
}
|
|
5812
|
-
|
|
5813
5814
|
if (unmappedBones.size > 0) {
|
|
5814
5815
|
console.warn(`⚠️ ${unmappedBones.size} bone(s) could not be mapped:`, Array.from(unmappedBones).sort().join(', '));
|
|
5815
5816
|
}
|