вращать кватернион на 1 ось? - PullRequest
14 голосов
/ 14 декабря 2010

У меня есть модель, повернутая кватернионом. Я могу только установить вращение, я не могу ни добавлять, ни вычитать. Мне нужно получить значение оси, а затем добавить к ней угол (может быть, градус или радиан?), А затем повторно добавить модифицированный кватернион.

Как я могу это сделать? (ответ по каждой оси).

Ответы [ 2 ]

32 голосов
/ 14 декабря 2010

Вы можете умножить два кватерниона вместе, чтобы получить третий кватернион, который является результатом двух вращений. Обратите внимание, что умножение кватернионов не является коммутативным, то есть порядок имеет значение (если вы сделаете это несколько раз в своей голове, вы поймете, почему).

Вы можете создать кватернион, представляющий вращение на заданный угол вокруг определенной оси, с чем-то вроде этого (извините, что это 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) и умножить его на текущий кватернион вращения вашей модели.

2 голосов
/ 15 января 2016

Сделал исполняемый код из поста 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)

...