Finding Materials

This note is about how to find materials in Maya API and Max SDK. In Maya, we use MItDag to walk through all meshes to look for attached materials. All types of geometry, mesh, NURBS surface, SubDiv, could have material, but for simplicity, here only meshes are listed.

MItDag itdag(MItDag::kDepthFirst, MFn::kMesh);
for
(; !itdag.isDone(); itdag.next())
{
MDagPath path;
itdag.getPath(path);

MObject omesh = itdag.currentItem();

// find the material and do something to it

}

There is no direct connection between mesh and material, there are linked up via a Shading Engine (or SG). Find the SG by MItDependencyGraph go downstream:

MObject findShadingEngine(MObject &mesh)
{
MStatus result;
MItDependencyGraph itdep(mesh, MFn::kShadingEngine, MItDependencyGraph::kDownstream, MItDependencyGraph::kDepthFirst, MItDependencyGraph::kNodeLevel, &result);
for(; !itdep.isDone(); itdep.next())
{
return itdep.currentItem();
}
return MObject::kNullObj;
}

Then go upstream from the “surfaceShader” plug of SG to find the material. Only lambert, blinn, and phong is listed here:

MObject findMaterial(MObject &mesh)
{
MObject osg = findShadingEngine(mesh);
if(osg == MObject::kNullObj)
return osg;
MStatus result;
MPlug plgsurface = MFnDependencyNode(osg).findPlug("surfaceShader");
MItDependencyGraph itdep(plgsurface, MFn::kInvalid, MItDependencyGraph::kUpstream, MItDependencyGraph::kDepthFirst, MItDependencyGraph::kNodeLevel, &result);
for(; !itdep.isDone(); itdep.next())
{
MObject ocur = itdep.currentItem();
if(ocur.hasFn(MFn::kLambert) || ocur.hasFn(MFn::kBlinn) || ocur.hasFn(MFn::kPhong))
return ocur;
}
return MObject::kNullObj;
}

Now we have the MObject pointed to the material ready for further operation.

In Max, there is nothing like MItDag, I do it myself:

void lsChildNode( INode *parent, std::vector<INode *>& nodeList)
{
int objectCount = parent->NumberOfChildren();
for(int i = 0; i < objectCount; i++)
{
INode* cur = parent->GetChildNode(i);
nodeList.push_back(cur);
lsChildNode( cur, nodeList);
}
}
void lsAllNodeInScene(std::vector<INode *>& nodeList)
{
Interface* ip = GetCOREInterface();
INode* parent = ip->GetRootNode();
int objectCount = parent->NumberOfChildren();
for(int i = 0; i < objectCount; i++)
{
INode* cur = parent->GetChildNode(i);
nodeList.push_back(cur);
lsChildNode( cur, nodeList);
}
}

It starts with scene root, lists everything under it, generating a long list of INode. Material is accessed directly by INode::GetMtl()

for(int i=0; i < allNode.size(); i++)
{
Mtl* m =  allNode[i]->GetMtl();
if(m) do_something_to(m);
}
Advertisements

Leave a comment

Filed under Max SDK, Maya API

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s