Quellcode durchsuchen

FBXLoader: Correct bind matrix. (#33317)

Michael Herzog vor 2 Wochen
Ursprung
Commit
f04b082d40
1 geänderte Dateien mit 61 neuen und 14 gelöschten Zeilen
  1. 61 14
      examples/jsm/loaders/FBXLoader.js

+ 61 - 14
examples/jsm/loaders/FBXLoader.js

@@ -938,6 +938,57 @@ class FBXTreeParser {
 
 
 		} );
 		} );
 
 
+		// Like Blender's FBX importer, use the BindPose section to set the
+		// rest pose for bones that are not part of a skin cluster. The BindPose
+		// provides a more authoritative rest pose than the Lcl properties which
+		// may represent an animation frame rather than the true rest state.
+		// Bones WITH clusters will get their bind pose from TransformLink
+		// (set via bindSkeleton below), which takes priority.
+		const bindPoseMatrices = this.parsePoseNodes();
+		const clusterBoneIDs = new Set();
+
+		for ( const ID in deformers.skeletons ) {
+
+			deformers.skeletons[ ID ].rawBones.forEach( function ( _, i ) {
+
+				const bone = deformers.skeletons[ ID ].bones[ i ];
+				if ( bone ) clusterBoneIDs.add( bone.ID );
+
+			} );
+
+		}
+
+		const tempMatrix = new Matrix4();
+
+		sceneGraph.traverse( function ( node ) {
+
+			if ( node.isBone && node.ID !== undefined && ! clusterBoneIDs.has( node.ID ) ) {
+
+				const bindPose = bindPoseMatrices[ node.ID ];
+
+				if ( bindPose !== undefined ) {
+
+					if ( node.parent ) {
+
+						tempMatrix.copy( node.parent.matrixWorld ).invert();
+						tempMatrix.multiply( bindPose );
+
+					} else {
+
+						tempMatrix.copy( bindPose );
+
+					}
+
+					tempMatrix.decompose( node.position, node.quaternion, node.scale );
+					node.updateMatrix();
+					node.matrixWorld.copy( bindPose );
+
+				}
+
+			}
+
+		} );
+
 		// Bind skeletons after transforms are applied so that bind matrices
 		// Bind skeletons after transforms are applied so that bind matrices
 		// are computed from the final scene state. This ensures the rest pose
 		// are computed from the final scene state. This ensures the rest pose
 		// is correct even when the FBX file's Cluster TransformLink matrices
 		// is correct even when the FBX file's Cluster TransformLink matrices
@@ -1463,8 +1514,6 @@ class FBXTreeParser {
 
 
 	bindSkeleton( skeletons, geometryMap, modelMap ) {
 	bindSkeleton( skeletons, geometryMap, modelMap ) {
 
 
-		const bindMatrices = this.parsePoseNodes();
-
 		for ( const ID in skeletons ) {
 		for ( const ID in skeletons ) {
 
 
 			const skeleton = skeletons[ ID ];
 			const skeleton = skeletons[ ID ];
@@ -1504,19 +1553,16 @@ class FBXTreeParser {
 
 
 							const model = modelMap.get( geoConnParent.ID );
 							const model = modelMap.get( geoConnParent.ID );
 
 
-							// Always provide a bind matrix to prevent bind() from
-							// calling calculateInverses() which would overwrite the
-							// TransformLink-based bone inverses computed above.
-							let bindMatrix = bindMatrices[ geoConnParent.ID ];
-
-							if ( bindMatrix === undefined ) {
-
-								model.updateMatrixWorld( true );
-								bindMatrix = model.matrixWorld;
-
-							}
+							// Use the mesh's current matrixWorld as bind matrix.
+							// The BindPose section is intentionally not used here
+							// since it may contain scale/rotation from the model
+							// hierarchy that is inconsistent with the TransformLink-
+							// based bone inverses. Always provide a bind matrix to
+							// prevent bind() from calling calculateInverses() which
+							// would overwrite the bone inverses computed above.
+							model.updateMatrixWorld( true );
 
 
-							model.bind( new Skeleton( skeleton.bones, boneInverses ), bindMatrix );
+							model.bind( new Skeleton( skeleton.bones, boneInverses ), model.matrixWorld );
 
 
 						}
 						}
 
 
@@ -1530,6 +1576,7 @@ class FBXTreeParser {
 
 
 	}
 	}
 
 
+	// Parse BindPose nodes and return a map of node ID to bind matrix.
 	parsePoseNodes() {
 	parsePoseNodes() {
 
 
 		const bindMatrices = {};
 		const bindMatrices = {};

粤ICP备19079148号