HAnim Export from Maya
Well, I have been able to export out HAnim characters from Maya, but only if the Joint Orient attributes of the joints are frozen first.
To see the result visit the following URL:
http://onaslant.ndsu.edu/x3d\_content/hanim/
However I have an issue that I still need to work out. As I said above, the export only works if the Joints have their "Joint Orient" attributes frozen before a mesh is bound to the skeleton. This is because the HAnim specification requires that the "rotation" field of the HAnimJoint node be set to "0 0 1 0" by default. Any other value is considered a a deformation movement.
I thought that this was a good solution for setting up character rigs and exporting them to HAnim, but as it turns out the animators who tested the export stated that the act of freezing the Joint Orient attribute makes it impossible for them to animate their characters because the attribute is frozen, the joints no longer rotate as you would expect a real-life person's joints to rotate.
Solution?
Well, I have a solution, but unfortunately, I do not have the math skills or 3D knowledge to make it work. I need somekind of formula to convert the "Rotate" value of an non-frozen joint to a "Rotate" value of a frozen joint so that if a joint of a skeleton is rotated, the identical joint (with its Joint Orient attribute frozen) on an identical skeleton moves its children to the same 3D world position as the children of the original skeleton.
Below is the API I code that I wrote to do this. It can also be viewed online at the following location:
http://onaslant.ndsu.edu/x3d\_content/hanim/
This code is obviously incorrect. Any suggestions on how to properly write this code is greatly appreciated. Any formula should have the frozen joint's Rotate attribute set to 0 0 0 when the original joint is set to 0 0 0.
void webX3DExporter::updateHARot(MNodeMessage::AttributeMessage msg, MPlug &plug, MPlug &otherPlug, void *clientData)
{
if ( msg & MNodeMessage::kAttributeSet )
{
if(plug.partialName(false, false, false, false, false, true) == "rotate" ||
plug.partialName(false, false, false, false, false, true) == "rotateX" ||
plug.partialName(false, false, false, false, false, true) == "rotateY" ||
plug.partialName(false, false, false, false, false, true) == "rotateZ" ||
plug.partialName(false, false, false, false, false, true) == "jointOrient" ||
plug.partialName(false, false, false, false, false, true) == "jointOrientX" ||
plug.partialName(false, false, false, false, false, true) == "jointOrientY" ||
plug.partialName(false, false, false, false, false, true) == "jointOrientZ" ||
plug.partialName(false, false, false, false, false, true) == "rotateAxis" ||
plug.partialName(false, false, false, false, false, true) == "rotateAxisX" ||
plug.partialName(false, false, false, false, false, true) == "rotateAxisY" ||
plug.partialName(false, false, false, false, false, true) == "rotateAxisZ")
{
double add0=0;
double add1=0;
double add2=0;
double get0=0;
double get1=0;
double get2=0;
MObject nodeObj = plug.node();
MFnDependencyNode jNode(nodeObj);
MPlug rPlug = jNode.findPlug("rotate");
MPlug xr = rPlug.child(0);
MPlug yr = rPlug.child(1);
MPlug zr = rPlug.child(2);
MPlug haPlug = jNode.findPlug("hanimRotation");
MPlug xha = haPlug.child(0);
MPlug yha = haPlug.child(1);
MPlug zha = haPlug.child(2);
MPlug joPlug = jNode.findPlug("jointOrient");
MPlug xjo = joPlug.child(0);
MPlug yjo = joPlug.child(1);
MPlug zjo = joPlug.child(2);
MPlug raPlug = jNode.findPlug("rotateAxis");
MPlug xra = raPlug.child(0);
MPlug yra = raPlug.child(1);
MPlug zra = raPlug.child(2);
xjo.getValue(get0);
yjo.getValue(get1);
zjo.getValue(get2);
MEulerRotation joEuler(get0, get1, get2, MEulerRotation::kXYZ);
MMatrix joMat = joEuler.asMatrix();//.inverse();
/*
add0 = add0+get0;
add1 = add1+get1;
add2 = add2+get2;
*/
xra.getValue(get0);
yra.getValue(get1);
zra.getValue(get2);
MEulerRotation raEuler(get0, get1, get2, MEulerRotation::kXYZ);
MMatrix raMat = raEuler.asMatrix();//.inverse();
/*
add0 = add0+get0;
add1 = add1+get1;
add2 = add2+get2;
*/
xr.getValue(get0);
yr.getValue(get1);
zr.getValue(get2);
MEulerRotation rEuler(get0, get1, get2, MEulerRotation::kXYZ);
MMatrix rMat = rEuler.asMatrix();
MMatrix rMat1 = rMat.operator *(raMat);
MMatrix rMat2 = rMat1.operator *(joMat);
// MMatrix rMat1 = joMat.operator *(rMat);
// MMatrix rMat2 = raMat.operator *(rMat1);
MEulerRotation nEuler;
nEuler.operator =(rMat2);
/*
add0 = add0+get0;
add1 = add1+get1;
add2 = add2+get2;
*/
add0 = nEuler.x - raEuler.x - joEuler.x;
add1 = nEuler.y - raEuler.y - joEuler.y;
add2 = nEuler.z - raEuler.z - joEuler.z;
// add0 = nEuler.x;
// add1 = nEuler.y;
// add2 = nEuler.z;
xha.setValue(add0);
yha.setValue(add1);
zha.setValue(add2);
}
}
}