cut scenes, gimbal lock even using quaternions

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
arnir
Competition winner
Posts: 154
Joined: Sat Jan 20, 2007 4:36 pm
Location: Czech Republic

cut scenes, gimbal lock even using quaternions

Post by arnir »

Hi, I want to make simple cut scenes using keyframes made of position and target of camera and interpolate between them.

here is the snapshot (keyframe) structure

Code: Select all

struct SRecordedFrame
{
    vector3df position;
    vector3df target;
    unsigned int transition_time;
};
transition time is time that it takes to smoothly move to the next snapshot.
snapshots are saved in std::vector container

here is my take snapshot method

Code: Select all

void CGameModeRail::takeSnapshot()
{
    SRecordedFrame frame;
    frame.position = m_pGame->getPlayerCamera()->getAbsolutePosition();
    frame.target = m_pGame->getPlayerCamera()->getTarget();
    frame.transition_time = 1000;
 
    m_RecordedFrames.push_back(frame);
}
currently with constant transition time.

and finally, here is the animate method

Code: Select all

void CGameModeRail::animatePlayerMovement(int delta)
{
    if (m_RecordedFrames.size() < 2)
    {
        return;
    }
 
    if (!m_bPlaybacking)
    {
        return;
    }
 
    //get two frames we will be interpolating between
    SRecordedFrame &a = m_RecordedFrames[m_nStage];
    SRecordedFrame &b = m_RecordedFrames[m_nStage + 1];
    int transition_time = a.transition_time;
 
    //advance time
    m_nActionTime += delta;
 
    //calculate transition ratio
    float transition_ratio;
 
    //finished?
    if (m_nActionTime > transition_time)
    {
        //goto next move
        m_nActionTime = 0;
        ++m_nStage;
        transition_ratio = 1.0f;
 
        //or stop playing when done
        if (m_nStage + 1 == m_RecordedFrames.size())
        {
            m_bPlaybacking = false;
        }
    }
    //not yet finished
    else
    {
        transition_ratio = (float)m_nActionTime / transition_time;
    }
 
 
    //update position
    vector3df new_position = a.position.getInterpolated(b.position, transition_ratio);
    m_pGame->getPlayerCamera()->setPosition(new_position);
 
 
    //update rotation
    vector3df a_rotation = a.target - a.position;
    vector3df b_rotation = b.target - b.position;
 
    quaternion a_q(a_rotation);
    quaternion b_q(b_rotation);
 
    quaternion new_q;
    new_q.slerp(a_q, b_q, transition_ratio);
 
    vector3df new_rotation;
    new_q.toEuler(new_rotation);
 
    m_pGame->getPlayerCamera()->setTarget(new_position + new_rotation);
}
delta is time elapsed since last rendered frame
and because rotation of camera is always zero vector, I am using: setTarget(pos + rot)

and now, even that I am using quaternions, when I take one snapshot looking forward, and another snapshot looking backward (about 180 degrees)
when I then play the animation, the transition between frames is not straight, but its like some wave, because exactly between the frames
the camera is looking down, which I think is due gimbal lock.

Gimbal lock was present when I was using euler rotation interpolation, but why the problem stays, when I am now using quaternions?
programmer is bad designer
designer is bad programmer
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: cut scenes, gimbal lock even using quaternions

Post by hendu »

Sounds like it has to do with the camera's up vector. Do you really want the transition to go through the down direction? Having it go either left or right would solve the up-vector issue and usually look nicer.
arnir
Competition winner
Posts: 154
Joined: Sat Jan 20, 2007 4:36 pm
Location: Czech Republic

Re: cut scenes, gimbal lock even using quaternions

Post by arnir »

oh I see, I was thinking that: cameraTarget - cameraPos = cameraRotation, but thats absolutely not truth. it is the direction of where the camera is looking
so change of question :-D how to actually get camera rotation? so when I will be looking from left to right, the Y coordinate will be changing (and up/down the x coord)?
programmer is bad designer
designer is bad programmer
arnir
Competition winner
Posts: 154
Joined: Sat Jan 20, 2007 4:36 pm
Location: Czech Republic

Re: cut scenes, gimbal lock even using quaternions

Post by arnir »

ok I think this is correct:

Code: Select all

cameraDir = cameraTarget - cameraPos;
cameraRot = cameraDir.getHorizontalAngles();
so now when I got the correct camera rotation when I take the snapshot, I can interpolate between these rotations using quaternions.

so for given time T, I will get new rotation. but how can I now use rotation to setup correct camera target?
programmer is bad designer
designer is bad programmer
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: cut scenes, gimbal lock even using quaternions

Post by hendu »

The camera has getRotation setRotation calls ;)

Just remember to bind rotation and target when initializing your camera.
Post Reply