Skip to content

Commit 13a06fc

Browse files
authored
FBXLoader: Add skinning fixes. (#33316)
1 parent d2d9d40 commit 13a06fc

7 files changed

Lines changed: 51 additions & 5 deletions

File tree

examples/jsm/loaders/FBXLoader.js

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -824,8 +824,6 @@ class FBXTreeParser {
824824
indices: [],
825825
weights: [],
826826
transformLink: new Matrix4().fromArray( boneNode.TransformLink.a ),
827-
// transform: new Matrix4().fromArray( boneNode.Transform.a ),
828-
// linkMode: boneNode.Mode,
829827

830828
};
831829

@@ -918,8 +916,6 @@ class FBXTreeParser {
918916

919917
} );
920918

921-
this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
922-
923919
this.addGlobalSceneSettings();
924920

925921
sceneGraph.traverse( function ( node ) {
@@ -942,6 +938,13 @@ class FBXTreeParser {
942938

943939
} );
944940

941+
// Bind skeletons after transforms are applied so that bind matrices
942+
// are computed from the final scene state. This ensures the rest pose
943+
// is correct even when the FBX file's Cluster TransformLink matrices
944+
// differ from the reconstructed bone transforms (common in files
945+
// without a BindPose section).
946+
this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
947+
945948
const animations = new AnimationParser().parse();
946949

947950
// if all the models where already combined in a single group, just return that
@@ -1466,6 +1469,26 @@ class FBXTreeParser {
14661469

14671470
const skeleton = skeletons[ ID ];
14681471

1472+
// Compute bone inverses from TransformLink rather than from the
1473+
// bones' current matrixWorld. The TransformLink matrices represent
1474+
// each bone's global transform at the time the skin weights were
1475+
// painted, which may differ from the scene-reconstructed transforms.
1476+
const boneInverses = [];
1477+
1478+
for ( let i = 0, l = skeleton.bones.length; i < l; i ++ ) {
1479+
1480+
const inverse = new Matrix4();
1481+
1482+
if ( skeleton.bones[ i ] && skeleton.rawBones[ i ] ) {
1483+
1484+
inverse.copy( skeleton.rawBones[ i ].transformLink ).invert();
1485+
1486+
}
1487+
1488+
boneInverses.push( inverse );
1489+
1490+
}
1491+
14691492
const parents = connections.get( parseInt( skeleton.ID ) ).parents;
14701493

14711494
parents.forEach( function ( parent ) {
@@ -1481,7 +1504,19 @@ class FBXTreeParser {
14811504

14821505
const model = modelMap.get( geoConnParent.ID );
14831506

1484-
model.bind( new Skeleton( skeleton.bones ), bindMatrices[ geoConnParent.ID ] );
1507+
// Always provide a bind matrix to prevent bind() from
1508+
// calling calculateInverses() which would overwrite the
1509+
// TransformLink-based bone inverses computed above.
1510+
let bindMatrix = bindMatrices[ geoConnParent.ID ];
1511+
1512+
if ( bindMatrix === undefined ) {
1513+
1514+
model.updateMatrixWorld( true );
1515+
bindMatrix = model.matrixWorld;
1516+
1517+
}
1518+
1519+
model.bind( new Skeleton( skeleton.bones, boneInverses ), bindMatrix );
14851520

14861521
}
14871522

311 KB
Binary file not shown.
339 KB
Loading
71 KB
Loading
497 KB
Loading
1.96 MB
Binary file not shown.

examples/webgl_loader_fbx.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,16 @@
5050
'monkey',
5151
'monkey_embedded_texture',
5252
'vCube',
53+
'archer/ArcherRi01',
54+
'warrior/Warrior',
55+
'stanford-bunny',
56+
'mixamo',
5357
];
5458

59+
const scales = new Map();
60+
scales.set( 'warrior/Warrior', 100 );
61+
scales.set( 'archer/ArcherRi01', 100 );
62+
scales.set( 'stanford-bunny', 0.001 );
5563

5664
init();
5765

@@ -162,6 +170,9 @@
162170

163171
object = group;
164172

173+
const scale = scales.get( asset );
174+
object.scale.setScalar( scale || 1 );
175+
165176
if ( object.animations && object.animations.length ) {
166177

167178
mixer = new THREE.AnimationMixer( object );

0 commit comments

Comments
 (0)