# LookAt() functionality for FPS (Euler Angle) Camera

This topic is 3154 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

[I had posted this in the Game Programming forum, but thought it might be better here] I have a FPS style camera that accumulates Euler angles, and works well. But now I want to implement a lookAt( Vector ) method which will take in a vector, and then calculate an absolute rotation in Euler Angles to aim the camera at that point in space. This is what I have so far:
    void lookAt( float x1, float y1, float z1 )
{
VectorR3 v( x1, y1, z1 );
v.x = m_position.x - v.x;
v.y = m_position.y - v.y;
v.z = m_position.z - v.z;

float r = v.length();
float yaw = acos( v.z / r );
float pitch = atan2( v.y, v.x );

setRotation( yaw, pitch, 0.0f, true ); // This just wraps the values to ensure they stay within range
}


Bbuutt... things aren't working. This is Cartesian Coordinate to Spherical coordinate conversion, or at least it's suppose to be. Does anything jump out as majorly wrong here?

##### Share on other sites
I'd think you'd want target - position, rather than position - target. Also, it looks like you might have yaw and pitch backwards. That is, it should be:
float pitch = acos( v.z / r );float yaw = atan2( v.y, v.x );
Also, since acos() can fail if the input falls outside of the range [-1, 1] (e.g. due to numerical error), an (IMO) better way to compute the pitch is:
float length = sqrt(v.x*v.x+v.y*v.y);float pitch = atan2(v.z, length);

##### Share on other sites
Ok so let me see if I get this right:
    void lookAt( float x1, float y1, float z1 )    {        VectorR3 v( x1, y1, z1 );        v -= m_position;        float r = sqrt( v.x*v.x + v.y*v.y ); // I'm not suppose to take Z into account?        float yaw = atan2( v.y, v.x );        float pitch = atan2( v.z, r );        setRotation( yaw, pitch, 0.0f, true );    }

I'm not getting proper rotations with this.

##### Share on other sites
Quote:
 Original post by WavesonicsOk so let me see if I get this right:*** Source Snippet Removed ***I'm not getting proper rotations with this.
Take another look at my example code (you're computing 'r' differently than what was shown).

But yeah, you don't need to include z there. Think about it this way. Take the vector to the target (v) and project it orthogonally onto the ground plane (call the projected vector v'). v and v' taken together form a right triangle. The length of one of the legs is |v'|, and the length of the other leg is v.z. The lengths of these edges are proportional to the cosine and sine (respectively) of the opposite angle, which means you can submit them directly to atan2(), as shown, to get the angle.

Ok, that wasn't a very good explanation, but maybe it'll be enough to give you the general idea...

##### Share on other sites
I had miss-typed and left out the sqrt() but fixed it, is that what you are referring to? Even with the sqrt() i'm still getting incorrect results though.

If there is something else amiss, i don't see it.

##### Share on other sites
Can you post your setRotation() function?

##### Share on other sites
    inline float zeroClamp( float x )    {        return ( std::fabs(x) > std::numeric_limits<float>::epsilon() ? x : 0.0f );    }    inline float wrap( float a )    {        while( a >= RAD360 || a < 0.0f )        {            if(a >= RAD360 )                a -= RAD360;            else if( a < 0.0f )                a += RAD360;        }        return a;    }    void setRotation( float yaw, float pitch, float roll, bool isInRadians = false ) {        m_yaw = 0.0f;        m_pitch = 0.0f;        m_roll = 0.0f;        rotate( yaw, pitch, roll, isInRadians );    }    void rotate( float yaw, float pitch, float roll, bool isInRadians = false ) {        yaw = zeroClamp( yaw );        pitch = zeroClamp( pitch );        roll = zeroClamp( roll );        if( !isInRadians )        {            yaw = Rotation3D::deg2rad( yaw );            pitch = Rotation3D::deg2rad( pitch );            roll = Rotation3D::deg2rad( roll );        }        m_yaw += yaw;        m_yaw = wrap( m_yaw ); // Keep the angle between 0 and 360        m_pitch += pitch;        m_pitch = wrap( m_pitch );        m_roll += roll;        m_roll = wrap( m_roll );    }

[Edited by - Wavesonics on February 26, 2010 2:51:07 PM]

##### Share on other sites
Hi Wavesonics,

I tried the following code and it works; It's pretty much what jyk was suggesting, however I still post it. However here I explicitly assume a right-hand setting in which plane XZ is the ground and y-axis is the UP direction, which I think would be the case in a typical OpenGL setting.

The program outputs:

Pitch = -35
Yaw = 135

Which makes sense for the input.

Bye!

#include <stdio.h>#include <math.h>int main(int argc, char *argv[]){        float x1 = -1;        float y1 = -1;        float z1 = 3;        float position_x = 1;        float position_y = 1;        float position_z = 1;        float v_x = x1 - position_x;        float v_y = y1 - position_y;        float v_z = z1 - position_z;        float length = sqrt(v_x * v_x + v_z * v_z);        float pitch = atan2(v_y, length);        float yaw = atan2(v_z, v_x);        printf("Pitch = %d\n", (int)(180 * (pitch / 3.1415)));        printf("Yaw   = %d\n", (int)(180 * (yaw / 3.1415)));        return 0;}

##### Share on other sites
I don't see anything wrong with your code, after triple checking things. Are you sure the problem does not lie outside of this function?

For instance, you are using the yaw and pitch to rotate a vector (1, 0, 0) by first applying the pitch (rotation around Y), then the yaw (rotation around Z)? This vector should of course be added to your viewpoint to get your target point back.

And you are certain your Z axis is your up axis? If this would be Y, then you need to swap some coordinates and possibly place a - sign somewhere.

##### Share on other sites
Ah no my Z axis is not up, it's standard OpenGL coordinate system so -Z should be forward if I'm not mistaken, and +y is up.

Also how I'm applying the rotation is by generating a quaternion from the Euler Angles, then extracting a matrix from that (Just for convince at the moment).

1. 1
2. 2
3. 3
Rutin
18
4. 4
5. 5

• 13
• 14
• 9
• 9
• 9
• ### Forum Statistics

• Total Topics
632926
• Total Posts
3009239
• ### Who's Online (See full list)

There are no registered users currently online

×