0

I am using a Quaternion to represent the rotation of some object, and I would like to allow the user to rotate it about a single axis at a time using textbox, so he would write the angle that the object is rotated by (ex. at X-axis), then the object rotation is set to that rotation.
I know that, this operation q1 * q will rotate q by q1, but I don't know how to set the rotation at a single axis, Could any one help me to complete this function?

public void SetRotationX(float Angle)
{

}
O-BL
  • 103
  • 1
  • 4

2 Answers2

1

Based on your function naming, I take it your just trying to set the rotation to a completely new rotation along that angle, as opposed to offsetting the rotation by a set amount.

In this case, rather than concatenating a quaternion to the current one, you can just create a new quaternion entirely. Note that you'll still probably want to pass in an x, y and z value to the function, relating to the other text boxes, or the current rotations along those angles.

Here are the outlines for the formulae to working out each axis of a quaternion, assuming no prior code is in place to create these Euler conversions already (note, pseudocode to avoid language issues):

void EulerAnglesToQuaternion( Quaternion q , double x , double y , double z )
{
    double cx = cos(x*0.5);
    double cy = cos(y*0.5);    
    double cz = cos(z*0.5);
    double sx = sin(x*0.5);
    double sy = sin(y*0.5);    
    double sz = sin(z*0.5);

    q.w = (cz*cx*cy)+(sz*sx*sy);
    q.x = (cz*sx*cy)-(sz*cx*sy);
    q.y = (cz*cx*sy)+(sz*sx*cy);
    q.z = (sz*cx*cy)-(cz*sx*sy);              
}
Joeb Rogers
  • 131
  • 2
1

Going from the definition of quaternions as 3D rotations, we can represent a rotation about an arbitrary 3D axis by taking a unit vector in that direction, scaling it by the sine of half the angle of rotation, and using it as the 3 imaginary components of a quaternion. The remaining real component is then the cosine of half the angle, to keep the quaternion of unit length.

Quaternion AngleAxis(Vector3 axis, float angle) {

   Vector3 imaginary = axis.normalized * sin(angle/2f);

   Quaternion q;
   q.x = imaginary.x;
   q.y = imaginary.y;
   q.z = imaginary.z;

   q.w = cos(angle/2f);

   return q;
}

Rotating around just the x axis is then a simple special case:

Quaternion RotationAroundX(float angle) {

    // Equivalent to AngleAxis(new Vector3(1, 0, 0), angle)

    Quaternion q;
    q.x = sin(angle/2f);
    q.y = 0f;
    q.z = 0f;
    q.w = cos(angle/2f);

    return q;
}
DMGregory
  • 134,153
  • 22
  • 242
  • 357
  • Thanks DMGregory, when I am rotating around a single axis I have a pre-rotated object, so I cannot do it that simple. – O-BL Sep 18 '17 at 09:52
  • void RotationAroundX(Quaternion q, float Angle) {//implementation... } – O-BL Sep 18 '17 at 09:54
  • What about this case, where you have whatever rotation represented by quaternion and you want to set the rotation on a single axis? – O-BL Sep 18 '17 at 09:56
  • It sounds like you expect to be able to change just the "x part" of a rotation, independent of what's happened on the other axes, the way you might do by setting just one component of a translation vector while leaving the others untouched. Rotations don't work this way - their result is always dependent on the order in which the rotations are applied. So to pull out the "X part" of a quaternion, we need to know what other rotations were applied after X, or recompose the quaternion from the updated contributing rotations. – DMGregory Sep 18 '17 at 10:04
  • Could you provide a mathematical equations please? – O-BL Sep 18 '17 at 10:08
  • If we know our rotation was formed from 3 component rotations, a yaw, pitch, and roll, composed like this: q_old = q_yaw * q_pitch * q_roll and we want to change pitch to a new angle value pitch', we could either recompose the quaternion from the new components q_new = q_yaw * q_pitch' * q_roll or "undo" the yaw first: q_new = q_yaw * q_pitch' * inverse(q_yaw) * q_old. Either way, we need more than just the new pitch component, since there's nothing about a rotation that's uniquely identifiable as pitch (see the link above for examples where 2-axis rotations can duplicate a third) – DMGregory Sep 18 '17 at 10:16
  • (Note in that second example, q_pitch' would be the difference in pitch to apply — ran out of characters) – DMGregory Sep 18 '17 at 10:35