Procházet zdrojové kódy

SkeletonUtils: fix retargetClip duration and last frame (#27653)

* SkeletonUtils: fix retargetClip duration and last frame

* SkeletonUtils: set retargetClip default fps to source clip fps

* SkeletonUtils: Update retargetClip to set default fps based on the longest track
Alaric.Baraou před 1 rokem
rodič
revize
edb39714e3
1 změnil soubory, kde provedl 14 přidání a 3 odebrání
  1. 14 3
      examples/jsm/utils/SkeletonUtils.js

+ 14 - 3
examples/jsm/utils/SkeletonUtils.js

@@ -200,7 +200,8 @@ function retarget( target, source, options = {} ) {
 function retargetClip( target, source, clip, options = {} ) {
 
 	options.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false;
-	options.fps = options.fps !== undefined ? options.fps : 30;
+	// Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided.
+	options.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration );
 	options.names = options.names || [];
 
 	if ( ! source.isObject3D ) {
@@ -210,7 +211,7 @@ function retargetClip( target, source, clip, options = {} ) {
 	}
 
 	const numFrames = Math.round( clip.duration * ( options.fps / 1000 ) * 1000 ),
-		delta = 1 / options.fps,
+		delta = clip.duration / ( numFrames - 1 ),
 		convertedTracks = [],
 		mixer = new AnimationMixer( source ),
 		bones = getBones( target.skeleton ),
@@ -287,7 +288,17 @@ function retargetClip( target, source, clip, options = {} ) {
 
 		}
 
-		mixer.update( delta );
+		if ( i === numFrames - 2 ) {
+
+			// last mixer update before final loop iteration
+			// make sure we do not go over or equal to clip duration
+			mixer.update( delta - 0.0000001 );
+
+		} else {
+
+			mixer.update( delta );
+
+		}
 
 		source.updateMatrixWorld();