Я хочу определить горизонтальный и вертикальный угол от положения камеры до мировой точки относительно передней оси камеры. Я боролся в течение довольно долгого времени.
Моя линейная алгебра немного заржавела, но, учитывая направление вперед, вверх и вправо камеры, например:
camForward = [0 0 1];
camUp = [0 1 0];
camRight = [1 0 0];
И камера положение и мировая точка, например:
camPosition = [1 2 3];
worldPoint = [5 6 4];
Требуемые углы должны быть определены, сначала беря разницу в положениях:
delta = worldPoint-camPosition;
Затем проецируя ее на оси камеры используя точечные произведения:
deltaHorizontal = dot(delta,camRight);
deltaVertical = dot(delta,camUp);
deltaDepth = dot(delta,camForward);
И, наконец, вычисляем углы как:
angleHorizontal = atan(deltaHorizontal/deltaDepth);
angleVertical = atan(deltaVertical/deltaDepth);
В этом примере это дает, что оба угла становятся ~ 76 °, что кажется разумным; изменение положения и осей также, по-видимому, дает приемлемые результаты.
Таким образом, если я не получаю ожидаемые углы, это должно быть связано с тем, что я использую либо неправильное положение, и / или оси камеры. Стоит отметить, что 3D-движок использует OpenGL и GLM.
Я совершенно уверен, что положения правильные, поскольку перемещение по сцене и проверка позиций относительно известных опорных точек дают согласованные и правильные Результаты. Приводит меня к мысли, что я использую неправильные оси камеры. Чтобы получить углы, которые я использую (эквивалент):
glm::vec3 worldPoint = glm::unProject( glm::vec3(windowX, windowY, windowZ), viewMatrix, projectionMatrix, glm::vec4(0,0,windowWidth,windowHeight));
glm::vec3 delta = glm::vec3(worldPoint.x, worldPoint.y, worldPoint.z);
float horizontalDistance = glm::dot(delta, cameraData->right);
float verticalDistance = glm::dot(delta, cameraData->up);
float depthDistance = glm::dot(delta, cameraData->forward);
float horizontalAngle = glm::atan(horizontalDistance/depthDistance)
float verticalAngle = glm::atan(verticalDistance/depthDistance)
Каждый кадр forward
, up
и right
считывается из матрицы вида, viewMatrix
, которая, в свою очередь, производится путем преобразования кватерниона Q
, который удерживает вращение камеры, управляемое мышью:
void updateView(CameraData * cameraData, MouseData * mouseData, MouseParameters * mouseParameters){
float deltaX = mouseData->currentX - mouseData->lastX;
float deltaY = mouseData->currentY - mouseData->lastY;
mouseData->lastX = mouseData->currentX;
mouseData->lastY = mouseData->currentY;
float pitch = mouseParameters->sensitivityY * deltaY;
float yaw = mouseParameters->sensitivityX * deltaX;
glm::quat pitch_Q = glm::quat(glm::vec3(pitch, 0.0f, 0.0f));
glm::quat yaw_Q = glm::quat(glm::vec3(0.0f, yaw, 0.0f));
cameraData->Q = pitch_Q * cameraData->Q * yaw_Q;
cameraData->Q = glm::normalize(cameraData->Q);
glm::mat4 rotation = glm::toMat4(cameraData->Q);
glm::mat4 translation = glm::mat4(1.0f);
translation = glm::translate(translation, -(cameraData->position));
cameraData->viewMatrix = rotation * translation;
cameraData->forward = (cameraData->viewMatrix)[2];
cameraData->up = (cameraData->viewMatrix)[1];
cameraData->right = (cameraData->viewMatrix)[0];
}
Однако что-то идет не так, и правильные углы, по-видимому, создаются только при взгляде вдоль, или перпендикулярно мировой оси z ([0 0 1]). Где я ошибаюсь? Любая помощь будет наиболее ценится!
Спасибо