Panda3D

mayaShaders.cxx

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