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