0
\$\begingroup\$

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

}
\$\endgroup\$
1
\$\begingroup\$

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);              
}
\$\endgroup\$
1
  • \$\begingroup\$ I will try this as soon as possible, thanks Joeb Rogers \$\endgroup\$
    – O-BL
    Sep 18 '17 at 9:59
1
\$\begingroup\$

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;
}
\$\endgroup\$
7
  • \$\begingroup\$ Thanks DMGregory, when I am rotating around a single axis I have a pre-rotated object, so I cannot do it that simple. \$\endgroup\$
    – O-BL
    Sep 18 '17 at 9:52
  • \$\begingroup\$ void RotationAroundX(Quaternion q, float Angle) {//implementation... } \$\endgroup\$
    – O-BL
    Sep 18 '17 at 9:54
  • \$\begingroup\$ What about this case, where you have whatever rotation represented by quaternion and you want to set the rotation on a single axis? \$\endgroup\$
    – O-BL
    Sep 18 '17 at 9:56
  • \$\begingroup\$ 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. \$\endgroup\$
    – DMGregory
    Sep 18 '17 at 10:04
  • \$\begingroup\$ Could you provide a mathematical equations please? \$\endgroup\$
    – O-BL
    Sep 18 '17 at 10:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .