Yesterday I have been trying to solve the following problem: calculate the local rotation quaternion for a bone given its global rotation quaternion and the skeleton state.
I figured that the global quaternion equals to the parent bone global multiplied by the bone's local quaternion:
global = globalParent * local
After a couple of simple manipulations, I got the following:
local = (globalParent)-1 * global
I did some tests on that equation and, to my surprise, it sometimes yields the correct answer and sometimes I get the correct answer multiplied by -1. Not the local quaternion's conjugate, but the whole quaternion multiplied by -1.
So I went back to the original equation (global = globalParent * local) and tested it too. The same thing happened, sometimes the right answer and sometimes the right answer multiplied by -1.
I found that really strange and went further to make the matrix product (globalParent * local) and extract the quaternion for the result. In this situation, I always got the right answer.
Finally, my question is pretty simple. Where is the mistake in my thought process when manipulating the quaternions?
The code I used to check the things I said is the following:
{
var p = new THREE.Vector3();
var s = new THREE.Vector3();
var bone = this.get_model_bone(label);
var gm = bone.matrixWorld;
var g = new THREE.Quaternion();
gm.decompose(p, g, s);
console.log(label + " - GLOBAL: (" + g.x + ", " + g.y + ", " + g.z + ", " + g.w + ")");
var m = bone.matrix;
var q = new THREE.Quaternion();
m.decompose(p, q, s);
console.log(label + " - LOCAL: (" + q.x + ", " + q.y + ", " + q.z + ", " + q.w + ")");
if(bone.parent !== null)
{
var gpm = bone.parent.matrixWorld;
var gp = new THREE.Quaternion();
gpm.decompose(p, gp, s);
console.log(label + " - PARENT GLOBAL: (" + gp.x + ", " + gp.y + ", " + gp.z + ", " + gp.w + ")");
var productMatrix = new THREE.Matrix4().multiplyMatrices(gpm, m);
var qprod = new THREE.Quaternion();
productMatrix.decompose(p, qprod, s);
console.log(label + " - MATRIX PROD: (" + qprod.x + ", " + qprod.y + ", " + qprod.z + ", " + qprod.w + ")");
var gpq = new THREE.Quaternion().multiplyQuaternions(gp, q);
console.log(label + " - QUAT PROD: (" + gpq.x + ", " + gpq.y + ", " + gpq.z + ", " + gpq.w + ")");
}
}
In my logs, sometimes "MATRIX PROD" is different than "QUAT PROD". The model I am using can be found at:
https://raw.githubusercontent.com/poli-libras/virtual-jonah2/master/resources/model/human.js
I did some tests on that equation and, to my surprise, it sometimes yields the correct answer and sometimes I get the correct answer multiplied by -1.
Quaternion and quaternion multiplied by -1 represent exact same transformation (rotation).