Camera controll yaw-pich-bank.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Hiroo
Posts: 10
Joined: Sun Dec 28, 2014 6:59 am

Camera controll yaw-pich-bank.

Post by Hiroo »

I just started playing with Irrlicht a couple days ago. I took the "terrain" example and I am trying to manipulate the camera such that I can look around the terrain, look up and down, and tilt my head. First thing I did was to replace the FPS camera with SceneMode camera.

Then, I found a function

Code: Select all

camera->setRotation()
which I thought would do exactly what I wanted, except, it only allowed me to "pan around" horizontally and not up and down, or roll sideways.

Further poking around in the forum showed that I can manipulate the "UpVector" to tilt the camera. Now, I got the following code with the commented out function below

Code: Select all

 
//      TiltRotation.fromAngleAxis(core::DEGTORAD * (rz / 500), Forwards);  // this code will bank the camera all the way around.
 
This allows me to roll all the way around. Thinking that replacing the Forward vector with the UpVector will give me a turn around a point like in "setRotation" except it will not move the camera at all.

The net effect is that I can do one of the three things but not all three at the same time.

It seems that this question has been asked a few times in the past except I do not see a clear answer to it. Could I get a bit of assistance here?

Hiroo

Code: Select all

 
    int lastFPS = -1;
    core::vector3df cam_up(0, 1, 0);
    core::vector3df cam_lookat(camera->getTarget());
 
    //We will use this to create make the up vector tilt
    irr::core::matrix4 TiltMatrix;
 
    //Get the Forwards vector, we will use this for our quat
    irr::core::vector3df Forwards = (camera->getTarget() - camera->getPosition()).normalize();
    //Create a quat, facing in the same direction as our camera
    //with a 45 degree rotation
 
 
    rx = 0; ry = 0; rz = 0;
 
    while(device->run())
    if (device->isWindowActive())
    {
        driver->beginScene(true, true, 0 );
        cam_up = core::vector3df(0, 1, 0);
 
        irr::core::quaternion TiltRotation;
//      TiltRotation.fromAngleAxis(core::DEGTORAD * (rz / 500), Forwards);  // this code will bank the camera all the way around.
        TiltRotation.fromAngleAxis(core::DEGTORAD * (rz / 500), cam_up.normalize());  // this code does nothing.
 
        //Now we need to get that rotation in Euler so we can use it
        irr::core::vector3df EulerRot;
        TiltRotation.toEuler(EulerRot);
        //Its stored in radians, convert to a degrees
        EulerRot = EulerRot * 57.2957795f;
        //Set our tilt matrix to that rotation
        TiltMatrix.setRotationDegrees(EulerRot);
 
        //The Upvector tilted
        TiltMatrix.transformVect(cam_up);
        //Set the upvector for the camera
        camera->setUpVector(cam_up);
 
        smgr->drawAll();
        env->drawAll();
 
        driver->endScene();
 
        // display frames per second in window title
        int fps = driver->getFPS();
        if (lastFPS != fps)
        {
            core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
            str += driver->getName();
            str += "] FPS:";
            str += fps;
            // Also print terrain height of current camera position
            // We can use camera position because terrain is located at coordinate origin
            str += " Height: ";
            str += terrain->getHeight(camera->getAbsolutePosition().X,
                    camera->getAbsolutePosition().Z);
 
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
        }
        ++rz;
        if (rz > 180000) rz = -180000;
    }
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: Camera controll yaw-pich-bank.

Post by robmar »

Yes its not very clear anywhere. If I remember right, you need to set the up vector for the camera based on current look direction and pitch (cross product does that), this is to calculate the actual orientation of the camera at the settings you need. The setrotation function does not handle the gimble lock condition occurring when setting the x y and z rotations separately, nor does it set the camera up vector, so you need to use quarternian math to achieve any rotation which you can find in the forum.
Hiroo
Posts: 10
Joined: Sun Dec 28, 2014 6:59 am

Re: Camera controll yaw-pich-bank.

Post by Hiroo »

Hmmm... Let me see if I understand the reply correctly. So what you are saying is that you control the direction the camera points at by moving the target and then roll the view using the quints math in the code above? That seems to match what I am observing since I am able to roll the camera but not shift the focus point.

The camera gets set up using this code.

Code: Select all

    // add camera
    scene::ICameraSceneNode* camera =
    smgr->addCameraSceneNode(); //changed to scene mode camera
 
    camera->setPosition(core::vector3df(2700*2,255*2,2600*2));
    camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
    camera->setFarValue(42000.0f);
    camera->bindTargetAndRotation(false);
 
So, I added this code...

Code: Select all

 
        irr::core::vector3df NewForwards = camera->getTarget().rotationToDirection(core::vector3df(rx, ry, rz));
        camera->setTarget(NewForwards);
 

Essentially, to take the existing target, then rotate it to the direction pointed by the rx, ry, rz, which the header says are in Euler degrees, then set that as the new forward direction, then use that to do the quints in the first post.

Well, this does not seem to have any effect at all since the camera still roll sideways but not look around as I would expect.
Hiroo
Posts: 10
Joined: Sun Dec 28, 2014 6:59 am

SOLVED: Camera controll yaw-pich-bank.

Post by Hiroo »

I figured it out. As it turns out, I was pretty close. Just a matter of reading the header more deeply and thinking through the rational of things.

One thing I needed to get through my thick skull was that "BindTargetAndRotation" on the camera meant the opposite of what I thought it meant. It meant that the target moves with the rotation of the camera. So I actually wanted it to be TRUE instead FALSE the way I had it. With it enabled, the call to setRotation actually moves the target around X and Y axis based on Euler angle specified. Once that is done, then use the quarternion math to compute the "up" vector based on the new "Forward" vector and presto! the camera yaws, pitches, and banks.

Here is the code.

Code: Select all

 
//  You only need to rotate around X (pitch)  and Y (yaw) axis ..
        camera->setRotation(core::vector3df(rx, ry, 0));  
 
        irr::core::quaternion TiltRotation;
 
 // Figure out where the new "Forward" is
       irr::core::vector3df Forwards = (camera->getTarget() - camera->getPosition()).normalize();  
 
//  Now, put in the Z rotation (bank)
        TiltRotation.fromAngleAxis(core::DEGTORAD * rz, Forwards);  
        
        //Now we need to get that rotation in Euler so we can use it
        irr::core::vector3df EulerRot;
        TiltRotation.toEuler(EulerRot);
        //Its stored in radians, convert to a degrees
        EulerRot = EulerRot * 57.2957795f;
        //Set our tilt matrix to that rotation
        TiltMatrix.setRotationDegrees(EulerRot);
 
        //The Upvector tilted
        TiltMatrix.transformVect(cam_up);
 
        //Set the upvector for the camera
        camera->setUpVector(cam_up);
 
 
Post Reply