source: OGRE/trunk/ogrenew/Tools/MayaExport/shared/src/OgreMayaMaterial.cpp @ 657

Revision 657, 14.4 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2============================================================================
3This source file is part of the Ogre-Maya Tools.
4Distributed as part of Ogre (Object-oriented Graphics Rendering Engine).
5Copyright (C) 2003 Fifty1 Software Inc., Bytelords
6
7This program is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public License
9as published by the Free Software Foundation; either version 2
10of the License, or (at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20or go to http://www.gnu.org/licenses/gpl.txt
21============================================================================
22*/
23#include "OgreMayaMaterial.h"
24#include "OgreMayaOptions.h"
25
26#include <maya/MDagPath.h>
27#include <maya/MGlobal.h>
28#include <maya/MPlug.h>
29#include <maya/MFnLambertShader.h>
30#include <maya/MFnBlinnShader.h>
31#include <maya/MFnPhongShader.h>
32#include <maya/MFnReflectShader.h>
33#include <maya/MFnSet.h>
34#include <maya/MPlugArray.h>
35#include <maya/MItDependencyGraph.h>
36#include <maya/MItDag.h>
37
38#include <iostream>
39
40namespace OgreMaya {
41
42        using namespace std;
43
44        //      --------------------------------------------------------------------------
45        /** Standard constructor. Creates Ogre MaterialManger and defines known options.
46        */     
47        //      --------------------------------------------------------------------------
48        MatGenerator::MatGenerator() {
49        }
50
51
52        //      --------------------------------------------------------------------------
53        /** Destructor.
54        */     
55        //      --------------------------------------------------------------------------
56        MatGenerator::~MatGenerator() {
57        }
58
59
60        //      --------------------------------------------------------------------------
61        /** Finds and exports all connected materials in the Maya scene.
62                \return         True if exported ok, false otherwise
63        */     
64        //      --------------------------------------------------------------------------
65        bool MatGenerator::exportAll() {
66
67        cout << "\nMatGenerator::exportAll\n";
68
69                MStatus status;
70                bool bStatus = true;
71
72        _extractMaterials();
73
74        {           
75            // export
76           
77                        ofstream out(OPTIONS.outMatFile.c_str());
78
79            out.precision(5);
80            out.setf(ios::fixed);
81
82            vector<Material*>::iterator it  = materials.begin();
83            vector<Material*>::iterator end = materials.end();
84           
85            for(;it!=end; ++it) {
86               
87                Material& mat = **it;
88
89                list<TextureUnitState>::iterator tlIt  = mat.textureLayers.begin();
90                list<TextureUnitState>::iterator tlEnd = mat.textureLayers.end();
91               
92                out << "material " << mat.name << '\n';
93                out << "{\n";   
94
95                                out << "\ttechnique\n";
96                                out << "\t{\n";
97
98                                out << "\t\tpass\n";
99                                out << "\t\t{\n";
100
101                out << "\t\t\tshading " << mat.shadingMode << "\n\n";
102
103                out << "\t\t\tambient "
104                    << mat.ambient.r << ' '
105                    << mat.ambient.g << ' '
106                    << mat.ambient.b << ' '
107                    << mat.ambient.a << '\n';
108
109                out << "\t\t\tdiffuse "
110                    << mat.diffuse.r << ' '
111                    << mat.diffuse.g << ' '
112                    << mat.diffuse.b << ' '
113                    << mat.diffuse.a << '\n';
114
115                out << "\t\t\tspecular "
116                    << mat.specular.r << ' '
117                    << mat.specular.g << ' '
118                    << mat.specular.b << ' '
119                    << mat.specular.a << ' '
120                                        << mat.shininess  << '\n';
121
122                out << "\t\t\temissive "
123                    << mat.selfIllumination.r << ' '
124                    << mat.selfIllumination.g << ' '
125                    << mat.selfIllumination.b << ' '
126                    << mat.selfIllumination.a << "\n\n";
127
128                for(;tlIt!=tlEnd; ++tlIt) {
129                    TextureUnitState& layer = *tlIt;
130                    out << "\t\t\ttexture_unit\n";
131                                        out << "\t\t\t{\n";
132                    out << "\t\t\t\ttexture " << layer.textureName << '\n';
133                    out << "\t\t\t\ttex_coord_set " << layer.uvSet << '\n';
134                    out << "\t\t\t}\n\n";
135                }
136
137                                out << "\t\t}\n";
138                                out << "\t}\n";
139                out << "}\n\n";
140            }                       
141
142            out.close();           
143        }
144
145        deleteAll(materials.begin(), materials.end());
146        materials.clear();
147
148                return true;
149        }
150
151
152
153        bool MatGenerator::_extractMaterials() {
154                MStatus status;
155                MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &status );
156
157                for ( ; !dagIter.isDone(); dagIter.next()) {
158                        MDagPath dagPath;
159                        status = dagIter.getPath( dagPath );
160
161                        if (status) {
162                                MFnDagNode dagNode( dagPath, &status );
163
164                                if(
165                    dagNode.isIntermediateObject()
166                                    || !dagPath.hasFn( MFn::kMesh )
167                                    || dagPath.hasFn( MFn::kTransform )
168                )
169                    continue;
170
171                                MFnMesh fnMesh( dagPath );
172
173                                // Get all connected shaders (materials)
174                                MObjectArray ShaderSets;
175                                MIntArray    ShaderVertexIndices;
176                                unsigned int iInstance = dagPath.instanceNumber();
177                                fnMesh.getConnectedShaders(iInstance, ShaderSets, ShaderVertexIndices);
178
179                                // Iterate over all connected shaders
180                                unsigned int iShader;
181                                for (iShader = 0; iShader < ShaderSets.length(); ++iShader) {
182                                        _makeMaterials(ShaderSets[iShader]);
183                                }
184                        }
185                }
186
187                return (status == MStatus::kSuccess);
188        }
189
190
191        void MatGenerator::_makeMaterials(MObject &ShaderSet) {
192                MFnDependencyNode fnDNSet(ShaderSet);
193                MPlug             ShaderPlug = fnDNSet.findPlug("surfaceShader");
194                MPlugArray        ShaderPlugArray;
195                ShaderPlug.connectedTo(ShaderPlugArray, true, false);
196
197                unsigned int iPlug, nPlugs;
198                nPlugs = ShaderPlugArray.length();
199                for (iPlug=0; iPlug < nPlugs; ++iPlug) {
200                        Material *mat = NULL;                   
201                       
202                        // Basic material properties
203                        MObject ShaderNode = ShaderPlugArray[iPlug].node();
204                        if (ShaderNode.hasFn(MFn::kPhong)) {
205                                mat = _makePhongMaterial(ShaderNode);
206                        }
207                        else if (ShaderNode.hasFn(MFn::kBlinn)) {
208                                mat = _makeBlinnMaterial(ShaderNode);
209                        }
210                        else if (ShaderNode.hasFn(MFn::kLambert)) {
211                                mat = _makeLambertMaterial(ShaderNode);
212                        }
213                        else {
214                                MFnDependencyNode FnShader(ShaderNode);
215                                cout << "\tunable to create Ogre material for shader " << FnShader.name().asChar() << '\n';
216                        }
217
218                        // Check for duplicates
219                        if (mat) {
220                                vector<Material*>::iterator iterMat;
221                                iterMat = materials.begin();
222                                for(;iterMat != materials.end(); ++iterMat) {
223                                        if ((*iterMat)->name == mat->name) {
224                                                delete mat;
225                                                mat = NULL;
226                                                break;
227                                        }
228                                }
229                        }
230
231                        // Textures
232                        if (mat) {
233                materials.push_back(mat);
234
235                                MFnDependencyNode ShaderFn(ShaderPlugArray[iPlug].node());
236                                MPlug thePlug = ShaderPlugArray[iPlug];
237                                MItDependencyGraph ItShaderGraph(thePlug,
238                                                                     MFn::kFileTexture,
239                                                                                         MItDependencyGraph::kUpstream);
240                                int iTexCoordSet = 0;
241                                while (!ItShaderGraph.isDone()) {
242                                        MObject ShaderTexture = ItShaderGraph.thisNode();
243                                        MFnDependencyNode FnTexture(ShaderTexture);
244
245                    MString textureFile;
246                    FnTexture.findPlug("fileTextureName").getValue(textureFile);
247
248                    int substrI;
249                    substrI = textureFile.rindex('\\');
250                    if(substrI<0)
251                        substrI = textureFile.rindex('/');
252
253                    if(substrI>0)
254                        textureFile = textureFile.substring(substrI+1, textureFile.length()-1);
255
256                                mat->textureLayers.push_back(
257                        TextureUnitState(textureFile.asChar(), iTexCoordSet)
258                    );
259                                 
260                    ItShaderGraph.next();
261                                        ++iTexCoordSet;
262                                }
263                        }
264                }
265        }
266
267        Material* MatGenerator::_makePhongMaterial(MObject &ShaderNode) {
268                Material *mat = new Material;
269
270                MFnPhongShader FnShader(ShaderNode);
271                       
272                mat->name = OPTIONS.matPrefix + FnShader.name().asChar();
273
274                mat->shadingMode = "phong";
275
276                mat->ambient.r = FnShader.ambientColor().r;
277        mat->ambient.g = FnShader.ambientColor().g;
278                mat->ambient.b = FnShader.ambientColor().b;
279        mat->ambient.a = FnShader.ambientColor().a;
280
281                mat->diffuse.r = FnShader.diffuseCoeff()*FnShader.color().r;
282        mat->diffuse.g = FnShader.diffuseCoeff()*FnShader.color().g;
283                mat->diffuse.b = FnShader.diffuseCoeff()*FnShader.color().b;
284        mat->diffuse.a = FnShader.diffuseCoeff()*FnShader.color().a;
285
286                mat->specular.r = FnShader.specularColor().r;
287                mat->specular.g = FnShader.specularColor().g;
288        mat->specular.b = FnShader.specularColor().b;       
289        mat->specular.a = FnShader.specularColor().a;       
290
291        mat->selfIllumination.r = FnShader.incandescence().r;
292                mat->selfIllumination.g = FnShader.incandescence().g;
293        mat->selfIllumination.b = FnShader.incandescence().b;       
294        mat->selfIllumination.a = FnShader.incandescence().a;       
295               
296                mat->shininess = FnShader.cosPower();
297                       
298                cout << "\tCreated phong material " << mat->name << '\n';
299                return mat;
300        }
301
302
303        Material* MatGenerator::_makeBlinnMaterial(MObject &ShaderNode) {
304                Material* mat = new Material;
305
306                MFnBlinnShader FnShader(ShaderNode);
307               
308                mat->name = OPTIONS.matPrefix + FnShader.name().asChar();
309               
310                mat->shadingMode = "gouraud";
311
312                mat->ambient.r = FnShader.ambientColor().r;
313        mat->ambient.g = FnShader.ambientColor().g;
314                mat->ambient.b = FnShader.ambientColor().b;
315        mat->ambient.a = FnShader.ambientColor().a;
316
317                mat->diffuse.r = FnShader.diffuseCoeff()*FnShader.color().r;
318        mat->diffuse.g = FnShader.diffuseCoeff()*FnShader.color().g;
319                mat->diffuse.b = FnShader.diffuseCoeff()*FnShader.color().b;
320        mat->diffuse.a = FnShader.diffuseCoeff()*FnShader.color().a;
321
322                mat->specular.r = FnShader.specularColor().r;
323                mat->specular.g = FnShader.specularColor().g;
324        mat->specular.b = FnShader.specularColor().b;       
325        mat->specular.a = FnShader.specularColor().a;       
326
327        mat->selfIllumination.r = FnShader.incandescence().r;
328                mat->selfIllumination.g = FnShader.incandescence().g;
329        mat->selfIllumination.b = FnShader.incandescence().b;       
330        mat->selfIllumination.a = FnShader.incandescence().a;       
331               
332                mat->shininess = FnShader.specularRollOff();
333                       
334                cout << "MatGenerator: Created blinn material " << mat->name << '\n';
335                return mat;
336        }
337
338
339        Material* MatGenerator::_makeLambertMaterial(MObject &ShaderNode) {
340                Material* mat = new Material;
341
342                MFnLambertShader FnShader(ShaderNode);         
343               
344        mat->name = OPTIONS.matPrefix + FnShader.name().asChar();                               
345
346                mat->shadingMode = "gouraud";
347
348                mat->ambient.r = FnShader.ambientColor().r;
349        mat->ambient.g = FnShader.ambientColor().g;
350                mat->ambient.b = FnShader.ambientColor().b;
351        mat->ambient.a = FnShader.ambientColor().a;
352
353                mat->diffuse.r = FnShader.diffuseCoeff()*FnShader.color().r;
354        mat->diffuse.g = FnShader.diffuseCoeff()*FnShader.color().g;
355                mat->diffuse.b = FnShader.diffuseCoeff()*FnShader.color().b;
356        mat->diffuse.a = FnShader.diffuseCoeff()*FnShader.color().a;
357
358                mat->selfIllumination.r = FnShader.incandescence().r;
359                mat->selfIllumination.g = FnShader.incandescence().g;
360        mat->selfIllumination.b = FnShader.incandescence().b;       
361        mat->selfIllumination.a = FnShader.incandescence().a;       
362               
363                mat->shininess = 0;
364                       
365                cout << "\tCreated lambert material " << mat->name << '\n';
366                return mat;
367        }
368
369
370        //      --------------------------------------------------------------------------
371        /**     Get material name for a single mesh.
372                Adapted from "How to Write a Simple Maya Model Exporter", Rafael Baptista,
373                Gamedev.net, April 2003
374        */     
375        //      --------------------------------------------------------------------------
376        MString MatGenerator::getMaterialName(MFnMesh &fnMesh) {
377                MStatus status = MStatus::kSuccess;
378                MString MaterialName = "";
379               
380
381                // ===== Connected sets and members
382                // (Required to determine texturing of different faces)
383
384                // Determine instance number
385                fnMesh.dagPath().extendToShape();
386                int iInstance = 0;
387                if (fnMesh.dagPath().isInstanced()) {
388                        iInstance = fnMesh.dagPath().instanceNumber();
389                }
390
391                // Get the connected sets and members
392                MObjectArray PolygonSets;
393                MObjectArray PolygonComponents;
394                status = fnMesh.getConnectedSetsAndMembers(iInstance,
395                                                               PolygonSets,
396                                                                                                   PolygonComponents,
397                                                                                                   true);
398                if (!status) {
399                        MGlobal::displayError("MFnMesh::getConnectedSetsAndMembers");
400                        return MaterialName;
401                }
402
403
404                // ===== Materials
405                unsigned int iSet;
406                for (iSet = 0; iSet < PolygonSets.length(); ++iSet) {
407                        MObject PolygonSet = PolygonSets[iSet];
408                        MObject PolygonComponent = PolygonComponents[iSet];
409
410                        MFnDependencyNode dnSet(PolygonSet);
411                        MObject ssAttr = dnSet.attribute(MString("surfaceShader"));
412                        MPlug ssPlug(PolygonSet, ssAttr);
413
414                        MPlugArray srcPlugArray;
415                        ssPlug.connectedTo(srcPlugArray, true, false);
416                       
417                        if (srcPlugArray.length() > 0) {
418                                // This object contains a reference to a shader or material.
419                                // Check for known material types and extract material name.
420                                MObject srcNode = srcPlugArray[0].node();
421                               
422                                if (srcNode.hasFn(MFn::kPhong)) {
423                                        MFnPhongShader fnPhong(srcNode);
424                                        MaterialName = fnPhong.name();
425                                }
426                                else if (srcNode.hasFn(MFn::kLambert)) {
427                                        MFnLambertShader fnLambert(srcNode);
428                                        MaterialName = fnLambert.name();
429                                }
430                                else if (srcNode.hasFn(MFn::kBlinn)) {
431                                        MFnBlinnShader fnBlinn(srcNode);
432                                        MaterialName = fnBlinn.name();
433                                }
434                                else if (srcNode.hasFn(MFn::kReflect)) {
435                                        MFnReflectShader fnReflect(srcNode);
436                                        MaterialName = fnReflect.name();
437                                }
438
439            }
440                }
441
442
443                // ===== Done
444                return MaterialName;
445
446        }
447
448} // namespace OgreMaya
Note: See TracBrowser for help on using the repository browser.