在 1 轴上旋转四元数?

Posted

技术标签:

【中文标题】在 1 轴上旋转四元数?【英文标题】:rotating a quaternion on 1 axis? 【发布时间】:2011-05-25 02:51:44 【问题描述】:

我有一个由四元数旋转的模型。我只能设置旋转,我不能添加或减去任何东西。我需要获取轴的值,然后为其添加一个角度(可能是度数或弧度?),然后重新添加修改后的四元数。

我该怎么做? (每个轴上的答案)。

【问题讨论】:

我认为您需要进一步澄清。你说你只能设置旋转......四元数的用途与旋转矩阵相同。不同之处在于四元数在数值上是稳定的,它们应用于 3d 几何的成本更高,但连接成本更低……因此,它们通常用于需要应用长系列旋转然后将它们转换回旋转的情况应用前的矩阵。请澄清每个轴上的答案是什么意思,也许您想要四元数->三个旋转矩阵,每个矩阵大约是一个轴? 【参考方案1】:

您可以将两个四元数相乘以产生第三个四元数,这是两次旋转的结果。请注意,四元数乘法不是可交换的,这意味着顺序很重要(如果您在脑海中多次这样做,您就会明白为什么)。

您可以生成一个四元数,它表示围绕特定轴的给定角度旋转,如下所示(请原谅它是 c++,而不是 java):

Quaternion Quaternion::create_from_axis_angle(const double &xx, const double &yy, const double &zz, const double &a)

    // Here we calculate the sin( theta / 2) once for optimization
    double factor = sin( a / 2.0 );

    // Calculate the x, y and z of the quaternion
    double x = xx * factor;
    double y = yy * factor;
    double z = zz * factor;

    // Calcualte the w value by cos( theta / 2 )
    double w = cos( a / 2.0 );

    return Quaternion(x, y, z, w).normalize();

例如,要围绕 x 轴旋转,您可以使用 createFromAxisAngle(1, 0, 0, M_PI/2) 创建一个四元数,并将其乘以模型的当前旋转四元数。

【讨论】:

所以如果我想创建一个在 X 轴上旋转 -15 度的四元数,我应该调用 createFromAxisAngle(1, 0, 0, -15*PI/180) 吗?谢谢! @Hubrus:是的,没错。然后,如果您调用该四元数x 和您的模型四元数y,您通常会使用x * y 设置总旋转(当然取决于您实现乘法的方式)。 将变量命名为“result”并不是一个好的约定,它给人的印象是它是返回值。 “因素”呢? @lahjaton_j 同意。固定。【参考方案2】:

从 sje397 的帖子中制作了一个可运行的代码,以便稍后测试其他细节,我想我会分享的。最终使用 C 是没有 Quaternion 类的原因。

#include <iostream>
#include <math.h>
using namespace std;

struct float4
   float x;
   float y;
   float z;
   float w;  
;
float4 make_float4(float x, float y, float z, float w)
   float4 quat = x,y,z,w;
   return quat;

float dot(float4 a)

   return (((a.x * a.x) + (a.y * a.y)) + (a.z * a.z)) + (a.w * a.w);

float4 normalize(float4 q)

   float num = dot(q);
   float inv = 1.0f / (sqrtf(num));
   return make_float4(q.x * inv, q.y * inv, q.z * inv, q.w * inv);

float4 create_from_axis_angle(const float &xx, const float &yy, const float &zz, const float &a)

   // Here we calculate the sin( theta / 2) once for optimization
   float factor = sinf( a / 2.0f );

   float4 quat;
   // Calculate the x, y and z of the quaternion
   quat.x = xx * factor;
   quat.y = yy * factor;
   quat.z = zz * factor;

   // Calcualte the w value by cos( theta / 2 )
   quat.w = cosf( a / 2.0f );
   return normalize(quat);

int main()

   float degrees = 10.0f;
   float4 quat = create_from_axis_angle(1, 0, 0, degrees*(3.14159f/180.0f));
   cout << "> (" << quat.x << ", " <<quat.y << ", " <<quat.z << ", " <<quat.w << ")" << endl; 
   return 0;

输出

(0.0871557, 0, 0, 0.996195)

【讨论】:

以上是关于在 1 轴上旋转四元数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 transform.Rotate 的情况下在其本地或世界轴上旋转带有第二个四元数的四元数?

两个四元数的区别

四元数运动学笔记旋转的雅克比矩阵

四元数运动学笔记四元数和旋转相关的约定表述

四元数法

将四元数旋转转换为旋转矩阵?