Download - Introduction to the Maya C++ API
Topics
• Mud Plugin Introduction
• How to Create a MLL
• Command Basics
• Node Basics
Programming for Maya
• The Book (Complete Maya Programming)• MEL Scripts
– Can be really easy to test– Can see how Maya does its own with echo– Hard to get complex data structures– Slow, due to interpretation
• C++ API Plugins– Very confusing at first (and later), hard to find help /
concise examples– Fast, due to machine language
Particles in Maya
• Maya has a built in particle system• Can exploit this to build a particle based fluid
dynamics system• I took a procedural rather than physically based
approach
Particle Based Fluid
• Idea– Use maya particle
dynamics to create the fluid
– Have a voxelized force field, with a different force in each voxel
– Force depends on particles as well as constants
Plugin Realization
• Needs– Command to create
the mud system– Node(s) to do the
computations– Visual cues to locate
where the field is– Go FAST (so I used
the API + split particle system)
Topics
• Mud Plugin Introduction
• How to Create a MLL
• Command Basics
• Node Basics
Create a Visual C++ Project
• The project creation wizard is not installed
• Make a Win32Project
• Under application settings, choose dll and empty project
Open the Project Properties
Note: make sure you apply the settings on the next slide to both the debug and release versions (all configs should work).
Set the Project Properties
• C/C++ -> General -> Additional Include Directories: C:\Program Files\AliasWavefront\Maya6.0\include
• C/C++ -> CommandLine -> Additional Options: /I "C:\Program Files\AliasWavefront\Maya6.0\include“
• C/C++ -> Preprocessor -> Preprocessor Definitions: WIN32;NDEBUG;_WINDOWS;NT_PLUGIN
• Linker -> General -> Output File: change the .dll to .mll
• Linker -> Input -> Additional Dependencies: opengl32.lib Foundation.lib OpenMaya.lib OpenMayaUI.lib OpenMayaAnim.lib OpenMayaFX.lib OpenMayaRender.lib
• Linker -> CommandLine -> Additional Options: /LIBPATH:"C:\Program Files\AliasWavefront\Maya6.0\lib" /export:initializePlugin /export:uninitializePlugin
Required Code#include <maya/MFnPlugin>#include <maya/MObject>#include <maya/MStatus>
MStatus initializePlugin(MObject obj){ MStatus stat; MFnPlugin plugin(obj, "Brent Haley",
"2.2.1", "5.0.1"); return(stat);}
MStatus unintializePlugin(MObject obj){ MStatus stat; MFnPlugin plugin(obj); return(stat);}
• Initialize plugin procedure is an entry point that gets called when you load your plugin in Maya
• Uninitialize plugin procedure is an entry point that gets called when you unload your plugin from Maya
• Remember these were specified under the project settings
• Through these entry points we tell Maya what Nodes and Commands our Plugin has
Topics
• Mud Plugin Introduction
• How to Create a MLL
• Command Basics
• Node Basics
Example Command• Specification
class MudBoxCommand : public MPxCommand
{public:
//creator functionstatic void *creator();
//command execution functionsvirtual MStatus doIt(const MArgList &args);virtual MStatus redoIt();virtual MStatus undoIt();virtual bool isUndoable() const;
private://graph modifier, used to support undo and redoMDagModifier dagMod;
};
• Implementation (except doIt)
void *MudBoxCommand::creator(){
return new MudBoxCommand;}MStatus MudBoxCommand::redoIt(){
//commit the work set in doItMStatus stat = dagMod.doIt();return(stat);
}MStatus MudBoxCommand::undoIt(){
//erase any work set in doItMStatus stat = dagMod.undoIt();return(stat);
}bool MudBoxCommand::isUndoable()
const {return(true);}
doIt
• Where the actual work is done
• Changes made to the graph
• Get nodes through selection
• Get data through those nodes “plugs”
• Be careful not to setup a cyclic graph
• See examples (mud & joint extractor plugins, note the joint extract is a LOT simpler to script)
(De)Register the Command
• Register commands in the initializePlugin procedure (from the required bit of code)
stat = plugin.registerCommand(
"makeMud",
MudBoxCommand::creator);
if (!stat) MGlobal::displayError("register MudBoxCommand failed");
• Deregister commands in the unitializePlugin procedure
stat = plugin.deregisterCommand("makeMud");
if (!stat) MGlobal::displayError("deregister MudBoxCommand failed");
Topics
• Mud Plugin Introduction
• How to Create a MLL
• Command Basics
• Node Basics
Example Node• Specification
class MudBoxNode : public MPxNode{public:
//identifierstatic MTypeId id;//attributesstatic MObject boxCenterX;…//creator functionstatic void *creator();//initializer for the nodestatic MStatus initialize();//computational function to do the real workvirtual MStatus compute (const MPlug &plug, MDataBlock &data);
private:…
};
• Implementation (except for compute)
void *MudBoxNode::creator(){
return new MudBoxNode;}MStatus MudBoxNode::initialize(){
//create the attributes for spacial subdivisionMFnNumericAttribute boxAttributes;boxCenterX = boxAttributes.create("boxCenterX", "bcx", MFnNumericData::kDouble, 0.0);...//add the attributes to the nodeaddAttribute(boxCenterX);...//specify attribute relationsattributeAffects(boxCenterX, boxData);...//return without errorreturn(MS::kSuccess);
}
Compute• Where the actual work is done• See examples (mud plugin)
MStatus MudBoxNode::compute (const MPlug &plug, MDataBlock &data) { MStatus stat; //determine which output plug needs to be computed if (plug == boxData) { //get input data handles MDataHandle boxCenterXData = data.inputValue(boxCenterX); ... //turn input handles into data double bcx = boxCenterXData.asDouble(); ... //get output data handles MDataHandle outputBoxData = data.outputValue(boxData); //turn output handles into data <SNIP> //set the output data and mark the plug outputBoxData.set(ssbDataFn.object()); data.setClean(plug);} else //the plug is for an ancestor, return unknown stat = MS::kUnknownParameter; return(stat);}
(De)Register the Node
• Register nodes in the initializePlugin procedure
stat = plugin.registerNode("MudBoxNode",MudBoxNode::id,&MudBoxNode::creator,&MudBoxNode::initialize,MPxNode::kDependNode
);if (!stat) MGlobal::displayError("register MudBoxNode failed");
• Deregister nodes in the uninitializePlugin procedure
stat = plugin.deregisterNode(MudBoxNode::id);if (!stat) MGlobal::displayError("deregister MudBoxNode failed");