Page 1 of 1

How to tell if a mesh was animated this frame

Posted: Wed Jan 18, 2017 1:34 am
by lumirion
What would be the best way to tell if an animated mesh has moved or deformed since the last frame?

Re: How to tell if a mesh was animated this frame

Posted: Wed Jan 18, 2017 9:12 am
by REDDemon
Irrclicht has no api for that. Probably it is worth adding the following methods to IAnimatedMeshSceneNode

Code: Select all

 
 
/// All these methods refer to an animation between 2 frames, in case of looping those methods refer to one looping interval
/// (meaning getAnimationProgress periodically goes from 0 to 1 and the restart again going from 0 to 1) etc.
 
// is the mesh animating?
virtual bool isAnimating()= 0;
 
// return animation progress in the [0,1) interval
virtual float getAnimationProgress() = 0;
 
// return animation duration (seconds)
virtual float getAnimationDuration() = 0;
 
In example: how to print time remaining to end an animation

Code: Select all

 
IAnimatedSceneNode n = animatedSceneNode;
if( n-> isAnimating())
    std::cout<< "Animation/Loop cycle ends in " << ( n->getAnimationDuration() * (1-  n->getAnimationProgress()  ) <<  " seconds" << std::endl;
 
 
There's a bunch of classes that can be updated with these methods. However seems they all have not a common parent, so there will be the need to duplicate some code.

Let's see what Others think of that:)

Re: How to tell if a mesh was animated this frame

Posted: Wed Jan 18, 2017 12:01 pm
by CuteAlien
@REDDemon: IAnimatedMesh has getAnimationSpeed() and getFrameCount() which alllows calculating the getAnimationDuration.
getAnimationProgress() can also be calculated already by using IAnimatedMeshSceneNode functions getFrameNr, getStartFrame, getEndFrame.
Not sure what isAnimating would return... as if it's animates might for example depend on whether the user calls OnAnimate (when the node is not in the SceneGraph but manually updated). So it's kinda hard to see when to set that to true or false.

The check if anything changed is hard. Internally CSkinnedMesh seems to have the info about LastAnimatedFrame and SkinnedLastFrame, but I'm not exactly sure right now which one would be useful in this case.

Re: How to tell if a mesh was animated this frame

Posted: Wed Jan 18, 2017 12:24 pm
by REDDemon
Well few utility methods can be added (to provide once and forever a implementation that users can implement in a buggy way), they can just re-use the implementation (and don't even need to be virtual !).

Code: Select all

 
node->getAnimationProgress();
 
VS

Code: Select all

 
// Internal implementation would look like that (using "this" instead of "node" of course)
float start = node->getStartFrame(); 
float end = node->getEndFrame();
float curr = node->getFrameNr();
float progress = fabs(start- curr) / fabs(start -end);
 
For isAnimating it is weird. The proper thing to handle that would be having also "Play/Pause/Stop" methods, OnAnimate is basically inversion of control, but user could change that :/ . But that would be a breaking change u.u. Meaning actually it is undefined if mesh is playing from Irrlicht point of view (only user know that because it is user calling OnAnimate() and there is not way to stop calling it, apart setting playing speed to 0). So the user should in theory creat its own Scene node, wrapping the animated mesh and adding "Play/Pause/Stop/IsAnimating/IsComplete" methods in order to have something that is not in "undefined" animation state.

Re: How to tell if a mesh was animated this frame

Posted: Wed Jan 18, 2017 1:31 pm
by CuteAlien
play/pause/stop are basically all handled by setAnimationSpeed(). So getAnimationSpeed could also be seen as kind of an isAnimating() function. It would be possible to have an extra flag for that as well I guess.

Re: How to tell if a mesh was animated this frame

Posted: Thu Jan 19, 2017 12:12 pm
by REDDemon
If we are sure OnAnimation is called always, then a flag will suffice. I would not use AnimationSpeed for that because of consistency with animation code in all other animation libraries/frameworks (that provide time scale indipendent of pause status, I think the reason is that if we pause by setting speed to 0, then how do we know which speed value to restore when calling start? Users would have to call Start with a Speed parameter then but then we could just use setAnimationSpeed altogheter).

Stop => should set FrameNr to StartFrame and set pause flag (clean animation progress & pause)
Pause => set pause flag (that prevent updating on OnAnimate) (pause)
Start => remove pause flag (no effect if flag is already removed). (resume)



IsAnimating could return !pauseFlag. (so should return true even if animation speed is 0).

Re: How to tell if a mesh was animated this frame

Posted: Thu Jan 19, 2017 2:22 pm
by CuteAlien
There are 2 speed values. One for the node and one for the mesh. Generally the one for the node is set to the one of the mesh (Irrlicht does that per default if I remember right). If that's the wrong value then users generally have to get another one from some stored variable anyway.

Using additional flags and functions is still probably ok. Start/Stop/Pause sounds a little bit more like an UI implementation, but it might make sense for a library as well. Can't really say I remember other api's there right now...

But I think that's not the original question. Because you can have an animation playing without the mesh changing (just 2 frames with same mesh). So that would still be another thing.

Re: How to tell if a mesh was animated this frame

Posted: Fri Jan 20, 2017 8:35 am
by lumirion
That could be useful for when I write an animation managing class. at the moment I was thinking more like detecting morphological changes or movement reletive to the active camera. I'm hoping to sort render order based the interrelation of the scene elements, and only change the sequence when animation or movement nessesitate it. sorting all elements every frame gets slow when it is accurate. I had been considering profiling the joint's keys and for each frame saving a bool indicating whether anything changed since last frame. Bad idea on my part. That's a waste of memory and it would never work. What if the camera moved? Everything would be invalidated and need to be resorted any way.
Probably the best way to do this part is still testing with the bounding boxes. I was hoping to do it quicker. I suppose I could speed it up in c++ 11 with multithreading, as long as I don't use any concurrent writes. Any other options? Opinions?

Re: How to tell if a mesh was animated this frame

Posted: Fri Jan 20, 2017 2:00 pm
by REDDemon
@lumirion I'm not sure I understand your problem. You want to skip animations when not necessary? Animated nodes that have "OnAnimate" could as well have a animator that makes them moving through the scene, if you skip animating them for reasons like "out of frustum" you could end up altering game logic, so you cannot stop "animating" without knowing what the scene node is doing which unluckily is a gamespecific fact.

Usually there are 3 kind of animations (very simplified) in "professional" games.

Transform => this is updated by physics or game logic
Tween => animate any property, but usually just animate the transform
Animation => refers to skinned mesh animations.

It does make sense having 1 bounding box that is wrapped around all possible animations of skinned mesh

Transform & Tweens are relatively cheap and are always updated very frame.
Animation => updated only if the scene node is near enourgh or inside the frustum (the frameNr is updated anyway but bones are not updated). If using a phys engine, this is where ragdoll comes into play (check against bounding box).
Physics => usually rigidbodies automatically go to sleep if their speed become lower than a treshold.

Any more complex optimization would just eat more CPU cycles than CPU cycles saved.

Since it is very usefull having Pause/Stop/Start methods you can implement then yourself in a wrapper class so you don't have to wait for that coming into Irrlicht.

Code: Select all

 
public AnimatedNode{
 
    IAnimatedMeshSceneNode * target;+ 
    bool pause;
 
public:
 
    AnimatedNode( IAnimatedMeshSceneNode * node){
        node->grab();
        target = node;
        pause = true; // start animated or not?
    }
 
    ~AnimatedNode(){
        target->drop();
    }
   
    void update( u32 ms){ 
        if(pause == false)
            target->OnAnimate( ms); // Good only if we are using a Skinned Mesh.
    }
 
    void stop(){
        pause = true;
        target->setCurrentFrame( target->getStartFrame());
    }
 
    void pause(){
        pause = true;
    }
 
    void start(){
        pause = false;
    }
}
 

Re: How to tell if a mesh was animated this frame

Posted: Sat Jan 21, 2017 1:54 am
by lumirion
Sorry, I'll explain better. What I want to do is find the most efficient way to tell if a mesh's animation during the current frame has invalidated the meshes position in the render sequence. Then I will be able to adjust when it renders by moving it's position in the render que.
The way it works in the default scenemanager is all renderable nodes are sorted by their centers distance to the camera every frame. This causes grafical issues if a mesh is flattened or envelopes others.
To keep things running fast I thought I could maybe use animation information to tell if geometry changed or moved. then do more complex tests to tell how to sort it, back farther or nearer the camera, without sorting every object every frame.

I have an example where I implemented ogre 3d's sub mesh sorting by saving indexes to several vertices per mesh buffer that are as far apart as possible. this makes a form fitting bounding envelope around each buffer. I can grab the nearest one and use the distance from the camera to it to sort a buffer's position in the render order. This is quite accurate, but extremely and agonizingly slow.
I think it is simpler to generate the nearest 3 edges from an aabbox's two coordinates. Then compair their lengths to tell if the mesh has become flat. a plane sort works in this case. Otherwise the default sort should be used. But if one transparent mesh surrounds, or almost does, other meshes; then it should be rendered with its front faces culled first. Next it's contained meshes should be rendered, followed by it's front faces.

I want to find the most efficient way do this so I was trying to tell from the animation data if any render order changes are nessesary before doing complex tests to determine what kind.

The play pause and reverse stuff will also be usefull to me soon.

Re: How to tell if a mesh was animated this frame

Posted: Sat Jan 21, 2017 10:54 am
by devsh
I wrote an animation/pose manager class together with hardware skinning for IrrBAW, its in the github repository

The problem with irrlicht is that if you have 2 nodes using the same mesh, in 2 different poses NOT being animated, they will be reskinned 2ce every frame... so imagine what happens when you have 1000