Skip to content

Instantly share code, notes, and snippets.

@gregoiredehame
Last active October 15, 2024 03:21
Show Gist options
  • Select an option

  • Save gregoiredehame/1af94cce663a844243fe5319fd41b489 to your computer and use it in GitHub Desktop.

Select an option

Save gregoiredehame/1af94cce663a844243fe5319fd41b489 to your computer and use it in GitHub Desktop.
c++ plugin for joint parent matrix, that maintain 0.0.0 rotations angles on joints.
#include <maya/MPxNode.h>
#include <maya/MFnMatrixAttribute.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MGlobal.h>
#include <maya/MQuaternion.h>
#include <maya/MMatrix.h>
#include <maya/MFnPlugin.h>
#include <maya/MVector.h>
#include <maya/MEulerRotation.h>
class ParentJointMatrix : public MPxNode
{
public:
ParentJointMatrix() {}
virtual ~ParentJointMatrix() {}
static void* creator() { return new ParentJointMatrix(); }
static MStatus initialize();
virtual MStatus compute(const MPlug& plug, MDataBlock& data) override;
static MTypeId id;
// Attributes
static MObject inputMatrix;
static MObject offsetMatrix;
static MObject parentMatrix;
static MObject jointOrient;
static MObject inputRotateOrder;
static MObject outputMatrix;
static MObject outputTranslate;
static MObject outputRotate;
static MObject outputScale;
static MObject outputShear;
};
MTypeId ParentJointMatrix::id(0x00124dfe);
MObject ParentJointMatrix::inputMatrix = MObject::kNullObj;
MObject ParentJointMatrix::offsetMatrix = MObject::kNullObj;
MObject ParentJointMatrix::parentMatrix = MObject::kNullObj;
MObject ParentJointMatrix::jointOrient = MObject::kNullObj;
MObject ParentJointMatrix::inputRotateOrder = MObject::kNullObj;
MObject ParentJointMatrix::outputMatrix = MObject::kNullObj;
MObject ParentJointMatrix::outputTranslate = MObject::kNullObj;
MObject ParentJointMatrix::outputRotate = MObject::kNullObj;
MObject ParentJointMatrix::outputScale = MObject::kNullObj;
MObject ParentJointMatrix::outputShear = MObject::kNullObj;
MStatus ParentJointMatrix::initialize()
{
MFnMatrixAttribute fnMatrix;
MFnUnitAttribute fnUnit;
MFnNumericAttribute fnNumeric;
MFnEnumAttribute fnEnum;
// INPUTS
inputMatrix = fnMatrix.create("inputMatrix", "im");
fnMatrix.setStorable(true);
fnMatrix.setKeyable(true);
addAttribute(inputMatrix);
offsetMatrix = fnMatrix.create("offsetMatrix", "ofm");
addAttribute(offsetMatrix);
parentMatrix = fnMatrix.create("jointParentMatrix", "jpm");
addAttribute(parentMatrix);
MObject jointOrientX = fnUnit.create("jointOrientX", "jox", MFnUnitAttribute::kAngle, 0.0);
MObject jointOrientY = fnUnit.create("jointOrientY", "joy", MFnUnitAttribute::kAngle, 0.0);
MObject jointOrientZ = fnUnit.create("jointOrientZ", "joz", MFnUnitAttribute::kAngle, 0.0);
jointOrient = fnNumeric.create("jointOrient", "jo", jointOrientX, jointOrientY, jointOrientZ);
addAttribute(jointOrient);
inputRotateOrder = fnEnum.create("inputRotateOrder", "iro", 0);
fnEnum.addField("xyz", 0);
fnEnum.addField("yzx", 1);
fnEnum.addField("zxy", 2);
fnEnum.addField("xzy", 3);
fnEnum.addField("yxz", 4);
fnEnum.addField("zyx", 5);
addAttribute(inputRotateOrder);
// OUTPUTS
outputMatrix = fnMatrix.create("outputMatrix", "om");
fnMatrix.setStorable(false);
fnMatrix.setWritable(false);
addAttribute(outputMatrix);
MObject outputTranslateX = fnUnit.create("outputTranslateX", "otx", MFnUnitAttribute::kDistance, 0.0);
MObject outputTranslateY = fnUnit.create("outputTranslateY", "oty", MFnUnitAttribute::kDistance, 0.0);
MObject outputTranslateZ = fnUnit.create("outputTranslateZ", "otz", MFnUnitAttribute::kDistance, 0.0);
outputTranslate = fnNumeric.create("outputTranslate", "ot", outputTranslateX, outputTranslateY, outputTranslateZ);
addAttribute(outputTranslate);
MObject outputRotateX = fnUnit.create("outputRotateX", "orx", MFnUnitAttribute::kAngle, 0.0);
MObject outputRotateY = fnUnit.create("outputRotateY", "ory", MFnUnitAttribute::kAngle, 0.0);
MObject outputRotateZ = fnUnit.create("outputRotateZ", "orz", MFnUnitAttribute::kAngle, 0.0);
outputRotate = fnNumeric.create("outputRotate", "or", outputRotateX, outputRotateY, outputRotateZ);
addAttribute(outputRotate);
MObject outputScaleX = fnNumeric.create("outputScaleX", "osx", MFnNumericData::kDouble, 1.0);
MObject outputScaleY = fnNumeric.create("outputScaleY", "osy", MFnNumericData::kDouble, 1.0);
MObject outputScaleZ = fnNumeric.create("outputScaleZ", "osz", MFnNumericData::kDouble, 1.0);
outputScale = fnNumeric.create("outputScale", "os", outputScaleX, outputScaleY, outputScaleZ);
addAttribute(outputScale);
MObject outputShearX = fnNumeric.create("outputShearX", "oshx", MFnNumericData::kDouble, 0.0);
MObject outputShearY = fnNumeric.create("outputShearY", "oshy", MFnNumericData::kDouble, 0.0);
MObject outputShearZ = fnNumeric.create("outputShearZ", "oshz", MFnNumericData::kDouble, 0.0);
outputShear = fnNumeric.create("outputShear", "osh", outputShearX, outputShearY, outputShearZ);
addAttribute(outputShear);
// Attribute Affects
attributeAffects(inputMatrix, outputMatrix);
attributeAffects(inputMatrix, outputTranslate);
attributeAffects(inputMatrix, outputRotate);
attributeAffects(inputMatrix, outputScale);
attributeAffects(inputMatrix, outputShear);
attributeAffects(offsetMatrix, outputMatrix);
attributeAffects(offsetMatrix, outputTranslate);
attributeAffects(offsetMatrix, outputRotate);
attributeAffects(offsetMatrix, outputScale);
attributeAffects(offsetMatrix, outputShear);
attributeAffects(parentMatrix, outputMatrix);
attributeAffects(parentMatrix, outputTranslate);
attributeAffects(parentMatrix, outputRotate);
attributeAffects(parentMatrix, outputScale);
attributeAffects(parentMatrix, outputShear);
attributeAffects(jointOrient, outputMatrix);
attributeAffects(jointOrient, outputTranslate);
attributeAffects(jointOrient, outputRotate);
attributeAffects(jointOrient, outputScale);
attributeAffects(jointOrient, outputShear);
attributeAffects(inputRotateOrder, outputMatrix);
attributeAffects(inputRotateOrder, outputTranslate);
attributeAffects(inputRotateOrder, outputRotate);
attributeAffects(inputRotateOrder, outputScale);
attributeAffects(inputRotateOrder, outputShear);
return MS::kSuccess;
}
MStatus ParentJointMatrix::compute(const MPlug& plug, MDataBlock& data)
{
if (plug == outputMatrix || plug == outputTranslate || plug == outputRotate || plug == outputScale || plug == outputShear)
{
MMatrix inputMat = data.inputValue(inputMatrix).asMatrix();
MMatrix parentMat = data.inputValue(parentMatrix).asMatrix();
MMatrix offsetMat = data.inputValue(offsetMatrix).asMatrix();
// Create the orient matrix based on jointOrient
MTransformationMatrix orientMat;
MVector jointOrientVal = data.inputValue(jointOrient).asVector();
MEulerRotation jointOrientEuler(jointOrientVal.x, jointOrientVal.y, jointOrientVal.z);
orientMat.rotateBy(jointOrientEuler.asQuaternion(), MSpace::kTransform);
// Calculate the output matrix with joint orientation considered
MTransformationMatrix outputMat(offsetMat * inputMat * parentMat.inverse());
MTransformationMatrix offsetOrientMat(inputMat * (orientMat.asMatrix() * parentMat).inverse());
// Replace the rotation of outputMat with offsetOrientMat rotation
MQuaternion offsetRotation = offsetOrientMat.rotation();
outputMat.setRotationQuaternion(offsetRotation.x, offsetRotation.y, offsetRotation.z, offsetRotation.w);
// Set output matrix
MDataHandle outputMatrixHandle = data.outputValue(outputMatrix);
outputMatrixHandle.setMMatrix(outputMat.asMatrix());
// Set output translate
MDataHandle outputTranslateHandle = data.outputValue(outputTranslate);
MVector translation = outputMat.getTranslation(MSpace::kTransform);
outputTranslateHandle.set3Double(translation.x, translation.y, translation.z);
// Set output rotate
MDataHandle outputRotateHandle = data.outputValue(outputRotate);
MQuaternion quatRotation = outputMat.rotation();
MEulerRotation eulerRotation = quatRotation.asEulerRotation();
outputRotateHandle.set3Double(eulerRotation.x, eulerRotation.y, eulerRotation.z);
// Set output scale
MDataHandle outputScaleHandle = data.outputValue(outputScale);
double scale[3] = { 1.0, 1.0, 1.0 };
outputMat.getScale(scale, MSpace::kTransform);
outputScaleHandle.set3Double(scale[0], scale[1], scale[2]);
// Set output shear
MDataHandle outputShearHandle = data.outputValue(outputShear);
double shear[3] = { 0.0, 0.0, 0.0 };
outputMat.getShear(shear, MSpace::kTransform);
outputShearHandle.set3Double(shear[0], shear[1], shear[2]);
// Mark the plug as clean
data.setClean(plug);
}
return MS::kSuccess;
}
MStatus initializePlugin(MObject obj)
{
MFnPlugin plugin(obj, "Gregoire Dehame", "1.0", "Any");
return plugin.registerNode("parentJointMatrix", ParentJointMatrix::id, ParentJointMatrix::creator, ParentJointMatrix::initialize);
}
MStatus uninitializePlugin(MObject obj)
{
MFnPlugin plugin(obj);
return plugin.deregisterNode(ParentJointMatrix::id);
}
@gregoiredehame
Copy link
Author

preview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment