Camera: no gimbal lock but...

Post your questions, suggestions and experiences regarding to Image manipulation, 3d modeling and level editing for the Irrlicht engine here.
Post Reply
azerty69
Posts: 11
Joined: Tue Jun 11, 2013 1:33 pm

Camera: no gimbal lock but...

Post by azerty69 »

Hi,

I've found code in this topic http://irrlicht.sourceforge.net/forum// ... ra&start=0
but I'm encountering a problem: roll occurs while I use pitch and yaw only...

The code of the topic has been adapted because the camera stays at (0, 0, 0).

Code: Select all

 
    void rotate(vector3df rot)
    {
        matrix4 m;
        m.setRotationDegrees(node->getRotation());
        matrix4 n;
        n.setRotationDegrees(rot);
        m *= n;
        node->setRotation(m.getRotationDegrees());
        node->updateAbsolutePosition();
    }
 
    //--- turn ship left or right ---
    void turn(f32 rot)
    {
        rotate(vector3df(0.0f, rot, 0.0f));
    }
 
    //--- pitch ship up or down ---
    void pitch(f32 rot)
    {
        rotate(vector3df(rot, 0.0f, 0.0f) );
    }
 

Code: Select all

 
    void makeCockpit()
    {
        // get transformation matrix of node
        matrix4 m;
        m.setRotationDegrees(node->getRotation());
 
        // transform forward vector of camera
        vector3df frv = vector3df(0.0f, 0.0f, 1.0f);
        m.transformVect(frv);
   
        // transform upvector of camera
        vector3df upv = vector3df(0.0f, 1.0f, 0.0f);
        m.transformVect(upv);
 
        // set camera
        camera->setUpVector(upv);
        camera->setTarget(frv);
 
        // update absolute position
        camera->updateAbsolutePosition();
    }
 

Code: Select all

 
    void update(f32 dtime)
    {
        //  Get rotation angles from relative mouse position
        position2d<f32> cursorPos = device->getCursorControl()->getRelativePosition();
        
        //  Put back cursor at center of the screen
        device->getCursorControl()->setPosition(.5f, .5f);
 
        f32 dx = cursorPos.X - .5f;
        if (dx != 0.f)
            turn(dx * RADTODEG);
 
        f32 dy = cursorPos.Y - .5f;
        if (dy != 0.f)
            pitch(-dy * RADTODEG);
 
        makeCockpit();
 
        (...)
}
 
Thanks in advance for any help...
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Camera: no gimbal lock but...

Post by mongoose7 »

A yaw followed by a pitch will produce a roll. In order not to roll, the pitch would have to be performed in the frame of reference of the object (which has changed). Perhaps perform the pitch *before* the yaw.
azerty69
Posts: 11
Joined: Tue Jun 11, 2013 1:33 pm

Re: Camera: no gimbal lock but...

Post by azerty69 »

@mongoose7: thanks for the correction. Unhopefully, it didn't solved the problem.

I've read somewhere that it is preferable to use a separate node for each rotation. In this case, how can I combine them
to obtain the final up and forward vectors?
Suvi
Competition winner
Posts: 45
Joined: Mon Oct 01, 2007 11:24 am
Location: Finland
Contact:

Re: Camera: no gimbal lock but...

Post by Suvi »

azerty69 wrote:I've read somewhere that it is preferable to use a separate node for each rotation. In this case, how can I combine them
to obtain the final up and forward vectors?
I posted something similar using 3 nodes to get the rotations here:
http://irrlicht.sourceforge.net/forum/v ... =4&t=48857
Just ignore the Oculus Rift parts of the code.
azerty69
Posts: 11
Joined: Tue Jun 11, 2013 1:33 pm

Re: Camera: no gimbal lock but...

Post by azerty69 »

@Suvi: thanks for your reply. I've better results now :)

The only problem with the following code is that when I make a half turn (up or down), left and right are inverted...

Code: Select all

 
        
    //  Rotate node relative to its current rotation.
    void rotate(ISceneNode *node, vector3df rot)
    {
        matrix4 m;
        m.setRotationDegrees(node->getRotation());
        matrix4 n;
        n.setRotationDegrees(rot);
        m *= n;
        node->setRotation(m.getRotationDegrees());
        node->updateAbsolutePosition();
    }
 
    void yaw(f32 rot)
    {
        rotate(headX, vector3df(0.0f, rot, 0.0f));
    }
 
    void pitch(f32 rot)
    {
        rotate(headY, vector3df(rot, 0.0f, 0.0f));
    }
 
    void updateCamera(f32 dtime)
    {
        //  Get rotation angles from relative mouse position
        position2d<f32> cursorPos = device->getCursorControl()->getRelativePosition();
        device->getCursorControl()->setPosition(.5f, .5f);      // put back cursor at center of the screen
 
        fYaw = (cursorPos.X - .5f);
        if (fYaw != 0.f)
            yaw(fYaw * fMouseSensitivity);
 
        fPitch = (cursorPos.Y - .5f);
        if (fPitch != 0.f)
            pitch(fPitch * fMouseSensitivity);
 
        matrix4 m;
        m.setRotationDegrees(headY->getAbsoluteTransformation().getRotationDegrees());
 
        vector3df frv = vector3df(0, 0, 1);
        vector3df upv = vector3df(0, 1, 0);
 
        m.transformVect(frv);
        m.transformVect(upv);
 
        camera->setTarget(frv);
        camera->setUpVector(upv);
        camera->updateAbsolutePosition();
    }
 
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Camera: no gimbal lock but...

Post by Mel »

In fact, rotations can be tricky because they can't be commutative, as they alter the orientation of an object, and hence, the order of the rotations can't be ignored. Normally, to make sure the rotations work well, there is a fixed order in which they are performed always, so choose a rotation order, and stick to it.

Also, the rotation of an object in Irrlicht ca be aditive, so you just have to add or substract a rotation to an object's rotation, and Irrlicht will calculate the matrix properly on its own.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply