Panda3D
|
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 }