If someone can take a look to the timing problem in the ExtendedCamera::update method, please, feel free to do it. The problem is that slow framerates and fast movement will result in bad camera updates.
In any case, this system wasn't designed with that artifact in mind, and the updating is proportional, so there wouldn't be much difference (if the distance is larger, the half of the distance is still the half). The only problem is that it would take more time to reach the point than before if the performance is poor.

Anyways, I think it's fine this way. I won't remove the elapsedTime parameter for that purpose :-)


For movements and such to be independent of framerate, you just have to weight them by the time since the last frame was rendered. This can be done simply with Ogre using FrameEvent::timeSinceLastFrame, wich you're already passing to ExtendedCamera::update. So all we have to add is something like :

 void update (Real elapsedTime, Vector3 cameraPosition, Vector3 targetPosition) {
     // Handle movement
     Vector3 displacement;
 
     displacement = (cameraPosition - mCameraNode->getPosition ()) * mTightness;
     mCameraNode->translate ( displacement * time );
 
     displacement = (targetPosition - mTargetNode->getPosition ()) * mTightness;
     mTargetNode->translate ( displacement * time );
 }

So, your cinematic camera will have the same speed, regardless of performance.
mTightness acts then more than a speed value, and it has to be greater than 1 for movements to be instant. However, a too large value can provoke undesired behaviours ; so, if you want to agree with the definition of mTightness, I suggest to multiply your translation vector by some fixed empiric value greater than 1, like :

 node->translate ( displacement * time * someScalar )




Just a question about :

 if( mOwnCamera )
 {
     delete mCamera;
     mCamera = 0;
 }

Doesn't the scene manager still have a reference to the camera ? (calling mSceneMgr->destroyAllCameras(=) causes a segfault after deleting mCamera). Shouldn't be replaced by :

 if( mOwnCamera )
 {
     mSceneMgr->destroyCamera( mCamera );
     mCamera = 0;
 }

?


Yes, probably. I missed that, though you most likely want to write your own camera system using this method, not this base code. Thanks for pointing that out. If you can confirm this, feel free to fix that or tell me to do it.


Syedhs, Camera::setPosition() sets the position relative to the scene node it's attached to, not world coordinates. Also, it defaults to Vector3::ZERO, so those lines are redundant. It's the same for lights, though as they are usually more attached to a single scene node, it makes sense there.

Great Tutorial!

You're the man! I was trying to work on a 3rd person camera system yesteday and today and having trouble. This is far better than what I would have come up with on my own. Thank you so much!! =D Moohasha 18:24, 11 April 2008 (BST)

I twinked the ExtendedCamera class to have a private Character* member and a method called attachObject(Character*). Doing that I was able to move a lot of the camera updating inside of the update() method instead of doing it inside of frameStarted(). So now the ExtendedCamera
:update method looks like this (I added a mode enum to simplify things for me):

 void update (Real elapsedTime) {
     // Handle movement
     Vector3 displacement;
     Vector3 cameraPosition;
     Vector3 targetPosition;
 
     if( !mChar )
         return;
 
     switch (mMode) {
         case MODE_3RDCHASE: // 3rd person chase
             cameraPosition = mChar->getCameraNode()->getWorldPosition();
             targetPosition = mChar->getSightNode()->getWorldPosition();
             break;
 
         case MODE_3RDFIXED: // 3rd person fixed
             cameraPosition = Vector3 (0, 200, 0);
             targetPosition = mChar->getSightNode ()->getWorldPosition ();
             break;
 
         case MODE_1ST: // 1st person
             cameraPosition = mChar->getWorldPosition ();
             targetPosition = mChar->getSightNode ()->getWorldPosition ();
             break;
     }
 
     displacement = (cameraPosition - mCameraNode->getPosition ()) * mTightness;
     mCameraNode->translate (displacement);
 
     displacement = (targetPosition - mTargetNode->getPosition ()) * mTightness;
     mTargetNode->translate (displacement);
 }
and in frameStarted() I just have to do



 mChar->update (evt.timeSinceLastFrame, mKeyboard);
 mExCamera->update(evt.timeSinceLastFrame);
This way I can just attach a Character to the camera and the camera takes care of all the updating, and if I want to change objects I just call attachObject() with a different instance of the Character class.
) Moohasha 19:46, 11 April 2008 (BST)





Hey, thanks for the feedback Moohasha :-) This tutorial is indeed very prone to enhancements. Indeed I developed a much much better version that I'll eventually release someday (I'm such a procrastinator!). I didn't want to overcomplicate things, so did a quick and dirty implementation showcasing a bit of its potential and possible uses, but there's definitely room for much more :-)

Hope you find it useful!

<div align="right">Kencho 02:50, 16 April 2008 (BST)</div>