"Looking At"具有四元数的对象
"Looking At" an object with a Quaternion
所以我目前正在尝试创建一个函数,将采取两个3D点a和B,并为我提供四元数表示点a的旋转需要"看"点B(这样点a的局部Z轴通过点B,如果你愿意)。
我最初发现这篇文章,上面的答案似乎为我提供了一个很好的起点。我继续实现下面的代码;而不是假设一个默认的(0,0,-1)方向,作为原始答案建议,我试图提取一个单位向量表示相机的实际方向。
void Camera::LookAt(sf::Vector3<float> Target)
{
///Derived from pseudocode found here:
///https://stackoverflow.com/questions/13014973/quaternion-rotate-to
//Get the normalized vector from the camera position to Target
sf::Vector3<float> VectorTo(Target.x - m_Position.x,
Target.y - m_Position.y,
Target.z - m_Position.z);
//Get the length of VectorTo
float 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<float> LocalVector = m_Orientation.MultVect(sf::Vector3<float>(0, 0, -1));
//Get the cross product as the axis of rotation
sf::Vector3<float> 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);
//Get the dot product to find the angle
float Angle = acos(VectorTo.x*LocalVector.x +
VectorTo.y*LocalVector.y +
VectorTo.z*LocalVector.z);
//Determine whether or not the angle is positive
//Get the cross product of the axis and the local vector
sf::Vector3<float> 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;
AxisAngle.FromAxisAngle(Angle, Axis.x, Axis.y, Axis.z);
//And multiply it into the current orientation
m_Orientation = AxisAngle * m_Orientation;
}
这个几乎可以工作。发生的情况是,相机似乎朝着目标点旋转了一半的距离。如果我再次尝试旋转,它会执行一半的剩余旋转,无限地,这样如果我按住"Look-At-Button",相机的方向会越来越接近于直视目标,但它的旋转速度也会不断减慢,这样它就永远不会完全到达那里。
注意,我不想使用gluLookAt(),因为我最终还需要这段代码将对象指向相机以外的对象,并且我的对象已经使用四元数来确定它们的方向。例如,我可能想创建一个眼球,它可以跟踪在它前面移动的物体的位置,或者一个炮弹,它可以更新它的方向来寻找它的目标。
将Axis
向量归一化后再传递给FromAxisAngle
为什么要使用四元数?在这种情况下,你只是让事情变得更复杂,需要更多的计算。设置矩阵:-
calculate vector from observer to observed (which you're doing already)
normalise it (again, doing it already) = at
cross product this with the observer's up direction = right
normalise right
cross product at and right to get up
就完成了。right, up和at向量是矩阵的第一,第二和第三行(或第三列,取决于你如何设置)。最后一行/列是对象的位置。
但是看起来你想要在几帧内将一个现有矩阵转换成这个新矩阵。slerp对矩阵和四元数都这样做(当您研究数学时,这并不奇怪)。对于转换,存储初始矩阵和目标矩阵,然后在它们之间存储SLERP,每帧更改SLERP的数量(例如0,0.25,0.5,0.75,1.0 -尽管非线性级数看起来更好)。
不要忘记,你将一个四元数转换回一个矩阵,以便将其传递给渲染管道(除非在着色器中有一些新的特性来本地处理四元数)。因此,由于使用四元数而产生的任何效率都必须考虑到转换过程。
- 单元测试欧拉到四元数实现失败
- 零四元数和任何向量都不为零的特征积,这是一个错误吗?
- 将四元数旋转的游戏对象旋转另一个四元数时出现问题
- 在OpenGL(GLM/C++)中使用四元数旋转时出现问题
- 想要将 CGAL 与四元数相结合是否合乎逻辑
- Eigen::Quaternion FromTwoVectors() 不返回有效的四元数
- C++四元数方程程序
- 四元数旋转不起作用
- 四元数和翻译
- 使用四元数防止绕某个轴旋转
- 如何使用四元数来描述超过360度的旋转角度?
- 四元数旋转错误
- 为什么我简单的四元数乘法比SSE快
- 特征:将矩阵3d旋转转换为四元数
- 从四元数查看矩阵
- 用四元数绕轴旋转矢量
- 基于四元数的相机不需要的卷轴
- 在C++中使用1D FFT的四元数FFT
- 四元数到轴的角度
- "Looking At"具有四元数的对象