Panda3D
mayaShaders.cxx
1 // Filename: mayaShaders.cxx
2 // Created by: drose (11Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "mayaShaders.h"
16 #include "mayaShader.h"
17 #include "maya_funcs.h"
18 #include "config_maya.h"
19 
20 #include "pre_maya_include.h"
21 #include <maya/MStatus.h>
22 #include <maya/MObject.h>
23 #include <maya/MFnDependencyNode.h>
24 #include <maya/MFnMesh.h>
25 #include <maya/MObjectArray.h>
26 #include <maya/MPlug.h>
27 #include <maya/MPlugArray.h>
28 #include <maya/MFn.h>
29 #include "post_maya_include.h"
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: MayaShaders::Constructor
33 // Access: Public
34 // Description:
35 ////////////////////////////////////////////////////////////////////
36 MayaShaders::
37 MayaShaders() {
38 }
39 
40 ////////////////////////////////////////////////////////////////////
41 // Function: MayaShaders::Destructor
42 // Access: Public
43 // Description:
44 ////////////////////////////////////////////////////////////////////
45 MayaShaders::
46 ~MayaShaders() {
47  clear();
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: MayaShaders::find_shader_for_node
52 // Access: Public
53 // Description: Extracts the shader assigned to the indicated node.
54 ////////////////////////////////////////////////////////////////////
56 find_shader_for_node(MObject node, bool legacy_shader) {
57  MStatus status;
58  MFnDependencyNode node_fn(node);
59  // Look on the instObjGroups attribute for shading engines.
60  MObject iog_attr = node_fn.attribute("instObjGroups", &status);
61  if (!status) {
62  // The node is not renderable. What are you thinking?
63  maya_cat.error()
64  << node_fn.name().asChar() << " : not a renderable object.\n";
65  return (MayaShader *)NULL;
66  }
67 
68  // instObjGroups is a multi attribute, whatever that means. For
69  // now, we'll just get the first connection, since that's what the
70  // example code did. Is there any reason to search deeper?
71 
72  MPlug iog_plug(node, iog_attr);
73  MPlugArray iog_pa;
74  iog_plug.elementByLogicalIndex(0).connectedTo(iog_pa, false, true, &status);
75  if (!status) {
76  // No shading group defined for this object.
77  maya_cat.error()
78  << node_fn.name().asChar() << " : no shading group defined.\n";
79  return (MayaShader *)NULL;
80  }
81 
82  // Now we have a number of ShadingEngines defined, one for each of
83  // these connections we just turned up. Usually there will only be
84  // one. In fact, we'll just take the first one we find.
85 
86  size_t i;
87  for (i = 0; i < iog_pa.length(); i++) {
88  MObject engine = iog_pa[i].node();
89  if (engine.hasFn(MFn::kShadingEngine)) {
90  return find_shader_for_shading_engine(engine, legacy_shader);
91  }
92  }
93 
94  // Well, we didn't find a ShadingEngine after all. Huh.
95  maya_cat.debug()
96  << node_fn.name().asChar() << " : no shading engine found.\n";
97  return (MayaShader *)NULL;
98 }
99 
100 ////////////////////////////////////////////////////////////////////
101 // Function: MayaShaders::bind_uvsets
102 // Access: Public
103 // Description: Causes all shaders in the set to use the given
104 // mesh as a file-to-uvset map.
105 ////////////////////////////////////////////////////////////////////
106 void MayaShaders::
107 bind_uvsets(MObject mesh) {
108  _uvset_names.clear();
109  _file_to_uvset.clear();
110 
111  if (mesh.hasFn(MFn::kMesh)) {
112  MFnMesh mesh_fn(mesh);
113  MStatus status;
114  MStringArray maya_uvset_names;
115  status = mesh_fn.getUVSetNames(maya_uvset_names);
116  for (size_t i=0; i<maya_uvset_names.length(); ++i) {
117  MObjectArray moa;
118  string uvset_name = maya_uvset_names[i].asChar();
119  _uvset_names.push_back(uvset_name);
120  mesh_fn.getAssociatedUVSetTextures(maya_uvset_names[i], moa);
121  for (size_t j=0; j<moa.length(); ++j){
122  MFnDependencyNode dt(moa[j]);
123  string tex_name = dt.name().asChar();
124  _file_to_uvset[tex_name] = uvset_name;
125  }
126  }
127  }
128 
129  Shaders::iterator sha;
130  for (sha=_shaders.begin(); sha!=_shaders.end(); sha++) {
131  (*sha).second->bind_uvsets(_file_to_uvset);
132  }
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: MayaShaders::find_shader_for_shading_engine
137 // Access: Public
138 // Description: Returns the MayaShader object associated with the
139 // indicated "shading engine". This will create a new
140 // MayaShader object if this is the first time we have
141 // encountered the indicated engine.
142 ////////////////////////////////////////////////////////////////////
144 find_shader_for_shading_engine(MObject engine, bool legacy_shader) {
145  MFnDependencyNode engine_fn(engine);
146  // See if we have already decoded this engine.
147  string engine_name = engine_fn.name().asChar();
148  Shaders::const_iterator si = _shaders.find(engine_name);
149  if (si != _shaders.end()) {
150  return (*si).second;
151  }
152 
153  // All right, this is a newly encountered shading engine. Create a
154  // new MayaShader object to represent it.
155  MayaShader *shader = new MayaShader(engine, legacy_shader);
156  shader->bind_uvsets(_file_to_uvset);
157 
158  // Record this for the future.
159  _shaders.insert(Shaders::value_type(engine_name, shader));
160  _shaders_in_order.push_back(shader);
161  return shader;
162 }
163 
164 ////////////////////////////////////////////////////////////////////
165 // Function: MayaShaders::find_uv_link
166 // Access: Public
167 // Description: Returns the current mapping from file to uvset
168 // for the given file texture name.
169 ////////////////////////////////////////////////////////////////////
170 string MayaShaders::
171 find_uv_link(const string &match) {
172  MayaFileToUVSetMap::iterator it = _file_to_uvset.find(match);
173  if (it == _file_to_uvset.end()) {
174  return "not found";
175  } else {
176  return (*it).second;
177  }
178 }
179 
180 ////////////////////////////////////////////////////////////////////
181 // Function: MayaShaders::get_num_shaders
182 // Access: Public
183 // Description: Returns the number of unique MayaShaders that have
184 // been discovered so far.
185 ////////////////////////////////////////////////////////////////////
186 int MayaShaders::
188  return _shaders_in_order.size();
189 }
190 
191 ////////////////////////////////////////////////////////////////////
192 // Function: MayaShaders::get_shader
193 // Access: Public
194 // Description: Returns the nth MayaShader that has been discovered
195 // so far.
196 ////////////////////////////////////////////////////////////////////
198 get_shader(int n) const {
199  nassertr(n >= 0 && n < (int)_shaders_in_order.size(), NULL);
200  return _shaders_in_order[n];
201 }
202 
203 ////////////////////////////////////////////////////////////////////
204 // Function: MayaShaders::clear
205 // Access: Public
206 // Description: Frees all of the previously-defined MayaShader
207 // objects associated with this set.
208 ////////////////////////////////////////////////////////////////////
209 void MayaShaders::
210 clear() {
211  ShadersInOrder::iterator si;
212  for (si = _shaders_in_order.begin(); si != _shaders_in_order.end(); ++si) {
213  delete (*si);
214  }
215 
216  _shaders.clear();
217  _shaders_in_order.clear();
218  _file_to_uvset.clear();
219 }
void bind_uvsets(MObject mesh)
Causes all shaders in the set to use the given mesh as a file-to-uvset map.
MayaShader * find_shader_for_node(MObject node, bool legacy_shader)
Extracts the shader assigned to the indicated node.
Definition: mayaShaders.cxx:56
string find_uv_link(const string &match)
Returns the current mapping from file to uvset for the given file texture name.
MayaShader * get_shader(int n) const
Returns the nth MayaShader that has been discovered so far.
Corresponds to a single "shader" in Maya.
Definition: mayaShader.h:35
MayaShader * find_shader_for_shading_engine(MObject engine, bool legacy_shader)
Returns the MayaShader object associated with the indicated "shading engine".
MayaShader(MObject engine, bool legacy_shader)
Reads the Maya "shading engine" to determine the relevant shader properties.
Definition: mayaShader.cxx:43
void clear()
Frees all of the previously-defined MayaShader objects associated with this set.
int get_num_shaders() const
Returns the number of unique MayaShaders that have been discovered so far.
void bind_uvsets(MayaFileToUVSetMap &map)
Assigns the uvset_name of each MayaShaderColorDef using the given file-to-uvset map.
Definition: mayaShader.cxx:274