Panda3D

mayaShaders.cxx

00001 // Filename: mayaShaders.cxx
00002 // Created by:  drose (11Feb00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "mayaShaders.h"
00016 #include "mayaShader.h"
00017 #include "maya_funcs.h"
00018 #include "config_maya.h"
00019 
00020 #include "pre_maya_include.h"
00021 #include <maya/MStatus.h>
00022 #include <maya/MObject.h>
00023 #include <maya/MFnDependencyNode.h>
00024 #include <maya/MFnMesh.h>
00025 #include <maya/MObjectArray.h>
00026 #include <maya/MPlug.h>
00027 #include <maya/MPlugArray.h>
00028 #include <maya/MFn.h>
00029 #include "post_maya_include.h"
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: MayaShaders::Constructor
00033 //       Access: Public
00034 //  Description:
00035 ////////////////////////////////////////////////////////////////////
00036 MayaShaders::
00037 MayaShaders() {
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: MayaShaders::Destructor
00042 //       Access: Public
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 MayaShaders::
00046 ~MayaShaders() {
00047   clear();
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: MayaShaders::find_shader_for_node
00052 //       Access: Public
00053 //  Description: Extracts the shader assigned to the indicated node.
00054 ////////////////////////////////////////////////////////////////////
00055 MayaShader *MayaShaders::
00056 find_shader_for_node(MObject node, bool legacy_shader) {
00057   MStatus status;
00058   MFnDependencyNode node_fn(node);
00059   // Look on the instObjGroups attribute for shading engines.
00060   MObject iog_attr = node_fn.attribute("instObjGroups", &status);
00061   if (!status) {
00062     // The node is not renderable.  What are you thinking?
00063     maya_cat.error()
00064       << node_fn.name().asChar() << " : not a renderable object.\n";
00065     return (MayaShader *)NULL;
00066   }
00067 
00068   // instObjGroups is a multi attribute, whatever that means.  For
00069   // now, we'll just get the first connection, since that's what the
00070   // example code did.  Is there any reason to search deeper?
00071 
00072   MPlug iog_plug(node, iog_attr);
00073   MPlugArray iog_pa;
00074   iog_plug.elementByLogicalIndex(0).connectedTo(iog_pa, false, true, &status);
00075   if (!status) {
00076     // No shading group defined for this object.
00077     maya_cat.error()
00078       << node_fn.name().asChar() << " : no shading group defined.\n";
00079     return (MayaShader *)NULL;
00080   }
00081 
00082   // Now we have a number of ShadingEngines defined, one for each of
00083   // these connections we just turned up.  Usually there will only be
00084   // one.  In fact, we'll just take the first one we find.
00085 
00086   size_t i;
00087   for (i = 0; i < iog_pa.length(); i++) {
00088     MObject engine = iog_pa[i].node();
00089     if (engine.hasFn(MFn::kShadingEngine)) {
00090       return find_shader_for_shading_engine(engine, legacy_shader);
00091     }
00092   }
00093 
00094   // Well, we didn't find a ShadingEngine after all.  Huh.
00095   maya_cat.debug()
00096     << node_fn.name().asChar() << " : no shading engine found.\n";
00097   return (MayaShader *)NULL;
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: MayaShaders::bind_uvsets
00102 //       Access: Public
00103 //  Description: Causes all shaders in the set to use the given
00104 //               mesh as a file-to-uvset map.
00105 ////////////////////////////////////////////////////////////////////
00106 void MayaShaders::
00107 bind_uvsets(MObject mesh) {
00108   _uvset_names.clear();
00109   _file_to_uvset.clear();
00110   
00111   if (mesh.hasFn(MFn::kMesh)) {
00112     MFnMesh mesh_fn(mesh);
00113     MStatus status;
00114     MStringArray maya_uvset_names;
00115     status = mesh_fn.getUVSetNames(maya_uvset_names);
00116     for (size_t i=0; i<maya_uvset_names.length(); ++i) {
00117       MObjectArray moa;
00118       string uvset_name = maya_uvset_names[i].asChar();
00119       _uvset_names.push_back(uvset_name);
00120       mesh_fn.getAssociatedUVSetTextures(maya_uvset_names[i], moa);
00121       for (size_t j=0; j<moa.length(); ++j){
00122         MFnDependencyNode dt(moa[j]);
00123         string tex_name = dt.name().asChar();
00124         _file_to_uvset[tex_name] = uvset_name;
00125       }
00126     }
00127   }
00128   
00129   Shaders::iterator sha;
00130   for (sha=_shaders.begin(); sha!=_shaders.end(); sha++) {
00131     (*sha).second->bind_uvsets(_file_to_uvset);
00132   }
00133 }
00134 
00135 ////////////////////////////////////////////////////////////////////
00136 //     Function: MayaShaders::find_shader_for_shading_engine
00137 //       Access: Public
00138 //  Description: Returns the MayaShader object associated with the
00139 //               indicated "shading engine".  This will create a new
00140 //               MayaShader object if this is the first time we have
00141 //               encountered the indicated engine.
00142 ////////////////////////////////////////////////////////////////////
00143 MayaShader *MayaShaders::
00144 find_shader_for_shading_engine(MObject engine, bool legacy_shader) {
00145   MFnDependencyNode engine_fn(engine);
00146   // See if we have already decoded this engine.
00147   string engine_name = engine_fn.name().asChar();
00148   Shaders::const_iterator si = _shaders.find(engine_name);
00149   if (si != _shaders.end()) {
00150     return (*si).second;
00151   }
00152 
00153   // All right, this is a newly encountered shading engine.  Create a
00154   // new MayaShader object to represent it.
00155   MayaShader *shader = new MayaShader(engine, legacy_shader);
00156   shader->bind_uvsets(_file_to_uvset);
00157   
00158   // Record this for the future.
00159   _shaders.insert(Shaders::value_type(engine_name, shader));
00160   _shaders_in_order.push_back(shader);
00161   return shader;
00162 }
00163 
00164 ////////////////////////////////////////////////////////////////////
00165 //     Function: MayaShaders::find_uv_link
00166 //       Access: Public
00167 //  Description: Returns the current mapping from file to uvset
00168 //               for the given file texture name.  
00169 ////////////////////////////////////////////////////////////////////
00170 string MayaShaders::
00171 find_uv_link(const string &match) {
00172   MayaFileToUVSetMap::iterator it = _file_to_uvset.find(match);
00173   if (it == _file_to_uvset.end()) {
00174     return "not found";
00175   } else {
00176     return (*it).second;
00177   }
00178 }
00179 
00180 ////////////////////////////////////////////////////////////////////
00181 //     Function: MayaShaders::get_num_shaders
00182 //       Access: Public
00183 //  Description: Returns the number of unique MayaShaders that have
00184 //               been discovered so far.
00185 ////////////////////////////////////////////////////////////////////
00186 int MayaShaders::
00187 get_num_shaders() const {
00188   return _shaders_in_order.size();
00189 }
00190 
00191 ////////////////////////////////////////////////////////////////////
00192 //     Function: MayaShaders::get_shader
00193 //       Access: Public
00194 //  Description: Returns the nth MayaShader that has been discovered
00195 //               so far.
00196 ////////////////////////////////////////////////////////////////////
00197 MayaShader *MayaShaders::
00198 get_shader(int n) const {
00199   nassertr(n >= 0 && n < (int)_shaders_in_order.size(), NULL);
00200   return _shaders_in_order[n];
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: MayaShaders::clear
00205 //       Access: Public
00206 //  Description: Frees all of the previously-defined MayaShader
00207 //               objects associated with this set.
00208 ////////////////////////////////////////////////////////////////////
00209 void MayaShaders::
00210 clear() {
00211   ShadersInOrder::iterator si;
00212   for (si = _shaders_in_order.begin(); si != _shaders_in_order.end(); ++si) {
00213     delete (*si);
00214   }
00215 
00216   _shaders.clear();
00217   _shaders_in_order.clear();
00218   _file_to_uvset.clear();
00219 }
 All Classes Functions Variables Enumerations