1 | #include "material.h"
|
---|
2 |
|
---|
3 | namespace OgreMayaExporter
|
---|
4 | {
|
---|
5 | // Constructor
|
---|
6 | Material::Material()
|
---|
7 | {
|
---|
8 | clear();
|
---|
9 | }
|
---|
10 |
|
---|
11 |
|
---|
12 | // Destructor
|
---|
13 | Material::~Material()
|
---|
14 | {
|
---|
15 | }
|
---|
16 |
|
---|
17 |
|
---|
18 | // Get material name
|
---|
19 | MString& Material::name()
|
---|
20 | {
|
---|
21 | return m_name;
|
---|
22 | }
|
---|
23 |
|
---|
24 |
|
---|
25 | // Clear data
|
---|
26 | void Material::clear()
|
---|
27 | {
|
---|
28 | m_name = "";
|
---|
29 | m_type = MT_LAMBERT;
|
---|
30 | m_lightingOff = false;
|
---|
31 | m_isTransparent = false;
|
---|
32 | m_isTextured = false;
|
---|
33 | m_isMultiTextured = false;
|
---|
34 | m_ambient = MColor(0,0,0,0);
|
---|
35 | m_diffuse = MColor(0,0,0,0);
|
---|
36 | m_specular = MColor(0,0,0,0);
|
---|
37 | m_emissive = MColor(0,0,0,0);
|
---|
38 | m_textures.clear();
|
---|
39 | }
|
---|
40 |
|
---|
41 |
|
---|
42 | // Load material data
|
---|
43 | MStatus Material::load(MFnLambertShader* pShader,MStringArray& uvsets,ParamList& params)
|
---|
44 | {
|
---|
45 | MStatus stat;
|
---|
46 | clear();
|
---|
47 | //read material name, adding the requested prefix
|
---|
48 | m_name = params.matPrefix;
|
---|
49 | if (m_name != "")
|
---|
50 | m_name += "/";
|
---|
51 | m_name += pShader->name();
|
---|
52 | //check if we want to export with lighting off option
|
---|
53 | m_lightingOff = params.lightingOff;
|
---|
54 |
|
---|
55 | MFnPhongShader* pPhong = NULL;
|
---|
56 | MFnBlinnShader* pBlinn = NULL;
|
---|
57 | MPlugArray colorSrcPlugs;
|
---|
58 | MPlugArray texSrcPlugs;
|
---|
59 | MPlugArray placetexSrcPlugs;
|
---|
60 |
|
---|
61 | // GET MATERIAL DATA
|
---|
62 |
|
---|
63 | // Check material type
|
---|
64 | if (pShader->object().hasFn(MFn::kPhong))
|
---|
65 | {
|
---|
66 | m_type = MT_PHONG;
|
---|
67 | pPhong = new MFnPhongShader(pShader->object());
|
---|
68 | }
|
---|
69 | else if (pShader->object().hasFn(MFn::kBlinn))
|
---|
70 | {
|
---|
71 | m_type = MT_BLINN;
|
---|
72 | pBlinn = new MFnBlinnShader(pShader->object());
|
---|
73 | }
|
---|
74 |
|
---|
75 | // Check if material is textured
|
---|
76 | pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
|
---|
77 | for (int i=0; i<colorSrcPlugs.length(); i++)
|
---|
78 | {
|
---|
79 | if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
|
---|
80 | {
|
---|
81 | m_isTextured = true;
|
---|
82 | continue;
|
---|
83 | }
|
---|
84 | else if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
|
---|
85 | {
|
---|
86 | m_isTextured = true;
|
---|
87 | m_isMultiTextured = true;
|
---|
88 | continue;
|
---|
89 | }
|
---|
90 | }
|
---|
91 |
|
---|
92 | // Check if material is transparent
|
---|
93 | if (pShader->findPlug("transparency").isConnected() || pShader->transparency().r>0.0f)
|
---|
94 | m_isTransparent = true;
|
---|
95 |
|
---|
96 | // Get material colours
|
---|
97 | //diffuse colour
|
---|
98 | if (m_isTextured)
|
---|
99 | m_diffuse = MColor(1.0,1.0,1.0,1.0);
|
---|
100 | else
|
---|
101 | {
|
---|
102 | m_diffuse = pShader->color();
|
---|
103 | m_diffuse.a = 1.0 - pShader->transparency().r;
|
---|
104 | }
|
---|
105 | //ambient colour
|
---|
106 | m_ambient = m_diffuse;
|
---|
107 | //emissive colour
|
---|
108 | m_emissive = pShader->incandescence();
|
---|
109 | //specular colour
|
---|
110 | switch(m_type)
|
---|
111 | {
|
---|
112 | case MT_PHONG:
|
---|
113 | m_specular = pPhong->specularColor();
|
---|
114 | m_specular.a = pPhong->cosPower();
|
---|
115 | break;
|
---|
116 | case MT_BLINN:
|
---|
117 | m_specular = pBlinn->specularColor();
|
---|
118 | m_specular.a = 1.0 / pBlinn->eccentricity();
|
---|
119 | break;
|
---|
120 | default:
|
---|
121 | m_specular = MColor(0.0,0.0,0.0,0.0);
|
---|
122 | }
|
---|
123 |
|
---|
124 | // Get textures data
|
---|
125 | if (m_isTextured)
|
---|
126 | {
|
---|
127 | // Translate multiple textures if material is multitextured
|
---|
128 | if (m_isMultiTextured)
|
---|
129 | {
|
---|
130 | // Get layered texture node
|
---|
131 | MFnDependencyNode* pLayeredTexNode = NULL;
|
---|
132 | pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
|
---|
133 | for (i=0; i<colorSrcPlugs.length(); i++)
|
---|
134 | {
|
---|
135 | if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
|
---|
136 | {
|
---|
137 | pLayeredTexNode = new MFnDependencyNode(colorSrcPlugs[i].node());
|
---|
138 | continue;
|
---|
139 | }
|
---|
140 | }
|
---|
141 |
|
---|
142 | // Get inputs to layered texture
|
---|
143 | MPlug inputsPlug = pLayeredTexNode->findPlug("inputs");
|
---|
144 |
|
---|
145 | // Scan inputs and export textures
|
---|
146 | for (i=inputsPlug.numElements()-1; i>=0; i--)
|
---|
147 | {
|
---|
148 | MFnDependencyNode* pTextureNode = NULL;
|
---|
149 | // Search for a connected texture
|
---|
150 | inputsPlug[i].child(0).connectedTo(colorSrcPlugs,true,false);
|
---|
151 | for (int j=0; j<colorSrcPlugs.length(); j++)
|
---|
152 | {
|
---|
153 | if (colorSrcPlugs[j].node().hasFn(MFn::kFileTexture))
|
---|
154 | {
|
---|
155 | pTextureNode = new MFnDependencyNode(colorSrcPlugs[j].node());
|
---|
156 | continue;
|
---|
157 | }
|
---|
158 | }
|
---|
159 |
|
---|
160 | // Translate the texture if it was found
|
---|
161 | if (pTextureNode)
|
---|
162 | {
|
---|
163 | // Get blend mode
|
---|
164 | TexOpType opType;
|
---|
165 | short bm;
|
---|
166 | inputsPlug[i].child(2).getValue(bm);
|
---|
167 | switch(bm)
|
---|
168 | {
|
---|
169 | case 0:
|
---|
170 | opType = TOT_REPLACE;
|
---|
171 | break;
|
---|
172 | case 1:
|
---|
173 | opType = TOT_ALPHABLEND;
|
---|
174 | break;
|
---|
175 | case 4:
|
---|
176 | opType = TOT_ADD;
|
---|
177 | break;
|
---|
178 | case 6:
|
---|
179 | opType = TOT_MODULATE;
|
---|
180 | break;
|
---|
181 | default:
|
---|
182 | opType = TOT_MODULATE;
|
---|
183 | }
|
---|
184 |
|
---|
185 | stat = loadTexture(pTextureNode,opType,uvsets,params);
|
---|
186 | delete pTextureNode;
|
---|
187 | if (MS::kSuccess != stat)
|
---|
188 | {
|
---|
189 | std::cout << "Error loading layered texture\n";
|
---|
190 | delete pLayeredTexNode;
|
---|
191 | return MS::kFailure;
|
---|
192 | }
|
---|
193 | }
|
---|
194 | }
|
---|
195 | if (pLayeredTexNode)
|
---|
196 | delete pLayeredTexNode;
|
---|
197 | }
|
---|
198 | // Else translate the single texture
|
---|
199 | else
|
---|
200 | {
|
---|
201 | // Get texture node
|
---|
202 | MFnDependencyNode* pTextureNode = NULL;
|
---|
203 | pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
|
---|
204 | for (i=0; i<colorSrcPlugs.length(); i++)
|
---|
205 | {
|
---|
206 | if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
|
---|
207 | {
|
---|
208 | pTextureNode = new MFnDependencyNode(colorSrcPlugs[i].node());
|
---|
209 | continue;
|
---|
210 | }
|
---|
211 | }
|
---|
212 | if (pTextureNode)
|
---|
213 | {
|
---|
214 | TexOpType opType = TOT_MODULATE;
|
---|
215 | stat = loadTexture(pTextureNode,opType,uvsets,params);
|
---|
216 | delete pTextureNode;
|
---|
217 | if (MS::kSuccess != stat)
|
---|
218 | {
|
---|
219 | std::cout << "Error loading texture\n";
|
---|
220 | return MS::kFailure;
|
---|
221 | }
|
---|
222 | }
|
---|
223 | }
|
---|
224 | }
|
---|
225 | // Free up memory
|
---|
226 | if (pPhong)
|
---|
227 | delete pPhong;
|
---|
228 | if (pBlinn)
|
---|
229 | delete pBlinn;
|
---|
230 |
|
---|
231 | return MS::kSuccess;
|
---|
232 | }
|
---|
233 |
|
---|
234 |
|
---|
235 | // Load texture data from a texture node
|
---|
236 | MStatus Material::loadTexture(MFnDependencyNode* pTexNode,TexOpType& opType,MStringArray& uvsets,ParamList& params)
|
---|
237 | {
|
---|
238 | texture tex;
|
---|
239 | // Get texture filename
|
---|
240 | MString filename, absFilename;
|
---|
241 | MRenderUtil::exactFileTextureName(pTexNode->object(),absFilename);
|
---|
242 | filename = absFilename.substring(absFilename.rindex('/')+1,absFilename.length()-1);
|
---|
243 | MString command = "toNativePath(\"";
|
---|
244 | command += absFilename;
|
---|
245 | command += "\")";
|
---|
246 | MGlobal::executeCommand(command,absFilename);
|
---|
247 | tex.absFilename = absFilename;
|
---|
248 | tex.filename = filename;
|
---|
249 | tex.uvsetIndex = 0;
|
---|
250 | tex.uvsetName = "";
|
---|
251 | // Set texture operation type
|
---|
252 | tex.opType = opType;
|
---|
253 | // Get connections to uvCoord attribute of texture node
|
---|
254 | MPlugArray texSrcPlugs;
|
---|
255 | pTexNode->findPlug("uvCoord").connectedTo(texSrcPlugs,true,false);
|
---|
256 | // Get place2dtexture node (if connected)
|
---|
257 | MFnDependencyNode* pPlace2dTexNode = NULL;
|
---|
258 | for (int j=0; j<texSrcPlugs.length(); j++)
|
---|
259 | {
|
---|
260 | if (texSrcPlugs[j].node().hasFn(MFn::kPlace2dTexture))
|
---|
261 | {
|
---|
262 | pPlace2dTexNode = new MFnDependencyNode(texSrcPlugs[j].node());
|
---|
263 | continue;
|
---|
264 | }
|
---|
265 | }
|
---|
266 | // Get uvChooser node (if connected)
|
---|
267 | MFnDependencyNode* pUvChooserNode = NULL;
|
---|
268 | if (pPlace2dTexNode)
|
---|
269 | {
|
---|
270 | MPlugArray placetexSrcPlugs;
|
---|
271 | pPlace2dTexNode->findPlug("uvCoord").connectedTo(placetexSrcPlugs,true,false);
|
---|
272 | for (j=0; j<placetexSrcPlugs.length(); j++)
|
---|
273 | {
|
---|
274 | if (placetexSrcPlugs[j].node().hasFn(MFn::kUvChooser))
|
---|
275 | {
|
---|
276 | pUvChooserNode = new MFnDependencyNode(placetexSrcPlugs[j].node());
|
---|
277 | continue;
|
---|
278 | }
|
---|
279 | }
|
---|
280 | }
|
---|
281 | // Get uvset index
|
---|
282 | if (pUvChooserNode)
|
---|
283 | {
|
---|
284 | bool foundMesh = false;
|
---|
285 | bool foundUvset = false;
|
---|
286 | MPlug uvsetsPlug = pUvChooserNode->findPlug("uvSets");
|
---|
287 | MPlugArray uvsetsSrcPlugs;
|
---|
288 | for (int i=0; i<uvsetsPlug.evaluateNumElements() && !foundMesh; i++)
|
---|
289 | {
|
---|
290 | uvsetsPlug[i].connectedTo(uvsetsSrcPlugs,true,false);
|
---|
291 | for (j=0; j<uvsetsSrcPlugs.length() && !foundMesh; j++)
|
---|
292 | {
|
---|
293 | if (uvsetsSrcPlugs[j].node().hasFn(MFn::kMesh))
|
---|
294 | {
|
---|
295 | uvsetsSrcPlugs[j].getValue(tex.uvsetName);
|
---|
296 | for (int k=0; k<uvsets.length() && !foundUvset; k++)
|
---|
297 | {
|
---|
298 | if (uvsets[k] == tex.uvsetName)
|
---|
299 | {
|
---|
300 | tex.uvsetIndex = k;
|
---|
301 | foundUvset = true;
|
---|
302 | }
|
---|
303 | }
|
---|
304 | }
|
---|
305 | }
|
---|
306 | }
|
---|
307 | }
|
---|
308 | // add texture to material texture list
|
---|
309 | m_textures.push_back(tex);
|
---|
310 | // free up memory
|
---|
311 | if (pUvChooserNode)
|
---|
312 | delete pUvChooserNode;
|
---|
313 | if (pPlace2dTexNode)
|
---|
314 | delete pPlace2dTexNode;
|
---|
315 |
|
---|
316 | return MS::kSuccess;
|
---|
317 | }
|
---|
318 |
|
---|
319 |
|
---|
320 | // Write material data to Ogre XML file
|
---|
321 | MStatus Material::writeXML(ParamList ¶ms)
|
---|
322 | {
|
---|
323 | //Start material description
|
---|
324 | params.outMaterial << "material " << m_name.asChar() << "\n";
|
---|
325 | params.outMaterial << "{\n";
|
---|
326 |
|
---|
327 | //Start technique description
|
---|
328 | params.outMaterial << "\ttechnique\n";
|
---|
329 | params.outMaterial << "\t{\n";
|
---|
330 |
|
---|
331 | //Start render pass description
|
---|
332 | params.outMaterial << "\t\tpass\n";
|
---|
333 | params.outMaterial << "\t\t{\n";
|
---|
334 | //set lighting off option if requested
|
---|
335 | if (m_lightingOff)
|
---|
336 | params.outMaterial << "\t\t\tlighting off\n\n";
|
---|
337 | //ambient colour
|
---|
338 | params.outMaterial << "\t\t\tambient " << m_ambient.r << " " << m_ambient.g << " " << m_ambient.b
|
---|
339 | << " " << m_ambient.a << "\n";
|
---|
340 | //diffuse colour
|
---|
341 | params.outMaterial << "\t\t\tdiffuse " << m_diffuse.r << " " << m_diffuse.g << " " << m_diffuse.b
|
---|
342 | << " " << m_diffuse.a << "\n";
|
---|
343 | //specular colour
|
---|
344 | params.outMaterial << "\t\t\tspecular " << m_specular.r << " " << m_specular.g << " " << m_specular.b
|
---|
345 | << " " << m_specular.a << "\n";
|
---|
346 | //emissive colour
|
---|
347 | params.outMaterial << "\t\t\temissive " << m_emissive.r << " " << m_emissive.g << " "
|
---|
348 | << m_emissive.b << "\n";
|
---|
349 | //if material is transparent set blend mode and turn off depth_writing
|
---|
350 | if (m_isTransparent)
|
---|
351 | {
|
---|
352 | params.outMaterial << "\n\t\t\tscene_blend alpha_blend\n";
|
---|
353 | params.outMaterial << "\t\t\tdepth_write off\n";
|
---|
354 | }
|
---|
355 | //write texture units
|
---|
356 | for (int i=0; i<m_textures.size(); i++)
|
---|
357 | {
|
---|
358 | //start texture unit description
|
---|
359 | params.outMaterial << "\n\t\t\ttexture_unit\n";
|
---|
360 | params.outMaterial << "\t\t\t{\n";
|
---|
361 | //write texture name
|
---|
362 | params.outMaterial << "\t\t\t\ttexture " << m_textures[i].filename.asChar() << "\n";
|
---|
363 | //write texture coordinate index
|
---|
364 | params.outMaterial << "\t\t\t\ttex_coord_set " << m_textures[i].uvsetIndex << "\n";
|
---|
365 | //write colour operation
|
---|
366 | switch (m_textures[i].opType)
|
---|
367 | {
|
---|
368 | case TOT_REPLACE:
|
---|
369 | params.outMaterial << "\t\t\t\tcolour_op replace\n";
|
---|
370 | break;
|
---|
371 | case TOT_ADD:
|
---|
372 | params.outMaterial << "\t\t\t\tcolour_op add\n";
|
---|
373 | break;
|
---|
374 | case TOT_MODULATE:
|
---|
375 | params.outMaterial << "\t\t\t\tcolour_op modulate\n";
|
---|
376 | break;
|
---|
377 | case TOT_ALPHABLEND:
|
---|
378 | params.outMaterial << "\t\t\t\tcolour_op alpha_blend\n";
|
---|
379 | break;
|
---|
380 | }
|
---|
381 | //end texture unit desription
|
---|
382 | params.outMaterial << "\t\t\t}\n";
|
---|
383 | }
|
---|
384 |
|
---|
385 | //End render pass description
|
---|
386 | params.outMaterial << "\t\t}\n";
|
---|
387 |
|
---|
388 | //End technique description
|
---|
389 | params.outMaterial << "\t}\n";
|
---|
390 |
|
---|
391 | //End material description
|
---|
392 | params.outMaterial << "}\n";
|
---|
393 |
|
---|
394 | //Copy textures to output dir if required
|
---|
395 | if (params.copyTextures)
|
---|
396 | copyTextures(params);
|
---|
397 |
|
---|
398 | return MS::kSuccess;
|
---|
399 | }
|
---|
400 |
|
---|
401 |
|
---|
402 | // Copy textures to path specified by params
|
---|
403 | MStatus Material::copyTextures(ParamList ¶ms)
|
---|
404 | {
|
---|
405 | for (int i=0; i<m_textures.size(); i++)
|
---|
406 | {
|
---|
407 | // Copy file texture to output dir
|
---|
408 | MString command = "copy \"";
|
---|
409 | command += m_textures[i].absFilename;
|
---|
410 | command += "\" \"";
|
---|
411 | command += params.texOutputDir;
|
---|
412 | command += "\"";
|
---|
413 | system(command.asChar());
|
---|
414 | }
|
---|
415 | return MS::kSuccess;
|
---|
416 | }
|
---|
417 |
|
---|
418 | }; //end namespace |
---|