18

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

1
  • 1
    I think you need to clarify a bit further. You say you can only set the rotation... A quaternion serves the same purpose as a rotation matrix. The difference being that the quaternion is numerically stable, they are more expensive to apply to 3d geometry but are less expensive for concatenation... So they are typically used when long series of rotations need to be applied and then they are transformed back to rotation matrices before application. Please clarify what you mean by answer on each axis, perhaps you want quaternion -> three rotation matrix where each is about one axis? Commented Dec 14, 2010 at 7:27

2 Answers 2

38

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.

Sign up to request clarification or add additional context in comments.

4 Comments

So if I want to create a quaternion with a -15 degrees rotation on the X axis, I should call createFromAxisAngle(1, 0, 0, -15*PI/180)? Thanks!
@Hubrus: Yep, that'd be correct. Then, if you call that quaternion x and your model quaternion y, you would normally set the total rotation using x * y (depending on how you implement multiplication of course).
Naming a variable "result" is not a good convention, it gives the impression it would be the return value. How about "factor"?
@lahjaton_j Agreed. Fixed.
5

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)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.