所以我在OpenGL场景中为我的3D对象实现旋转,到目前为止,基本旋转本身(使用四元数)工作正常。我也主要解决了“看”问题,这样我现在可以让任何3D物体(包括相机)完全毫无困难地面对3D空间中的任何一点。
然而,当命令一个物体面对一个给定的点时,它会经常沿着它的局部Z轴滚动;看到这张图片,小船正在看红色,绿色和蓝色线汇合的点。您可以看到它看起来不像人们可能期望的那样,例如,沿着Y轴旋转以面向绿线,然后沿着X轴向下倾斜以面向三条线的会合点。
我不一定要这个。我希望它直接看到那一点,但是顺时针稍微倾斜(从前面看),这样它的翅膀的尖端处于相同的Y水平。由于面向点的整个点是局部Z轴穿过该点,因此对象围绕其局部Z轴旋转无关紧要,但是所得到的旋转始终是倾斜的,尽管偏斜似乎取决于物体的相对位置及其焦点。
在任何情况下,这是我的LookAt()代码,我想修改它,以便我可以更好地控制最终的Z旋转。
void Thing::LookAt(sf::Vector3<float> Target)
{
///Derived from pseudocode found here:
///http://stackoverflow.com/questions/13014973/quaternion-rotate-to
//Reset the rotation to default
m_Orientation = Quaternion();
//Get the normalized vector from the camera position to Target
sf::Vector3<double> VectorTo(Target.x - m_Position.x,
Target.y - m_Position.y,
Target.z - m_Position.z);
//Get the length of VectorTo
double VectorLength = sqrt(VectorTo.x*VectorTo.x +
VectorTo.y*VectorTo.y +
VectorTo.z*VectorTo.z);
//Normalize VectorTo
VectorTo.x /= VectorLength;
VectorTo.y /= VectorLength;
VectorTo.z /= VectorLength;
//Straight-ahead vector
sf::Vector3<double> LocalVector = m_Orientation.MultVect(sf::Vector3<double>(0, 0, -1));
//Get the cross product as the axis of rotation
sf::Vector3<double> Axis(VectorTo.y*LocalVector.z - VectorTo.z*LocalVector.y,
VectorTo.z*LocalVector.x - VectorTo.x*LocalVector.z,
VectorTo.x*LocalVector.y - VectorTo.y*LocalVector.x);
//Normalize the axis
//Get the length of VectorTo
double AxisLength = sqrt(Axis.x*Axis.x +
Axis.y*Axis.y +
Axis.z*Axis.z);
//Normalize VectorTo
Axis.x /= AxisLength;
Axis.y /= AxisLength;
Axis.z /= AxisLength;
//Get the dot product to find the angle
double DotProduct = (VectorTo.x*LocalVector.x +
VectorTo.y*LocalVector.y +
VectorTo.z*LocalVector.z);
double Angle = acos(DotProduct);
//Determine whether or not the angle is positive
//Get the cross product of the axis and the local vector
sf::Vector3<double> ThirdVect(Axis.y*LocalVector.z - Axis.z*LocalVector.y,
Axis.z*LocalVector.x - Axis.x*LocalVector.z,
Axis.x*LocalVector.y - Axis.y*LocalVector.x);
//If the dot product of that and the local vector is negative, so is the angle
if (ThirdVect.x*VectorTo.x + ThirdVect.y*VectorTo.y + ThirdVect.z*VectorTo.z < 0)
{
Angle = -Angle;
}
//Finally, create a quaternion
//Quaternion AxisAngle;
m_Orientation.FromAxisAngle(Angle, Axis.x, Axis.y, Axis.z);
m_Orientation.RotationMatrix(m_RotationMatrix);
}
我的问题是我不知道如何控制绕Z轴的最终旋转。请注意,当我从m_Orientation四元数中提取Z角时,它告诉我上面描绘的船绕其Z轴旋转0弧度。我尝试手动将Z组件设置为0并重新规范化四元数,但(显然我认为)不起作用。
目前,可以计算船舶“自上而下”旋转所需的特定Z分量,即使其两个翼尖处于相同的Y水平且其Y轴如同陡峭一样可能,但我想更清楚地了解如何操纵最终的Z旋转。任何想法或资源?
答案 0 :(得分:2)
如果围绕任意轴执行单次旋转,则很自然地得到此结果。你有没有想过转型?
但是,有一种更简单的方法来构造旋转矩阵。您只需要找到轴映射到的矢量。
所以,例如如果模型指向-z,则z轴(正向)映射到z = VectorTo
或z = -VectorTo
。要保留向上方向,您需要定义它。我们说up = (0, 1, 0)
。然后x轴被映射到x = z x up
的叉积。最后,您需要重新计算向上矢量以使用y = x x z
保持纯旋转。 (中间的x指定叉积运算符)。
计算完这些向量后,您现在可以按如下方式构建变换矩阵(使用标准化向量):
/ x.x y.x z.x 0 \
| x.y y.y z.y 0 |
T = | x.z y.z z.z 0 |
\ 0 0 0 1 /
根据您的API,您可能需要转置此矩阵。
如果您需要四元数,可以使用this one等方法。