四元数不仅可以描述旋转,还可以描述方向,即从初始(零)位置旋转。
我希望模拟从一个方向到另一个方向的平滑旋转。我计算了起始方向startOrientation
和结束方向endOrientation
,并希望将startOrientation*(1-argument) + endOrientation*argument
描述为argument
,0
从1
更改为@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;
}
}
}
}
。
猴子引擎更新功能的代码如下:
fraction
预计余弦公式可以在开始时模拟平滑加速,在结束时减速。
代码有效但不符合预期:平滑旋转开始并在argument
和1
值达到orientation
之前很久结束,我不明白,为什么。
为什么endOrientation
值如此快地达到{{1}}?
答案 0 :(得分:4)
您已声明在您的情况下startOrientation
正在被修改。然而;以下是真的
为此目的,方法slerp
包含在Quaternion类中:interpolating between two rotations.
假设我们有两个四元数startOrientation
和endOrientation
,我们希望它们之间有点interpolation
,然后我们使用以下代码进行插值:
float interpolation=0.2f;
Quaternion result=new Quaternion();
result.slerp(startOrientation, endOrientation, interpolation);
四元数在内部有些复杂,并且遵循一些不同的数学规则来表示向量。您已在四元数上调用multiply(float scalar)
方法。在内部,这看起来像这样
public QuaternionD mult(float scalar) {
return new QuaternionD(scalar * x, scalar * y, scalar * z, scalar * w);
}
所以它只是对所有元素进行简单的乘法运算。这显然不会返回大小为scalar
倍的轮换。事实上,这样的四元数不再代表有效的旋转,因为它不再是单位四元数。如果您在此quaterion上调用normalise
,它将立即撤消缩放。我确定Quaternion#multiply(float scalar)
有一些用处,但我还没找到它们。
同样的情况是"添加"四元数不会将它们组合在一起。事实上,你将它们相乘。因此,结合q1然后q2然后q3将如下实现:
Quaternion q0 = q1.mult(q2).mult(q3);
非常有用
在你的情况下,你的插值公式几乎但不太正确。这显示了使用两种方法在两个四元数之间插值的偏航图