OpenGL 四元数 class 用法
OpenGL Quaternion class usage
对于我正在做的一个编码项目,我得到了一个四元数 class 用于使我的相机旋转更容易并解决万向节锁定问题。
我不太精通四元数的使用,所以我想知道如何将它应用到我的相机中 class。
目前我正在使用内置的 glRotatef 函数来旋转相机。
相机功能
void Camera::Pitch(float aAngle)
{
m_fPitchAngle += aAngle;
}
void Camera::Roll(float aAngle)
{
//aAngle = 5.0f;
m_fRollAngle += aAngle;
}
void Camera::Yaw(float aAngle)
{
m_fYawAngle += aAngle;
}
void Camera::MoveForward(float aDistance)
{
m_vPosition.z += aDistance;
}
void Camera::Strafe(float aDistance)
{
m_vPosition.x += aDistance;
}
这些变量在相机的渲染函数中使用。
Inside Camera's Render 函数
// Yaw
glRotatef(m_fYawAngle, m_vUp.x, m_vUp.y, m_vUp.z);
// Pitch
glRotatef(m_fPitchAngle, m_vRight.z, m_vRight.y, m_vRight.z);
//Roll
glRotatef(m_fRollAngle, m_vFacing.x, m_vFacing.y, m_vFacing.z);
//angleBetween = cosf(m_fYawAngle) + m_vPosition.z;
// Move Forward
glTranslatef(m_vPosition.x, m_vPosition.y, m_vPosition.z);
在相机的更新功能中使用的,在 switch 语句中。
相机更新功能
case SDLK_a:
Yaw(-kAngleToTurn);
break;
case SDLK_d:
Yaw(kAngleToTurn);
break;
其他变量依此类推。这是我得到的基本四元数头文件。
Quaternion.h
struct Quaternion
{
float w;
Vector3D vec;
Quaternion()
{
vec.x = 0.0f;
vec.y = 0.0f;
vec.z = 0.0f;
}
Quaternion(float startW, Vector3D startVec)
{
vec.x = startVec.x;
vec.y = startVec.y;
vec.z = startVec.z;
}
};
class QuaternionMath
{
public:
~QuaternionMath();
static QuaternionMath* Instance();
void QuaternionToMatrix(Quaternion* q, float m[4][4]);
void MatrixToQuaternion(float m[4][4], Quaternion* q);
void EulerToQuaternion(float roll, float pitch, float yaw, Quaternion* q);
void Multiply(Quaternion* q1, Quaternion* q2, Quaternion* resultingQuaternion);
void RotateVector(Quaternion* q, Vector3D* v, Vector3D* resultingVector);
private:
QuaternionMath();
private:
static QuaternionMath* mInstance;
};
不使用 glRotate
调用链,而是使用 MatrixToQuaternion
从四元数实例中检索一个 4×4 矩阵,然后将其乘以 [=12= 到堆栈顶部的矩阵].
在进一步的步骤中,您应该摆脱使用任何使用 OpenGL 固定函数矩阵堆栈的代码,并使用类似 GLM 或类似的东西。
对于我正在做的一个编码项目,我得到了一个四元数 class 用于使我的相机旋转更容易并解决万向节锁定问题。
我不太精通四元数的使用,所以我想知道如何将它应用到我的相机中 class。
目前我正在使用内置的 glRotatef 函数来旋转相机。
相机功能
void Camera::Pitch(float aAngle)
{
m_fPitchAngle += aAngle;
}
void Camera::Roll(float aAngle)
{
//aAngle = 5.0f;
m_fRollAngle += aAngle;
}
void Camera::Yaw(float aAngle)
{
m_fYawAngle += aAngle;
}
void Camera::MoveForward(float aDistance)
{
m_vPosition.z += aDistance;
}
void Camera::Strafe(float aDistance)
{
m_vPosition.x += aDistance;
}
这些变量在相机的渲染函数中使用。
Inside Camera's Render 函数
// Yaw
glRotatef(m_fYawAngle, m_vUp.x, m_vUp.y, m_vUp.z);
// Pitch
glRotatef(m_fPitchAngle, m_vRight.z, m_vRight.y, m_vRight.z);
//Roll
glRotatef(m_fRollAngle, m_vFacing.x, m_vFacing.y, m_vFacing.z);
//angleBetween = cosf(m_fYawAngle) + m_vPosition.z;
// Move Forward
glTranslatef(m_vPosition.x, m_vPosition.y, m_vPosition.z);
在相机的更新功能中使用的,在 switch 语句中。
相机更新功能
case SDLK_a:
Yaw(-kAngleToTurn);
break;
case SDLK_d:
Yaw(kAngleToTurn);
break;
其他变量依此类推。这是我得到的基本四元数头文件。
Quaternion.h
struct Quaternion
{
float w;
Vector3D vec;
Quaternion()
{
vec.x = 0.0f;
vec.y = 0.0f;
vec.z = 0.0f;
}
Quaternion(float startW, Vector3D startVec)
{
vec.x = startVec.x;
vec.y = startVec.y;
vec.z = startVec.z;
}
};
class QuaternionMath
{
public:
~QuaternionMath();
static QuaternionMath* Instance();
void QuaternionToMatrix(Quaternion* q, float m[4][4]);
void MatrixToQuaternion(float m[4][4], Quaternion* q);
void EulerToQuaternion(float roll, float pitch, float yaw, Quaternion* q);
void Multiply(Quaternion* q1, Quaternion* q2, Quaternion* resultingQuaternion);
void RotateVector(Quaternion* q, Vector3D* v, Vector3D* resultingVector);
private:
QuaternionMath();
private:
static QuaternionMath* mInstance;
};
不使用 glRotate
调用链,而是使用 MatrixToQuaternion
从四元数实例中检索一个 4×4 矩阵,然后将其乘以 [=12= 到堆栈顶部的矩阵].
在进一步的步骤中,您应该摆脱使用任何使用 OpenGL 固定函数矩阵堆栈的代码,并使用类似 GLM 或类似的东西。