我正在为我的游戏引擎创建一个 3D 相机,我想用一个四元数来表示相机的方向。通过将此四元数转换为旋转矩阵来生成局部上、前和侧摄像机轴。该矩阵的第一行给出了相机的 X 轴(侧向量),第二行给出了 UP 向量,第三行给出了 FRONT 向量。为了移动相机,我的函数需要移动方向,更新数量和位置,并更新视图矩阵()。要旋转相机,我的函数获取要旋转的轴和角度。从这个轴和角度创建一个临时四元数,并应用于我相机的当前方向。我围绕世界 Y 轴旋转以进行偏航,并围绕相机的侧向量进行俯仰。这个投球没有 当我的相机轴未与世界轴对齐时,无法正常工作。如果我改为围绕全局 X 轴进行推销,那么它可以正常工作,但我知道这不是我想要的。此外,当我的相机轴与世界轴不对齐时,运动也会出错。我正在使用基本的“wasd”运动。我的运动和俯仰函数使用局部轴,因此我有一种预感,我从四元数中提取局部轴的方式不正确,但我无法弄清楚出了什么问题。
相机类:
#include "stdafx.h"
Camera * Camera::m_currentCamera = NULL;
Camera::Camera(vec3 position , double distToNear , double distToFar , double fovy)
{
m_position = position;
m_distToNear = distToNear;
m_distToFar = distToFar;
m_fovy = fovy;
// generate the view and projection matrices
updateViewMatrix();
projection = glm::perspective(m_fovy, 4.0/3.0, m_distToNear, m_distToFar);
// in radians
m_deltaAngle = 10.0 * PIOVER180;
if(m_currentCamera != NULL)
{
delete m_currentCamera;
}
m_currentCamera = this;
}
Camera::Camera()
{
}
Camera::~Camera()
{
// empty for now
}
Camera* Camera::getCurrentCamera()
{
return m_currentCamera;
}
/** set and get camera position */
vec3 Camera::getPosition()
{
return m_position;
}
void Camera::setPosition(vec3 pos)
{
m_position = pos;
}
/** set and get near plane distance */
double Camera::getNearPlaneDist()
{
return m_distToNear;
}
void Camera::setNearPlaneDist(double dist)
{
m_distToNear = dist;
}
/** set and get far plane distance */
double Camera::getFarPlaneDist()
{
return m_distToFar;
}
void Camera::setFarPlaneDist(double dist)
{
m_distToFar = dist;
}
/** set and get camera field of view */
double Camera::getFovy()
{
return m_fovy;
}
void Camera::setFovy(double angle)
{
m_fovy = angle;
}
mat4 Camera::getViewMatrix()
{
return view;
}
mat4 Camera::getProjectionMatrix()
{
return projection;
}
Quaternion Camera::getOrientation()
{
return m_rotation;
}
void Camera::setOrientation(Quaternion *q)
{
m_rotation.setQuaternion(q);
}
/** this function will be called whenever the camera's position, up vector or lookat vector changes */
void Camera::updateViewMatrix()
{
mat4 orientation = m_rotation.toMatrix();
mat4 translation = translate(mat4(1.0f),vec3(-m_position.x,-m_position.y,-m_position.z));
view = orientation * translation;
}
/** Control Functions */
void Camera::rollCamera(float theta)
{
Quaternion tempRotation;
tempRotation.quaternionFromAxis(getFront(), theta);
tempRotation.normalise();
m_rotation = m_rotation * &tempRotation;
m_rotation.normalise();
updateViewMatrix();
}
void Camera::pitchCamera(float theta)
{
Quaternion tempRotation;
// INSTEAD OF LOCAL AXIS IF (1.0,0.0,0.0) GLOBAL X AXIS IS USED THIS WORKS FINE!!!
tempRotation.quaternionFromAxis(getSide(), theta);
tempRotation.normalise();
m_rotation = m_rotation * &tempRotation;
m_rotation.normalise();
updateViewMatrix();
}
void Camera::yawCamera(float theta)
{
Quaternion tempRotation;
tempRotation.quaternionFromAxis(vec3(0.0,1.0,0.0), theta);
tempRotation.normalise();
m_rotation = m_rotation * &tempRotation;
m_rotation.normalise();
updateViewMatrix();
}
void Camera::moveCamera(vec3 dir, float amt)
{
normalize(dir);
m_position += dir * amt;
updateViewMatrix();
}
vec3 Camera::getFront()
{
m_rotation.normalise();
mat4 orientation = m_rotation.toMatrix();
vec3 front(orientation[2][0], orientation[2][1], orientation[2][2]);
normalize(front);
cout << "FRONT " << front.x << " " << front.y << " " << front.z << endl;
return front;
}
vec3 Camera::getSide()
{
m_rotation.normalise();
mat4 orientation = m_rotation.toMatrix();
vec3 side(orientation[0][0], orientation[0][1], orientation[0][2]);
normalize(side);
cout << "SIDE " << side.x << " " << side.y << " " << side.z << endl;
return side;
}
vec3 Camera::getUp()
{
m_rotation.normalise();
mat4 orientation = m_rotation.toMatrix();
vec3 up(orientation[1][0], orientation[1][1], orientation[1][2]);
normalize(up);
cout << "UP " << up.x << " " << up.y << " " << up.z << endl;
return up;
}
移动和旋转相机的功能:
void specialKeyboard(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
Camera::getCurrentCamera()->yawCamera(1.0 * PIOVER180);
break;
case GLUT_KEY_RIGHT:
Camera::getCurrentCamera()->yawCamera(-1.0 * PIOVER180);
break;
case GLUT_KEY_UP:
Camera::getCurrentCamera()->pitchCamera(1.0 * PIOVER180);
break;
case GLUT_KEY_DOWN:
Camera::getCurrentCamera()->pitchCamera(-1.0 * PIOVER180);
break;
}
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'w':
Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getFront(), -0.1f);
break;
case 's':
Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getFront(), 0.1f);
break;
case 'a':
Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getSide(), -0.1f);
break;
case 'd':
Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getSide(), 0.1f);
break;
}
glutPostRedisplay();
}
这是我关于堆栈溢出的第一篇文章,所以如果需要更多信息,请告诉我。如果您在我的代码和方法中发现任何错误,请提供帮助。谢谢!