Search code examples
c++opengl3dlinear-algebraopenscenegraph

Rotating the camera around the Y axis of the world (at O(0,0,0))


I'm trying to rotate the camera around the Y axis of the world, marked in my project by a 3D cross.

What I've accomplished is rotating it around its own axis, which is cool, but it's not what I wanted.

How to achieve that by using quaternions and some maths, not osg::PositionAttitudeTransforms or any easy-to-use but hard to understand infrastructure.

I would like to be exposed to the maths behind it.

The relevant piece of code is

osg::Matrixd camM;
std::stringstream oss;
osg::Quat x_rot_q(osg::DegreesToRadians(-DEG), osg::Vec3d(1.0, 0.0, 0.0));
osg::Quat y_rot_q(osg::DegreesToRadians(DEG), osg::Vec3d(0.0, 1.0, 0.0));
camM = cameraManipulator->getMatrix();
camM.makeRotate(x_rot_q * y_rot_q);
camM.setTrans(250.0, 300.0, 250.0);
cameraManipulator->setByMatrix(camM);

osg::Quat y_delta_trans(osg::DegreesToRadians(DEG_DELTA), osg::Vec3d(0.0, 1.0, 0.0));

while(!viewer.done()) {
    oss.str(std::string());
    oss.clear();
    camM = cameraManipulator->getMatrix();
    camM.makeRotate(camM.getRotate() * y_delta_trans);
    camM.setTrans(250.0, 300.0, 250.0);
    cameraManipulator->setByMatrix(camM);
    oss << getMatrixRepresentation(camM);
    hudGeode->setStatus(oss.str());
    viewer.frame();
}

which you can find at the bottom of the file Simple.cpp. The entire project can be found at this revision in a gist.

On a GNU/Linux box, just type make and it should work out of the box with the proper tools installed.


Solution

  • Rotating the camera around another axis than its own is fairly simple, just perform these steps in order:

    • Translate the camera to the origin of your world
      • if the camera is at (Xc,Yc,Zc) relative to the world's origin that would imply a translation of (-Xc,-Yc,-Zc).
    • Rotate the camera the way you want it rotated
    • Reverse the previous translation, i.e. perform a translation of (Xc,Yc,Zc)

    Or mathematically as a matrix product:

                            [ 1 0 0 -Xc ]                 [ 1 0 0 Xc ]
    Transformation Matrix = [ 0 1 0 -Yc ] Rotation Matrix [ 0 1 0 Yc ]
                            [ 0 0 1 -Zc ]                 [ 0 0 1 Zc ]
                            [ 0 0 0  1  ]                 [ 0 0 0 1  ]
    

    Edit:

    Note that this is the general way of rotating an object around an origin not its own.