Interpolating With Matrices/Quaternions

So i am making a simple program in opengl that allows the user to create a list of keyframes then animates a skeleton through those keyframes using 4 different types of interpolation.

I have implemented the keyframe system. It is essentially a vector of skeletons, and a skeleton is just a collection of joint structs which contain information (local transform, global transform, etc) for each joint in the skeleton.

Each joint in the skeleton hierarchy has a vector3 position, a local transform matrix and a global transform matrix.

Here is the draw code:


for (unsigned i=0; i<joints.size(); i++)
    {
        glPushMatrix();
        if (joints[i].isPicked)
            glColor3f(1.0, 0.0, 0.0);
        else if (joints[i].isHovered)
            glColor3f(0.1, 1.0, 0.1);
        else
            glColor3f(0.3, 0.3, 0.9);

        glMultMatrixf(joints[i].global_t);
        
        glTranslated(joints[i].position.x, joints[i].position.y, joints[i].position.z);
        glutSolidSphere(0.01, 15, 15);
        glTranslated(-joints[i].position.x, -joints[i].position.y, -joints[i].position.z);
        
        if (joints[i].parentID !=-1)//draw bones for all joints
        {
            glColor3f(0.7, 0.3, 0.3);
            glBegin(GL_LINES);
                glVertex3d(joints[i].position.x, joints[i].position.y, joints[i].position.z);
                glVertex3d(joints[joints[i].parentID].position.x,
                        joints[joints[i].parentID].position.y,
                        joints[joints[i].parentID].position.z);
            glEnd();
        }
        glPopMatrix();
    }

For each joint we multiply by the global transform, then translate.

So given 2 different skeletons, each with distinct joints, I need to interpolate between them given an arbitrary float between 0 and 1 inclusive.


void Interpolate(float fract)
{
	Keyframe cur = keyframes[keyframe]; // note that Keyframe is a struct which contains "joints" which is a vector of joint structs
	Keyframe next = keyframes[keyframe + 1];
	Keyframe result = cur;
	result.number = cur.number;

	switch(interpMode)
	{
		case 1:
			for (unsigned i=0; i<cur.joints.size(); i++)
			{
				for (int j = 0; j < 15; j++)
				{
					result.joints[i].local_t[j] = cur.joints[i].local_t[j] * (1-fract) + next.joints[i].local_t[j] * fract;
				}
			}
			break;
		case 2:
			//euler
			break;
		case 3:
			//quaternion
			break;
		case 4:
			//slerp quaternion
			break;
	}

	myDefMesh.mySkeleton.joints = result.joints;
}

This code doesn’t do anything, i need to update the global transform after altering the local transform i think. Can anyone provide insight?

Correct.

But there’s no point trying to interpolate matrices, the results will be garbage. Euler angles or axis-and-angle won’t be much better. This is why everyone uses quaternions.

Agreed, this program is meant to show what each method looks like, even if they are wrong. It’s more of a demonstration as to why quaternions are ideal for this sort of thing.

Right, or dual quaternions, which handle the translation component too.