C ++ OpenGl使用四元数问题的相机旋转
我在执行四元数相机时遇到问题。 我在OpenGL中创建了一个3D空间射击游戏,我需要避免使用万向节锁。 如果我只在一个轴上旋转就很好,但是一旦我应用了俯仰和偏航,他们就会有一种奇怪的行为。 我的旋转角度是使用我的鼠标的输入。
在这里,我计算我的ViewMatrix及其更新的每一帧
Matrix4x4 camera::GetViewMat()
{
m_rotation.AddX((oInput.MousePosition.GetY() - oInput.PrevMousePosition.GetY()) * m_sensitivity * dt);
m_rotation.AddY((oInput.MousePosition.GetX() - oInput.PrevMousePosition.GetX()) * -m_sensitivity * dt);
Matrix4x4 oTranslateOrigin, oRotate, oView;
oView.SetIdentity();
//constructor creates a quaternion from an AxisAngle, the constructor will be shown below
Quaternions pitch = Quaternions(m_rotation.GetX() * Utility::DegToRad(), Vector3(1, 0, 0));
Quaternions yaw = Quaternions(m_rotation.GetY() * Utility::DegToRad(), Vector3(0, 1, 0));
//update orientation with the new quaternion times its current orientation
ori = ori * yaw * pitch;
//convert quaternion to matrix, also shown below
oRotate = ori.ToMatrix();
oTranslateOrigin.BuildTranslate(-m_camPosition.GetX(), -m_camPosition.GetY(), -m_camPosition.GetZ());
oView = oRotate * oTranslateOrigin;
return oView;
}
初始化ProjectionMatrix
Matrix4x4 camera::GetProjMat(float fFieldOfViewY, float fAspectRatio, float fNearZ, float fFarZ)
{
// Transposed version of D3DXMatrixPerspectiveFovRH
float fYScale = 1 / tanf( fFieldOfViewY / 2.0f );
float fXScale = fYScale / fAspectRatio;
memset( &m_projMat, 0, sizeof( Matrix4x4 ) );
m_projMat.Set(0, 0, fXScale);
m_projMat.Set(1, 1, fYScale);
m_projMat.Set(2, 2, fFarZ / ( fNearZ - fFarZ ));
m_projMat.Set(2, 3, ( fNearZ * fFarZ ) / ( fNearZ - fFarZ ));
m_projMat.Set(3, 2, -1.0f);
return m_projMat;
}
这是创建AxisAngle四元数的构造函数之一
Quaternions::Quaternions(float angle, Vector3& axis)
{
FromAxisAngle(angle, axis);
}
void Quaternions::FromAxisAngle(float angle, Vector3& axis)
{
float halfAngle = angle * ((float)PI/360.0f);
float sin = sinf(halfAngle);
this->w = cosf(halfAngle);
this->x = axis.GetX() * sin;
this->y = axis.GetY() * sin;
this->z = axis.GetZ() * sin;
}
Matrix4x4 Quaternions::ToMatrix()
{
Normalize();
Matrix4x4 mat;
mat.SetIdentity();
mat.Set(0, 0, 1.0f - 2*(this->y * this->y) - 2*(this->z * this->z));
mat.Set(0, 1, 2*(this->x*this->y) - 2*(this->w*this->z));
mat.Set(0, 2, 2*(this->x * this->z) + 2*(this->w * this->y));
mat.Set(1, 0, 2*(this->x * this->y) + 2*(this->w * this->z));
mat.Set(1, 1, 1.0f - 2*(this->x * this->x) - 2*(this->z * this->z));
mat.Set(1, 2, 2*(this->y * this->z) - 2*(this->w * this->x));
mat.Set(2, 0, 2*(this->x * this->z) - 2*(this->w * this->y));
mat.Set(2, 1, 2*(this->y * this->z) + 2*(this->w * this->x));
mat.Set(2, 2, 1.0f - 2*(this->x * this->x) - 2*(this->y * this->y));
return mat;
}
这就是我正在做的事情。
你们能带领我走向正确的方向吗?
是因为这一行:
ori = ori * yaw * pitch;
错误的顺序是?
您始终可以使用openGL函数旋转相机矩阵。 只要确保你在栈上有相机矩阵。
glRotate(angle, 1, 0, 0);
glRotate(angle, 0, 1, 0);
你可以用这个函数来看一个点:
void gluLookAt( GLdouble eyeX , GLdouble eyeY , GLdouble eyeZ ,
GLdouble centerX , GLdouble centerY , GLdouble centerZ ,
GLdouble upX , GLdouble upY , GLdouble upZ );
在哪里需要眼睛的位置,目标(中心)位置以及相机的向上向量。
好的,这是你想要做的,以避免与四元数的灵活锁定。 此外,还包括一些Opengl特定代码,希望能够让您朝着正确的方向前进。 首先确定第一件事,我将把键映射到旋转。
W - Pitch up(x rot)
S - Pitch down(x rot)
A - Yaw left(y rot)
D - Yaw Right(y rot)
Q - Roll left(z rot)
E - Roll right(z rot)
所有你想要的是当这些被按下时调用正确的旋转。 因此,例如用户按下W,我们需要做的就是创建一个四元数,以1degrees围绕x旋转。 使用你的四元数类来做到这一点:
a = EulerToQuat(angle,0,0);
cameraOri = cameraOri * a;
显然对其他控件也是这样做的! 好的最后一步你需要做的是在Opengl中使用旋转命令来正确旋转世界。 我们做这个很好而且容易阅读的方法是将四元数转换成一个角度和轴(希望你的四元数类可以做到这一点!)然后继续用这个做一个glRotate!
m_frustumCamera->getQuat().GetAxisAngle(axis,angle);
angle = (float)(angle * radToDeg);
glRotatef(angle,axis.x,axis.y,axis.z);
glTranslatef(-1*m_frustumCamera->getPos().x,-1*m_frustumCamera->getPos().y,-1*m_frustumCamera->getPos().z);
如果你没有工作四元类,我建议:http://www.wolframalpha.com/,以确保所有的功能给予正确的回应!
链接地址: http://www.djcxy.com/p/81757.html