Reputation: 3706
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
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
Reputation:
Use
horizontalAngle = atan2(directionX, directionZ);
this will return an angle between -Pi and + Pi. (The factor cos(verticalAngle)
cancels out.)
Upvotes: 1