mirror of
https://github.com/raysan5/raylib.git
synced 2026-08-15 11:59:15 +00:00
Fix glTF pose sampled at the end of an animation returning a pose from the start (#6048)
GetPoseAtTimeGLTF searches for the interval containing the requested time with (tstart <= time) && (time < tend). A time equal to the last keyframe satisfies no interval, so the loop ends without a match and keyframe stays at its 0 default, making the function return a pose from the beginning of the animation. LoadModelAnimationsGLTF samples at t = j/60 for j in [0, keyframeCount), with keyframeCount = (int)(duration*60) + 1, so the last sample lands exactly on the end of the animation whenever duration*60 is a whole number. The last pose of those clips is wrong, which looks like a jerk right before the animation ends. Measured on a glTF with a 0.85 s clip: the delta between the last two poses was 23x the median delta between consecutive poses; with this change it is 0.3x, in line with every other step.
This commit is contained in:
@@ -6390,6 +6390,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_
|
||||
float tstart = 0.0f;
|
||||
float tend = 0.0f;
|
||||
int keyframe = 0; // Defaults to first pose
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < (int)input->count - 1; i++)
|
||||
{
|
||||
@@ -6402,10 +6403,26 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_
|
||||
if ((tstart <= time) && (time < tend))
|
||||
{
|
||||
keyframe = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No interval contains a time at (or past) the last keyframe, because the
|
||||
// search above requires time < tend: clamp to the edge interval instead of
|
||||
// falling back to keyframe 0, which returns a pose from the start
|
||||
if (!found && ((int)input->count >= 2))
|
||||
{
|
||||
keyframe = (int)input->count - 2;
|
||||
|
||||
float tfirst = 0.0f;
|
||||
if (!cgltf_accessor_read_float(input, 0, &tfirst, 1)) return false;
|
||||
if (time < tfirst) keyframe = 0;
|
||||
|
||||
if (!cgltf_accessor_read_float(input, keyframe, &tstart, 1)) return false;
|
||||
if (!cgltf_accessor_read_float(input, keyframe + 1, &tend, 1)) return false;
|
||||
}
|
||||
|
||||
// Constant animation, no need to interpolate
|
||||
if (FloatEquals(tend, tstart))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user