| 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 | |
|---|
| 24 | import base |
|---|
| 25 | from base import * |
|---|
| 26 | |
|---|
| 27 | import os |
|---|
| 28 | import shutil |
|---|
| 29 | import Blender |
|---|
| 30 | |
|---|
| 31 | def clamp(value): |
|---|
| 32 | if value < 0.0: |
|---|
| 33 | value = 0.0 |
|---|
| 34 | elif value > 1.0: |
|---|
| 35 | value = 1.0 |
|---|
| 36 | return value |
|---|
| 37 | |
|---|
| 38 | class 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 | |
|---|
| 54 | class 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 | |
|---|
| 75 | class 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 | |
|---|
| 225 | class 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 | |
|---|
| 733 | class 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 |
|---|