1

I have a game where there is a 2D compass from 0-360 degrees that tells you the angle the camera is facing regardless of height.

I am trying to figure out how to get that angle using the model-view matrix. My algorithm works but not 100% of the time.

I have the following code for grabbing the angles from the model-view matrix.

Vector3D<float> GetEulerAngles(float ModelView[16])
{
    float X = atan2(ModelView[9], ModelView[10])  * (180 / PI);
    float Y = atan2(-ModelView[8], sqrt(pow(ModelView[0], 2) + pow(ModelView[4], 2)))  * (180 / PI);
    float Z = atan2(ModelView[4], ModelView[0]) * (180 / PI);
    return {X < 0 ? 360 - X : X, Y < 0 ? 360 - Y : Y, Z < 0 ? 360 - Z : Z};
}


/*
    Works so long as the camera is at its highest point (looking down on the player - 66deg angle)
    -------
    OR any height and: 90 < CompassAngle < 360  is true.
*/
int GetCompassAngle()
{
    glGetFloatv(GL_MODELVIEW_MATRIX, &ModelView[0]);
    Vector3D<float> angles = GetEulerAngles(ModelView);
    return round(to_degrees(Z));
}



/*
    Works so long as the camera is at any height (and: 0 < CompassAngle < 90)
*/
int GetCompassAngle()
{
    glGetFloatv(GL_MODELVIEW_MATRIX, &ModelView[0]);
    Vector3D<float> angles = GetEulerAngles(ModelView);
    return round(360 - to_degrees(Y));
}

When I lower the camera, the second GetCompassAngle works. It reads the "Y" from the euler angles. However, if the camera is at the highest point, it reads the "Z" from the euler angles.

These work but when rotating and changing the camera angle changes the value and sometimes it gives me the wrong compass angle.

How can I combine them in some way or get the compass angle regardless of camera height?

Here are some numbers if it helps my case:

CompassHeight (Max - 65 deg from floor):
CompassDeg (X, Y, Z):

0deg:        65.0537253622628   358.814165052872   1.07537657735905
90deg:       88.1642315504792   312.258382165551   85.6596194029266
180deg:      115.286564608444   358.615368311296   178.747763300624
270deg:      90.1881102037367   47.9243745800853   269.562655218025


//Notice the "Z" values are the right compass angle or close enough.



CompassHeight (Low - 13 deg from floor):
CompassDeg (X, Y, Z):

0deg:        13.7624148875505   1.69169652884413   359.597596807979
90deg:       77.9527238194348   283.654247204305   77.5930785465022
180deg:      166.486754945655   355.694293448629   178.99462624173
270deg:      87.8507577921787   77.1021010565408   272.207848194156
Brandon
  • 22,723
  • 11
  • 93
  • 186
  • I assume it's a transcription error that your function is called `GetEulerAngles`, but the function call is to `GetEulerAngle`? – user1118321 Dec 15 '14 at 16:04
  • 2
    Euler angles are subject to gimbal lock issues. Also, if your camera is looking straight up or down (Y axis), you won't be able to obtain an angle for the XZ plane (in world coordinates that is). – didierc Dec 15 '14 at 16:07
  • 1
    Ah yes. I fixed the type. It's not 100% straight up. It's at a 66 degree angle at the highest and 14 at the lowest. – Brandon Dec 15 '14 at 16:10
  • Normally, the camera X, Y and Z vectors should be given by the modelview matrix columns 0, 1 and 2 respectively (iirc). Extract the X and Z vectors, project them on the XZ plane (ie keep only the X and Z components) *after* having normalised them, take their opposite (ie negate them), then you should finally have the vectors you need to draw your compass, without having to compute the angles. – didierc Dec 15 '14 at 20:44
  • 1
    See http://stackoverflow.com/questions/15022630/how-to-calculate-the-angle-from-roational-matrix: I believe your ***`Y`*** angle calculation is incorrect. Though, as @didierc mentions, you can find the vector in the camera z direction more simply, if that's all you're after. – beaker Dec 15 '14 at 22:46

0 Answers0