在 1 个轴上旋转四元数?

发布于 2024-10-07 08:23:04 字数 110 浏览 3 评论 0原文

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

我该怎么做? (在每个轴上回答)。

I have a model rotated by a quaternion. I can only set the rotation, I can't add or subtract from anything. I need to get the value of an axis, and than add an angle to it (maybe a degree or radian?) and than re-add the modified quaternion.

How can I do this? (answer on each axis).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南七夏 2024-10-14 08:23:05

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

您可以生成一个四元数,表示围绕特定轴旋转给定角度,如下所示(请原谅它是 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) 并将其乘以模型的当前旋转四元数。

You can multiply two quaternions together to produce a third quaternion that is the result of the two rotations. Note that quaternion multiplication is not commutative, meaning order matters (if you do this in your head a few times, you can see why).

You can produce a quaternion that represents a rotation by a given angle around a particular axis with something like this (excuse the fact that it is c++, not 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();
}

So to rotate around the x axis for example, you could create a quaternion with createFromAxisAngle(1, 0, 0, M_PI/2) and multiply it by the current rotation quaternion of your model.

终止放荡 2024-10-14 08:23:05

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

#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)

Made a runable code from sje397's post for testing other details later, thought I would share. Eventually using C the reason for no Quaternion class.

#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;
}

Output

(0.0871557, 0, 0, 0.996195)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文