вращение кватерниона по 1 оси?

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

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


person William    schedule 14.12.2010    source источник
comment
Я думаю, вам нужно немного уточнить. Вы говорите, что можете установить только вращение... Кватернион служит той же цели, что и матрица вращения. Разница в том, что кватернион численно стабилен, они дороже для применения к 3D-геометрии, но дешевле для конкатенации... Поэтому они обычно используются, когда необходимо применить длинные серии вращений, а затем они преобразуются обратно в вращение. матрицы перед нанесением. Пожалуйста, уточните, что вы подразумеваете под ответом по каждой оси, возможно, вы хотите кватернион → три матрицы вращения, где каждая из них относится к одной оси?   -  person Quaternion    schedule 14.12.2010


Ответы (2)


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

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

person sje397    schedule 14.12.2010
comment
Итак, если я хочу создать кватернион с поворотом на -15 градусов по оси X, я должен вызвать createFromAxisAngle(1, 0, 0, -15*PI/180)? Спасибо! - person VladN; 25.10.2012
comment
@Hubrus: Да, это было бы правильно. Затем, если вы назовете этот кватернион x, а кватернион вашей модели y, вы обычно задаете общее вращение, используя x * y (конечно, в зависимости от того, как вы реализуете умножение). - person sje397; 26.10.2012
comment
Именование результата переменной не является хорошим соглашением, оно создает впечатление, что это будет возвращаемое значение. Как насчет фактора? - person lahjaton_j; 10.12.2015
comment
@lahjaton_j Согласен. Фиксированный. - person sje397; 11.12.2015

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

person Greg    schedule 15.01.2016