Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;使用四元数问题的OpenGl相机旋转_C++_Opengl_Camera_Orientation_Quaternions - Fatal编程技术网

C++ C++;使用四元数问题的OpenGl相机旋转

C++ C++;使用四元数问题的OpenGl相机旋转,c++,opengl,camera,orientation,quaternions,C++,Opengl,Camera,Orientation,Quaternions,我在为我的相机实现四元数时遇到问题。我正在用OpenGL创建一个3D空间射击游戏,我需要避免万向节锁。如果我只在一个轴上旋转,这很好,但一旦我同时应用俯仰和偏航,它们就会有一种奇怪的行为。我的旋转角度使用鼠标的输入 在这里,我计算ViewMatrix,并在每一帧更新它 Matrix4x4 camera::GetViewMat() { m_rotation.AddX((oInput.MousePosition.GetY() - oInput.PrevMousePosition.GetY()

我在为我的相机实现四元数时遇到问题。我正在用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;
}
初始化投影矩阵

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;
   }
这是创建轴角四元数的构造函数之一

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,我们需要做的就是创建一个四元数,围绕x旋转1度。使用您的四元数类执行此操作:

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);
如果你没有一个有效的四元数类,我建议:
确保您的所有功能都能给出正确的响应

嗯,它看起来好多了,但还不能很好地工作。假设我使用Vector3(0,1,0)来旋转四分之一,使用Vector3(0,1,0)来旋转偏航,使用Vector3(1,0,0)来旋转俯仰右侧?是的,如果你想每次都绕同一个轴旋转,但实际上你可能想绕对象的
上轴
俯仰
。这取决于你的相机设计。我明白了,好吧。不管怎样,当我旋转时,它在特定的时间像正弦曲线一样旋转。我看过其他地方,他们也和我一样。我可能错过了一些我还没有注意到的小东西。你觉得很好,对吧?是的,乍一看很好。你知道你不必使用四元数。看我的编辑。你是什么意思?这是我第一次来这里,所以我有点困惑,抱歉。不管怎么说,我认为它看起来不错,可能只是我认为它错了。但无论如何,我还有一个问题。如何使用注视向量使相机注视它。我可以在一个规则的矩阵旋转中做,但我不知道如何在四元数上做。从“注视”到摄影机位置的向量如下所示:Vector3 viewZ=注视-摄影机位置;在那之后我该如何使用它?请不要认为使用四元数意味着你看不到万向节锁。万向节锁是使用欧拉角(俯仰、偏航、横摇)的结果。如果使用euler角四元数或euler角矩阵,结果将完全相同。好的,我来看看这是如何工作的。我尽量避免使用这些gl功能,但我会看看是否能使其正常工作。你知道怎么让照相机看东西吗?我以前用矩阵做过,但现在我用四元数,我有点困惑。我有一个Vector3 LookAt,所以你知道如何让相机在不使用gluLookAt的情况下观察它吗?我不确定这是否可能,因为矩阵存储位置和方向。