Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/MayaExport/src/material.cpp @ 48

Last change on this file since 48 was 6, checked in by anonymous, 17 years ago

=…

File size: 17.9 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// material.cpp
3// Author     : Francesco Giordana
4// Start Date : January 13, 2005
5// Copyright  : (C) 2006 by Francesco Giordana
6// Email      : fra.giordana@tiscali.it
7////////////////////////////////////////////////////////////////////////////////
8
9/*********************************************************************************
10*                                                                                *
11*   This program is free software; you can redistribute it and/or modify         *
12*   it under the terms of the GNU Lesser General Public License as published by  *
13*   the Free Software Foundation; either version 2 of the License, or            *
14*   (at your option) any later version.                                          *
15*                                                                                *
16**********************************************************************************/
17
18#include "material.h"
19
20namespace OgreMayaExporter
21{
22        // Constructor
23        Material::Material()
24        {
25                clear();
26        }
27
28
29        // Destructor
30        Material::~Material()
31        {
32        }
33
34
35        // Get material name
36        MString& Material::name()
37        {
38                return m_name;
39        }
40
41
42        // Clear data
43        void Material::clear()
44        {
45                m_name = "";
46                m_type = MT_LAMBERT;
47                m_lightingOff = false;
48                m_isTransparent = false;
49                m_isTextured = false;
50                m_isMultiTextured = false;
51                m_ambient = MColor(0,0,0,0);
52                m_diffuse = MColor(0,0,0,0);
53                m_specular = MColor(0,0,0,0);
54                m_emissive = MColor(0,0,0,0);
55                m_textures.clear();
56        }
57
58
59        // Load material data
60        MStatus Material::load(MFnDependencyNode* pShader,MStringArray& uvsets,ParamList& params)
61        {
62                int i;
63                MStatus stat;
64                clear();
65                //read material name, adding the requested prefix
66                MString tmpStr = params.matPrefix;
67                if (tmpStr != "")
68                        tmpStr += "/";
69                tmpStr += pShader->name();
70                MStringArray tmpStrArray;
71                tmpStr.split(':',tmpStrArray);
72                m_name = "";
73                for (i=0; i<tmpStrArray.length(); i++)
74                {
75                        m_name += tmpStrArray[i];
76                        if (i < tmpStrArray.length()-1)
77                                m_name += "_";
78                }
79
80                //check if we want to export with lighting off option
81                m_lightingOff = params.lightingOff;
82
83                // GET MATERIAL DATA
84
85                // Check material type
86                if (pShader->object().hasFn(MFn::kPhong))
87                {
88                        stat = loadPhong(pShader);
89                }
90                else if (pShader->object().hasFn(MFn::kBlinn))
91                {
92                        stat = loadBlinn(pShader);
93                }
94                else if (pShader->object().hasFn(MFn::kLambert))
95                {
96                        stat = loadLambert(pShader);
97                }
98                else if (pShader->object().hasFn(MFn::kPluginHwShaderNode))
99                {
100                        stat = loadCgFxShader(pShader);
101                }
102                else
103                {
104                        stat = loadSurfaceShader(pShader);
105                }
106
107                // Get textures data
108                MPlugArray colorSrcPlugs;
109                MPlugArray texSrcPlugs;
110                MPlugArray placetexSrcPlugs;
111                if (m_isTextured)
112                {
113                        // Translate multiple textures if material is multitextured
114                        if (m_isMultiTextured)
115                        {
116                                // Get layered texture node
117                                MFnDependencyNode* pLayeredTexNode = NULL;
118                                if (m_type == MT_SURFACE_SHADER)
119                                        pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
120                                else
121                                        pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
122                                for (i=0; i<colorSrcPlugs.length(); i++)
123                                {
124                                        if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
125                                        {
126                                                pLayeredTexNode = new MFnDependencyNode(colorSrcPlugs[i].node());
127                                                continue;
128                                        }
129                                }
130
131                                // Get inputs to layered texture
132                                MPlug inputsPlug = pLayeredTexNode->findPlug("inputs");
133
134                                // Scan inputs and export textures
135                                for (i=inputsPlug.numElements()-1; i>=0; i--)
136                                {
137                                        MFnDependencyNode* pTextureNode = NULL;
138                                        // Search for a connected texture
139                                        inputsPlug[i].child(0).connectedTo(colorSrcPlugs,true,false);
140                                        for (int j=0; j<colorSrcPlugs.length(); j++)
141                                        {
142                                                if (colorSrcPlugs[j].node().hasFn(MFn::kFileTexture))
143                                                {
144                                                        pTextureNode = new MFnDependencyNode(colorSrcPlugs[j].node());
145                                                        continue;
146                                                }
147                                        }
148
149                                        // Translate the texture if it was found
150                                        if (pTextureNode)
151                                        {
152                                                // Get blend mode
153                                                TexOpType opType;
154                                                short bm;
155                                                inputsPlug[i].child(2).getValue(bm);
156                                                switch(bm)
157                                                {                               
158                                                case 0:
159                                                        opType = TOT_REPLACE;
160                                                        break;
161                                                case 1:
162                                                        opType = TOT_ALPHABLEND;
163                                                        break;                         
164                                                case 4:
165                                                        opType = TOT_ADD;
166                                                        break;
167                                                case 6:
168                                                        opType = TOT_MODULATE;
169                                                        break;
170                                                default:
171                                                        opType = TOT_MODULATE;
172                                                }
173
174                                                stat = loadTexture(pTextureNode,opType,uvsets,params);
175                                                delete pTextureNode;
176                                                if (MS::kSuccess != stat)
177                                                {
178                                                        std::cout << "Error loading layered texture\n";
179                                                        std::cout.flush();
180                                                        delete pLayeredTexNode;
181                                                        return MS::kFailure;
182                                                }
183                                        }
184                                }
185                                if (pLayeredTexNode)
186                                        delete pLayeredTexNode;
187                        }
188                        // Else translate the single texture
189                        else
190                        {
191                                // Get texture node
192                                MFnDependencyNode* pTextureNode = NULL;
193                                if (m_type == MT_SURFACE_SHADER)
194                                        pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
195                                else
196                                        pShader->findPlug("color").connectedTo(colorSrcPlugs,true,false);
197                                for (i=0; i<colorSrcPlugs.length(); i++)
198                                {
199                                        if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
200                                        {
201                                                pTextureNode = new MFnDependencyNode(colorSrcPlugs[i].node());
202                                                continue;
203                                        }
204                                }
205                                if (pTextureNode)
206                                {
207                                        TexOpType opType = TOT_MODULATE;
208                                        stat = loadTexture(pTextureNode,opType,uvsets,params);
209                                        delete pTextureNode;
210                                        if (MS::kSuccess != stat)
211                                        {
212                                                std::cout << "Error loading texture\n";
213                                                std::cout.flush();
214                                                return MS::kFailure;
215                                        }
216                                }
217                        }
218                }
219
220                return MS::kSuccess;
221        }
222
223
224        // Load a surface shader
225        MStatus Material::loadSurfaceShader(MFnDependencyNode *pShader)
226        {
227                int i;
228                m_type = MT_SURFACE_SHADER;
229                MPlugArray colorSrcPlugs;
230                // Check if material is textured
231                pShader->findPlug("outColor").connectedTo(colorSrcPlugs,true,false);
232                for (i=0; i<colorSrcPlugs.length(); i++)
233                {
234                        if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
235                        {
236                                m_isTextured = true;
237                                continue;
238                        }
239                        else if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
240                        {
241                                m_isTextured = true;
242                                m_isMultiTextured = true;
243                                continue;
244                        }
245                }
246
247                // Check if material is transparent
248                float trasp;
249                pShader->findPlug("outTransparencyR").getValue(trasp);
250                if (pShader->findPlug("outTransparency").isConnected() || trasp>0.0f)
251                        m_isTransparent = true;
252
253                // Get material colours
254                if (m_isTextured)
255                        m_diffuse = MColor(1.0,1.0,1.0,1.0);
256                else
257                {
258                        pShader->findPlug("outColorR").getValue(m_diffuse.r);
259                        pShader->findPlug("outColorG").getValue(m_diffuse.g);
260                        pShader->findPlug("outColorB").getValue(m_diffuse.b);
261                        float trasp;
262                        pShader->findPlug("outTransparencyR").getValue(trasp);
263                        m_diffuse.a = 1.0 - trasp;
264                }
265                m_ambient = MColor(0,0,0,1);
266                m_emissive = MColor(0,0,0,1);
267                m_specular = MColor(0,0,0,1);
268                return MS::kSuccess;
269        }
270
271        // Load a lambert shader
272        MStatus Material::loadLambert(MFnDependencyNode *pShader)
273        {
274                int i;
275                MPlugArray colorSrcPlugs;
276                m_type = MT_LAMBERT;
277                MFnLambertShader* pLambert = new MFnLambertShader(pShader->object());
278                // Check if material is textured
279                pLambert->findPlug("color").connectedTo(colorSrcPlugs,true,false);
280                for (i=0; i<colorSrcPlugs.length(); i++)
281                {
282                        if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
283                        {
284                                m_isTextured = true;
285                                continue;
286                        }
287                        else if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
288                        {
289                                m_isTextured = true;
290                                m_isMultiTextured = true;
291                                continue;
292                        }
293                }
294
295                // Check if material is transparent
296                if (pLambert->findPlug("transparency").isConnected() || pLambert->transparency().r>0.0f)
297                        m_isTransparent = true;
298
299                // Get material colours
300                //diffuse colour
301                if (m_isTextured)
302                        m_diffuse = MColor(1.0,1.0,1.0,1.0);
303                else
304                {
305                        m_diffuse = pLambert->color();
306                        m_diffuse.a = 1.0 - pLambert->transparency().r;
307                }
308                //ambient colour
309                m_ambient = pLambert->ambientColor();
310                //emissive colour
311                m_emissive = pLambert->incandescence();
312                //specular colour
313                m_specular = MColor(0,0,0,1);
314                delete pLambert;
315                return MS::kSuccess;
316        }
317
318        // Load a phong shader
319        MStatus Material::loadPhong(MFnDependencyNode *pShader)
320        {
321                int i;
322                MPlugArray colorSrcPlugs;
323                m_type = MT_PHONG;
324                MFnPhongShader* pPhong = new MFnPhongShader(pShader->object());
325                // Check if material is textured
326                pPhong->findPlug("color").connectedTo(colorSrcPlugs,true,false);
327                for (i=0; i<colorSrcPlugs.length(); i++)
328                {
329                        if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
330                        {
331                                m_isTextured = true;
332                                continue;
333                        }
334                        else if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
335                        {
336                                m_isTextured = true;
337                                m_isMultiTextured = true;
338                                continue;
339                        }
340                }
341
342                // Check if material is transparent
343                if (pPhong->findPlug("transparency").isConnected() || pPhong->transparency().r>0.0f)
344                        m_isTransparent = true;
345
346                // Get material colours
347                //diffuse colour
348                if (m_isTextured)
349                        m_diffuse = MColor(1.0,1.0,1.0,1.0);
350                else
351                {
352                        m_diffuse = pPhong->color();
353                        m_diffuse.a = 1.0 - pPhong->transparency().r;
354                }
355                //ambient colour
356                m_ambient = pPhong->ambientColor();
357                //emissive colour
358                m_emissive = pPhong->incandescence();
359                //specular colour
360                m_specular = pPhong->specularColor();
361                m_specular.a = pPhong->cosPower();
362                delete pPhong;
363                return MS::kSuccess;
364        }
365
366        // load a blinn shader
367        MStatus Material::loadBlinn(MFnDependencyNode *pShader)
368        {
369                int i;
370                MPlugArray colorSrcPlugs;
371                m_type = MT_BLINN;
372                MFnBlinnShader* pBlinn = new MFnBlinnShader(pShader->object());
373                // Check if material is textured
374                pBlinn->findPlug("color").connectedTo(colorSrcPlugs,true,false);
375                for (i=0; i<colorSrcPlugs.length(); i++)
376                {
377                        if (colorSrcPlugs[i].node().hasFn(MFn::kFileTexture))
378                        {
379                                m_isTextured = true;
380                                continue;
381                        }
382                        else if (colorSrcPlugs[i].node().hasFn(MFn::kLayeredTexture))
383                        {
384                                m_isTextured = true;
385                                m_isMultiTextured = true;
386                                continue;
387                        }
388                }
389
390                // Check if material is transparent
391                if (pBlinn->findPlug("transparency").isConnected() || pBlinn->transparency().r>0.0f)
392                        m_isTransparent = true;
393
394                // Get material colours
395                //diffuse colour
396                if (m_isTextured)
397                        m_diffuse = MColor(1.0,1.0,1.0,1.0);
398                else
399                {
400                        m_diffuse = pBlinn->color();
401                        m_diffuse.a = 1.0 - pBlinn->transparency().r;
402                }
403                //ambient colour
404                m_ambient = pBlinn->ambientColor();
405                //emissive colour
406                m_emissive = pBlinn->incandescence();
407                //specular colour
408                m_specular = pBlinn->specularColor();
409                m_specular.a = 1.0 / pBlinn->eccentricity();
410                delete pBlinn;
411                return MS::kSuccess;
412        }
413
414        // load a cgFx shader
415        MStatus Material::loadCgFxShader(MFnDependencyNode *pShader)
416        {
417                m_type = MT_CGFX;
418                // Create a default white lambert
419                m_isTextured = false;
420                m_isMultiTextured = false;
421                m_diffuse = MColor(1.0,1.0,1.0,1.0);
422                m_specular = MColor(0,0,0,1);
423                m_emissive = MColor(0,0,0,1);
424                m_ambient = MColor(0,0,0,1);
425                return MS::kSuccess;
426        }
427
428        // Load texture data from a texture node
429        MStatus Material::loadTexture(MFnDependencyNode* pTexNode,TexOpType& opType,MStringArray& uvsets,ParamList& params)
430        {
431                int j;
432                Texture tex;
433                // Get texture filename
434                MString filename, absFilename;
435                MRenderUtil::exactFileTextureName(pTexNode->object(),absFilename);
436                filename = absFilename.substring(absFilename.rindex('/')+1,absFilename.length()-1);
437                MString command = "toNativePath(\"";
438                command += absFilename;
439                command += "\")";
440                MGlobal::executeCommand(command,absFilename);
441                tex.absFilename = absFilename;
442                tex.filename = filename;
443                tex.uvsetIndex = 0;
444                tex.uvsetName = "";
445                // Set texture operation type
446                tex.opType = opType;
447                // Get connections to uvCoord attribute of texture node
448                MPlugArray texSrcPlugs;
449                pTexNode->findPlug("uvCoord").connectedTo(texSrcPlugs,true,false);
450                // Get place2dtexture node (if connected)
451                MFnDependencyNode* pPlace2dTexNode = NULL;
452                for (j=0; j<texSrcPlugs.length(); j++)
453                {
454                        if (texSrcPlugs[j].node().hasFn(MFn::kPlace2dTexture))
455                        {
456                                pPlace2dTexNode = new MFnDependencyNode(texSrcPlugs[j].node());
457                                continue;
458                        }
459                }
460                // Get uvChooser node (if connected)
461                MFnDependencyNode* pUvChooserNode = NULL;
462                if (pPlace2dTexNode)
463                {
464                        MPlugArray placetexSrcPlugs;
465                        pPlace2dTexNode->findPlug("uvCoord").connectedTo(placetexSrcPlugs,true,false);
466                        for (j=0; j<placetexSrcPlugs.length(); j++)
467                        {
468                                if (placetexSrcPlugs[j].node().hasFn(MFn::kUvChooser))
469                                {
470                                        pUvChooserNode = new MFnDependencyNode(placetexSrcPlugs[j].node());
471                                        continue;
472                                }
473                        }
474                }
475                // Get uvset index
476                if (pUvChooserNode)
477                {
478                        bool foundMesh = false;
479                        bool foundUvset = false;
480                        MPlug uvsetsPlug = pUvChooserNode->findPlug("uvSets");
481                        MPlugArray uvsetsSrcPlugs;
482                        for (int i=0; i<uvsetsPlug.evaluateNumElements() && !foundMesh; i++)
483                        {
484                                uvsetsPlug[i].connectedTo(uvsetsSrcPlugs,true,false);
485                                for (j=0; j<uvsetsSrcPlugs.length() && !foundMesh; j++)
486                                {
487                                        if (uvsetsSrcPlugs[j].node().hasFn(MFn::kMesh))
488                                        {
489                                                uvsetsSrcPlugs[j].getValue(tex.uvsetName);
490                                                for (int k=0; k<uvsets.length() && !foundUvset; k++)
491                                                {
492                                                        if (uvsets[k] == tex.uvsetName)
493                                                        {
494                                                                tex.uvsetIndex = k;
495                                                                foundUvset = true;
496                                                        }
497                                                }
498                                        }
499                                }
500                        }
501                }
502                // Get texture options from Place2dTexture node
503                if (pPlace2dTexNode)
504                {
505                        // Get address mode
506                        //U
507                        bool wrapU, mirrorU;
508                        pPlace2dTexNode->findPlug("wrapU").getValue(wrapU);
509                        pPlace2dTexNode->findPlug("mirrorU").getValue(mirrorU);
510                        if (mirrorU)
511                                tex.am_u = TAM_MIRROR;
512                        else if (wrapU)
513                                tex.am_u = TAM_WRAP;
514                        else
515                                tex.am_u = TAM_CLAMP;
516                        // V
517                        bool wrapV,mirrorV;
518                        pPlace2dTexNode->findPlug("wrapV").getValue(wrapV);
519                        pPlace2dTexNode->findPlug("mirrorV").getValue(mirrorV);
520                        if (mirrorV)
521                                tex.am_v = TAM_MIRROR;
522                        else if (wrapV)
523                                tex.am_v = TAM_WRAP;
524                        else
525                                tex.am_v = TAM_CLAMP;
526                        // Get texture scale
527                        double covU,covV;
528                        pPlace2dTexNode->findPlug("coverageU").getValue(covU);
529                        pPlace2dTexNode->findPlug("coverageV").getValue(covV);
530                        tex.scale_u = covU;
531                        if (fabs(tex.scale_u) < PRECISION)
532                                tex.scale_u = 0;
533                        tex.scale_v = covV;
534                        if (fabs(tex.scale_v) < PRECISION)
535                                tex.scale_v = 0;
536                        // Get texture scroll
537                        double transU,transV;
538                        pPlace2dTexNode->findPlug("translateFrameU").getValue(transU);
539                        pPlace2dTexNode->findPlug("translateFrameV").getValue(transV);
540                        tex.scroll_u = -0.5 * (covU-1.0)/covU - transU/covU;
541                        if (fabs(tex.scroll_u) < PRECISION)
542                                tex.scroll_u = 0;
543                        tex.scroll_v = 0.5 * (covV-1.0)/covV + transV/covV;
544                        if (fabs(tex.scroll_v) < PRECISION)
545                                tex.scroll_v = 0;
546                        // Get texture rotation
547                        double rot;
548                        pPlace2dTexNode->findPlug("rotateFrame").getValue(rot);
549                        tex.rot = -rot;
550                        if (fabs(rot) < PRECISION)
551                                tex.rot = 0;
552                }
553                // add texture to material texture list
554                m_textures.push_back(tex);
555                // free up memory
556                if (pUvChooserNode)
557                        delete pUvChooserNode;
558                if (pPlace2dTexNode)
559                        delete pPlace2dTexNode;
560
561                return MS::kSuccess;
562        }
563
564
565        // Write material data to an Ogre material script file
566        MStatus Material::writeOgreScript(ParamList &params)
567        {
568                //Start material description
569                params.outMaterial << "material " << m_name.asChar() << "\n";
570                params.outMaterial << "{\n";
571
572                //Start technique description
573                params.outMaterial << "\ttechnique\n";
574                params.outMaterial << "\t{\n";
575
576                //Start render pass description
577                params.outMaterial << "\t\tpass\n";
578                params.outMaterial << "\t\t{\n";
579                //set lighting off option if requested
580                if (m_lightingOff)
581                        params.outMaterial << "\t\t\tlighting off\n\n";
582                //ambient colour
583                params.outMaterial << "\t\t\tambient " << m_ambient.r << " " << m_ambient.g << " " << m_ambient.b
584                        << " " << m_ambient.a << "\n";
585                //diffuse colour
586                params.outMaterial << "\t\t\tdiffuse " << m_diffuse.r << " " << m_diffuse.g << " " << m_diffuse.b
587                        << " " << m_diffuse.a << "\n";
588                //specular colour
589                params.outMaterial << "\t\t\tspecular " << m_specular.r << " " << m_specular.g << " " << m_specular.b
590                        << " " << m_specular.a << "\n";
591                //emissive colour
592                params.outMaterial << "\t\t\temissive " << m_emissive.r << " " << m_emissive.g << " " 
593                        << m_emissive.b << "\n";
594                //if material is transparent set blend mode and turn off depth_writing
595                if (m_isTransparent)
596                {
597                        params.outMaterial << "\n\t\t\tscene_blend alpha_blend\n";
598                        params.outMaterial << "\t\t\tdepth_write off\n";
599                }
600                //write texture units
601                for (int i=0; i<m_textures.size(); i++)
602                {
603                        //start texture unit description
604                        params.outMaterial << "\n\t\t\ttexture_unit\n";
605                        params.outMaterial << "\t\t\t{\n";
606                        //write texture name
607                        params.outMaterial << "\t\t\t\ttexture " << m_textures[i].filename.asChar() << "\n";
608                        //write texture coordinate index
609                        params.outMaterial << "\t\t\t\ttex_coord_set " << m_textures[i].uvsetIndex << "\n";
610                        //write colour operation
611                        switch (m_textures[i].opType)
612                        {
613                        case TOT_REPLACE:
614                                params.outMaterial << "\t\t\t\tcolour_op replace\n";
615                                break;
616                        case TOT_ADD:
617                                params.outMaterial << "\t\t\t\tcolour_op add\n";
618                                break;
619                        case TOT_MODULATE:
620                                params.outMaterial << "\t\t\t\tcolour_op modulate\n";
621                                break;
622                        case TOT_ALPHABLEND:
623                                params.outMaterial << "\t\t\t\tcolour_op alpha_blend\n";
624                                break;
625                        }
626                        //write texture transforms
627                        params.outMaterial << "\t\t\t\tscale " << m_textures[i].scale_u << " " << m_textures[i].scale_v << "\n";
628                        params.outMaterial << "\t\t\t\tscroll " << m_textures[i].scroll_u << " " << m_textures[i].scroll_v << "\n";
629                        params.outMaterial << "\t\t\t\trotate " << m_textures[i].rot << "\n";
630                        //end texture unit desription
631                        params.outMaterial << "\t\t\t}\n";
632                }
633
634                //End render pass description
635                params.outMaterial << "\t\t}\n";
636
637                //End technique description
638                params.outMaterial << "\t}\n";
639
640                //End material description
641                params.outMaterial << "}\n";
642
643                //Copy textures to output dir if required
644                if (params.copyTextures)
645                        copyTextures(params);
646
647                return MS::kSuccess;
648        }
649
650
651        // Copy textures to path specified by params
652        MStatus Material::copyTextures(ParamList &params)
653        {
654                for (int i=0; i<m_textures.size(); i++)
655                {
656                        // Copy file texture to output dir
657                        MString command = "copy \"";
658                        command += m_textures[i].absFilename;
659                        command += "\" \"";
660                        command += params.texOutputDir;
661                        command += "\"";
662                        system(command.asChar());
663                }
664                return MS::kSuccess;
665        }
666
667};      //end namespace
Note: See TracBrowser for help on using the repository browser.