四元数绕轴旋转的分量 [英] Component of a quaternion rotation around an axis

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

问题描述

我无法找到有关此主题的任何好的信息.基本上我想找到四元数旋转的分量,即围绕给定轴(不一定是 X、Y 或 Z - 任何任意单位向量).有点像将四元数投影到向量上.因此,如果我要求绕平行于四元数轴的某个轴旋转,我会得到相同的四元数.如果我要求绕与四元数轴正交的轴旋转,我会得到一个恒等四元数.中间......好吧,这就是我想知道如何解决的问题:)

I'm having trouble finding any good information on this topic. Basically I want to find the component of a quaternion rotation, that is around a given axis (not necessarily X, Y or Z - any arbitrary unit vector). Sort of like projecting a quaternion onto a vector. So if I was to ask for the rotation around some axis parallel to the quaternion's axis, I'd get the same quaternion back out. If I was to ask for the rotation around an axis orthogonal to the quaternion's axis, I'd get out an identity quaternion. And in-between... well, that's what I'd like to know how to work out :)

推荐答案

前几天我试图为动画编辑器找到完全相同的东西;我是这样做的:

I spent the other day trying to find the exact same thing for an animation editor; here is how I did it:

  1. 取你想要绕其旋转的轴,并找到它的正交向量.
  2. 使用四元数旋转这个新向量.
  3. 将此旋转的向量投影到平面上,该平面的法线是您的轴
  4. 这个投影向量和原始正交的点积的 acos 就是你的角度.

  1. Take the axis you want to find the rotation around, and find an orthogonal vector to it.
  2. Rotate this new vector using your quaternion.
  3. Project this rotated vector onto the plane the normal of which is your axis
  4. The acos of the dot product of this projected vector and the original orthogonal is your angle.

public static float FindQuaternionTwist(Quaternion q, Vector3 axis)
{
    axis.Normalize();

    // Get the plane the axis is a normal of
    Vector3 orthonormal1, orthonormal2;
    ExMath.FindOrthonormals(axis, out orthonormal1, out orthonormal2);

    Vector3 transformed = Vector3.Transform(orthonormal1, q);

    // Project transformed vector onto plane
    Vector3 flattened = transformed - (Vector3.Dot(transformed, axis) * axis);
    flattened.Normalize();

    // Get angle between original vector and projected transform to get angle around normal
    float a = (float)Math.Acos((double)Vector3.Dot(orthonormal1, flattened));

    return a;
}

这是查找标准正交函数的代码,但是如果您只想要上述方法的正交函数,您可能会做得更好:

Here is the code to find the orthonormals however you can probably do much better if you only want the one for the above method:

private static Matrix OrthoX = Matrix.CreateRotationX(MathHelper.ToRadians(90));
private static Matrix OrthoY = Matrix.CreateRotationY(MathHelper.ToRadians(90));

public static void FindOrthonormals(Vector3 normal, out Vector3 orthonormal1, out Vector3 orthonormal2)
{
    Vector3 w = Vector3.Transform(normal, OrthoX);
    float dot = Vector3.Dot(normal, w);
    if (Math.Abs(dot) > 0.6)
    {
        w = Vector3.Transform(normal, OrthoY);
    }
    w.Normalize();

    orthonormal1 = Vector3.Cross(normal, w);
    orthonormal1.Normalize();
    orthonormal2 = Vector3.Cross(normal, orthonormal1);
    orthonormal2.Normalize();
}

尽管上述工作正常,但您可能会发现它的行为与您预期的不一样.例如,如果您的四元数将向量旋转 90 度.大约 X 和 90 度.在 Y 周围你会发现,如果你分解围绕 Z 的旋转,它将是 90 度.以及.如果您想象一个向量进行这些旋转,那么这很有意义,但根据您的应用程序,它可能不是所需的行为.对于我的应用程序——约束骨架关节——我最终得到了一个混合系统.矩阵/四元组贯穿始终,但是当涉及到约束关节的方法时,我在内部使用了欧拉角,每次将旋转四元组分解为围绕 X、Y、Z 的旋转.

Though the above works you may find it doesn't behave as you'd expect. For example, if your quaternion rotates a vector 90 deg. around X and 90 deg. around Y you'll find if you decompose the rotation around Z it will be 90 deg. as well. If you imagine a vector making these rotations then this makes perfect sense but depending on your application it may not be desired behaviour. For my application - constraining skeleton joints - I ended up with a hybrid system. Matrices/Quats used throughout but when it came to the method to constrain the joints I used euler angles internally, decomposing the rotation quat to rotations around X, Y, Z each time.

祝你好运,希望有所帮助.

Good luck, Hope that helped.

这篇关于四元数绕轴旋转的分量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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