Here is a video of the node implementation I made ( which I think is similar to what you’re after having looked at your maya scene )
Video Link
Below I have copy pasted the main block of code. I have left out the debug drawing OGL stuff, but you can just remove those calls if you wanted to compile and try it. It could be optimised a bit more, but it does the job.
cpp file
//-------------------------------------------
// Attribute Declaration : Inputs
MObject starPivot::inBackAttr;
MObject starPivot::inFrontAttr;
MObject starPivot::inLeftAttr;
MObject starPivot::inRightAttr;
MObject starPivot::inRollAttr;
MObject starPivot::inBankAttr;
MObject starPivot::inRotationFactorAttr;
MObject starPivot::inOffsetPivotAttr;
MObject starPivot::inDebuggingAttr;
//-------------------------------------------
// Attribute Declaration : Outputs
MObject starPivot::outTargetAttr;
MObject starPivot::outRotateAttr;
MObject starPivot::outTranslateAttr;
//--------------------------------------------------------------------------------
// Returns a new instance of this
// node
void* starPivot::creator()
{
return new starPivot;
}
//--------------------------------------------------------------------------------
// Called on the initialisation of the node
MStatus starPivot::initialize()
{
// Define the attribute types we need to use
MFnNumericAttribute numericAttrFn;
MFnMatrixAttribute matrixAttrFn;
MFnUnitAttribute unitAttrFn;
MFnCompoundAttribute compoundAttrFn;
// Add our input attributes
starPivot::inBackAttr = numericAttrFn.create("inNegZPivot", "ibp", MFnNumericData::kDouble);
addAttribute(starPivot::inBackAttr);
starPivot::inFrontAttr = numericAttrFn.create("inPosZPivot", "ifp", MFnNumericData::kDouble);
addAttribute(starPivot::inFrontAttr);
starPivot::inLeftAttr = numericAttrFn.create("inPosXPivot", "ilp", MFnNumericData::kDouble);
addAttribute(starPivot::inLeftAttr);
starPivot::inRightAttr = numericAttrFn.create("inNegXPivot", "irp", MFnNumericData::kDouble);
addAttribute(starPivot::inRightAttr);
starPivot::inRotationFactorAttr = numericAttrFn.create("inRotationFactor", "irf", MFnNumericData::kDouble);
addAttribute(starPivot::inRotationFactorAttr);
starPivot::inOffsetPivotAttr = matrixAttrFn.create("inOffset", "iof");
addAttribute(starPivot::inOffsetPivotAttr);
starPivot::inRollAttr = numericAttrFn.create("inXRoll", "ir", MFnNumericData::kDouble);
numericAttrFn.setSoftMax(1);
numericAttrFn.setSoftMin(-1);
numericAttrFn.setKeyable(true);
addAttribute(starPivot::inRollAttr);
starPivot::inBankAttr = numericAttrFn.create("inZRoll", "ib", MFnNumericData::kDouble);
numericAttrFn.setSoftMax(1);
numericAttrFn.setSoftMin(-1);
numericAttrFn.setKeyable(true);
addAttribute(starPivot::inBankAttr);
starPivot::inDebuggingAttr = numericAttrFn.create("inDebugging", "idb", MFnNumericData::kBoolean );
addAttribute( starPivot::inDebuggingAttr );
// Add our output attributes
starPivot::outTargetAttr = matrixAttrFn.create("outMat4", "om");
addAttribute(starPivot::outTargetAttr);
MObject rX = unitAttrFn.create("rotationX", "rx", MFnUnitAttribute::kAngle);
MObject rY = unitAttrFn.create("rotationY", "ry", MFnUnitAttribute::kAngle);
MObject rZ = unitAttrFn.create("rotationZ", "rz", MFnUnitAttribute::kAngle);
starPivot::outRotateAttr = compoundAttrFn.create("outRotation", "ro");
compoundAttrFn.addChild(rX);
compoundAttrFn.addChild(rY);
compoundAttrFn.addChild(rZ);
addAttribute(starPivot::outRotateAttr);
starPivot::outTranslateAttr = numericAttrFn.createPoint("outTranslate", "ot");
addAttribute(starPivot::outTranslateAttr);
// Define the dependency
attributeAffects(starPivot::inBackAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inFrontAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inLeftAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inRightAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inBackAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inRollAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inBankAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inRotationFactorAttr, starPivot::outTargetAttr);
attributeAffects(starPivot::inOffsetPivotAttr , starPivot::outTargetAttr);
attributeAffects(starPivot::inBackAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inFrontAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inLeftAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inRightAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inBackAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inRollAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inBankAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inRotationFactorAttr, starPivot::outRotateAttr);
attributeAffects(starPivot::inOffsetPivotAttr , starPivot::outRotateAttr);
attributeAffects(starPivot::inBackAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inFrontAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inLeftAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inRightAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inBackAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inRollAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inBankAttr , starPivot::outTranslateAttr);
attributeAffects(starPivot::inRotationFactorAttr, starPivot::outTranslateAttr);
attributeAffects(starPivot::inOffsetPivotAttr , starPivot::outTranslateAttr);
return MS::kSuccess;
}
//--------------------------------------------------------------------------------
// This is the caluclation method
MStatus starPivot::compute(const MPlug& plug, MDataBlock& dataBlock)
{
// We want to do as little computation as we can
// get away with, so start by reading out the
// roll and bank values
double roll = dataBlock.inputValue(starPivot::inRollAttr ).asDouble();
double bank = dataBlock.inputValue(starPivot::inBankAttr ).asDouble();
double factor = dataBlock.inputValue(starPivot::inRotationFactorAttr).asDouble();
MMatrix offset = dataBlock.inputValue(starPivot::inOffsetPivotAttr ).asMatrix();
// Create a transform we can pass between
// transformations
MMatrix mat4 = MMatrix();
MVector translation(0,0,0);
MEulerRotation eulerRotation(0,0,0);
//------------------------------------------
// ROLLING
// Do we need to add any negativ rolling?
if ( roll < -1e-99 )
{
double f = dataBlock.inputValue(starPivot::inFrontAttr).asDouble();
translation = MVector(0, 0, f);
eulerRotation = MEulerRotation( 0.0174532925 * (roll * -factor ), 0, 0);
}
// Do we need to add any positive rolling?
if ( roll > 1e-99 )
{
double f = dataBlock.inputValue(starPivot::inBackAttr).asDouble();
translation = MVector(0, 0, f);
eulerRotation = MEulerRotation( 0.0174532925 * (roll * -factor ), 0, 0);
}
// Create a transformation class
MTransformationMatrix rollXform = MTransformationMatrix();
rollXform.setRotatePivot(translation, MSpace::kObject, false);
rollXform.rotateBy(eulerRotation, MSpace::kObject);
mat4 = rollXform.asMatrix() * mat4;
//------------------------------------------
// BANKING
// Do we need to do any positive banking?
if ( bank > -1e-99)
{
double f = dataBlock.inputValue(starPivot::inLeftAttr).asDouble();
translation = MVector(f, 0, 0);
eulerRotation = MEulerRotation( 0, 0, 0.0174532925 * (bank * -factor ));
}
// Do we need to do any negative banking?
if ( bank < -1e-99)
{
double f = dataBlock.inputValue(starPivot::inRightAttr).asDouble();
translation = MVector(f, 0, 0);
eulerRotation = MEulerRotation( 0, 0, 0.0174532925 * (bank * -factor ));
}
// Create a transformation class
MTransformationMatrix bankXform = MTransformationMatrix();
bankXform.setRotatePivot(translation, MSpace::kObject, true);
bankXform.rotateBy(eulerRotation, MSpace::kObject);
mat4 = bankXform.asMatrix() * mat4;
// Apply the offset
mat4 = offset * mat4;
// Set the output variables
dataBlock.outputValue(starPivot::outTargetAttr).set(mat4);
// Now map the data to translate and
// rotate
MTransformationMatrix outXform(mat4);
MEulerRotation outEulerRotation = outXform.eulerRotation();
MVector rotationVector(outEulerRotation.x, outEulerRotation.y, outEulerRotation.z);
MFloatVector translationVector(outXform.getTranslation(MSpace::kWorld));
MGlobal::displayInfo(MString("") + translationVector.x + ", " + translationVector.y + ", " + translationVector.z);
dataBlock.outputValue(starPivot::outRotateAttr).set(rotationVector);
dataBlock.outputValue(starPivot::outTranslateAttr).set(translationVector);
return MStatus::kSuccess;
}
bool starPivot::drawLast() const
{
return false;
}
void starPivot::draw( M3dView& view,
const MDagPath& path,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status)
{
// Get this node as a class
MObject self = thisMObject();
// First thing to do is ensure we need to
// draw...
bool inEnabled = MPlug( self, starPivot::inDebuggingAttr).asBool();
if ( inEnabled == false )
return;
// Define the used colors
MFloatVector red(1, 0, 0);
MFloatVector green(0, 1, 0);
MFloatVector yellow(1, 1, 0);
// Now we know we need to draw, so lets do so
float len_back = MPlug( self, starPivot::inBackAttr ).asFloat();
float len_front = MPlug( self, starPivot::inFrontAttr ).asFloat();
float len_left = MPlug( self, starPivot::inLeftAttr ).asFloat();
float len_right = MPlug( self, starPivot::inRightAttr ).asFloat();
// Start drawing the quad
view.beginGL();
MMatrix m = MPlug( self, starPivot::outTargetAttr ).asMDataHandle().asMatrix();
MMatrix identity = MMatrix();;
drawGridPlane( view, m, len_left, len_right, len_front, len_back, yellow, 1);
drawGridPlane( view, identity, len_left, len_right, len_front, len_back, red, 1);
// End Drawing the GL
view.endGL();
}
h file
#include <maya/MPxLocatorNode.h>
#include <maya/MDataBlock.h>
#include <maya/MPlug.h>
#include <maya/MStatus.h>
// Create a node class
class starPivot : public MPxLocatorNode
{
public :
//-------------------------------------------
// Returns a new instance of this
// node
static void* creator();
//-------------------------------------------
// Called on the initialisation of the node
static MStatus initialize();
//-------------------------------------------
// This is the caluclation method
MStatus compute(const MPlug& plug, MDataBlock& dataBlock);
virtual bool drawLast() const;
virtual void draw( M3dView& view ,
const MDagPath& path ,
M3dView::DisplayStyle style,
M3dView::DisplayStatus status);
//-------------------------------------------
// Attribute Declaration : Inputs
static MObject inBackAttr;
static MObject inFrontAttr;
static MObject inLeftAttr;
static MObject inRightAttr;
static MObject inRollAttr;
static MObject inBankAttr;
static MObject inRotationFactorAttr;
static MObject inOffsetPivotAttr;
static MObject inDebuggingAttr;
//-------------------------------------------
// Attribute Declaration : Outputs
static MObject outTargetAttr;
static MObject outRotateAttr;
static MObject outTranslateAttr;
//--------------------------------------------
// Export Attribute
static MObject exportableAttr;
};