removed slow list handeling
faster vert comparisons replaced spaces for tabs removed unneeded getData() calls general cleanup.
This commit is contained in:
@@ -57,7 +57,6 @@ What's Not Handled:<br>
|
||||
"""
|
||||
|
||||
import Blender
|
||||
import math
|
||||
from flt_filewalker import FltOut
|
||||
|
||||
class ExporterOptions:
|
||||
@@ -78,15 +77,14 @@ class ExporterOptions:
|
||||
|
||||
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]):
|
||||
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
|
||||
|
||||
@@ -105,21 +103,18 @@ class MaterialDesc:
|
||||
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
|
||||
return 'f%i' % (self.face_name-1)
|
||||
|
||||
def vertex_count(self):
|
||||
return len(self.vertex_lst)
|
||||
@@ -129,24 +124,18 @@ class GlobalResourceRepository:
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -158,7 +147,7 @@ class GlobalResourceRepository:
|
||||
|
||||
def request_texture_index(self, filename):
|
||||
match = None
|
||||
for i in range(len(self.texture_lst)):
|
||||
for i in xrange(len(self.texture_lst)):
|
||||
if self.texture_lst[i] != filename:
|
||||
continue
|
||||
match = i
|
||||
@@ -177,7 +166,7 @@ class GlobalResourceRepository:
|
||||
|
||||
def request_material_index(self, desc):
|
||||
match = None
|
||||
for i in range(len(self.material_lst)):
|
||||
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:
|
||||
@@ -208,9 +197,7 @@ class GlobalResourceRepository:
|
||||
# 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]
|
||||
r,g,b = tuple(col)
|
||||
m = max(r, g, b)
|
||||
if m > 0.0:
|
||||
intensity = m / 1.0
|
||||
@@ -223,7 +210,7 @@ class GlobalResourceRepository:
|
||||
intensity = 0.0
|
||||
|
||||
match = None
|
||||
for i in range(len(self.color_lst)):
|
||||
for i in xrange(len(self.color_lst)):
|
||||
if self.color_lst[i] != brightest:
|
||||
continue
|
||||
|
||||
@@ -266,9 +253,7 @@ class Node:
|
||||
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())
|
||||
print '\t' * level[0], self.name, self.object.getType()
|
||||
|
||||
level[0] += 1
|
||||
|
||||
@@ -285,8 +270,8 @@ class Node:
|
||||
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):
|
||||
for i in xrange(4):
|
||||
for j in xrange(4):
|
||||
self.header.fw.write_float(self.matrix[i][j])
|
||||
|
||||
def write_push(self):
|
||||
@@ -324,22 +309,22 @@ class Node:
|
||||
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)
|
||||
|
||||
# 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:
|
||||
dat = child.getData()
|
||||
t = type(dat)
|
||||
|
||||
if dat == None:
|
||||
BlenderEmpty(self, header, child, left_over)
|
||||
if t == Blender.Types.NMeshType:
|
||||
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):
|
||||
@@ -353,14 +338,14 @@ class BlenderMesh(Node):
|
||||
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 materials == []:
|
||||
if not materials:
|
||||
materials = [Blender.Material.New()]
|
||||
|
||||
for mat in materials:
|
||||
@@ -404,21 +389,14 @@ class BlenderMesh(Node):
|
||||
|
||||
# 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]
|
||||
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:
|
||||
@@ -438,24 +416,10 @@ class BlenderMesh(Node):
|
||||
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()
|
||||
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:
|
||||
@@ -559,15 +523,15 @@ class BlenderMesh(Node):
|
||||
|
||||
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:
|
||||
if self.children:
|
||||
self.open_flight_type= 'Group'
|
||||
else: # Empty list.
|
||||
self.open_flight_type = 'Object'
|
||||
|
||||
|
||||
class BlenderEmpty(Node):
|
||||
def write(self):
|
||||
@@ -580,7 +544,7 @@ class BlenderEmpty(Node):
|
||||
|
||||
self.write_matrix()
|
||||
|
||||
if self.children != []:
|
||||
if self.children: # != []
|
||||
self.write_push()
|
||||
|
||||
for child in self.children:
|
||||
@@ -618,7 +582,7 @@ class Database(Node):
|
||||
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()):
|
||||
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
|
||||
@@ -638,7 +602,7 @@ class Database(Node):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing texture palette.'
|
||||
# Write record for texture palette
|
||||
for i in range(self.GRR.texture_count()):
|
||||
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
|
||||
@@ -649,7 +613,7 @@ class Database(Node):
|
||||
def write_mat_pal(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing material palette.'
|
||||
for i in range(self.GRR.material_count()):
|
||||
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
|
||||
@@ -679,7 +643,7 @@ class Database(Node):
|
||||
self.fw.write_short(4228) # Length of record
|
||||
self.fw.pad(128)
|
||||
count = self.GRR.color_count()
|
||||
for i in range(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
|
||||
@@ -726,34 +690,30 @@ def fs_callback(filename):
|
||||
print 'Export cancelled.'
|
||||
return
|
||||
|
||||
time1 = Blender.sys.time() # Start timing
|
||||
|
||||
fw = FltOut(filename)
|
||||
|
||||
db = Database(Blender.Scene.GetCurrent(), fw)
|
||||
|
||||
if options.verbose >= 1:
|
||||
print
|
||||
print 'Pass 1: Exporting from Blender.'
|
||||
print
|
||||
print 'Pass 1: Exporting from Blender.\n'
|
||||
|
||||
db.blender_export()
|
||||
|
||||
if options.verbose >= 1:
|
||||
print
|
||||
print 'Pass 2: Writing', filename
|
||||
print
|
||||
print 'Pass 2: Writing %s\n' % filename
|
||||
|
||||
db.write()
|
||||
|
||||
fw.close_file()
|
||||
if options.verbose >= 1:
|
||||
print
|
||||
print 'Done.'
|
||||
print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1)
|
||||
|
||||
Blender.Window.WaitCursor(False)
|
||||
|
||||
if options.verbose >= 1:
|
||||
print
|
||||
print 'OpenFlight Exporter'
|
||||
print '\nOpenFlight Exporter'
|
||||
print 'Version:', __version__
|
||||
print 'Author: Greg MacDonald'
|
||||
print __url__[2]
|
||||
|
||||
Reference in New Issue
Block a user