RBF Solver for Quaternions Interpolation in Maya

Recently I came across this paper:
RBF Solver for Quaternions Interpolation by: Rinaldi FabioDolci Daniele

Using their pseudocode:

SamplesPositions = LIST ()
SampleValues = LIST ()
MatrixT = Creatematrixfromlist(SamplesPositions)
MatrixS = CreatematrixfromList(SampleValues)
Epsilon = INT ()
MatrixD = ComputeDistanceMatrix(Matrix T)
Kernel = CreateKernel(SQUARED(MatrixD), Epsilon)
Invertedkernel = Kernel.Interpolate(INTERPOLATION TYPE).Invert()
WeightsMatrix = Invertedkernel∗MatrixS
CurrentPosition = MATRIX()
CurrentDistanceMatrix = ComputeDistanceMatrix(CurrentPosition)
Result = CurrentDistanceMatrix∗WeightsMatrix

We can build a simple MPxNode to interpolate Quaternions using Eigen. In the .gif below we have a simple scene to illustrate what we can do with this solver. We have 9 poses as inputs, and 9 rotations as inputValues, solve for the weights, and use a vector of the locator’s position as the driver as the current position:

In the next .gif, we took a jaw joint driven by an expression, and trained the RBF with Jaw controller as the driver, and the jaw joint as the driven. With 8 poses we have a good interpolating jaw joint.

This technique combined with more control on the input of the data type, we are able to create a pretty good RBF solver to handle almost anything we would like to drive.


Pro-Tip:

Eigen doesn’t seem to have built-in exp/log methods for quaternions, here is some code that can help with that:
Lionel Heng on github:

#ifndef QUATERNIONMAPPING_H
#define QUATERNIONMAPPING_H

namespace px
{
	double sinc(const double x)
	{
		if (x == 0)
			return 1;
		return sin(x) / x;
	}

	template<typename T>
	Eigen::Quaternion<T> expq(const Eigen::Quaternion<T>& q)
	{
		T a = q.vec().norm();
		T exp_w = exp(q.w());

		if (a == T(0))
		{
			return Eigen::Quaternion<T>(exp_w, 0, 0, 0);
		}

		Eigen::Quaternion<T> res;
		res.w() = exp_w * T(cos(a));
		res.vec() = exp_w * T(sinc(a)) * q.vec();

		return res;
	}

	template<typename T>
	Eigen::Quaternion<T> logq(const Eigen::Quaternion<T>& q)
	{
		T exp_w = q.norm();
		T w = log(exp_w);
		T a = acos(q.w() / exp_w);

		if (a == T(0))
		{
			return Eigen::Quaternion<T>(w, T(0), T(0), T(0));
		}

		Eigen::Quaternion<T> res;
		res.w() = w;
		res.vec() = q.vec() / exp_w / (sin(a) / a);

		return res;
	}

}

#endif

~Cheers!

maya python, finding the distance between two vectors

Great little funciton for finding the distance between two points in maya.

import maya.cmds as Mc 
from math import pow,sqrt

def GetDistance(objA, objB):
	gObjA = Mc.xform(objA, q=True, t=True, ws=True)
	gObjB = Mc.xform(objB, q=True, t=True, ws=True)
	
	return sqrt(pow(gObjA[0]-gObjB[0],2)+pow(gObjA[1]-gObjB[1],2)+pow(gObjA[2]-gObjB[2],2))