# skinning with quaternion + position

Hello,

I’m experimenting with skinning and trying to do the calculation directly with the quaternion, but I’m stuck getting the translation to be the same as with the matrix. I

In the code-block below I know that the matrix is correct (mesh is displayed correctly). Now instead of using the matrix, I’m trying to do the same but directly using the quaternion. For verifying, I create a matrix out of the Quaternion + vector. The problem is that the 3x3 rotation-part of that matrix is correct but the translation isn’t.

Question: How do I calculate the worldspace-translation using the current localspace-quaternion/translation + parent-worldspace-quaternion/translation ?

``````void _computeWorldPose(const Model& model, const Animation& anim, size_t frame, KeyFrame& keyframe)
{
// reserve space for the output
keyframe.pose.resize(model.rig.size());
keyframe.poseQ.resize(model.rig.size());
keyframe.poseT.resize(model.rig.size());

for (int b=0; b<model.rig.size(); b++)
{
// anim-bone-index may have different index as model-bone-index, lookup by name
int abid = anim.getIndexByName(model.rig[b].name);

if(abid!=-1)
{
Quaternion qq;
vector3 pos;
float scale;
unsigned int parentid = model.rig[b].ParentID;

anim.GetDataForKeyframe(abid, frame, qq, pos, scale);

// prepare the matrix
Quaternion q = qq.Inverse();   // (not entirely sure why, but with this the mesh is rendered correctly... )
matrix4 m4 = q.ToMatrix4();
m4.set_translation(pos);

// do calculation as Matrix and as Quaternion
keyframe.pose[b] = keyframe.pose[parentid] * m4;
keyframe.poseQ[b] = q * keyframe.poseQ[parentid];
keyframe.poseT[b] = q.transform(pos) + keyframe.poseT[parentid]; // ? what needs to be done here ?

// verify that we get the same result
matrix4 m(keyframe.poseQ[b], keyframe.poseT[b]);
if (keyframe.pose[b] != m) {
assert(0); // this fires, with the 3x3-rotation being identical, but translation is different
}

}
else
{
// "Root"
keyframe.pose[b].identity();
keyframe.poseQ[b] = Quaternion();
keyframe.poseT[b] = VECTOR3_ZERO;
}
}
}
``````

If you partition matrices into blocks, so that you have matrices whose elements are matrices, the rules for multiplication are the same as for matrices of scalars.

So:

``````
[R1 T1] * [R2 T2] = [R1*R2+T1*0 R1*T2+T1*1]
[ 0  1]   [ 0  1]   [ 0*R2+ 1*0  0*T2+ 1*1]

= [R1*R2 R1*T2+T1]
[    0        1]

``````

Where R1,R2 are the 3x3 rotation matrices, T1,T2 are the 3x1 translation vectors, 0 is a 1x3 zero vector [0,0,0] and 1 is a 1x1 unit matrix [1].

IOW, transform the right-hand translation by the left-hand rotation and add the left-hand translation to give the overall translation. Multiply the rotations to get the final rotation.

If the rotations are quaternions rather than matrices, it just means that the matrixmatrix->matrix and matrixvector->vector operations become quaternionquaternion->quaternion and quaternionvector->vector respectively.

Before posting I tried “all” combinations of multiplying things together (none worked), read your comment and tried the code below and it instantly worked!
So now the cpu-side quaternion-calculation gives the same result as the cpu-side matrix calculation. Your explanation was really helpful, thanks!

``````keyframe.poseT[b] = keyframe.poseQ[parentid].transform(pos) + keyframe.poseT[parentid];
``````

Going to make a dual-quaternion out of it now and try and use that in the shader instead of the matrix…

[CODE=glsl]
struct dquat
{
vec4 real;
vec4 dual;
};

// v - the vertex; dq - dual quaternion
vec3 dq_transform(in vec3 v,in dquat dq)
{
return (cross(dq.real.xyz,cross(dq.real.xyz,v)+vdq.real.w+dq.dual.xyz)+dq.dual.xyzdq.real.w-dq.real.xyz*dq.dual.w)*2.0+v;
}