PDA

View Full Version : Accessing a mesh's material in Maya API


Sennah
01-09-2010, 06:26 PM
I've been trying to accomplish this for several days and it's not working. I've read the source for the gpExport plug-in and did exactly like they did; Find the connected shaders to the mesh, get the "surfaceShader" plug and find its members. When I do this it only finds the "outColor" attribute of the material/shader. The full name of that attribute is "lambert1.outColor" and my material I use is called "lambert1" so obviously I thought it was possible to somehow access the material since I'm accessing one of its children, but after days of trying I've given up.

I've actually found a function called "parent()" which is supposed to return the MObject of the parent but it's NULL.

My questions are:
1) Isn't outColor a child/attribute of the MMaterial?
2) If it is, is it possible to access the lambert1 object at all?
3) How could I solve this mess? I just want to find the material of the mesh and access the textures and other attributes.

cbamber85
01-10-2010, 10:21 AM
Normally a material is just a dependency node, and as such has a completely variable number/type of attributes, so there cannot be a pre-determined MFn object for it. But because Maya ships with some, there are MFnBlinnShader, MFnLambertShader, etc. Personally, I wouldn't touch them as all somebody has to do is connect an MR shader or a custom shader and your plugin will fall apart.

So, I'd get your MPlug that refers to <shaderNode>.outColor and then call node() to get the MObject of the dependency node, push that into an MFnDependencyNode and then call findPlug() to get an MPlug to the attributes you want.

By the way parent() returns an MObject to the 'root' of a compound attribute, as .outColor is the parent, a NULL is expected - you are already at the parent!

Sennah
01-10-2010, 10:28 AM
Thanks a lot for this! I really appreciate it, though I wonder:

1) Do you know how I then could find out if a texture has been used for a specific attribute in the material? Let's say I want to find out if the user has chosen to use a map for the specular values and I need to know if there's a specular map in use or just a value for the whole material.
2) Do you know if it's actually possible to find the file names of the textures used in the material this way?
3) I've been trying to find a list of attribute names but no luck, also have I not understood how I should use the MObject to represent an attribute (maybe just looking in the wrong place, haven't actually spent much time on this part).

cbamber85
01-10-2010, 11:48 AM
1. Just test if anything is connected to the attribute (MPlug::isConnected()), if it is, get an MPlug to it.
2. The texture file name is just another attribute, query it.
3. The attributes for all the nodes are listed in the help file, also there are MEL commands that can return them. MObjects are kind of like void pointers, in this scenario put them into an MPlug to get attribute data.

Sennah
01-11-2010, 06:03 PM
It has no plugs connected to it apart for the surfaceShader plug/node. I've now also been going through OGRE's Maya export plug-in and it does the same thing as the gpExport plug-in. I find all connected shaders (which are connected to the mesh) and I loop through them and search for the "surfaceShader" node which I find all connections for. In this case I find a node which has the MFn::kLambert but the only plug/node it's connected to is the "outColor" which is just a float3. I've tried with more than 1 Maya mesh file containing mesh(es) which have materials with textures.


MObjectArray shaders;
MIntArray indices;
fnMesh.getConnectedShaders(0, shaders, indices);
for(uint i = 0; i < shaders.length(); i++)
{
MPlugArray connections;
MFnDependencyNode shaderGroup(shaders[i]);
MPlug shaderPlug = shaderGroup.findPlug("surfaceShader");
shaderPlug.connectedTo(connections, true, false);
for(uint u = 0; u < connections.length(); u++)
{
if(connections[u].node().hasFn(MFn::kLambert))
{
MPlugArray plugs;
MFnLambertShader lambertShader(connections[u].node());
lambertShader.findPlug("color").connectedTo(plugs, true, false);
for(uint y = 0; y < plugs.length(); y++)
{
std::cout << plugs[y].name().asChar() << std::endl;
std::cout.flush();
}
}
}
}

This is the code, and fnMesh is a mesh found in the DAG.

I'll try to rewrite the other exporters' codes and try them and see if they work. If anyone finds anything weird please let me now, several weeks have passed and still no success >.<

Thanks in advance!

Keilun
01-11-2010, 08:24 PM
The code looks straightforward. Are you sure there are connections coming into the "color" attribute of that lambert1?

Note that you don't have to limit yourself to a lambert shader. You could use MFnDependencyNode and be just fine, since those are the only methods you're using (which MFnLambertShader inherits). One thing you might want to check is the ReturnStatus field, to identify if any particular call is failing and why.

Also just FYI:

The outColor attribute of a shader node does not represent actual data passing through the DG. The connection from outColor to surfaceShader is a special kind of connection when the Maya software renderer is used. For other renderers, this is merely a notational concept identifying which shader is responsible for the surfaceShader of that shading group.

CGTalk Moderation
01-11-2010, 08:24 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.