Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre/Tools/BlenderExport/ogrepkg/materialexport.py @ 42

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

=…

File size: 28.7 KB
Line 
1"""Material export classes.
2
3   @author Michael Reimpell
4"""
5# Copyright (C) 2005  Michael Reimpell
6#
7# This library is free software; you can redistribute it and/or
8# modify it under the terms of the GNU Lesser General Public
9# License as published by the Free Software Foundation; either
10# version 2.1 of the License, or (at your option) any later version.
11#
12# This library is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15# Lesser General Public License for more details.
16#
17# You should have received a copy of the GNU Lesser General Public
18# License along with this library; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21# epydoc doc format
22__docformat__ = "javadoc en"
23
24import base
25from base import *
26
27import os
28import shutil
29import Blender
30
31def clamp(value):
32        if value < 0.0:
33                value = 0.0
34        elif value > 1.0:
35                value = 1.0
36        return value
37
38class MaterialInterface:
39        def getName(self):
40                """Returns the material name.
41               
42                   @return Material name.
43                """
44                return
45        def write(self, f):
46                """Write material script entry.
47               
48                   All used texture files are registered at the MaterialManager.
49                   
50                   @param f Material script file object to write into.
51                """
52                return
53
54class DefaultMaterial(MaterialInterface):
55        def __init__(self, manager, name):
56                self.manager = manager
57                self.name = name
58                return
59        def getName(self):
60                return self.name
61        def write(self, f):
62                f.write("material %s\n" % self.getName())
63                f.write("{\n")
64                self.writeTechniques(f)
65                f.write("}\n")
66                return
67        def writeTechniques(self, f):
68                f.write(indent(1) + "technique\n" + indent(1) + "{\n")
69                f.write(indent(2) + "pass\n" + indent(2) + "{\n")
70                # empty pass
71                f.write(indent(2) + "}\n") # pass
72                f.write(indent(1) + "}\n") # technique
73                return
74
75class GameEngineMaterial(DefaultMaterial):
76        def __init__(self, manager, blenderMesh, blenderFace, colouredAmbient):
77                self.mesh = blenderMesh
78                self.face = blenderFace
79                self.colouredAmbient = colouredAmbient
80                # check if a Blender material is assigned
81                try:
82                        blenderMaterial = self.mesh.materials[self.face.mat]
83                except:
84                        blenderMaterial = None
85                self.material = blenderMaterial
86                DefaultMaterial.__init__(self, manager, self._createName())
87                return
88        def writeTechniques(self, f):
89                mat = self.material
90#Mesh#          if (not(mat)
91#Mesh#                  and not(self.mesh.vertexColors)
92#Mesh#                  and not(self.mesh.vertexUV or self.mesh.faceUV)):
93                if (not(mat)
94                        and not(self.mesh.hasVertexColours())
95                        and not(self.mesh.hasVertexUV())
96                        and not(self.mesh.hasFaceUV())):
97                        # default material
98                        DefaultMaterial.writeTechniques(self, f)
99                else:
100                        # default material
101                        # SOLID, white, no specular
102                        f.write(indent(1)+"technique\n")
103                        f.write(indent(1)+"{\n")
104                        f.write(indent(2)+"pass\n")
105                        f.write(indent(2)+"{\n")
106                        # ambient
107                        # (not used in Blender's game engine)
108                        if mat:
109                                if (not(mat.mode & Blender.Material.Modes["TEXFACE"])
110                                        and not(mat.mode & Blender.Material.Modes["VCOL_PAINT"])
111                                        and (self.colouredAmbient)):
112                                        ambientRGBList = mat.rgbCol
113                                else:
114                                        ambientRGBList = [1.0, 1.0, 1.0]
115                                # ambient <- amb * ambient RGB
116                                ambR = clamp(mat.amb * ambientRGBList[0])
117                                ambG = clamp(mat.amb * ambientRGBList[1])
118                                ambB = clamp(mat.amb * ambientRGBList[2])
119                                ##f.write(indent(3)+"ambient %f %f %f\n" % (ambR, ambG, ambB))
120                        # diffuse
121                        # (Blender's game engine uses vertex colours
122                        #  instead of diffuse colour.
123                        #
124                        #  diffuse is defined as
125                        #  (mat->r, mat->g, mat->b)*(mat->emit + mat->ref)
126                        #  but it's not used.)
127                        #Mesh#if self.mesh.vertexColors:
128                        if self.mesh.hasVertexColours():
129                                #TODO: Broken in Blender 2.36.
130                                # Blender does not handle "texface" mesh with vertex colours
131                                f.write(indent(3)+"diffuse vertexcolour\n")
132                        elif mat:
133                                if (not(mat.mode & Blender.Material.Modes["TEXFACE"])
134                                        and not(mat.mode & Blender.Material.Modes["VCOL_PAINT"])):
135                                        # diffuse <- rgbCol
136                                        diffR = clamp(mat.rgbCol[0])
137                                        diffG = clamp(mat.rgbCol[1])
138                                        diffB = clamp(mat.rgbCol[2])
139                                        f.write(indent(3)+"diffuse %f %f %f\n" % (diffR, diffG, diffB))
140                                elif (mat.mode & Blender.Material.Modes["VCOL_PAINT"]):
141                                        f.write(indent(3)+"diffuse vertexcolour\n")
142                        if mat:
143                                # specular <- spec * specCol, hard/4.0
144                                specR = clamp(mat.spec * mat.specCol[0])
145                                specG = clamp(mat.spec * mat.specCol[1])
146                                specB = clamp(mat.spec * mat.specCol[2])
147                                specShine = mat.hard/4.0
148                                f.write(indent(3)+"specular %f %f %f %f\n" % (specR, specG, specB, specShine))
149                                # emissive
150                                # (not used in Blender's game engine)
151                                if(not(mat.mode & Blender.Material.Modes["TEXFACE"])
152                                        and not(mat.mode & Blender.Material.Modes["VCOL_PAINT"])):
153                                        # emissive <-emit * rgbCol
154                                        emR = clamp(mat.emit * mat.rgbCol[0])
155                                        emG = clamp(mat.emit * mat.rgbCol[1])
156                                        emB = clamp(mat.emit * mat.rgbCol[2])
157                                        ##f.write(indent(3)+"emissive %f %f %f\n" % (emR, emG, emB))
158                        #Mesh#if self.mesh.faceUV:
159                        if self.mesh.hasFaceUV():
160                                # mesh has texture values, resp. tface data
161                                # scene_blend <- transp
162                                if (self.face.transp == Blender.Mesh.FaceTranspModes["ALPHA"]):
163                                        f.write(indent(3)+"scene_blend alpha_blend \n")
164                                elif (self.face.transp == Blender.NMesh.FaceTranspModes["ADD"]):
165                                        f.write(indent(3)+"scene_blend add\n")
166                                # cull_hardware/cull_software
167                                if (self.face.mode & Blender.Mesh.FaceModes['TWOSIDE']):
168                                        f.write(indent(3) + "cull_hardware none\n")
169                                        f.write(indent(3) + "cull_software none\n")
170                                # shading
171                                # (Blender's game engine is initialized with glShadeModel(GL_FLAT))
172                                ##f.write(indent(3) + "shading flat\n")
173                                # texture
174                                if (self.face.mode & Blender.Mesh.FaceModes['TEX']) and (self.face.image):
175                                        f.write(indent(3)+"texture_unit\n")
176                                        f.write(indent(3)+"{\n")
177                                        f.write(indent(4)+"texture %s\n" % self.manager.registerTextureFile(self.face.image.filename))
178                                        f.write(indent(3)+"}\n") # texture_unit
179                        f.write(indent(2)+"}\n") # pass
180                        f.write(indent(1)+"}\n") # technique
181                return
182        # private
183        def _createName(self):
184                """Create unique material name.
185               
186                   The name consists of several parts:
187                   <OL>
188                   <LI>rendering material name/</LI>
189                   <LI>blend mode (ALPHA, ADD, SOLID)</LI>
190                   <LI>/TEX</LI>
191                   <LI>/texture file name</LI>
192                   <LI>/VertCol</LI>
193                   <LI>/TWOSIDE></LI>
194                   </OL>
195                """
196                materialName = ''
197                # nonempty rendering material?
198                if self.material:
199                        materialName += self.material.getName() + '/'
200                # blend mode
201                #Mesh#if self.mesh.faceUV and (self.face.transp == Blender.Mesh.FaceTranspModes['ALPHA']):
202                if self.mesh.hasFaceUV() and (self.face.transp == Blender.Mesh.FaceTranspModes['ALPHA']):
203                        materialName += 'ALPHA'
204                #Mesh#elif self.mesh.faceUV and (self.face.transp == Blender.Mesh.FaceTranspModes['ADD']):
205                elif self.mesh.hasFaceUV() and (self.face.transp == Blender.Mesh.FaceTranspModes['ADD']):
206                        materialName += 'ADD'
207                else:
208                        materialName += 'SOLID'
209                # TEX face mode and texture?
210                #Mesh#if self.mesh.faceUV and (self.face.mode & Blender.Mesh.FaceModes['TEX']):
211                if self.mesh.hasFaceUV() and (self.face.mode & Blender.Mesh.FaceModes['TEX']):
212                        materialName += '/TEX'
213                        if self.face.image:
214                                materialName += '/' + PathName(self.face.image.filename).basename()
215                # vertex colours?
216                #Mesh#if self.mesh.vertexColors:
217                if self.mesh.hasVertexColours():
218                        materialName += '/VertCol'
219                # two sided?
220                #Mesh#if self.mesh.faceUV and (self.face.mode & Blender.Mesh.FaceModes['TWOSIDE']):
221                if self.mesh.hasFaceUV() and (self.face.mode & Blender.Mesh.FaceModes['TWOSIDE']):
222                        materialName += '/TWOSIDE'
223                return materialName
224
225class RenderingMaterial(DefaultMaterial):
226        def __init__(self, manager, blenderMesh, blenderFace, colouredAmbient):
227                self.mesh = blenderMesh
228                self.face = blenderFace
229                self.colouredAmbient = colouredAmbient
230                self.key = 0
231                self.mTexUVCol = None
232                self.mTexUVNor = None
233                self.mTexUVCsp = None
234                self.material = None
235                try:
236                        self.material = self.mesh.materials[self.face.mat]
237                except IndexError:
238                        Log.getSingleton().logWarning("Can't get material for mesh \"%s\"! Are any materials linked to object instead of linked to mesh?" % self.mesh.name)
239                if self.material:
240                        self._generateKey()
241                        DefaultMaterial.__init__(self, manager, self._createName())
242                else:
243                        DefaultMaterial.__init__(self, manager, 'None')
244                return
245        def writeTechniques(self, f):
246                # parse material
247                if self.key:
248                        if self.TECHNIQUES.has_key(self.key):
249                                techniques = self.TECHNIQUES[self.key]
250                                techniques(self, f)
251                        else:
252                                # default
253                                self.writeColours(f)
254                else:
255                        # Halo or empty material
256                        DefaultMaterial('').writeTechniques(f)
257                return
258        def writeColours(self, f):
259                # receive_shadows
260                self.writeReceiveShadows(f, 1)
261                f.write(indent(1) + "technique\n" + indent(1) + "{\n")
262                f.write(indent(2) + "pass\n" + indent(2) + "{\n")
263                # ambient
264                if (self.colouredAmbient):
265                        col = self.material.getRGBCol()
266                else:
267                        col = [1.0, 1.0, 1.0]
268                self.writeAmbient(f, col, 3)
269                # diffuse
270                self.writeDiffuse(f, self.material.rgbCol, 3)
271                # specular
272                self.writeSpecular(f, 3)
273                # emissive
274                self.writeEmissive(f, self.material.rgbCol, 3)
275                # blend mode
276                self.writeSceneBlend(f,3)
277                # options
278                self.writeCommonOptions(f, 3)
279                # texture units
280                self.writeDiffuseTexture(f, 3)
281                f.write(indent(2) + "}\n") # pass
282                f.write(indent(1) + "}\n") # technique
283                return
284        def writeTexFace(self, f):
285                # preconditions: TEXFACE set
286                #
287                # Note that an additional Col texture replaces the
288                # TEXFACE texture instead of blend over according to alpha.
289                #
290                # (amb+emit)textureCol + diffuseLight*ref*textureCol + specular
291                #
292                imageFileName = None
293                if self.mTexUVCol:
294                        # COL MTex replaces UV/Image Editor texture
295                        imageFileName = self.manager.registerTextureFile(self.mTexUVCol.tex.getImage().getFilename())
296                #Mesh#elif (self.mesh.faceUV and self.face.image):
297                elif (self.mesh.hasFaceUV() and self.face.image):
298                        # UV/Image Editor texture
299                        imageFileName = self.manager.registerTextureFile(self.face.image.filename)
300               
301                self.writeReceiveShadows(f, 1)
302                f.write(indent(1) + "technique\n" + indent(1) + "{\n")
303                col = [1.0, 1.0, 1.0]
304                # texture pass
305                f.write(indent(2) + "pass\n" + indent(2) + "{\n")
306                self.writeAmbient(f, col, 3)
307                self.writeDiffuse(f, col, 3)
308                if not(imageFileName):
309                        self.writeSpecular(f, 3)
310                self.writeEmissive(f, col, 3)
311                self.writeSceneBlend(f,3)
312                self.writeCommonOptions(f, 3)
313                if imageFileName:
314                        f.write(indent(3) + "texture_unit\n")
315                        f.write(indent(3) + "{\n")
316                        f.write(indent(4) + "texture %s\n" % imageFileName)
317                        if self.mTexUVCol:
318                                self.writeTextureAddressMode(f, self.mTexUVCol, 4)
319                                self.writeTextureFiltering(f, self.mTexUVCol, 4)
320                        # multiply with factors
321                        f.write(indent(4) + "colour_op modulate\n")
322                        f.write(indent(3) + "}\n") # texture_unit
323                        f.write(indent(2) + "}\n") # texture pass
324                        # specular pass
325                        f.write(indent(2) + "pass\n" + indent(2) + "{\n")
326                        f.write(indent(3) + "ambient 0.0 0.0 0.0\n")
327                        f.write(indent(3) + "diffuse 0.0 0.0 0.0\n")
328                        self.writeSpecular(f, 3)
329                        f.write(indent(3) + "scene_blend add\n")
330                        hasAlpha = 0
331                        if (self.material.getAlpha() < 1.0):
332                                hasAlpha = 1
333                        else:
334                                for mtex in self.material.getTextures():
335                                        if mtex:
336                                                if ((mtex.tex.type == Blender.Texture.Types['IMAGE'])
337                                                        and (mtex.mapto & Blender.Texture.MapTo['ALPHA'])):
338                                                        hasAlpha = 1
339                        if (hasAlpha):
340                                f.write(indent(3) + "depth_write off\n")
341                        self.writeCommonOptions(f, 3)
342                f.write(indent(2) + "}\n") # pass
343                f.write(indent(1) + "}\n") # technique
344                return
345        def writeVertexColours(self, f):
346                # preconditions: VCOL_PAINT set
347                #
348                # ambient = Amb*White resp. Amb*VCol if "Coloured Ambient"
349                # diffuse = Ref*VCol
350                # specular = Spec*SpeRGB, Hard/4.0
351                # emissive = Emit*VCol
352                # alpha = A
353                #
354                # Best match without vertex shader:
355                # ambient = Amb*white
356                # diffuse = Ref*VCol
357                # specular = Spec*SpeRGB, Hard/4.0
358                # emissive = black
359                # alpha = 1
360                #
361                self.writeReceiveShadows(f, 1)
362                f.write(indent(1) + "technique\n" + indent(1) + "{\n")
363                if (self.material.mode & Blender.Material.Modes['SHADELESS']):
364                        f.write(indent(2) + "pass\n" + indent(2) + "{\n")
365                        self.writeCommonOptions(f,3)
366                        f.write(indent(2) + "}\n")
367                else:
368                        # vertex colour pass
369                        f.write(indent(2) + "pass\n" + indent(2) + "{\n")
370                        f.write(indent(3) + "ambient 0.0 0.0 0.0\n")
371                        f.write(indent(3) + "diffuse vertexcolour\n")
372                        self.writeCommonOptions(f, 3)
373                        f.write(indent(2) + "}\n") # vertex colour pass
374                       
375                        # factor pass
376                        f.write(indent(2) + "pass\n" + indent(2) + "{\n")
377                        f.write(indent(3) + "ambient 0.0 0.0 0.0\n")
378                        ref = self.material.getRef()
379                        f.write(indent(3) + "diffuse %f %f %f\n" % (ref, ref, ref))
380                        f.write(indent(3) + "scene_blend modulate\n")
381                        self.writeCommonOptions(f, 3)
382                        f.write(indent(2) + "}\n") # factor pass
383                       
384                        # ambient and specular pass
385                        f.write(indent(2) + "pass\n" + indent(2) + "{\n")
386                        self.writeAmbient(f, [1.0, 1.0, 1.0], 3)
387                        f.write(indent(3) + "diffuse 0.0 0.0 0.0\n")
388                        self.writeSpecular(f, 3)
389                        f.write(indent(3) + "scene_blend add\n")
390                        self.writeCommonOptions(f, 3)
391                        f.write(indent(2) + "}\n") # specular pass
392               
393                f.write(indent(1) + "}\n") # technique
394                return
395        def writeNormalMap(self, f):
396                # preconditions COL and NOR textures
397                colImage = self.manager.registerTextureFile(self.mTexUVCol.tex.image.filename)
398                norImage = self.manager.registerTextureFile(self.mTexUVNor.tex.image.filename)
399                f.write("""     technique
400        {
401                pass
402                {
403                        ambient 1 1 1
404                        diffuse 0 0 0
405                        specular 0 0 0 0
406                        vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
407                        {
408                                param_named_auto worldViewProj worldviewproj_matrix
409                                param_named_auto ambient ambient_light_colour
410                        }
411                }
412                pass
413                {
414                        ambient 0 0 0
415                        iteration once_per_light
416                        scene_blend add
417                        vertex_program_ref Examples/BumpMapVPSpecular
418                        {
419                                param_named_auto lightPosition light_position_object_space 0
420                                param_named_auto eyePosition camera_position_object_space
421                                param_named_auto worldViewProj worldviewproj_matrix
422                        }
423                        fragment_program_ref Examples/BumpMapFPSpecular
424                        {
425                                param_named_auto lightDiffuse light_diffuse_colour 0
426                                param_named_auto lightSpecular light_specular_colour 0
427                        }
428                        texture_unit
429                        {
430                                texture %s
431                                colour_op replace
432                        }
433                        texture_unit
434                        {
435                                cubic_texture nm.png combinedUVW
436                                tex_coord_set 1
437                                tex_address_mode clamp
438                        }
439                        texture_unit
440                        {
441                                cubic_texture nm.png combinedUVW
442                                tex_coord_set 2
443                                tex_address_mode clamp
444                        }
445                }
446                pass
447                {
448                        lighting off
449                        vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
450                        {
451                                param_named_auto worldViewProj worldviewproj_matrix
452                                param_named ambient float4 1 1 1 1
453                        }
454                        scene_blend dest_colour zero
455                        texture_unit
456                        {
457                                texture %s
458                        }
459                }
460        }
461        technique
462        {
463                pass
464                {
465                        ambient 1 1 1
466                        diffuse 0 0 0
467                        specular 0 0 0 0
468                        vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
469                        {
470                                param_named_auto worldViewProj worldviewproj_matrix
471                                param_named_auto ambient ambient_light_colour
472                        }
473                }
474                pass
475                {
476                        ambient 0 0 0
477                        iteration once_per_light
478                        scene_blend add
479                        vertex_program_ref Examples/BumpMapVP
480                        {
481                                param_named_auto lightPosition light_position_object_space 0
482                                param_named_auto eyePosition camera_position_object_space
483                                param_named_auto worldViewProj worldviewproj_matrix
484                        }
485                        texture_unit
486                        {
487                                texture %s
488                                colour_op replace
489                        }
490                        texture_unit
491                        {
492                                cubic_texture nm.png combinedUVW
493                                tex_coord_set 1
494                                tex_address_mode clamp
495                                colour_op_ex dotproduct src_texture src_current
496                                colour_op_multipass_fallback dest_colour zero
497                        }
498                }
499                pass
500                {
501                        lighting off
502                        vertex_program_ref Ogre/BasicVertexPrograms/AmbientOneTexture
503                        {
504                                param_named_auto worldViewProj worldviewproj_matrix
505                                param_named ambient float4 1 1 1 1
506                        }
507                        scene_blend dest_colour zero
508                        texture_unit
509                        {
510                                texture %s
511                        }
512                }
513        }
514""" % (norImage, colImage, norImage, colImage)) 
515                return
516        def writeReceiveShadows(self, f, indentation=0):
517                if (self.material.mode & Blender.Material.Modes["SHADOW"]):
518                        f.write(indent(indentation)+"receive_shadows on\n")
519                else:
520                        f.write(indent(indentation)+"receive_shadows off\n")
521                return
522        def writeAmbient(self, f, col, indentation=0):
523                # ambient <- amb * ambient RGB
524                ambR = clamp(self.material.getAmb() * col[0])
525                ambG = clamp(self.material.getAmb() * col[1])
526                ambB = clamp(self.material.getAmb() * col[2])
527                if len(col) < 4:
528                        alpha = self.material.getAlpha()
529                else:
530                        alpha = col[3]
531                f.write(indent(indentation)+"ambient %f %f %f %f\n" % (ambR, ambG, ambB, alpha))
532                return
533        def writeDiffuse(self, f, col, indentation=0):
534                # diffuse = reflectivity*colour
535                diffR = clamp(col[0] * self.material.getRef())
536                diffG = clamp(col[1] * self.material.getRef())
537                diffB = clamp(col[2] * self.material.getRef())
538                if len(col) < 4:
539                        alpha = self.material.getAlpha()
540                else:
541                        alpha = col[3]
542                f.write(indent(indentation)+"diffuse %f %f %f %f\n" % (diffR, diffG, diffB, alpha))
543                return
544        def writeSpecular(self, f, indentation=0):
545                # specular <- spec * specCol, hard/4.0
546                specR = clamp(self.material.getSpec() * self.material.getSpecCol()[0])
547                specG = clamp(self.material.getSpec() * self.material.getSpecCol()[1])
548                specB = clamp(self.material.getSpec() * self.material.getSpecCol()[2])
549                specShine = self.material.getHardness()/4.0
550                alpha = self.material.getAlpha()
551                f.write(indent(indentation)+"specular %f %f %f %f %f\n" % (specR, specG, specB, alpha, specShine))
552                return
553        def writeEmissive(self, f, col, indentation=0):
554                # emissive <-emit * rgbCol
555                emR = clamp(self.material.getEmit() * col[0])
556                emG = clamp(self.material.getEmit() * col[1])
557                emB = clamp(self.material.getEmit() * col[2])
558                if len(col) < 4:
559                        alpha = self.material.getAlpha()
560                else:
561                        alpha = col[3]
562                f.write(indent(indentation)+"emissive %f %f %f %f\n" % (emR, emG, emB, alpha))
563                return
564        def writeSceneBlend(self, f, indentation=0):
565                hasAlpha = 0
566                if (self.material.getAlpha() < 1.0):
567                        hasAlpha = 1
568                else:
569                        for mtex in self.material.getTextures():
570                                if mtex:
571                                        if ((mtex.tex.type == Blender.Texture.Types['IMAGE'])
572                                                and (mtex.mapto & Blender.Texture.MapTo['ALPHA'])):
573                                                hasAlpha = 1
574                if (hasAlpha):
575                        f.write(indent(indentation) + "scene_blend alpha_blend\n")
576                        f.write(indent(indentation) + "depth_write off\n")
577                return
578        def writeCommonOptions(self, f, indentation=0):
579                # Shadeless, ZInvert, NoMist, Env
580                # depth_func  <- ZINVERT; ENV
581                if (self.material.mode & Blender.Material.Modes['ENV']):
582                        f.write(indent(indentation)+"depth_func always_fail\n")
583                elif (self.material.mode & Blender.Material.Modes['ZINVERT']):
584                        f.write(indent(indentation)+"depth_func greater_equal\n")
585                # twoside
586                #Mesh#if self.mesh.faceUV and (self.face.mode & Blender.NMesh.FaceModes['TWOSIDE']):
587                if self.mesh.hasFaceUV() and (self.face.mode & Blender.NMesh.FaceModes['TWOSIDE']):
588                        f.write(indent(3) + "cull_hardware none\n")
589                        f.write(indent(3) + "cull_software none\n")
590                # lighting <- SHADELESS
591                if (self.material.mode & Blender.Material.Modes['SHADELESS']):
592                        f.write(indent(indentation)+"lighting off\n")
593                # fog_override <- NOMIST
594                if (self.material.mode & Blender.Material.Modes['NOMIST']):
595                        f.write(indent(indentation)+"fog_override true\n")
596                return
597        def writeDiffuseTexture(self, f, indentation = 0):
598                if self.mTexUVCol:
599                        f.write(indent(indentation)+"texture_unit\n")
600                        f.write(indent(indentation)+"{\n")
601                        f.write(indent(indentation + 1) + "texture %s\n" % self.manager.registerTextureFile(self.mTexUVCol.tex.getImage().getFilename()))
602                        self.writeTextureAddressMode(f, self.mTexUVCol, indentation + 1)
603                        self.writeTextureFiltering(f, self.mTexUVCol, indentation + 1)                 
604                        self.writeTextureColourOp(f, self.mTexUVCol, indentation + 1)
605                        f.write(indent(indentation)+"}\n") # texture_unit
606                return
607        def writeTextureAddressMode(self, f, blenderMTex, indentation = 0):
608                # tex_address_mode inside texture_unit
609                #
610                # EXTEND   | clamp
611                # CLIP     |
612                # CLIPCUBE |
613                # REPEAT   | wrap
614                #
615                if (blenderMTex.tex.extend & Blender.Texture.ExtendModes['REPEAT']):
616                        f.write(indent(indentation) + "tex_address_mode wrap\n")
617                elif (blenderMTex.tex.extend & Blender.Texture.ExtendModes['EXTEND']):
618                        f.write(indent(indentation) + "tex_address_mode clamp\n")               
619                return
620        def writeTextureFiltering(self, f, blenderMTex, indentation = 0):
621                # filtering inside texture_unit
622                #
623                # InterPol | MidMap | filtering
624                # ---------+--------+----------
625                #    yes   |   yes  | trilinear
626                #    yes   |   no   | linear linear none
627                #    no    |   yes  | bilinear
628                #    no    |   no   | none
629                #
630                if (blenderMTex.tex.imageFlags & Blender.Texture.ImageFlags['INTERPOL']):
631                        if (blenderMTex.tex.imageFlags & Blender.Texture.ImageFlags['MIPMAP']):
632                                f.write(indent(indentation) + "filtering trilinear\n")
633                        else:
634                                f.write(indent(indentation) + "filtering linear linear none\n")
635                else:
636                        if (blenderMTex.tex.imageFlags & Blender.Texture.ImageFlags['MIPMAP']):
637                                f.write(indent(indentation) + "filtering bilinear\n")
638                        else:
639                                f.write(indent(indentation) + "filtering none\n")
640                return
641        def writeTextureColourOp(self, f, blenderMTex, indentation = 0):
642                # colour_op inside texture_unit
643                if ((blenderMTex.tex.imageFlags & Blender.Texture.ImageFlags['USEALPHA'])
644                        and not(blenderMTex.mapto & Blender.Texture.MapTo['ALPHA'])):
645                        f.write(indent(indentation) + "colour_op alpha_blend\n")
646                return
647        # private
648        def _createName(self):
649                # must be called after _generateKey()
650                materialName = self.material.getName()
651                # two sided?
652                #Mesh#if self.mesh.faceUV and (self.face.mode & Blender.NMesh.FaceModes['TWOSIDE']):
653                if self.mesh.hasFaceUV() and (self.face.mode & Blender.NMesh.FaceModes['TWOSIDE']):
654                        materialName += '/TWOSIDE'
655                # use UV/Image Editor texture?
656                if ((self.key & self.TEXFACE) and not(self.key & self.IMAGEUVCOL)):
657                        materialName += '/TEXFACE'
658                        if self.face.image:
659                                materialName += '/' + PathName(self.face.image.filename).basename()
660                return materialName
661        def _generateKey(self):
662                # generates key and populates mTex fields
663                if self.material:
664                        if not(self.material.mode & Blender.Material.Modes['HALO']):
665                                self.key |= self.NONHALO
666                                if (self.material.mode & Blender.Material.Modes['VCOL_LIGHT']):
667                                        self.key |= self.VCOLLIGHT
668                                if (self.material.mode & Blender.Material.Modes['VCOL_PAINT']):
669                                        self.key |= self.VCOLPAINT
670                                if (self.material.mode & Blender.Material.Modes['TEXFACE']):
671                                        self.key |= self.TEXFACE
672                                # textures
673                                for mtex in self.material.getTextures():
674                                        if mtex:
675                                                if (mtex.tex.type == Blender.Texture.Types['IMAGE']):
676                                                        if (mtex.texco & Blender.Texture.TexCo['UV']):
677                                                                if (mtex.mapto & Blender.Texture.MapTo['COL']):
678                                                                        self.key |= self.IMAGEUVCOL
679                                                                        self.mTexUVCol = mtex
680                                                                if (mtex.mapto & Blender.Texture.MapTo['NOR']):
681                                                                        # Check "Normal Map" image option
682                                                                        if (mtex.tex.imageFlags & 2048):
683                                                                                self.key |= self.IMAGEUVNOR
684                                                                                self.mTexUVNor = mtex
685                                                                        # else bumpmap
686                                                                if (mtex.mapto & Blender.Texture.MapTo['CSP']):
687                                                                        self.key |= self.IMAGEUVCSP
688                                                                        self.mTexUVCsp = mtex
689                return
690        NONHALO = 1
691        VCOLLIGHT = 2
692        VCOLPAINT = 4
693        TEXFACE = 8
694        IMAGEUVCOL = 16
695        IMAGEUVNOR = 32
696        IMAGEUVCSP = 64
697        # material techniques export methods
698        TECHNIQUES = {
699                NONHALO|IMAGEUVCOL : writeColours,
700                NONHALO|IMAGEUVCOL|IMAGEUVCSP : writeColours,
701                NONHALO|TEXFACE : writeTexFace,
702                NONHALO|TEXFACE|VCOLLIGHT : writeTexFace,
703                NONHALO|TEXFACE|IMAGEUVCOL : writeTexFace,
704                NONHALO|TEXFACE|IMAGEUVNOR : writeTexFace,
705                NONHALO|TEXFACE|IMAGEUVCSP : writeTexFace,
706                NONHALO|TEXFACE|VCOLLIGHT|IMAGEUVCOL : writeTexFace,
707                NONHALO|TEXFACE|VCOLLIGHT|IMAGEUVNOR : writeTexFace,
708                NONHALO|TEXFACE|VCOLLIGHT|IMAGEUVCSP : writeTexFace,
709                NONHALO|TEXFACE|IMAGEUVCOL|IMAGEUVCSP : writeTexFace,
710                NONHALO|TEXFACE|IMAGEUVNOR|IMAGEUVCSP : writeTexFace,
711                NONHALO|TEXFACE|VCOLLIGHT|IMAGEUVCOL|IMAGEUVCSP : writeTexFace,
712                NONHALO|TEXFACE|VCOLLIGHT|IMAGEUVNOR|IMAGEUVCSP : writeTexFace,
713                NONHALO|VCOLPAINT : writeVertexColours,
714                NONHALO|VCOLPAINT|VCOLLIGHT : writeVertexColours,
715                NONHALO|IMAGEUVCOL|IMAGEUVNOR : writeNormalMap,
716                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT : writeNormalMap,
717                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLPAINT : writeNormalMap,
718                NONHALO|IMAGEUVCOL|IMAGEUVNOR|TEXFACE : writeNormalMap,
719                NONHALO|IMAGEUVCOL|IMAGEUVNOR|IMAGEUVCSP : writeNormalMap,
720                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|VCOLPAINT : writeNormalMap,
721                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|TEXFACE : writeNormalMap,
722                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|IMAGEUVCSP : writeNormalMap,
723                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLPAINT|TEXFACE : writeNormalMap,
724                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLPAINT|IMAGEUVCSP : writeNormalMap,
725                NONHALO|IMAGEUVCOL|IMAGEUVNOR|TEXFACE|IMAGEUVCSP : writeNormalMap,
726                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLPAINT|TEXFACE|IMAGEUVCSP : writeNormalMap,
727                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|TEXFACE|IMAGEUVCSP : writeNormalMap,
728                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|VCOLPAINT|IMAGEUVCSP : writeNormalMap,
729                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|VCOLPAINT|TEXFACE : writeNormalMap,
730                NONHALO|IMAGEUVCOL|IMAGEUVNOR|VCOLLIGHT|VCOLPAINT|TEXFACE|IMAGEUVCSP : writeNormalMap
731                }
732
733class MaterialManager:
734        """Manages database of material definitions.
735        """
736        #TODO append to existing material script
737        def __init__(self, dir=None, file=None):
738                """Constructor.
739               
740                   @param path Directory to the material file. Default is directory of the last file read or written with Blender.
741                   @param file Material script file. Default is current scene name with ".material" prefix.
742                """
743                self.dir = dir or Blender.sys.dirname(Blender.Get('filename'))
744                self.file = file or (Blender.Scene.GetCurrent().getName() + ".material")
745                # key=name, value=material
746                self.materialsDict = {}
747                # key=basename, value=path
748                self.textureFilesDict = {}
749                return
750        def getMaterial(self, bMesh, bMFace, colouredAmbient, gameEngineMaterial):
751                """Returns material of a given face or <code>None</code>.
752                """
753                ## get name of export material for Blender's material settings of that face.
754                faceMaterial = None
755                if gameEngineMaterial:
756                        #Mesh#if bMesh.faceUV and not(bMFace.mode & Blender.Mesh.FaceModes['INVISIBLE']):
757                        if bMesh.hasFaceUV() and not(bMFace.mode & Blender.Mesh.FaceModes['INVISIBLE']):
758                                if (bMFace.image and (bMFace.mode & Blender.Mesh.FaceModes['TEX'])):
759                                        # image texture
760                                        faceMaterial = GameEngineMaterial(self, bMesh, bMFace, colouredAmbient)
761                        else:
762                                # material only
763                                bMaterial = None
764                                try:
765                                        bMaterial = bMesh.materials[bMFace.mat]
766                                except:
767                                        Log.getSingleton().logWarning("Face without material assignment in mesh \"%s\"!" % bMesh.name)
768                                if bMaterial:
769                                        faceMaterial = GameEngineMaterial(self, bMesh, bMFace, colouredAmbient)
770                                else:
771                                        faceMaterial = DefaultMaterial(self, 'default')
772                else:
773                        # rendering material
774                        bMaterial = None
775                        try:
776                                bMaterial = bMesh.materials[bMFace.mat]
777                        except:
778                                Log.getSingleton().logError("Face without material assignment in mesh \"%s\"!" % bMesh.name)
779                        if bMaterial:
780                                faceMaterial = RenderingMaterial(self, bMesh, bMFace, colouredAmbient)
781                        else:
782                                faceMaterial = DefaultMaterial(self, 'default')
783                ## return material or None
784                material = None
785                if faceMaterial:
786                        if not(self.materialsDict.has_key(faceMaterial.getName())):
787                                self.materialsDict[faceMaterial.getName()] = faceMaterial
788                        material = self.materialsDict[faceMaterial.getName()]
789                return material
790        def registerTextureFile(self, path):
791                """Register texture for export.
792               
793                   @param path Texture file path, i.e. dirname and basename.
794                   @return Basename of texture file.
795                """
796                texturePath = PathName(path)
797                key = texturePath.basename()
798                if self.textureFilesDict.has_key(key):
799                        if (path != self.textureFilesDict[key]):
800                                Log.getSingleton().logWarning('Texture filename conflict: \"%s\"' % key)
801                                Log.getSingleton().logWarning(' Location: \"%s\"' % path)
802                                Log.getSingleton().logWarning(' Conflicting location: \"%s\"' % self.textureFilesDict[key])
803                self.textureFilesDict[key] = path
804                return key
805        def export(self, dir=None, file=None, copyTextures=False):
806                exportDir = dir or self.dir
807                exportFile = file or self.file
808                Log.getSingleton().logInfo("Exporting materials \"%s\"" % exportFile)
809                f = open(Blender.sys.join(exportDir, exportFile), "w")
810                for material in self.materialsDict.values():
811                        material.write(f)
812                f.close()
813                if copyTextures and os.path.exists(dir):
814                        baseDirname = os.path.dirname(Blender.Get("filename"))
815                        for path in self.textureFilesDict.values():
816                                # convert Blender's relative paths "//" to absolute path
817                                if (path[0:2] == "//"):
818                                        Log.getSingleton().logInfo("Converting relative image name \"%s\"" % path)
819                                        path = os.path.join(baseDirname, path[2:])
820                                if os.path.exists(path):
821                                        # copy texture to dir
822                                        Log.getSingleton().logInfo("Copying texture \"%s\"" % path)
823                                        try:
824                                                shutil.copy(path, dir)
825                                        except (IOError, OSError), detail:
826                                                Log.getSingleton().logError("Error copying \"%s\": %s" % (path, str(detail)))
827                                else:
828                                        Log.getSingleton().logWarning("Can't copy texture \"%s\" because file does not exists!" % path)
829                return
Note: See TracBrowser for help on using the repository browser.