Kapichu
Kapichu

Reputation: 3706

Compute angles of direction

I followed a tutorial to be able to rotate the view in my OpenGL game with the mouse. I have to admit that I copy-and-pasted without really understanding and that's what I got...

The direction of the camera is computed by the yaw and the pitch:

directionX = cos(verticalAngle) * sin(horizontalAngle);
directionY = sin(verticalAngle);
directionZ = cos(verticalAngle) * cos(horizontalAngle);

Now I want to reverse the computation and get the angles out of the direction. I know how to compute the vertical angle:

verticalAngle = asin(directionY);

But I have no idea how to get the horizontal angle... I tried to rearrange the equation of the x component, but, as expected, it did not work (cause that would mean you don't need the z component to calculate the horizontal angle, which does not make sense).

Can someone show me the equation (maybe explain how to rearrange the equations / how it generally works)? I have no idea what I have to search for on Google/SA

It still does not work, the vertical angle is switching between two values every frame, and I can't turn 360° with the horizontal angle. Here is my code:

double elapsed;
frameTime = glfwGetTime();
elapsed = frameTime - lastFrameTime;

int winw, winh;
glfwGetWindowSize(window, &winw, &winh);

double mouseX, mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
glfwSetCursorPos(window, winw/2, winh/2);

// compute angles
float preAsinf = camDir[0] / cosf(camAngles[1]);
if (preAsinf < -1) preAsinf = -1;
if (preAsinf > 1) preAsinf = 1;
camAngles[0] = asinf(preAsinf);
camAngles[1] = atan2f(camDir[0], camDir[2]) * cos(camAngles[1]);
printf("%g\n", camAngles[0]);

// compute view
double dmx = (mouseX - winw/2);
double dmy = (mouseY - winh/2);
camAngles[0]+= elapsed * dmx;
camAngles[1]+= elapsed * dmy;

camDir[0] = cosf(camAngles[1]) * sinf(camAngles[0]);
camDir[1] = sinf(camAngles[1]);
camDir[2] = cosf(camAngles[1]) * cosf(camAngles[0]);
kmVec3Normalize((kmVec3 *) camDir, (kmVec3 *) camDir);

// horiAngle - 3.14 / 2 means horiAngle - 90°, which is the right
camRight[0] = sin(camAngles[0] - 3.14f/2.0f);
camRight[1] = 0;
camRight[2] = cos(camAngles[0] - 3.14f/2.0f);
kmVec3Normalize((kmVec3 *) camRight, (kmVec3 *) camRight);

kmVec3Cross((kmVec3 *) camUp, (kmVec3 *) camRight, (kmVec3 *) camDir);
kmVec3Normalize((kmVec3 *) camUp, (kmVec3 *) camUp);

float camCenter[3];
kmVec3Add((kmVec3 *) camCenter, (kmVec3 *) camPos, (kmVec3 *) camDir);
kmMat4LookAt((kmMat4 *) view, (kmVec3 *) camPos, (kmVec3 *) camCenter, (kmVec3 *) camUp);

// compute end matrix
kmMat4Multiply((kmMat4 *) tmp, (kmMat4 *) projection, (kmMat4 *) view);
kmMat4Multiply((kmMat4 *) tmp, (kmMat4 *) tmp, (kmMat4 *) model);
glUniformMatrix4fv(shaderUniforms.transform, 1, GL_FALSE, tmp);

The vectors are just arrays, [0] ^= x component, [1] ^= y component.

Upvotes: 0

Views: 640

Answers (2)

Kevin
Kevin

Reputation: 76194

directionX == cos(verticalAngle) * sin(horizontalAngle)

Divide by cos(verticalAngle).

directionX / cos(verticalAngle) == sin(horizontalAngle)

Take the asin of both sides.

asin(directionX / cos(verticalAngle) == horizontalAngle

Flip the equation around, and there's the result.

horizontalAngle = asin(directionX / cos(verticalAngle))

You don't need to use Z to recover horizontalAngle, because the Z component doesn't have any information that you can't recover from X and Y alone. This is because the camera direction vector is a unit vector, so Z = sqrt(1 - X^2 - Y^2).

Upvotes: 0

user1196549
user1196549

Reputation:

Use

horizontalAngle = atan2(directionX, directionZ);

this will return an angle between -Pi and + Pi. (The factor cos(verticalAngle) cancels out.)

Upvotes: 1

Related Questions