Upload
keenan
View
31
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Introduction to the Maya C++ API. Brent Haley The Ohio State University ([email protected]). Programming for Maya. The Book (Complete Maya Programming) Maya Help (Developer Resources, Commands, Nodes, API Classes) MEL Scripts Can be really easy to test - PowerPoint PPT Presentation
Citation preview
Programming for Maya
• The Book (Complete Maya Programming)• Maya Help (Developer Resources, Commands, Nodes,
API Classes)• MEL Scripts
– Can be really easy to test– Can see how Maya does its own with echo– Hard to get complex data structures– Slower, due to interpretation
• C++ API Plug-ins– Very confusing at first, hard to find help / concise examples– Faster, due to machine language
Topics
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples
Simple Scene in Maya• 3D View, Hypergraph,
and Outliner• Using built in
functionality• Mocap driven
animation
Nodes, Plugs, and Attributes
Note: I’m zooming in on LilyGeometry to get the 2nd image
Turning Character into Smoke
• Create a built in fluid container• Have the vertices on Lily’s surface generate density values• Requires a way to link Lily’s output geometry to the fluid
container’s density values in the hypergraph• Note: Lily’s input geometry is driven by her original mesh +
skeletal rig and smooth skin binding
Using a Plug-in (1)• Add new nodes and
commands to Maya• Requires one to load
the plug-in
Using a Plug-in (2)
• Select the required components
• Run the command
Tweak the SmokeNode1 Attributes
Topics
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples
Create a Visual C++ Project• The project creation wizard may not be
installed (or doesn’t work correctly)• 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\Alias\Maya8.0\include
• C/C++ -> Preprocessor -> Preprocessor Definitions: WIN32;NDEBUG;_WINDOWS;NT_PLUGIN
• Linker -> General -> Output File: change the .dll to .mll
• Linker-> General -> Additional Libarary: C:\Program Files\Alias\Maya8.0\lib
• Linker -> Input -> Additional Dependencies: opengl32.lib Foundation.lib OpenMaya.lib OpenMayaUI.lib OpenMayaAnim.lib OpenMayaFX.lib OpenMayaRender.lib
• Linker -> CommandLine -> Additional Options: /export:initializePlugin /export:uninitializePlugin
Required Code (main.cpp)#include <maya/MFnPlugin>#include <maya/MObject>#include <maya/MStatus>
MStatus initializePlugin(MObject obj){ MStatus stat; MFnPlugin plugin(obj, "Brent Haley",
“1.0", “8.0"); 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
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples
Example Command• Specification
class GeomToDensityCmd: 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 *GeomToDensityCmd::creator(){
return new GeomToDensityCm;}MStatus GeomToDensityCmd::redoIt(){
//commit the work set in doItMStatus stat = dagMod.doIt();return(stat);
}MStatus GeomToDensityCmd::undoIt(){
//erase any work set in doItMStatus stat = dagMod.undoIt();return(stat);
}bool GeomToDensityCmd::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 day 2 VC++ examples
(De)Register the Command
• Register commands in the initializePlugin procedure (from the required bit of code)
stat = plugin.registerCommand(
“geom2smoke",
GeomToDensityCmd::creator);
if (!stat) MGlobal::displayError("register MudBoxCommand failed");
• Deregister commands in the unitializePlugin procedure
stat = plugin.deregisterCommand(“geom2smoke");
if (!stat) MGlobal::displayError("deregister MudBoxCommand failed");
Topics
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples
Example Node• Specification
class SmokeNode : public MPxNode{public:
//identifierstatic MTypeId id;//attributesstatic MObject filterSize;…//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 (no compute)
void *SmokeNode::creator(){return new SmokeNode;}MStatus SmokeNode::initialize() {
//create the attributesMFnNumericAttribute fsAttribute;filterSize = fsAttribute.create(“filterSize", “fs", MFnNumericData::kInt, 0);...//add the attributes to the nodeaddAttribute(filterSize);...//specify attribute relationsattributeAffects(filterSize,is2D);...//return without errorreturn(MS::kSuccess);
}
Compute• Where the actual work is done
MStatus SmokeNode::compute (const MPlug &plug, MDataBlock &data) { MStatus stat; //determine which output plug needs to be computed if (plug == is2D) { //get input data handles MDataHandle filterSizeData = data.inputValue(filterSize); ... //turn input handles into data int fs = filterSizeData.asInt(); ... //get output data handles MDataHandle cfdData = data.outputValue(is2D); //turn output handles into data <SNIP> //set the output data and mark the plug cfdData.set(false); 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(“SmokeNode",SmokeNode::id,SmokeNode::creator,SmokeNode::initialize);
if (!stat) MGlobal::displayError("register SmokeNode failed");
• Deregister nodes in the uninitializePlugin procedure
stat = plugin.deregisterNode(SmokeNode::id);if (!stat) MGlobal::displayError("deregister SmokeNode
failed");
Topics
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples
Warnings (1)
• Node Ids need to be unique
• Bad:
• Good:
In NodeA’s implementation: MTypeId NodeA::id(0x43215);
In NodeB’s implementation: MTypeId NodeB::id(0x43215);
In NodeA’s implementation: MTypeId NodeA::id(0x43215);
In NodeB’s implementation: MTypeId NodeB::id(0x43216);
Warnings (2)• Attribute affects shouldn’t be multi-level
• Create several nodes instead of trying to accomplish everything in a single node
• Bad:
• Good:
In NodeA’s initialize() procedure:
attributeAffects(X,Y);
attributeAffects(Y,Z);
In NodeA’s initialize() procedure: attributeAffects(X,Y);
In NodeB’s initialize() procedure: attributeAffects(S,T);
Where Y’s output is plugged into S’s input
Warnings (3)
• Don’t create cyclic structures in the hypergraph (can result in infinite loops)
Warnings (4)
• Per-frame node evaluation will occur in chunks if you use the rendering farm– Don’t rely on old values from the previous
frame in your code since they may not exist– Alternatively (if you really need to),
• Explicitly step the time back for each frame• Particles can be cached• Dynamics can be forced to run from the start time
to the current time before rendering each frame
Topics
• Day 1– Plug-in Introduction– How to Create a MLL– Command Basics– Node Basics– Warnings
• Day 2– VC++ Examples