Hi there, I've been playing around with Neakors excellent MD5Importer for JME 1.0 the last few days, it seems to work perfectly for the most part, but I have either found a bug or am using it incorrectly.
The issue seems to be with changing between animations, the animation becomes very jerky, almost as if it is simply snapping between keyframes and not interpolating and the issue becomes a lot more noticeable when the speed is set quite low, such as 0.1.
I have taken a look at the source and it seems both the time and interpoaltion values are being updated correctly, so I'm not really sure what is wrong
Here are the changes I have made to the "TestFading.java" file in order to quickly showcase the problem. By pressing the 'O' key, the animation will switch between the idle and walking animations (before it simply switched from walking to idle and that was it). The problem seems to manifest itself after switching from walking to idle and then back to walking.
@Override
protected void setupGame() {
ModelNode node = (ModelNode)this.rootNode.getChild("ModelNode");
node.setLocalScale(1);
node.getController(0).setSpeed(1);
this.controller = (JointController)node.getController(0);
this.addFadingAnim();
this.setupKey();
this.controller.setSpeed(0.1f);/*I ADDED THIS TO SHOWCASE THE PROBLEM*/
}
protected void simpleUpdate() {
if(KeyBindingManager.getKeyBindingManager().isValidCommand("fade", false))
{
/*I ADDED THIS TO SHOWCASE THE PROBLEM*/
if(this.controller.getActiveAnimation().getName() != "Stand")
{
this.controller.setActiveAnimation("Stand", 10);
}
else
{
/*I ADDED THIS TO SHOWCASE THE PROBLEM*/
this.controller.setActiveAnimation("BodyAnimation", 10);
}
}
}
Please let me know if anyone has a solution for this (Neakor?) or whether I am not setting something I should be when changing the animation.
i think it might be a bug where after the fading, the frame index of the current animation is not setup correctly. ill try to find some time to work on it.
I can also confirm that this is a problem with version 2.0 as well.
The other thing I am wondering about is whether it is possible to reset an animation back to the start manually, as when fading between animations, the controller seems to remember the current position of the walk animation, when i switch from idle to walk again, he fades along the horizontal to reach the position of the translated root node.
Ideally I would like to be able to reset the walk animation back to the beginning so when it fades it fades from idle to walk, the model remains in the same place until the walk animation begins.
The other thing I am wondering about is whether it is possible to reset an animation back to the start manually, as when fading between animations, the controller seems to remember the current position of the walk animation, when i switch from idle to walk again, he fades along the horizontal to reach the position of the translated root node.
Ideally I would like to be able to reset the walk animation back to the beginning so when it fades it fades from idle to walk, the model remains in the same place until the walk animation begins.
Thanks again.
this is similar to the update transform feature in the old loader, neakor I know u aren't in favor of this feature,but, its just easier for some to animate the model in motion as opposed to threadmill style and as I've said before it just looks more natural
What I mean is that when i let the walk animation play half way through, then switch to idle, then switch back to the walk animation, it fades back to half way through the walk animation. i.e the model slides along the ground from the idle position to the current walk position.
What I really would like to do is set it so that when i fade from the idle to the walk animation, the walk animation starts from its first frame instead of half way through.
I hope that explanation made it a little clearer. It looks like I would need to be able to change the time, prevFrame and nextFrame variables in order to achieve this. Maybe I am just missing a "resetAnim()" function or something similar though.
the sliding is because the loader doesn't keep track of the models "position" in jme, so if a model is animated with forward motion when fading back to idle the loader willl not impose the models current position on the idle animation. the older buggy loader has this kind of feature but would be a step back, in many respects, although I still use it in my experiments.
That's right neakor, just resetting an animation is what I meant - does such a method exist?
With regards to the initial problem, I have taken a poke around the code. Part of the issue seems to be that the "if statement" which checks if Interpolation is greater than 1.0 and sets fading to false never gets hit (in the example).
The reason for this is that the time variable is simply being incrememnted as if it were normal animation - when the animation mode is set to wrap, the time variable is set back to 0 when the last frame is reached. Now consider that the animation is only 5 or 6 seconds long. If the fading time is set to 10 seconds as in the example, then fading will always be true as it is impossible for the interpolation value to be greater than 1.0 when fading.
I worked around this by simply having another special case timer for when fading is enabled. I also tried setting a number of variables back to their defaults, such as prevFrame, nextFrame, interpoaltion and time (when interpolation is greater than 1.0 and fading is enabled).
The above changes only half solved the issue though as it would still stutter for a moment, as if it were finishing the fade whilst beginning the next aniamtion then returning to normal.
Thanks a lot for the quick fix, the new setFade method works perfectly
There is however still an issue when changing animation with the "setActiveAnimation(String name)" method, where it produces the same stuttering animation after a change. It seems like I can just set the fade time to 0 and it reproduces the effects of this method. That's the only other method I have checked for switching animations, but possibly the other have this bug as well.
Anyway, I can get back to my project again now, thanks for the resolution.
EDIT I've also noticed that in your new updateTime piece of code for fading, you're not multiplying by the speed of the animation. Maybe it's juts me, but I would expect the fade to scale proportionally with the rest of the animation.
Thanks a lot for the quick fix, the new setFade method works perfectly :D
There is however still an issue when changing animation with the "setActiveAnimation(String name)" method, where it produces the same stuttering animation after a change. It seems like I can just set the fade time to 0 and it reproduces the effects of this method. That's the only other method I have checked for switching animations, but possibly the other have this bug as well.
np, thx for reporting the problem.
on that note, i think maybe i should just make setActiveAnimation(...) to private. it seems that the fading should be used to switch between animations. and if there isnt a current active animation, the fading time is enfored to 0. let me know what u think of this idea.
*EDIT* I've also noticed that in your new updateTime piece of code for fading, you're not multiplying by the speed of the animation. Maybe it's juts me, but I would expect the fade to scale proportionally with the rest of the animation.
i intentially made it that way so the value u pass in is the actual fading time. otherwise if u pass in 5 and the controller speed is set to 2, u will only get 2.5 seconds fading instead of the 5 u passed in.
I agree that setFading could simply be used with 0 fadingTime to do the same job. However, I don't think that forcing fade to 0 is a good idea if there is no aniamtion currently playing. My reasoning for this is that as far as I am aware, when you start an aniamtion and the model is in bind pose, you can blend from this to the new aniamtion. There may be situations where users would like to do this, they can always handle it in their code if they want any other behaviour.
I can see why you wanted it to be the actual fading time for the value passed in, but I can think of a few situations where you may want the fading time to scale, lets say you wanted to put bullet time in your game or slow motion, all you would do is set the controllers speed and everything would play nicely with each other without having to fiddle with fading values. Maybe you could just pass in a boolean into setFading as to whether you want to scale the fade time with the current speed or not. I think this would retain both the functionality we desire whilst also making it a little more flexible. What do you think?