四元数平滑旋转 [英] Smooth rotation with quaternions

查看:30
本文介绍了四元数平滑旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

四元数不仅可以描述旋转,还可以描述方向,即从初始(零)位置旋转.

Quaternion can describe not only rotation, but also an orientation, i.e. rotation from initial (zero) position.

我希望模拟从一个方向到另一个方向的平滑旋转.我计算了开始方向 startOrientation 和结束方向 endOrientation 并希望将中间方向描述为 startOrientation*(1-argument) + endOrientation*argumentargument0 变为 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.

代码有效但不符合预期:平滑旋转在 fractionargument 值到达 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.

假设我们有两个四元数 startOrientationendOrientation 并且我们想要它们之间的点 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆