Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2006-01-10 20:40:50 +0300
committerCampbell Barton <ideasman42@gmail.com>2006-01-10 20:40:50 +0300
commit185c6bb49ce994d66fc67673b01a014161fa307d (patch)
tree5b229a6d406980d42a1a83893fc074074861ac01 /release
parente2acc624f2907c0422c82ab243bfe24f065e38c6 (diff)
removed slow list handeling
faster vert comparisons replaced spaces for tabs removed unneeded getData() calls general cleanup.
Diffstat (limited to 'release')
-rwxr-xr-xrelease/scripts/flt_export.py1306
1 files changed, 633 insertions, 673 deletions
diff --git a/release/scripts/flt_export.py b/release/scripts/flt_export.py
index b5ab09255b2..b5c5797fa42 100755
--- a/release/scripts/flt_export.py
+++ b/release/scripts/flt_export.py
@@ -57,707 +57,667 @@ What's Not Handled:<br>
"""
import Blender
-import math
from flt_filewalker import FltOut
class ExporterOptions:
- def __init__(self):
- self.defaults = { 'Diffuse Color To OpenFlight Material': False,
- 'Diffuse Color To OpenFlight Face': True}
-
- d = Blender.Registry.GetKey('flt_export', True)
-
- if d == None or d.keys() != self.defaults.keys():
- d = self.defaults
- Blender.Registry.SetKey('flt_export', d, True)
-
- self.verbose = 1
- self.tolerance = 0.001
- self.use_mat_color = d['Diffuse Color To OpenFlight Material']
- self.use_face_color = d['Diffuse Color To OpenFlight Face']
-
+ def __init__(self):
+ self.defaults = { 'Diffuse Color To OpenFlight Material': False,
+ 'Diffuse Color To OpenFlight Face': True}
+
+ d = Blender.Registry.GetKey('flt_export', True)
+
+ if d == None or d.keys() != self.defaults.keys():
+ d = self.defaults
+ Blender.Registry.SetKey('flt_export', d, True)
+
+ self.verbose = 1
+ self.tolerance = 0.001
+ self.use_mat_color = d['Diffuse Color To OpenFlight Material']
+ self.use_face_color = d['Diffuse Color To OpenFlight Face']
+
options = ExporterOptions()
-def not_equal_float(f1, f2):
- return math.fabs(f1 - f2) > options.tolerance
+FLOAT_TOLERANCE = options.tolerance
identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
def is_identity(m):
- for i in range(4):
- for j in range(4):
- if not_equal_float(m[i][j], identity_matrix[i][j]):
- return False
- return True
+ for i in xrange(4):
+ for j in xrange(4):
+ if abs(m[i][j] - identity_matrix[i][j]) > FLOAT_TOLERANCE:
+ return False
+ return True
class MaterialDesc:
- def __init__(self):
- self.name = 'Blender'
+ def __init__(self):
+ self.name = 'Blender'
- # Colors, List of 3 floats.
- self.diffuse = [1.0, 1.0, 1.0]
- self.specular = [1.0, 1.0, 1.0]
+ # Colors, List of 3 floats.
+ self.diffuse = [1.0, 1.0, 1.0]
+ self.specular = [1.0, 1.0, 1.0]
- # Scalars
- self.ambient = 0.1 # [0.0, 1.0]
- self.emissive = 0.0 # [0.0, 1.0]
- self.shininess = 32.0 # Range is [0.0, 128.0]
- self.alpha = 1.0 # Range is [0.0, 1.0]
+ # Scalars
+ self.ambient = 0.1 # [0.0, 1.0]
+ self.emissive = 0.0 # [0.0, 1.0]
+ self.shininess = 32.0 # Range is [0.0, 128.0]
+ self.alpha = 1.0 # Range is [0.0, 1.0]
class VertexDesc:
- def __init__(self):
- self.x = 0.0
- self.y = 0.0
- self.z = 0.0
- self.nx = 0.0
- self.ny = 0.0
- self.nz = 0.0
- self.u = 0.0
- self.v = 0.0
+ def __init__(self, co=None, no=None, uv=None):
+ if co: self.x, self.y, self.z = tuple(co)
+ else: self.x = self.y = self.z = 0.0
+ if no: self.nx, self.ny, self.nz = tuple(no)
+ else: self.nx = self.ny = self.nz = 0.0
+ if uv: self.u, self.v = tuple(uv)
+ else: self.u = self.v = 0.0
class GlobalResourceRepository:
- def new_face_name(self):
- n = 'f' + str(self.face_name)
- self.face_name += 1
- return n
-
- def vertex_count(self):
- return len(self.vertex_lst)
-
- def request_vertex_desc(self, i):
- return self.vertex_lst[i]
-
- def request_vertex_index(self, desc):
- match = None
- for i in range(len(self.vertex_lst)):
- if not_equal_float(self.vertex_lst[i].x, desc.x):
- continue
- if not_equal_float(self.vertex_lst[i].y, desc.y):
- continue
- if not_equal_float(self.vertex_lst[i].z, desc.z):
- continue
- if not_equal_float(self.vertex_lst[i].nx, desc.nx):
- continue
- if not_equal_float(self.vertex_lst[i].ny, desc.ny):
- continue
- if not_equal_float(self.vertex_lst[i].nz, desc.nz):
- continue
- if not_equal_float(self.vertex_lst[i].u, desc.u):
- continue
- if not_equal_float(self.vertex_lst[i].v, desc.v):
- continue
-
- match = i
- break
-
- if match != None:
- return match
- else:
- self.vertex_lst.append(desc)
- return len(self.vertex_lst) - 1
-
- def request_texture_index(self, filename):
- match = None
- for i in range(len(self.texture_lst)):
- if self.texture_lst[i] != filename:
- continue
- match = i
- break
- if match != None:
- return match
- else:
- self.texture_lst.append(filename)
- return len(self.texture_lst) - 1
-
- def request_texture_filename(self, index):
- return self.texture_lst[index]
-
- def texture_count(self):
- return len(self.texture_lst)
-
- def request_material_index(self, desc):
- match = None
- for i in range(len(self.material_lst)):
- if self.material_lst[i].diffuse != desc.diffuse:
- continue
- if self.material_lst[i].specular != desc.specular:
- continue
- if self.material_lst[i].ambient != desc.ambient:
- continue
- if self.material_lst[i].emissive != desc.emissive:
- continue
- if self.material_lst[i].shininess != desc.shininess:
- continue
- if self.material_lst[i].alpha != desc.alpha:
- continue
- match = i
- break
-
- if match != None:
- return i
- else:
- self.material_lst.append(desc)
- return len(self.material_lst) - 1
-
- def request_material_desc(self, index):
- return self.material_lst[index]
-
- def material_count(self):
- return len(self.material_lst)
-
- # Returns not actual index but one that includes intensity information.
- # color_index = 127*intensity + 128*actual_index
- def request_color_index(self, col):
- r = col[0]
- g = col[1]
- b = col[2]
- m = max(r, g, b)
- if m > 0.0:
- intensity = m / 1.0
- r = int(round(r/m * 255.0))
- g = int(round(g/m * 255.0))
- b = int(round(b/m * 255.0))
- brightest = [r, g, b]
- else:
- brightest = [255, 255, 255]
- intensity = 0.0
-
- match = None
- for i in range(len(self.color_lst)):
- if self.color_lst[i] != brightest:
- continue
-
- match = i
- break
-
- if match != None:
- index = match
- else:
- length = len(self.color_lst)
- if length <= 1024:
- self.color_lst.append(brightest)
- index = length
- else:
- if options.verbose >= 1:
- print 'Warning: Exceeded max color limit.'
- index = 0
-
- color_index = int(round(127.0*intensity)) + 128*index
- return color_index
-
- # Returns color from actual index.
- def request_max_color(self, index):
- return self.color_lst[index]
-
- def color_count(self):
- return len(self.color_lst)
-
- def __init__(self):
- self.vertex_lst = []
- self.texture_lst = []
- self.material_lst = []
- self.color_lst = [[255, 255, 255]]
- self.face_name = 0
+ def new_face_name(self):
+ self.face_name += 1
+ return 'f%i' % (self.face_name-1)
+
+ def vertex_count(self):
+ return len(self.vertex_lst)
+
+ def request_vertex_desc(self, i):
+ return self.vertex_lst[i]
+
+ def request_vertex_index(self, desc):
+ match = None
+ for i, v in enumerate(self.vertex_lst):
+ if\
+ abs(v.x - desc.x) > FLOAT_TOLERANCE or\
+ abs(v.y - desc.y) > FLOAT_TOLERANCE or\
+ abs(v.z - desc.z) > FLOAT_TOLERANCE or\
+ abs(v.nx - desc.nx) > FLOAT_TOLERANCE or\
+ abs(v.ny - desc.ny) > FLOAT_TOLERANCE or\
+ abs(v.nz - desc.nz) > FLOAT_TOLERANCE or\
+ abs(v.u - desc.u) > FLOAT_TOLERANCE or\
+ abs(v.v - desc.v) > FLOAT_TOLERANCE:
+ pass
+ else:
+ match = i
+ break
+
+ if match != None:
+ return match
+ else:
+ self.vertex_lst.append(desc)
+ return len(self.vertex_lst) - 1
+
+ def request_texture_index(self, filename):
+ match = None
+ for i in xrange(len(self.texture_lst)):
+ if self.texture_lst[i] != filename:
+ continue
+ match = i
+ break
+ if match != None:
+ return match
+ else:
+ self.texture_lst.append(filename)
+ return len(self.texture_lst) - 1
+
+ def request_texture_filename(self, index):
+ return self.texture_lst[index]
+
+ def texture_count(self):
+ return len(self.texture_lst)
+
+ def request_material_index(self, desc):
+ match = None
+ for i in xrange(len(self.material_lst)):
+ if self.material_lst[i].diffuse != desc.diffuse:
+ continue
+ if self.material_lst[i].specular != desc.specular:
+ continue
+ if self.material_lst[i].ambient != desc.ambient:
+ continue
+ if self.material_lst[i].emissive != desc.emissive:
+ continue
+ if self.material_lst[i].shininess != desc.shininess:
+ continue
+ if self.material_lst[i].alpha != desc.alpha:
+ continue
+ match = i
+ break
+
+ if match != None:
+ return i
+ else:
+ self.material_lst.append(desc)
+ return len(self.material_lst) - 1
+
+ def request_material_desc(self, index):
+ return self.material_lst[index]
+
+ def material_count(self):
+ return len(self.material_lst)
+
+ # Returns not actual index but one that includes intensity information.
+ # color_index = 127*intensity + 128*actual_index
+ def request_color_index(self, col):
+ r,g,b = tuple(col)
+ m = max(r, g, b)
+ if m > 0.0:
+ intensity = m / 1.0
+ r = int(round(r/m * 255.0))
+ g = int(round(g/m * 255.0))
+ b = int(round(b/m * 255.0))
+ brightest = [r, g, b]
+ else:
+ brightest = [255, 255, 255]
+ intensity = 0.0
+
+ match = None
+ for i in xrange(len(self.color_lst)):
+ if self.color_lst[i] != brightest:
+ continue
+
+ match = i
+ break
+
+ if match != None:
+ index = match
+ else:
+ length = len(self.color_lst)
+ if length <= 1024:
+ self.color_lst.append(brightest)
+ index = length
+ else:
+ if options.verbose >= 1:
+ print 'Warning: Exceeded max color limit.'
+ index = 0
+
+ color_index = int(round(127.0*intensity)) + 128*index
+ return color_index
+
+ # Returns color from actual index.
+ def request_max_color(self, index):
+ return self.color_lst[index]
+
+ def color_count(self):
+ return len(self.color_lst)
+
+ def __init__(self):
+ self.vertex_lst = []
+ self.texture_lst = []
+ self.material_lst = []
+ self.color_lst = [[255, 255, 255]]
+ self.face_name = 0
class Node:
- # Gathers info from blender needed for export.
- # The =[0] is a trick to emulate c-like static function variables
- # that are persistant between calls.
- def blender_export(self, level=[0]):
- if self.object:
- if options.verbose >= 2:
- for j in range(level[0]):
- print ' ',
- print self.name, type(self.object.getData())
-
- level[0] += 1
-
- for child in self.children:
- child.blender_export()
-
- level[0] -= 1
-
- # Exports this node's info to file.
- def write(self):
- pass
-
- def write_matrix(self):
- if self.matrix and not is_identity(self.matrix):
- self.header.fw.write_short(49) # Matrix opcode
- self.header.fw.write_ushort(68) # Length of record
- for i in range(4):
- for j in range(4):
- self.header.fw.write_float(self.matrix[i][j])
-
- def write_push(self):
- self.header.fw.write_short(10)
- self.header.fw.write_ushort(4)
-
- def write_pop(self):
- self.header.fw.write_short(11)
- self.header.fw.write_ushort(4)
-
- def write_longid(self, name):
- length = len(name)
- if length >= 8:
- self.header.fw.write_short(33) # Long ID opcode
- self.header.fw.write_ushort(length+5) # Length of record
- self.header.fw.write_string(name, length+1) # name + zero terminator
-
- # Initialization sets up basic tree structure.
- def __init__(self, parent, header, object, object_lst):
- self.header = header
- self.object = object
- if object:
- self.name = self.object.getName()
- self.matrix = self.object.getMatrix('localspace')
- else:
- self.name = 'no name'
- self.matrix = None
-
- self.children = []
- self.parent = parent
- if parent:
- parent.children.append(self)
-
- left_over = object_lst[:]
- self.child_objects = []
-
- # Add children to child list and remove from left_over list.
- for obj in object_lst:
- if obj.getParent() == object:
- self.child_objects.append(obj)
- left_over.remove(obj)
-
- # Spawn children.
- self.has_object_child = False # For Database class.
- for child in self.child_objects:
- dat = child.getData()
- t = type(dat)
-
- if dat == None:
- BlenderEmpty(self, header, child, left_over)
- if t == Blender.Types.NMeshType:
- BlenderMesh(self, header, child, left_over)
- self.has_object_child = True
+ # Gathers info from blender needed for export.
+ # The =[0] is a trick to emulate c-like static function variables
+ # that are persistant between calls.
+ def blender_export(self, level=[0]):
+ if self.object:
+ if options.verbose >= 2:
+ print '\t' * level[0], self.name, self.object.getType()
+
+ level[0] += 1
+
+ for child in self.children:
+ child.blender_export()
+
+ level[0] -= 1
+
+ # Exports this node's info to file.
+ def write(self):
+ pass
+
+ def write_matrix(self):
+ if self.matrix and not is_identity(self.matrix):
+ self.header.fw.write_short(49) # Matrix opcode
+ self.header.fw.write_ushort(68) # Length of record
+ for i in xrange(4):
+ for j in xrange(4):
+ self.header.fw.write_float(self.matrix[i][j])
+
+ def write_push(self):
+ self.header.fw.write_short(10)
+ self.header.fw.write_ushort(4)
+
+ def write_pop(self):
+ self.header.fw.write_short(11)
+ self.header.fw.write_ushort(4)
+
+ def write_longid(self, name):
+ length = len(name)
+ if length >= 8:
+ self.header.fw.write_short(33) # Long ID opcode
+ self.header.fw.write_ushort(length+5) # Length of record
+ self.header.fw.write_string(name, length+1) # name + zero terminator
+
+ # Initialization sets up basic tree structure.
+ def __init__(self, parent, header, object, object_lst):
+ self.header = header
+ self.object = object
+ if object:
+ self.name = self.object.getName()
+ self.matrix = self.object.getMatrix('localspace')
+ else:
+ self.name = 'no name'
+ self.matrix = None
+
+ self.children = []
+ self.parent = parent
+ if parent:
+ parent.children.append(self)
+
+ left_over = object_lst[:]
+ self.child_objects = []
+
+ # Add children to child list and remove from left_over list.
+
+ # Pop is faster then remove
+ i = len(object_lst)
+ while i:
+ i-=1
+ if object_lst[i].parent == object:
+ self.child_objects.append(left_over.pop(i))
+
+ # Spawn children.
+ self.has_object_child = False # For Database class.
+ for child in self.child_objects:
+ if child.getType() == 'Mesh':
+ BlenderMesh(self, header, child, left_over)
+ self.has_object_child = True
+ else: # Treat all non meshes as emptys
+ BlenderEmpty(self, header, child, left_over)
class FaceDesc:
- def __init__(self):
- self.vertex_index_lst = []
- self.texture_index = -1
- self.material_index = -1
- self.color_index = 127
-
+ def __init__(self):
+ self.vertex_index_lst = []
+ self.texture_index = -1
+ self.material_index = -1
+ self.color_index = 127
+
class BlenderMesh(Node):
- def blender_export(self):
- Node.blender_export(self)
-
- mesh = self.object.getData()
-
- # Gather materials and textures.
- tex_index_lst = []
- mat_index_lst = []
- color_index_lst = []
- materials = mesh.getMaterials()
-
- if materials == []:
- materials = [Blender.Material.New()]
-
- for mat in materials:
- # Gather Color.
- if options.use_face_color:
- color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol()))
- else:
- color_index_lst.append(127) # white
- # Gather Texture.
- mtex_lst = mat.getTextures()
-
- index = -1
- mtex = mtex_lst[0] # Not doing multi-texturing at the moment.
- if mtex != None:
- tex = mtex_lst[0].tex
- if tex != None:
- image = tex.getImage()
- if image != None:
- filename = image.getFilename()
- index = self.header.GRR.request_texture_index(filename)
-
- tex_index_lst.append(index)
-
- # Gather Material
- mat_desc = MaterialDesc()
- mat_desc.name = mat.getName()
- mat_desc.alpha = mat.getAlpha()
- mat_desc.shininess = mat.getSpec() * 64.0 # 2.0 => 128.0
- if options.use_mat_color:
- mat_desc.diffuse = mat.getRGBCol()
- else:
- mat_desc.diffuse = [1.0, 1.0, 1.0]
-
- mat_desc.specular = mat.getSpecCol()
- amb = mat.getAmb()
- mat_desc.ambient = [amb, amb, amb]
- emit = mat.getEmit()
- mat_desc.emissive = [emit, emit, emit]
-
- mat_index_lst.append(self.header.GRR.request_material_index(mat_desc))
-
- # Faces described as lists of indices into the GRR's vertex_lst.
- for face in mesh.faces:
- # Create vertex description list for each face.
- vertex_lst = []
- for vertex in face.v:
- vert_desc = VertexDesc()
- vert_desc.x = vertex.co[0]
- vert_desc.y = vertex.co[1]
- vert_desc.z = vertex.co[2]
- vert_desc.nx = vertex.no[0]
- vert_desc.ny = vertex.no[1]
- vert_desc.nz = vertex.no[2]
- vertex_lst.append(vert_desc)
-
- for j in range( min(len(face.uv),len(vertex_lst)) ):
- vertex_lst[j].u = face.uv[j][0]
- vertex_lst[j].v = face.uv[j][1]
-
- index_lst = []
- for vert_desc in vertex_lst:
- index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
-
- face_desc = FaceDesc()
- face_desc.vertex_index_lst = index_lst
-
- if face.materialIndex < len(materials):
- face_desc.color_index = color_index_lst[face.materialIndex]
- face_desc.texture_index = tex_index_lst[face.materialIndex]
- face_desc.material_index = mat_index_lst[face.materialIndex]
- else:
- if options.verbose >=1:
- print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.'
-
- self.face_lst.append(face_desc)
-
- # Export double sided face as 2 faces with opposite orientations.
- if mesh.hasFaceUV() and face.mode & Blender.NMesh.FaceModes['TWOSIDE']:
- # Create vertex description list for each face.
- vertex_lst = []
- for vertex in face.v:
- vert_desc = VertexDesc()
- vert_desc.x = vertex.co[0]
- vert_desc.y = vertex.co[1]
- vert_desc.z = vertex.co[2]
- vert_desc.nx = -vertex.no[0]
- vert_desc.ny = -vertex.no[1]
- vert_desc.nz = -vertex.no[2]
- vertex_lst.append(vert_desc)
-
- for j in range( min(len(face.uv),len(vertex_lst)) ):
- vertex_lst[j].u = face.uv[j][0]
- vertex_lst[j].v = face.uv[j][1]
-
- vertex_lst.reverse()
-
- index_lst = []
- for vert_desc in vertex_lst:
- index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
-
- face_desc = FaceDesc()
- face_desc.vertex_index_lst = index_lst
- if face.materialIndex < len(materials):
- face_desc.color_index = color_index_lst[face.materialIndex]
- face_desc.texture_index = tex_index_lst[face.materialIndex]
- face_desc.material_index = mat_index_lst[face.materialIndex]
- else:
- if options.verbose >=1:
- print 'Error: No material for material index. Delete abandoned material indices in Blender.'
-
- self.face_lst.append(face_desc)
-
- def write_faces(self):
- for face_desc in self.face_lst:
- face_name = self.header.GRR.new_face_name()
-
- self.header.fw.write_short(5) # Face opcode
- self.header.fw.write_ushort(80) # Length of record
- self.header.fw.write_string(face_name, 8) # ASCII ID
- self.header.fw.write_int(-1) # IR color code
- self.header.fw.write_short(0) # Relative priority
- self.header.fw.write_char(0) # Draw type
- self.header.fw.write_char(0) # Draw textured white.
- self.header.fw.write_ushort(0) # Color name index
- self.header.fw.write_ushort(0) # Alt color name index
- self.header.fw.write_char(0) # Reserved
- self.header.fw.write_char(1) # Template
- self.header.fw.write_short(-1) # Detail tex pat index
- self.header.fw.write_short(face_desc.texture_index) # Tex pattern index
- self.header.fw.write_short(face_desc.material_index) # material index
- self.header.fw.write_short(0) # SMC code
- self.header.fw.write_short(0) # Feature code
- self.header.fw.write_int(0) # IR material code
- self.header.fw.write_ushort(0) # transparency 0 = opaque
- self.header.fw.write_uchar(0) # LOD generation control
- self.header.fw.write_uchar(0) # line style index
- self.header.fw.write_int(0x00000000) # Flags
- self.header.fw.write_uchar(2) # Light mode
- self.header.fw.pad(7) # Reserved
- self.header.fw.write_uint(-1) # Packed color
- self.header.fw.write_uint(-1) # Packed alt color
- self.header.fw.write_short(-1) # Tex map index
- self.header.fw.write_short(0) # Reserved
- self.header.fw.write_uint(face_desc.color_index) # Color index
- self.header.fw.write_uint(127) # Alt color index
- self.header.fw.write_short(0) # Reserved
- self.header.fw.write_short(-1) # Shader index
-
- self.write_longid(face_name)
-
- self.write_push()
-
- # Vertex list record
- self.header.fw.write_short(72) # Vertex list opcode
- num_verts = len(face_desc.vertex_index_lst)
- self.header.fw.write_ushort(4*num_verts+4) # Length of record
-
- for vert_index in face_desc.vertex_index_lst:
- # Offset into vertex palette
- self.header.fw.write_int(vert_index*64+8)
-
- self.write_pop()
-
- def write(self):
- if self.open_flight_type == 'Object':
- self.header.fw.write_short(4) # Object opcode
- self.header.fw.write_ushort(28) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(16)
-
- self.write_longid(self.name)
-
- self.write_matrix()
-
- if self.face_lst != []:
- self.write_push()
-
- self.write_faces()
-
- self.write_pop()
- else:
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(32)
-
- self.write_longid(self.name)
-
- # Because a group can contain faces as well as children.
- self.write_push()
-
- self.write_faces()
-
- for child in self.children:
- child.write()
-
- self.write_pop()
-
-
- def __init__(self, parent, header, object, object_lst):
- Node.__init__(self, parent, header, object, object_lst)
- self.face_lst = []
-
- if self.children == []:
- self.open_flight_type = 'Object'
- else:
- self.open_flight_type= 'Group'
+ def blender_export(self):
+ Node.blender_export(self)
+
+ mesh = self.object.getData()
+ mesh_hasuv = mesh.hasFaceUV()
+ # Gather materials and textures.
+ tex_index_lst = []
+ mat_index_lst = []
+ color_index_lst = []
+ materials = mesh.getMaterials()
+
+ if not materials:
+ materials = [Blender.Material.New()]
+
+ for mat in materials:
+ # Gather Color.
+ if options.use_face_color:
+ color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol()))
+ else:
+ color_index_lst.append(127) # white
+ # Gather Texture.
+ mtex_lst = mat.getTextures()
+
+ index = -1
+ mtex = mtex_lst[0] # Not doing multi-texturing at the moment.
+ if mtex != None:
+ tex = mtex_lst[0].tex
+ if tex != None:
+ image = tex.getImage()
+ if image != None:
+ filename = image.getFilename()
+ index = self.header.GRR.request_texture_index(filename)
+
+ tex_index_lst.append(index)
+
+ # Gather Material
+ mat_desc = MaterialDesc()
+ mat_desc.name = mat.getName()
+ mat_desc.alpha = mat.getAlpha()
+ mat_desc.shininess = mat.getSpec() * 64.0 # 2.0 => 128.0
+ if options.use_mat_color:
+ mat_desc.diffuse = mat.getRGBCol()
+ else:
+ mat_desc.diffuse = [1.0, 1.0, 1.0]
+
+ mat_desc.specular = mat.getSpecCol()
+ amb = mat.getAmb()
+ mat_desc.ambient = [amb, amb, amb]
+ emit = mat.getEmit()
+ mat_desc.emissive = [emit, emit, emit]
+
+ mat_index_lst.append(self.header.GRR.request_material_index(mat_desc))
+
+ # Faces described as lists of indices into the GRR's vertex_lst.
+ for face in mesh.faces:
+
+ face_v = face.v # Faster access
+
+ # Create vertex description list for each face.
+ if mesh_hasuv:
+ vertex_lst = [VertexDesc(v.co, v.no, face.uv[i]) for i, v in enumerate(face_v)]
+ else:
+ vertex_lst = [VertexDesc(v.co, v.no) for i, v in enumerate(face_v)]
+
+ index_lst = []
+ for vert_desc in vertex_lst:
+ index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
+
+ face_desc = FaceDesc()
+ face_desc.vertex_index_lst = index_lst
+
+ if face.materialIndex < len(materials):
+ face_desc.color_index = color_index_lst[face.materialIndex]
+ face_desc.texture_index = tex_index_lst[face.materialIndex]
+ face_desc.material_index = mat_index_lst[face.materialIndex]
+ else:
+ if options.verbose >=1:
+ print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.'
+
+ self.face_lst.append(face_desc)
+
+ # Export double sided face as 2 faces with opposite orientations.
+ if mesh_hasuv and face.mode & Blender.NMesh.FaceModes['TWOSIDE']:
+ # Create vertex description list for each face. they have a face mode, so we know they have a UV too.
+ vertex_lst = [VertexDesc(v.co, -v.no, face.uv[i]) for i, v in enumerate(face_v)]
+ vertex_lst.reverse() # Reversing flips the face.
+
+ index_lst = []
+ for vert_desc in vertex_lst:
+ index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
+
+ face_desc = FaceDesc()
+ face_desc.vertex_index_lst = index_lst
+ if face.materialIndex < len(materials):
+ face_desc.color_index = color_index_lst[face.materialIndex]
+ face_desc.texture_index = tex_index_lst[face.materialIndex]
+ face_desc.material_index = mat_index_lst[face.materialIndex]
+ else:
+ if options.verbose >=1:
+ print 'Error: No material for material index. Delete abandoned material indices in Blender.'
+
+ self.face_lst.append(face_desc)
+
+ def write_faces(self):
+ for face_desc in self.face_lst:
+ face_name = self.header.GRR.new_face_name()
+
+ self.header.fw.write_short(5) # Face opcode
+ self.header.fw.write_ushort(80) # Length of record
+ self.header.fw.write_string(face_name, 8) # ASCII ID
+ self.header.fw.write_int(-1) # IR color code
+ self.header.fw.write_short(0) # Relative priority
+ self.header.fw.write_char(0) # Draw type
+ self.header.fw.write_char(0) # Draw textured white.
+ self.header.fw.write_ushort(0) # Color name index
+ self.header.fw.write_ushort(0) # Alt color name index
+ self.header.fw.write_char(0) # Reserved
+ self.header.fw.write_char(1) # Template
+ self.header.fw.write_short(-1) # Detail tex pat index
+ self.header.fw.write_short(face_desc.texture_index) # Tex pattern index
+ self.header.fw.write_short(face_desc.material_index) # material index
+ self.header.fw.write_short(0) # SMC code
+ self.header.fw.write_short(0) # Feature code
+ self.header.fw.write_int(0) # IR material code
+ self.header.fw.write_ushort(0) # transparency 0 = opaque
+ self.header.fw.write_uchar(0) # LOD generation control
+ self.header.fw.write_uchar(0) # line style index
+ self.header.fw.write_int(0x00000000) # Flags
+ self.header.fw.write_uchar(2) # Light mode
+ self.header.fw.pad(7) # Reserved
+ self.header.fw.write_uint(-1) # Packed color
+ self.header.fw.write_uint(-1) # Packed alt color
+ self.header.fw.write_short(-1) # Tex map index
+ self.header.fw.write_short(0) # Reserved
+ self.header.fw.write_uint(face_desc.color_index) # Color index
+ self.header.fw.write_uint(127) # Alt color index
+ self.header.fw.write_short(0) # Reserved
+ self.header.fw.write_short(-1) # Shader index
+
+ self.write_longid(face_name)
+
+ self.write_push()
+
+ # Vertex list record
+ self.header.fw.write_short(72) # Vertex list opcode
+ num_verts = len(face_desc.vertex_index_lst)
+ self.header.fw.write_ushort(4*num_verts+4) # Length of record
+
+ for vert_index in face_desc.vertex_index_lst:
+ # Offset into vertex palette
+ self.header.fw.write_int(vert_index*64+8)
+
+ self.write_pop()
+
+ def write(self):
+ if self.open_flight_type == 'Object':
+ self.header.fw.write_short(4) # Object opcode
+ self.header.fw.write_ushort(28) # Length of record
+ self.header.fw.write_string(self.name, 8) # ASCII ID
+ self.header.fw.pad(16)
+
+ self.write_longid(self.name)
+
+ self.write_matrix()
+
+ if self.face_lst != []:
+ self.write_push()
+
+ self.write_faces()
+
+ self.write_pop()
+ else:
+ self.header.fw.write_short(2) # Group opcode
+ self.header.fw.write_ushort(44) # Length of record
+ self.header.fw.write_string(self.name, 8) # ASCII ID
+ self.header.fw.pad(32)
+
+ self.write_longid(self.name)
+
+ # Because a group can contain faces as well as children.
+ self.write_push()
+
+ self.write_faces()
+
+ for child in self.children:
+ child.write()
+
+ self.write_pop()
+
+ def __init__(self, parent, header, object, object_lst):
+ Node.__init__(self, parent, header, object, object_lst)
+ self.face_lst = []
+
+ if self.children:
+ self.open_flight_type= 'Group'
+ else: # Empty list.
+ self.open_flight_type = 'Object'
+
class BlenderEmpty(Node):
- def write(self):
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string(self.name, 8) # ASCII ID
- self.header.fw.pad(32)
-
- self.write_longid(self.name)
-
- self.write_matrix()
-
- if self.children != []:
- self.write_push()
-
- for child in self.children:
- child.write()
-
- self.write_pop()
+ def write(self):
+ self.header.fw.write_short(2) # Group opcode
+ self.header.fw.write_ushort(44) # Length of record
+ self.header.fw.write_string(self.name, 8) # ASCII ID
+ self.header.fw.pad(32)
+
+ self.write_longid(self.name)
+
+ self.write_matrix()
+
+ if self.children: # != []
+ self.write_push()
+
+ for child in self.children:
+ child.write()
+
+ self.write_pop()
class Database(Node):
- def write_header(self):
- if options.verbose >= 2:
- print 'Writing header.'
- self.fw.write_short(1) # Header opcode
- self.fw.write_ushort(324) # Length of record
- self.fw.write_string('db', 8) # ASCII ID
- self.fw.write_int(1600) # Revision Number
- self.fw.pad(44)
- self.fw.write_short(1) # Unit multiplier.
- self.fw.write_char(0) # Units, 0 = meters
- self.fw.write_char(0) # texwhite on new faces 0 = false
- self.fw.write_uint(0x80000000) # misc flags set to saving vertex normals
- self.fw.pad(24)
- self.fw.write_int(0) # projection type, 0 = flat earth
- self.fw.pad(30)
- self.fw.write_short(1) # double precision
- self.fw.pad(140)
- self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984
- self.fw.pad(52)
-
- def write_vert_pal(self):
- if options.verbose >= 2:
- print 'Writing vertex palette.'
- # Write record for vertex palette
- self.fw.write_short(67) # Vertex palette opcode.
- self.fw.write_short(8) # Length of record
- self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything.
-
- # Write records for individual vertices.
- for i in range(self.GRR.vertex_count()):
- desc = self.GRR.request_vertex_desc(i)
- self.fw.write_short(70) # Vertex with color normal and uv opcode.
- self.fw.write_ushort(64) # Length of record
- self.fw.write_ushort(0) # Color name index
- self.fw.write_short(0x2000) # Flags set to no color
- self.fw.write_double(desc.x)
- self.fw.write_double(desc.y)
- self.fw.write_double(desc.z)
- self.fw.write_float(desc.nx)
- self.fw.write_float(desc.ny)
- self.fw.write_float(desc.nz)
- self.fw.write_float(desc.u)
- self.fw.write_float(desc.v)
- self.fw.pad(12)
-
- def write_tex_pal(self):
- if options.verbose >= 2:
- print 'Writing texture palette.'
- # Write record for texture palette
- for i in range(self.GRR.texture_count()):
- self.fw.write_short(64) # Texture palette opcode.
- self.fw.write_short(216) # Length of record
- self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename
- self.fw.write_int(i) # Texture index
- self.fw.write_int(0) # X
- self.fw.write_int(0) # Y
-
- def write_mat_pal(self):
- if options.verbose >= 2:
- print 'Writing material palette.'
- for i in range(self.GRR.material_count()):
- desc = self.GRR.request_material_desc(i)
- self.fw.write_short(113) # Material palette opcode.
- self.fw.write_short(84) # Length of record
- self.fw.write_int(i) # Material index
- self.fw.write_string(desc.name, 12) # Material name
- self.fw.write_uint(0x80000000) # Flags
- self.fw.write_float(desc.ambient[0]) # Ambient color.
- self.fw.write_float(desc.ambient[1]) # Ambient color.
- self.fw.write_float(desc.ambient[2]) # Ambient color.
- self.fw.write_float(desc.diffuse[0]) # Diffuse color.
- self.fw.write_float(desc.diffuse[1]) # Diffuse color.
- self.fw.write_float(desc.diffuse[2]) # Diffuse color.
- self.fw.write_float(desc.specular[0]) # Specular color.
- self.fw.write_float(desc.specular[1]) # Specular color.
- self.fw.write_float(desc.specular[2]) # Specular color.
- self.fw.write_float(desc.emissive[0]) # Emissive color.
- self.fw.write_float(desc.emissive[1]) # Emissive color.
- self.fw.write_float(desc.emissive[2]) # Emissive color.
- self.fw.write_float(desc.shininess)
- self.fw.write_float(desc.alpha)
- self.fw.write_int(0) # Reserved
-
- def write_col_pal(self):
- if options.verbose >= 2:
- print 'Writing color palette.'
- self.fw.write_short(32) # Color palette opcode.
- self.fw.write_short(4228) # Length of record
- self.fw.pad(128)
- count = self.GRR.color_count()
- for i in range(count):
- col = self.GRR.request_max_color(i)
- self.fw.write_uchar(255) # alpha
- self.fw.write_uchar(col[2]) # b
- self.fw.write_uchar(col[1]) # g
- self.fw.write_uchar(col[0]) # r
- self.fw.pad(max(4096-count*4, 0))
-
- def write(self):
- self.write_header()
- self.write_vert_pal()
- self.write_tex_pal()
- self.write_mat_pal()
- self.write_col_pal()
-
- # Wrap everything in a group if it has an object child.
- if self.has_object_child:
- self.header.fw.write_short(2) # Group opcode
- self.header.fw.write_ushort(44) # Length of record
- self.header.fw.write_string('g1', 8) # ASCII ID
- self.header.fw.pad(32)
-
- self.write_push()
-
- for child in self.children:
- child.write()
-
- self.write_pop()
-
- def __init__(self, scene, fw):
- self.fw = fw
- self.scene = scene
- self.all_objects = scene.getChildren()
- self.GRR = GlobalResourceRepository()
-
- Node.__init__(self, None, self, None, self.all_objects)
+ def write_header(self):
+ if options.verbose >= 2:
+ print 'Writing header.'
+ self.fw.write_short(1) # Header opcode
+ self.fw.write_ushort(324) # Length of record
+ self.fw.write_string('db', 8) # ASCII ID
+ self.fw.write_int(1600) # Revision Number
+ self.fw.pad(44)
+ self.fw.write_short(1) # Unit multiplier.
+ self.fw.write_char(0) # Units, 0 = meters
+ self.fw.write_char(0) # texwhite on new faces 0 = false
+ self.fw.write_uint(0x80000000) # misc flags set to saving vertex normals
+ self.fw.pad(24)
+ self.fw.write_int(0) # projection type, 0 = flat earth
+ self.fw.pad(30)
+ self.fw.write_short(1) # double precision
+ self.fw.pad(140)
+ self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984
+ self.fw.pad(52)
+
+ def write_vert_pal(self):
+ if options.verbose >= 2:
+ print 'Writing vertex palette.'
+ # Write record for vertex palette
+ self.fw.write_short(67) # Vertex palette opcode.
+ self.fw.write_short(8) # Length of record
+ self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything.
+
+ # Write records for individual vertices.
+ for i in xrange(self.GRR.vertex_count()):
+ desc = self.GRR.request_vertex_desc(i)
+ self.fw.write_short(70) # Vertex with color normal and uv opcode.
+ self.fw.write_ushort(64) # Length of record
+ self.fw.write_ushort(0) # Color name index
+ self.fw.write_short(0x2000) # Flags set to no color
+ self.fw.write_double(desc.x)
+ self.fw.write_double(desc.y)
+ self.fw.write_double(desc.z)
+ self.fw.write_float(desc.nx)
+ self.fw.write_float(desc.ny)
+ self.fw.write_float(desc.nz)
+ self.fw.write_float(desc.u)
+ self.fw.write_float(desc.v)
+ self.fw.pad(12)
+
+ def write_tex_pal(self):
+ if options.verbose >= 2:
+ print 'Writing texture palette.'
+ # Write record for texture palette
+ for i in xrange(self.GRR.texture_count()):
+ self.fw.write_short(64) # Texture palette opcode.
+ self.fw.write_short(216) # Length of record
+ self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename
+ self.fw.write_int(i) # Texture index
+ self.fw.write_int(0) # X
+ self.fw.write_int(0) # Y
+
+ def write_mat_pal(self):
+ if options.verbose >= 2:
+ print 'Writing material palette.'
+ for i in xrange(self.GRR.material_count()):
+ desc = self.GRR.request_material_desc(i)
+ self.fw.write_short(113) # Material palette opcode.
+ self.fw.write_short(84) # Length of record
+ self.fw.write_int(i) # Material index
+ self.fw.write_string(desc.name, 12) # Material name
+ self.fw.write_uint(0x80000000) # Flags
+ self.fw.write_float(desc.ambient[0]) # Ambient color.
+ self.fw.write_float(desc.ambient[1]) # Ambient color.
+ self.fw.write_float(desc.ambient[2]) # Ambient color.
+ self.fw.write_float(desc.diffuse[0]) # Diffuse color.
+ self.fw.write_float(desc.diffuse[1]) # Diffuse color.
+ self.fw.write_float(desc.diffuse[2]) # Diffuse color.
+ self.fw.write_float(desc.specular[0]) # Specular color.
+ self.fw.write_float(desc.specular[1]) # Specular color.
+ self.fw.write_float(desc.specular[2]) # Specular color.
+ self.fw.write_float(desc.emissive[0]) # Emissive color.
+ self.fw.write_float(desc.emissive[1]) # Emissive color.
+ self.fw.write_float(desc.emissive[2]) # Emissive color.
+ self.fw.write_float(desc.shininess)
+ self.fw.write_float(desc.alpha)
+ self.fw.write_int(0) # Reserved
+
+ def write_col_pal(self):
+ if options.verbose >= 2:
+ print 'Writing color palette.'
+ self.fw.write_short(32) # Color palette opcode.
+ self.fw.write_short(4228) # Length of record
+ self.fw.pad(128)
+ count = self.GRR.color_count()
+ for i in xrange(count):
+ col = self.GRR.request_max_color(i)
+ self.fw.write_uchar(255) # alpha
+ self.fw.write_uchar(col[2]) # b
+ self.fw.write_uchar(col[1]) # g
+ self.fw.write_uchar(col[0]) # r
+ self.fw.pad(max(4096-count*4, 0))
+
+ def write(self):
+ self.write_header()
+ self.write_vert_pal()
+ self.write_tex_pal()
+ self.write_mat_pal()
+ self.write_col_pal()
+
+ # Wrap everything in a group if it has an object child.
+ if self.has_object_child:
+ self.header.fw.write_short(2) # Group opcode
+ self.header.fw.write_ushort(44) # Length of record
+ self.header.fw.write_string('g1', 8) # ASCII ID
+ self.header.fw.pad(32)
+
+ self.write_push()
+
+ for child in self.children:
+ child.write()
+
+ self.write_pop()
+
+ def __init__(self, scene, fw):
+ self.fw = fw
+ self.scene = scene
+ self.all_objects = scene.getChildren()
+ self.GRR = GlobalResourceRepository()
+
+ Node.__init__(self, None, self, None, self.all_objects)
def fs_callback(filename):
- Blender.Window.WaitCursor(True)
-
- if Blender.sys.exists(filename):
- r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No')
- if r != 1:
- if options.verbose >= 1:
- print 'Export cancelled.'
- return
-
- fw = FltOut(filename)
-
- db = Database(Blender.Scene.GetCurrent(), fw)
-
- if options.verbose >= 1:
- print
- print 'Pass 1: Exporting from Blender.'
- print
-
- db.blender_export()
-
- if options.verbose >= 1:
- print
- print 'Pass 2: Writing', filename
- print
-
- db.write()
-
- fw.close_file()
- if options.verbose >= 1:
- print
- print 'Done.'
-
- Blender.Window.WaitCursor(False)
-
+ Blender.Window.WaitCursor(True)
+
+ if Blender.sys.exists(filename):
+ r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No')
+ if r != 1:
+ if options.verbose >= 1:
+ print 'Export cancelled.'
+ return
+
+ time1 = Blender.sys.time() # Start timing
+
+ fw = FltOut(filename)
+
+ db = Database(Blender.Scene.GetCurrent(), fw)
+
+ if options.verbose >= 1:
+ print 'Pass 1: Exporting from Blender.\n'
+
+ db.blender_export()
+
+ if options.verbose >= 1:
+ print 'Pass 2: Writing %s\n' % filename
+
+ db.write()
+
+ fw.close_file()
+ if options.verbose >= 1:
+ print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1)
+
+ Blender.Window.WaitCursor(False)
+
if options.verbose >= 1:
- print
- print 'OpenFlight Exporter'
- print 'Version:', __version__
- print 'Author: Greg MacDonald'
- print __url__[2]
- print
-
+ print '\nOpenFlight Exporter'
+ print 'Version:', __version__
+ print 'Author: Greg MacDonald'
+ print __url__[2]
+ print
+
fname = Blender.sys.makename(ext=".flt")
Blender.Window.FileSelector(fs_callback, "Export OpenFlight v16.0", fname)