Quaternion from a vector

Question: I have a 3D rotation specified by three coordinates. How do I transform this into a CannonJS quaternion to physically rotate the body?


Repl link: https://replit.com/@JasonRoman/golf (see /game_defs.js line 66)

// I saw this online:
var qX = new CANNON.Quaternion()
var qY = new CANNON.Quaternion()
qX.setFromAxisAngle(new CANNON.Vec3(1,0,0), rx);
qY.setFromAxisAngle(new CANNON.Vec3(0,1,0), ry);
var combined = qX.mult(qY)
combined.normalize();
// So I tried this:
var qX = new CANNON.Quaternion()
var qY = new CANNON.Quaternion()
var qZ = new CANNON.Quaternion()
qX.setFromAxisAngle(new CANNON.Vec3(1,0,0), rx);
qY.setFromAxisAngle(new CANNON.Vec3(0,1,0), ry);
qZ.setFromAxisAngle(new CANNON.Vec3(0,0,1), rz);
var combined = qX.mult(qY).mult(qZ);
combined.normalize();
// But apparently that doesn't work because quaternion multiplication is not communative.

How can I combine my three qX, qY, and qZ quaternions to form one big quaternion?


I have also tried doing this (using a three.js object) in an attempt to get three.js to convert my rotation for me:

three_object.rotation.set(new THREE.Vector3( rx, ry, rz ));
cannon_object.quaternion.copy(three_object.quaternion)

However this results in values of NaN for all four coordinates in the quaternion.

Check if this Stack Overflow post might help with what you’re asking: javascript - How do I convert a rotation described by three coordinates into a quaternion? - Stack Overflow

That was actually asked by me.
There are no answers yet on that question…

1 Like

AI can be wrong a lot of times, but try and give this a shot:

To combine multiple quaternions into one, you can use the multiplication operation provided by the Cannon.js library. However, as you correctly noted, quaternion multiplication is not commutative, so the order in which you multiply the quaternions matters. The correct order of multiplication is from right to left, meaning the last quaternion you want to apply should be multiplied first.

Here’s an example of how you can combine the three quaternions qX, qY, and qZ in the correct order:

var qX = new CANNON.Quaternion();
var qY = new CANNON.Quaternion();
var qZ = new CANNON.Quaternion();

qX.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), rx);
qY.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), ry);
qZ.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), rz);

var combined = qZ.mult(qY).mult(qX);
combined.normalize();

In this example, the rotation around the Z-axis (qZ) is multiplied first, followed by the rotation around the Y-axis (qY), and finally the rotation around the X-axis (qX).

Regarding your second approach using three.js, it seems that there might be an issue with the conversion or setting of the rotation values. Here’s a revised version of the code that should work:

var three_object = new THREE.Object3D();
var cannon_object = new CANNON.Body();

three_object.rotation.set(rx, ry, rz);
cannon_object.quaternion.copy(new CANNON.Quaternion(
  three_object.quaternion.x,
  three_object.quaternion.y,
  three_object.quaternion.z,
  three_object.quaternion.w
));

Make sure that the rx, ry, and rz variables contain the rotation angles you want to apply. Also, ensure that you have imported the necessary libraries correctly (THREE and CANNON).

With these modifications, the cannon_object.quaternion should be correctly set based on the rotation specified by the rx, ry, and rz values.