As always, we are going to use the code from the previous chapter, and for once we don't need to delete anything:
FrameListener
. Add a pointer holding the entity we want to animate and a pointer to the used animation state:Ogre::Entity* _ent; Ogre::AnimationState* _aniState;
FrameListener
to get the entity pointer as a new parameter:Example34FrameListener(Ogre::SceneNode* node,Ogre::Entity* ent,RenderWindow* win,Ogre::Camera* cam)
_ent = ent;
Dance
from the entity and store it in the member variable we created for this purpose. Finally, set the animation to be enabled and loop it:_aniState = _ent->getAnimationState("Dance"); _aniState->setEnabled(true); _aniState->setLoop(true);
frameStarted()
method; through this we know how much time has passed:_aniState->addTime(evt.timeSinceLastFrame);
ExampleApplication
to work with the new FrameListener
. Add a new member variable to the application to hold a pointer to the entity:Ogre::Entity* _SinbadEnt;
Ogre::Entity* Sinbad = mSceneMgr->createEntity("Sinbad", "Sinbad.mesh");
with
_SinbadEnt = mSceneMgr->createEntity("Sinbad", "Sinbad.mesh");
_SinbadNode->attachObject(_SinbadEnt);
FrameListener
, add the new parameter to the constructor call:Ogre::FrameListener* FrameListener = new Example34FrameListener(_SinbadNode,_SinbadEnt,mWindow,mCamera);
With a few lines of code, we made Sinbad dance. In step 1, we added two new member variables, which will be needed later for animating the model. The first member variable was simply a pointer to the entity we want to animate. The second was a pointer to Ogre::AnimationState
, which is used by Ogre 3D for representing a single animation and its associated information. Steps 2 and 3 are straightforward; we changed the constructor to accommodate the new pointer we needed and in step 3 we stored the pointer in the member variables we created in step 1. Interesting stuff happened in step 4; there we asked the entity to return to us the animation named Dance
. Each entity stores all the animations it has and we can query them using a string identifier and getAnimationState()
. This function returns a pointer to this animation represented as an AnimationState
or if the animation doesn't exist, it will return a null pointer. After we got the animation state, we enabled it. This tells Ogre 3D to play this animation. Also, we set the loop property to true
so the animation will be played again and again until we stop it. Step 5 is the important one; with this code, we can make the animation come alive. Each time our scene is rendered, we add a bit of time to the animation and therefore Ogre 3D plays it a bit. To be precise, the bit corresponds to the time passed since the last frame. This could, of course, be done by Ogre 3D itself, but this way the function is much more flexible. As an example, we could add a second model which we want to be animated in slow motion. If Ogre 3D updated the animation itself, it could be difficult or impossible for us to animate one model with normal speed and one in slow motion. With the taken approach, we can add a * 0.25 to the time passed since last frame and the model will be animated in slow motion.
The steps after this are simply small modifications of our application so that it is compatible with the changed FrameListener
constructor. For this, we needed to save the pointer to the entity we wanted to animate.
Why do we need to tell Ogre 3D how much time has passed since the animation was last updated and what are the positive side effects of this architecture?
18.226.165.234