四元数平滑旋转 [英] Smooth rotation with quaternions
问题描述
四元数不仅可以描述旋转,还可以描述方向,即从初始(零)位置旋转.
Quaternion can describe not only rotation, but also an orientation, i.e. rotation from initial (zero) position.
我希望模拟从一个方向到另一个方向的平滑旋转.我计算了开始方向 startOrientation
和结束方向 endOrientation
并希望将中间方向描述为 startOrientation*(1-argument) + endOrientation*argument
而argument
从 0
变为 1
.
I was wishing to model smooth rotation from one orientation to another. I calculated start orientation startOrientation
and end orientation endOrientation
and was wishing to describe intermediate orientations as startOrientation*(1-argument) + endOrientation*argument
while argument
changes from 0
to 1
.
monkey 引擎更新功能代码如下:
The code for monkey engine update function is follows:
@Override
public void simpleUpdate(float tpf) {
if( endOrientation != null ) {
if( !started ) {
started = true;
}
else {
fraction += tpf * speed;
argument = (float) ((1 - Math.cos(fraction * Math.PI)) / 2);
orientation = startOrientation.mult(1-argument).add(endOrientation.mult(argument));
//orientation = startOrientation.mult(1-fraction).add(endOrientation.mult(fraction));
log.debug("tpf = {}, fraction = {}, argument = {}", tpf, fraction, argument);
//log.debug("orientation = {}", orientation);
rootNode.setLocalRotation(orientation);
if( fraction >= 1 ) {
rootNode.setLocalRotation(endOrientation);
log.debug("Stopped rotating");
startOrientation = endOrientation = null;
fraction = 0;
started = false;
}
}
}
}
余弦公式预期在开始时平滑加速并在结束时平滑地建模.
The cosine formula was expected to model smooth accelerating at the beginning and decelerating at the end.
代码有效但不符合预期:平滑旋转在 fraction
和 argument
值到达 1
之前很久就开始和结束,我不不明白,为什么.
The code works but not as expected: the smooth rotation starts and finishes long before fraction
and argument
values reach 1
and I don't understand, why.
为什么 orientation
值达到 endOrientation
这么快?
Why the orientation
value reaches endOrientation
so fast?
推荐答案
您已经声明在您的情况下 startOrientation
正在被修改.然而;以下仍然正确
You have stated that in your case startOrientation
was being modified. However; the following remains true
方法 slerp
包含在 Quaternion 类中用于此目的:在两次旋转之间进行插值.
The method slerp
is included within the Quaternion class for this purpose: interpolating between two rotations.
假设我们有两个四元数 startOrientation
和 endOrientation
并且我们想要它们之间的点 interpolation
然后我们使用以下代码在它们之间进行插值:
Assuming we have two quaternions startOrientation
and endOrientation
and we want the point interpolation
between them then we interpolate between then using the following code:
float interpolation=0.2f;
Quaternion result=new Quaternion();
result.slerp(startOrientation, endOrientation, interpolation);
为什么你的方法可能很危险
四元数在内部有些复杂,并且遵循有些不同的数学规则来表示向量.您已经在四元数上调用了 multiply(float scalar)
方法.内部看起来像这样
Why your approach may be dangerous
Quaternions are somewhat complex internally and follow somewhat different mathematical rules to say vectors. You have called the multiply(float scalar)
method on the quaternion. Internally this looks like this
public QuaternionD mult(float scalar) {
return new QuaternionD(scalar * x, scalar * y, scalar * z, scalar * w);
}
所以它只是对所有元素进行简单的乘法运算.这明确不会返回 scalar
乘以大小的旋转.事实上,这样的四元数不再代表有效的旋转,因为它不再是单位四元数.如果你在这个四元数上调用 normalise
它会立即撤销缩放.我确定 Quaternion#multiply(float scalar)
有一些用处,但我还没有找到它们.
So it just does a simple multiplication of all the elements. This explicitly does not return a rotation that is scalar
times the size. In fact such a quaternion no longer represents a valid rotation at all since its no longer a unit quaternion. If you called normalise
on this quaterion it would immediately undo the scaling. I'm sure Quaternion#multiply(float scalar)
has some use but I am yet to find them.
添加"四元数不会将它们组合起来也是如此.事实上,你将它们相乘.因此将 q1 然后 q2 然后 q3 组合如下:
It is also the case that "adding" quaternions does not combine them. In fact you multiply them. So combining q1 then q2 then q3 would be achieved as follows:
Quaternion q0 = q1.mult(q2).mult(q3);
备忘单对此非常有用
在您的情况下,您的插值公式几乎但不完全正确.这显示了使用两种方法在 2 个四元数之间进行插值的偏航图
In your case your formula for interpolation is nearly but not quite correct. This shows a graph of yaw for interpolation between 2 quaternions using both methods
这篇关于四元数平滑旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!