Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to make a class which controls a camera. It's pretty basic right now, it looks like this:

class HoveringCameraController
{
public:

   void init(Ogre::Camera & camera, AnimatedBody & target, Ogre::Real height);
   void update(Ogre::Real time_delta);
private:
   Ogre::Camera * camera_;
   AnimatedBody * target_;
   Ogre::Real height_;
};

HoveringCameraController.cpp

void HoveringCameraController::init(Ogre::Camera & camera, AnimatedBody & target, Ogre::Real height)
{
   camera_ = &camera;
   target_ = ⌖
   height_ = height;

   update(0.0);
}

void HoveringCameraController::update(Ogre::Real time_delta)
{
   auto position = target_->getPosition();
   position.y += height_;
   camera_->setPosition(position);
   camera_->lookAt(target_->getPosition());
}

AnimatedBody is just a class that encapsulates an entity, it's animations and a scene node. The getPosition function is simply forwarded to it's scene node.

What I want(for now) is for the camera to simply follow the AnimatedBody overhead at the distance given(the height parameter), and look down at it. It follows the object around, but it doesn't look straight down, it's tilted quite a bit in the positive Z direction. Does anybody have any idea why it would do that?

If I change this line:

position.y += height_;

to this:

position.x += height_;

or this:

position.z += height_;

it does exactly what I would expect. It follows the object from the side or front, and looks directly at it.

share|improve this question

2 Answers 2

I believe you are feeling the effects of Gimbal lock. 3D camera implementations typically do not allow for looking directly up or down because of this (because then the forward and up vectors would be parallel). I know from experience that OpenGL can do strange things, and my simple implementation of a camera doesn't allow for less than a 0.1-degree angle up or down.

If you can modify the camera's "up" vector to be something other than (0,0,1), then you should do so when you want to set its forward vector to (0,0,1) (i.e. when you want to look up). The forward and up vectors cannot be the same, though.

Other alternatives include making sure the 'up' vector is orthogonal to the 'forward' vector at all times, or using quaternions. I don't know how these options apply to the Ogre3D engine, sorry.

share|improve this answer
2  
+1 for the Quaternion hint. Here's some background info to Ogre3D and Quaternions: ogre3d.org/tikiwiki/…. This post might help too: ogre3d.org/forums/viewtopic.php?p=86862#p86862 –  bummzack Feb 22 '11 at 10:52
    
Thanks for the good info. And @bummzack, thanks for that first link. I had heard of quaternions before, but they seemed really confusing. That article cleared things up quite a bit, and it's what lead me to my solution, which I'll post below. –  Benjamin Lindley Feb 22 '11 at 20:08
up vote 1 down vote accepted

I found a simple solution to my problem using quaternions.

const Ogre::Real sqrt_one_half = 0.7071067811865475244; // Square root of 1/2
camera_->setOrientation(Ogre::Quaternion(sqrt_one_half,-sqrt_one_half,0.0,0.0));

Also, why the hell am I setting the rotation every update? I should just do it once in the init function, and then only modify the position in the update function. Here's my updated code, if anyone is interested:

void HoveringCameraController::init(Ogre::Camera & camera, AnimatedBody & target, Ogre::Real height)
{
    camera_ = &camera;
    target_ = ⌖
    height_ = height;

    auto p = target_->getPosition();
    p.y += height_;
    camera_->setPosition(p);

    const Ogre::Real sqrt_one_half = 0.7071067811865475244; // Square root of 1/2
    camera_->setOrientation(Ogre::Quaternion(sqrt_one_half,-sqrt_one_half,0.0,0.0));
}

void HoveringCameraController::update(Ogre::Real time_delta)
{
    auto p = target_->getPosition();
    p.y += height_;
    camera_->setPosition(p);
}
share|improve this answer
    
Though I hate the idea of accepting my own answer, I think this is the clearest, most simple solution(unless someone can come up with a better one). –  Benjamin Lindley Feb 22 '11 at 20:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.