Sky_Paladin
Sky_Paladin

Reputation: 113

Is it possible to rotate a vector in 3D space using quaternions only?

I want to rotate a vector in 3D space around the origin.

Let's say I have a hypothetical polygon centered around the origin, and laying perpendicular to the y-axis.

I then want to rotate this polygon around some arbitrary axis by some arbitrary rotation amount.

Example: Rotate around the Y axis by 90 degrees. View is along the -Y axis.

Rotate by 90 degrees

One way to do this would be to create a rotation matrix and apply the rotation to each of the points of the polygon. I can presently already do this.

However, I decided that I wanted to achieve this using quaternions.

Attempt: Rotate around the Y axis by 90 degrees. View is along the -Y axis.

Failure

It seems like there's something wrong with the code.

To try and isolate the problem, I created function qRotate that should rotate a single point (or vector) around the origin. To check that my math was correct, I derived the final rotation using two different methods. However, both methods yield an identically incorrect result.

void qRotate(glm::vec3 point, glm::vec3 rotate)
{
  printf("\n\n%f %f %f around point %f %f %f", 
          rotate.x, rotate.y, rotate.z, point.x, point.y, point.z);

  //Create quaternion.
  glm::quat orientation = glm::quat(rotate);

  //Normalize
  orientation = glm::normalize(orientation);

  /*Method 1 - pure vector quaternion.*/
  //Create the 'pure' vector quaternion
  glm::quat pure = glm::quat(0.0, point.x, point.y, point.z);
  glm::quat qpq = orientation * pure * (glm::conjugate(orientation));
  //Form the result
  glm::vec3 result = glm::vec3(qpq.x, qpq.y, qpq.z);
  printf("\nResult1 = %f %f %f", result.x, result.y, result.z);

  /*Method 2 - just apply the orientation to the point.*/
  glm::vec3 alpha = orientation * point;
  printf("\nResult2 = %f %f %f", alpha.x, alpha.y, alpha.z);
}

Some sample inputs and outputs:

qRotate(glm::vec3(10.0, 0.0, 0.0), glm::vec3(0.0, 45.0, 0.0));

0.000000 45.000000 0.000000 around point 10.000000 0.000000 0.000000
Result1 = 5.253221 0.000000 -8.509035
Result2 = 5.253221 0.000000 -8.509035

(expected results - close to 7.5, 0.0, 7.5)

qRotate(glm::vec3(10.0, 0.0, 0.0), glm::vec3(0.0, 90.0, 0.0));

0.000000 90.000000 0.000000 around point 10.000000 0.000000 0.000000
Result1 = -4.480736 0.000000 -8.939966
Result2 = -4.480736 0.000000 -8.939966

(expected results - 0.00000, 0.00000, 10.00000)

qRotate(glm::vec3(10.0, 0.0, 0.0), glm::vec3(0.0, 180.0, 0.0));
Result1 = -5.984600 0.000000 8.011526
Result2 = -5.984600 0.000000 8.011526

(expected results - -10.00000, 0.00000, 0.0000)


It's my understanding that the math checks out, therefore, there must be something wrong with the way I am trying to use it. I have seen many resources taking the rotation quaternion (orientation) and converting it to a 4x4 matrix, then applying the rotation to the vector, and converting the matrix back to the (rotated) 3d vector.

In other parts of my code, I currently do perform the quaternion-matrix-vector conversion, but I thought it seemed inefficient.

I've read that it's possible to derive the rotated point using quaternions alone, and have used those algorithms suggested in my code. I also considered that the results may not necessarily be garbage and are in fact representative of something useful, but I don't know what.

Is it not possible to do this with quaternions alone?

Upvotes: 0

Views: 1457

Answers (1)

Edward Doolittle
Edward Doolittle

Reputation: 4110

Your function rotates by angles in radians but you input angles in degrees. You should either input angles in radians, or convert from degrees to radians at the top of the function.

Upvotes: 2

Related Questions