forked from bartvdbraak/blender
c7a8f6cd9d
Only code change is cookie cut from View now only uses 3d curves to cut.
1890 lines
55 KiB
Python
Executable File
1890 lines
55 KiB
Python
Executable File
#!BPY
|
|
""" Registration info for Blender menus:
|
|
Name: 'OpenFlight (.flt)...'
|
|
Blender: 238
|
|
Group: 'Import'
|
|
Tip: 'Import OpenFlight (.flt)'
|
|
"""
|
|
|
|
__author__ = "Greg MacDonald, Campbell Barton"
|
|
__version__ = "1.2 10/20/05"
|
|
__url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
|
|
__bpydoc__ = """\
|
|
This script imports OpenFlight files into Blender. OpenFlight is a
|
|
registered trademark of MultiGen-Paradigm, Inc.
|
|
|
|
Run from "File->Import" menu.
|
|
|
|
Options are available from Blender's "Scripts Config Editor," accessible through
|
|
the "Scripts->System" menu from the scripts window.
|
|
|
|
All global_prefs are toggle switches that let the user choose what is imported. Most
|
|
are straight-forward, but one option could be a source of confusion. The
|
|
"Diffuse Color From Face" option when set pulls the diffuse color from the face
|
|
colors. Otherwise the diffuse color comes from the material. What may be
|
|
confusing is that this global_prefs only works if the "Diffuse Color" option is set.
|
|
|
|
New Features:<br>
|
|
* Importer is 14 times faster.<br>
|
|
* External triangle module is no longer required, but make sure the importer
|
|
has a 3d View screen open while its running or triangulation won't work.<br>
|
|
* Should be able to import all versions of flight files.
|
|
|
|
Features:<br>
|
|
* Heirarchy retained.<br>
|
|
* First texture imported.<br>
|
|
* Colors imported from face or material.<br>
|
|
* LOD seperated out into different layers.<br>
|
|
* Asks for location of unfound textures or external references.<br>
|
|
* Searches Blender's texture directory in the user preferences panel.<br>
|
|
* Triangles with more than 4 verts are triangulated if the Triangle python
|
|
module is installed.<br>
|
|
* Matrix transforms imported.<br>
|
|
* External references to whole files are imported.
|
|
|
|
Things To Be Aware Of:<br>
|
|
* Each new color and face attribute creates a new material and there are only a maximum of 16
|
|
materials per object.<br>
|
|
* For triangulated faces, normals must be recomputed outward manually by typing
|
|
CTRL+N in edit mode.<br>
|
|
* You can change global_prefs only after an initial import.<br>
|
|
* External references are imported as geometry and will be exported that way.<br>
|
|
* A work around for not using the Triangle python module is to simply to
|
|
triangulate in Creator before importing. This is only necessary if your
|
|
model contains 5 or more vertices.<br>
|
|
* You have to manually blend the material color with the texture color.
|
|
|
|
What's Not Handled:<br>
|
|
* Special texture repeating modes.<br>
|
|
* Replications and instancing.<br>
|
|
* Comment and attribute fields.<br>
|
|
* Light points.<br>
|
|
* Animations.<br>
|
|
* External references to a node within a file.<br>
|
|
* Multitexturing.<br>
|
|
* Vetex colors.<br>
|
|
"""
|
|
|
|
# flt_import.py is an OpenFlight importer for blender.
|
|
# Copyright (C) 2005 Greg MacDonald
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
import Blender
|
|
import os
|
|
import BPyMesh
|
|
import BPyImage
|
|
import flt_filewalker
|
|
|
|
Vector= Blender.Mathutils.Vector
|
|
|
|
def col_to_gray(c):
|
|
return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
|
|
|
|
|
|
global_prefs = dict()
|
|
global_prefs['verbose']= 1
|
|
global_prefs['get_texture'] = True
|
|
global_prefs['get_diffuse'] = True
|
|
global_prefs['get_specular'] = False
|
|
global_prefs['get_emissive'] = False
|
|
global_prefs['get_alpha'] = True
|
|
global_prefs['get_ambient'] = False
|
|
global_prefs['get_shininess'] = True
|
|
global_prefs['color_from_face'] = True
|
|
global_prefs['fltfile']= ''
|
|
msg_once = False
|
|
|
|
class MaterialDesc:
|
|
# Was going to use int(f*1000.0) instead of round(f,3), but for some reason
|
|
# round produces better results, as in less dups.
|
|
def make_key(self):
|
|
key = list()
|
|
if global_prefs['get_texture']:
|
|
if self.tex0:
|
|
key.append(self.tex0.getName())
|
|
else:
|
|
key.append(None)
|
|
|
|
if global_prefs['get_alpha']:
|
|
key.append(round(self.alpha, 3))
|
|
else:
|
|
key.append(None)
|
|
|
|
if global_prefs['get_shininess']:
|
|
key.append(round(self.shininess, 3))
|
|
else:
|
|
key.append(None)
|
|
|
|
if global_prefs['get_emissive']:
|
|
key.append(round(self.emissive, 3))
|
|
else:
|
|
key.append(None)
|
|
|
|
if global_prefs['get_ambient']:
|
|
key.append(round(self.ambient, 3))
|
|
else:
|
|
key.append(None)
|
|
|
|
if global_prefs['get_specular']:
|
|
for n in self.specular:
|
|
key.append(round(n, 3))
|
|
else:
|
|
key.extend([None, None, None])
|
|
|
|
if global_prefs['get_diffuse']:
|
|
for n in self.diffuse:
|
|
key.append(round(n, 3))
|
|
else:
|
|
key.extend([None, None, None])
|
|
|
|
# key.extend(self.face_props.values())
|
|
|
|
return tuple(key)
|
|
|
|
def __init__(self):
|
|
self.name = 'Material'
|
|
# 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.0 # [0.0, 1.0]
|
|
self.emissive = 0.0 # [0.0, 1.0]
|
|
self.shininess = 0.5 # Range is [0.0, 2.0]
|
|
self.alpha = 1.0 # Range is [0.0, 1.0]
|
|
|
|
self.tex0 = None
|
|
|
|
# OpenFlight Face attributes
|
|
self.face_props = dict.fromkeys(['comment', 'ir color', 'priority',
|
|
'draw type', 'texture white', 'template billboard',
|
|
'smc', 'fid', 'ir material', 'lod generation control',
|
|
'flags', 'light mode'])
|
|
|
|
class VertexDesc:
|
|
def make_key(self):
|
|
return round(self.x, 6), round(self.y, 6), round(self.z, 6)
|
|
|
|
def __init__(self):
|
|
|
|
# Assign later, save memory, all verts have a loc
|
|
self.x = 0.0
|
|
self.y = 0.0
|
|
self.z = 0.0
|
|
|
|
''' # IGNORE_NORMALS
|
|
self.nx = 0.0
|
|
self.ny = 1.0
|
|
self.nz = 0.0
|
|
'''
|
|
self.uv= Vector(0,0)
|
|
self.r = 1.0
|
|
self.g = 1.0
|
|
self.b = 1.0
|
|
self.a = 1.0
|
|
|
|
class LightPointAppDesc:
|
|
def make_key(self):
|
|
d = dict(self.props)
|
|
del d['id']
|
|
del d['type']
|
|
|
|
if d['directionality'] != 0: # not omni
|
|
d['nx'] = 0.0
|
|
d['ny'] = 0.0
|
|
d['nz'] = 0.0
|
|
|
|
return tuple(d.values())
|
|
|
|
def __init__(self):
|
|
self.props = dict()
|
|
self.props.update({'type': 'LPA'})
|
|
self.props.update({'id': 'ap'})
|
|
# Attribs not found in inline lightpoint.
|
|
self.props.update({'visibility range': 0.0})
|
|
self.props.update({'fade range ratio': 0.0})
|
|
self.props.update({'fade in duration': 0.0})
|
|
self.props.update({'fade out duration': 0.0})
|
|
self.props.update({'LOD range ratio': 0.0})
|
|
self.props.update({'LOD scale': 0.0})
|
|
|
|
class GlobalResourceRepository:
|
|
def request_lightpoint_app(self, desc):
|
|
match = self.light_point_app.get(desc.make_key())
|
|
|
|
if match:
|
|
return match.getName()
|
|
else:
|
|
# Create empty and fill with properties.
|
|
name = desc.props['type'] + ': ' + desc.props['id']
|
|
object = Blender.Object.New('Empty', name)
|
|
scene.link(object)
|
|
object.Layers= current_layer
|
|
object.sel= 1
|
|
|
|
# Attach properties
|
|
for name, value in desc.props.iteritems():
|
|
object.addProperty(name, value)
|
|
|
|
self.light_point_app.update({desc.make_key(): object})
|
|
|
|
return object.getName()
|
|
|
|
# Dont use request_vert - faster to make it from the vector direct.
|
|
"""
|
|
def request_vert(self, desc):
|
|
match = self.vert_dict.get(desc.make_key())
|
|
|
|
if match:
|
|
return match
|
|
else:
|
|
vert = Blender.Mathutils.Vector(desc.x, desc.y, desc.z)
|
|
''' IGNORE_NORMALS
|
|
vert.no[0] = desc.nx
|
|
vert.no[1] = desc.ny
|
|
vert.no[2] = desc.nz
|
|
'''
|
|
self.vert_dict.update({desc.make_key(): vert})
|
|
return vert
|
|
"""
|
|
def request_mat(self, mat_desc):
|
|
match = self.mat_dict.get(mat_desc.make_key())
|
|
if match: return match
|
|
|
|
mat = Blender.Material.New(mat_desc.name)
|
|
|
|
if mat_desc.tex0 != None:
|
|
mat.setTexture(0, mat_desc.tex0, Blender.Texture.TexCo.UV)
|
|
|
|
mat.setAlpha(mat_desc.alpha)
|
|
mat.setSpec(mat_desc.shininess)
|
|
mat.setHardness(255)
|
|
mat.setEmit(mat_desc.emissive)
|
|
mat.setAmb(mat_desc.ambient)
|
|
mat.setSpecCol(mat_desc.specular)
|
|
mat.setRGBCol(mat_desc.diffuse)
|
|
|
|
# Create a text object to store openflight face attribs until
|
|
# user properties can be set on materials.
|
|
# t = Blender.Text.New('FACE: ' + mat.getName())
|
|
#
|
|
# for name, value in mat_desc.face_props.items():
|
|
# t.write(name + '\n' + str(value) + '\n\n')
|
|
|
|
self.mat_dict.update({mat_desc.make_key(): mat})
|
|
|
|
return mat
|
|
|
|
def request_image(self, filename_with_path):
|
|
if not global_prefs['get_texture']: return None
|
|
return BPyImage.comprehensiveImageLoad(filename_with_path, global_prefs['fltfile']) # Use join in case of spaces
|
|
|
|
def request_texture(self, image):
|
|
if not global_prefs['get_texture']:
|
|
return None
|
|
|
|
tex = self.tex_dict.get(image.filename)
|
|
if tex: return tex
|
|
|
|
tex = Blender.Texture.New(Blender.sys.basename(image.filename))
|
|
tex.setImage(image)
|
|
tex.setType('Image')
|
|
self.tex_dict.update({image.filename: tex})
|
|
return tex
|
|
|
|
def __init__(self):
|
|
# material
|
|
self.mat_dict = dict()
|
|
mat_lst = Blender.Material.Get()
|
|
for mat in mat_lst:
|
|
mat_desc = MaterialDesc()
|
|
mapto_lst = mat.getTextures()
|
|
if mapto_lst[0]:
|
|
mat_desc.tex0 = mapto_lst[0].tex
|
|
else:
|
|
mat_desc.tex0 = None
|
|
mat_desc.alpha = mat.getAlpha()
|
|
mat_desc.shininess = mat.getSpec()
|
|
mat_desc.emissive = mat.getEmit()
|
|
mat_desc.ambient = mat.getAmb()
|
|
mat_desc.specular = mat.getSpecCol()
|
|
mat_desc.diffuse = mat.getRGBCol()
|
|
|
|
self.mat_dict.update({mat_desc.make_key(): mat})
|
|
|
|
# texture
|
|
self.tex_dict = dict()
|
|
tex_lst = Blender.Texture.Get()
|
|
|
|
for tex in tex_lst:
|
|
img = tex.getImage()
|
|
# Only interested in textures with images.
|
|
if img:
|
|
self.tex_dict.update({img.filename: tex})
|
|
|
|
# vertex
|
|
# self.vert_dict = dict()
|
|
|
|
# light point
|
|
self.light_point_app = dict()
|
|
|
|
# Globals
|
|
GRR = GlobalResourceRepository()
|
|
FF = flt_filewalker.FileFinder()
|
|
scene = Blender.Scene.GetCurrent() # just hope they dont chenge scenes once the file selector pops up.
|
|
current_layer = 0x01
|
|
|
|
|
|
# Opcodes that indicate its time to return control to parent.
|
|
throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63]
|
|
do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 100, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
|
|
|
|
opcode_name = { 0: 'db',
|
|
1: 'head',
|
|
2: 'grp',
|
|
4: 'obj',
|
|
5: 'face',
|
|
10: 'push',
|
|
11: 'pop',
|
|
14: 'dof',
|
|
19: 'push sub',
|
|
20: 'pop sub',
|
|
21: 'push ext',
|
|
22: 'pop ext',
|
|
23: 'cont',
|
|
31: 'comment',
|
|
32: 'color pal',
|
|
33: 'long id',
|
|
49: 'matrix',
|
|
50: 'vector',
|
|
52: 'multi-tex',
|
|
53: 'uv lst',
|
|
55: 'bsp',
|
|
60: 'rep',
|
|
61: 'inst ref',
|
|
62: 'inst def',
|
|
63: 'ext ref',
|
|
64: 'tex pal',
|
|
67: 'vert pal',
|
|
68: 'vert w col',
|
|
69: 'vert w col & norm',
|
|
70: 'vert w col, norm & uv',
|
|
71: 'vert w col & uv',
|
|
72: 'vert lst',
|
|
73: 'lod',
|
|
74: 'bndin box',
|
|
76: 'rot edge',
|
|
78: 'trans',
|
|
79: 'scl',
|
|
80: 'rot pnt',
|
|
81: 'rot and/or scale pnt',
|
|
82: 'put',
|
|
83: 'eyepoint & trackplane pal',
|
|
84: 'mesh',
|
|
85: 'local vert pool',
|
|
86: 'mesh prim',
|
|
87: 'road seg',
|
|
88: 'road zone',
|
|
89: 'morph vert lst',
|
|
90: 'link pal',
|
|
91: 'snd',
|
|
92: 'rd path',
|
|
93: 'snd pal',
|
|
94: 'gen matrix',
|
|
95: 'txt',
|
|
96: 'sw',
|
|
97: 'line styl pal',
|
|
98: 'clip reg',
|
|
100: 'ext',
|
|
101: 'light src',
|
|
102: 'light src pal',
|
|
103: 'reserved',
|
|
104: 'reserved',
|
|
105: 'bndin sph',
|
|
106: 'bndin cyl',
|
|
107: 'bndin hull',
|
|
108: 'bndin vol cntr',
|
|
109: 'bndin vol orient',
|
|
110: 'rsrvd',
|
|
111: 'light pnt',
|
|
112: 'tex map pal',
|
|
113: 'mat pal',
|
|
114: 'name tab',
|
|
115: 'cat',
|
|
116: 'cat dat',
|
|
117: 'rsrvd',
|
|
118: 'rsrvd',
|
|
119: 'bounding hist',
|
|
120: 'rsrvd',
|
|
121: 'rsrvd',
|
|
122: 'push attrib',
|
|
123: 'pop attrib',
|
|
124: 'rsrvd',
|
|
125: 'rsrvd',
|
|
126: 'curv',
|
|
127: 'road const',
|
|
128: 'light pnt appear pal',
|
|
129: 'light pnt anim pal',
|
|
130: 'indexed lp',
|
|
131: 'lp sys',
|
|
132: 'indx str',
|
|
133: 'shdr pal'}
|
|
|
|
class Handler:
|
|
def in_throw_back_lst(self, opcode):
|
|
return opcode in self.throw_back_lst
|
|
|
|
def handle(self, opcode):
|
|
return self.handler[opcode]()
|
|
|
|
def handles(self, opcode):
|
|
return opcode in self.handler.iterkeys()
|
|
|
|
def throws_back_all_unhandled(self):
|
|
return self.throw_back_unhandled
|
|
|
|
def set_throw_back_lst(self, a):
|
|
self.throw_back_lst = a
|
|
|
|
def set_throw_back_all_unhandled(self):
|
|
self.throw_back_unhandled = True
|
|
|
|
def set_only_throw_back_specified(self):
|
|
self.throw_back_unhandled = False
|
|
|
|
def set_handler(self, d):
|
|
self.handler = d
|
|
|
|
def __init__(self):
|
|
# Dictionary of opcodes to handler methods.
|
|
self.handler = dict()
|
|
# Send all opcodes not handled to the parent node.
|
|
self.throw_back_unhandled = False
|
|
# If throw_back_unhandled is False then only throw back
|
|
# if the opcodes in throw_back are encountered.
|
|
self.throw_back_lst = list()
|
|
|
|
class Node:
|
|
def blender_import(self):
|
|
if self.opcode in opcode_name and global_prefs['verbose'] >= 2:
|
|
for i in xrange(self.get_level()):
|
|
print ' ',
|
|
print opcode_name[self.opcode],
|
|
print '-', self.props['id'],
|
|
print '-', self.props['comment'],
|
|
|
|
print
|
|
|
|
for child in self.children:
|
|
child.blender_import()
|
|
|
|
# Import comment.
|
|
# if self.props['comment'] != '':
|
|
# name = 'COMMENT: ' + self.props['id']
|
|
# t = Blender.Text.New(name)
|
|
# t.write(self.props['comment'])
|
|
# self.props['comment'] = name
|
|
|
|
# Always ignore extensions and anything in between them.
|
|
def parse_push_extension(self):
|
|
self.saved_handler = self.active_handler
|
|
self.active_handler = self.extension_handler
|
|
return True
|
|
|
|
def parse_pop_extension(self):
|
|
self.active_handler = self.saved_handler
|
|
return True
|
|
|
|
def parse_push(self):
|
|
self.header.fw.up_level()
|
|
# Ignore unknown children.
|
|
self.ignore_unhandled = True
|
|
# Don't do child records that might overwrite parent info. ex: longid
|
|
self.active_handler = self.child_handler
|
|
return True
|
|
|
|
def parse_pop(self):
|
|
self.header.fw.down_level()
|
|
|
|
if self.header.fw.get_level() == self.level:
|
|
return False
|
|
|
|
return True
|
|
|
|
def parse(self):
|
|
while self.header.fw.begin_record():
|
|
opcode = self.header.fw.get_opcode()
|
|
|
|
# Print out info on opcode and tree level.
|
|
if global_prefs['verbose'] >= 3:
|
|
p = ''
|
|
for i in xrange(self.header.fw.get_level()):
|
|
p = p + ' '
|
|
if opcode in opcode_name:
|
|
p = p + opcode_name[opcode]
|
|
else:
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'undocumented opcode', opcode
|
|
continue
|
|
|
|
if self.global_handler.handles(opcode):
|
|
if global_prefs['verbose'] >= 3:
|
|
print p + ' handled globally'
|
|
if self.global_handler.handle(opcode) == False:
|
|
break
|
|
|
|
elif self.active_handler.handles(opcode):
|
|
if global_prefs['verbose'] >= 4:
|
|
print p + ' handled'
|
|
if self.active_handler.handle(opcode) == False:
|
|
break
|
|
|
|
else:
|
|
if self.active_handler.throws_back_all_unhandled():
|
|
if global_prefs['verbose'] >= 3:
|
|
print p + ' handled elsewhere'
|
|
self.header.fw.repeat_record()
|
|
break
|
|
|
|
elif self.active_handler.in_throw_back_lst(opcode):
|
|
if global_prefs['verbose'] >= 3:
|
|
print p + ' handled elsewhere'
|
|
self.header.fw.repeat_record()
|
|
break
|
|
|
|
else:
|
|
if global_prefs['verbose'] >= 3:
|
|
print p + ' ignored'
|
|
elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:
|
|
print opcode_name[opcode], 'not handled'
|
|
|
|
def get_level(self):
|
|
return self.level
|
|
|
|
def parse_long_id(self):
|
|
self.props['id'] = self.header.fw.read_string(self.header.fw.get_length()-4)
|
|
return True
|
|
|
|
def parse_comment(self):
|
|
self.props['comment'] = self.header.fw.read_string(self.header.fw.get_length()-4)
|
|
return True
|
|
|
|
def __init__(self, parent, header):
|
|
self.root_handler = Handler()
|
|
self.child_handler = Handler()
|
|
self.extension_handler = Handler()
|
|
self.global_handler = Handler()
|
|
|
|
self.global_handler.set_handler({21: self.parse_push_extension})
|
|
self.active_handler = self.root_handler
|
|
|
|
# used by parse_*_extension
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension})
|
|
self.saved_handler = None
|
|
|
|
self.header = header
|
|
self.children = list()
|
|
|
|
self.parent = parent
|
|
|
|
if parent:
|
|
parent.children.append(self)
|
|
|
|
self.level = self.header.fw.get_level()
|
|
self.opcode = self.header.fw.get_opcode()
|
|
|
|
self.props = {'id': 'unnamed', 'comment': '', 'type': 'untyped'}
|
|
|
|
class VertexPalette(Node):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
self.root_handler.set_handler({68: self.parse_vertex_c,
|
|
69: self.parse_vertex_cn,
|
|
70: self.parse_vertex_cnuv,
|
|
71: self.parse_vertex_cuv})
|
|
self.root_handler.set_throw_back_all_unhandled()
|
|
|
|
self.vert_desc_lst = list()
|
|
self.blender_verts = list()
|
|
self.offset = 8
|
|
# Used to create a map from byte offset to vertex index.
|
|
self.index = dict()
|
|
|
|
|
|
def blender_import(self):
|
|
self.blender_verts.extend([Vector(vert_desc.x, vert_desc.y, vert_desc.z) for vert_desc in self.vert_desc_lst ])
|
|
|
|
def parse_vertex_common(self):
|
|
# Add this vertex to an offset to index dictionary.
|
|
#self.index_lst.append( (self.offset, self.next_index) )
|
|
self.index[self.offset]= len(self.index)
|
|
|
|
# Get ready for next record.
|
|
self.offset += self.header.fw.get_length()
|
|
|
|
v = VertexDesc()
|
|
|
|
self.header.fw.read_ahead(2)
|
|
v.flags = self.header.fw.read_short()
|
|
|
|
v.x = self.header.fw.read_double()
|
|
v.y = self.header.fw.read_double()
|
|
v.z = self.header.fw.read_double()
|
|
|
|
return v
|
|
|
|
def parse_vertex_post_common(self, v):
|
|
if not v.flags & 0x2000: # 0x2000 = no color
|
|
if v.flags & 0x1000: # 0x1000 = packed color
|
|
v.a = self.header.fw.read_uchar()
|
|
v.b = self.header.fw.read_uchar()
|
|
v.g = self.header.fw.read_uchar()
|
|
v.r = self.header.fw.read_uchar()
|
|
else:
|
|
self.header.fw.read_ahead(4)
|
|
|
|
color_index = self.header.fw.read_uint()
|
|
v.r, v.g, v.b, v.a= self.header.get_color(color_index)
|
|
|
|
self.vert_desc_lst.append(v)
|
|
|
|
return True
|
|
|
|
def parse_vertex_c(self):
|
|
v = self.parse_vertex_common()
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
return True
|
|
|
|
def parse_vertex_cn(self):
|
|
v = self.parse_vertex_common()
|
|
|
|
'''
|
|
v.nx = self.header.fw.read_float()
|
|
v.ny = self.header.fw.read_float()
|
|
v.nz = self.header.fw.read_float()
|
|
'''
|
|
# Just to advance
|
|
self.header.fw.read_float()
|
|
self.header.fw.read_float()
|
|
self.header.fw.read_float()
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
return True
|
|
|
|
def parse_vertex_cuv(self):
|
|
v = self.parse_vertex_common()
|
|
|
|
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
return True
|
|
|
|
def parse_vertex_cnuv(self):
|
|
v = self.parse_vertex_common()
|
|
'''
|
|
v.nx = self.header.fw.read_float()
|
|
v.ny = self.header.fw.read_float()
|
|
v.nz = self.header.fw.read_float()
|
|
'''
|
|
# Just to advance
|
|
self.header.fw.read_float()
|
|
self.header.fw.read_float()
|
|
self.header.fw.read_float()
|
|
|
|
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
return True
|
|
|
|
def parse(self): # Run once per import
|
|
Node.parse(self)
|
|
|
|
class InterNode(Node):
|
|
def __init__(self):
|
|
self.object = None
|
|
self.mesh = None
|
|
self.isMesh = False
|
|
self.faceLs= []
|
|
self.matrix = None
|
|
|
|
def blender_import_my_faces(self):
|
|
|
|
# Add the verts onto the mesh
|
|
mesh = self.mesh
|
|
blender_verts= self.header.vert_pal.blender_verts
|
|
vert_desc_lst= self.header.vert_pal.vert_desc_lst
|
|
|
|
vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices]
|
|
|
|
mesh.verts.extend([blender_verts[i] for i in vert_list])
|
|
|
|
|
|
new_faces= []
|
|
new_faces_props= []
|
|
ngon= BPyMesh.ngon
|
|
vert_index= 1
|
|
for flt_face in self.faceLs:
|
|
material_index= flt_face.blen_mat_idx
|
|
image= flt_face.blen_image
|
|
|
|
face_len= len(flt_face.indices)
|
|
|
|
# Get the indicies in reference to the mesh.
|
|
|
|
uvs= [vert_desc_lst[j].uv for j in flt_face.indices]
|
|
if face_len <=4: # tri or quad
|
|
new_faces.append( [i+vert_index for i in xrange(face_len)] )
|
|
new_faces_props.append((material_index, image, uvs))
|
|
|
|
else: # fgon
|
|
mesh_face_indicies = [i+vert_index for i in xrange(face_len)]
|
|
tri_ngons= ngon(mesh, mesh_face_indicies)
|
|
new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons])
|
|
new_faces_props.extend( [ (material_index, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]) ) for tri in tri_ngons ] )
|
|
|
|
vert_index+= face_len
|
|
|
|
mesh.faces.extend(new_faces)
|
|
|
|
try: mesh.faceUV= True
|
|
except: pass
|
|
|
|
for i, f in enumerate(mesh.faces):
|
|
f.mat, f.image, f.uv= new_faces_props[i]
|
|
|
|
def blender_import(self):
|
|
# name = self.props['type'] + ': ' + self.props['id']
|
|
name = self.props['id']
|
|
if self.isMesh:
|
|
self.object = Blender.Object.New('Mesh', name)
|
|
#self.mesh = self.object.getData()
|
|
self.mesh = Blender.Mesh.New()
|
|
self.mesh.verts.extend( Vector() ) # DUMMYVERT
|
|
self.object.link(self.mesh)
|
|
else:
|
|
self.object = Blender.Object.New('Empty', name)
|
|
|
|
if self.parent:
|
|
self.parent.object.makeParent([self.object])
|
|
|
|
scene.link(self.object)
|
|
self.object.Layer = current_layer
|
|
self.object.sel = 1
|
|
|
|
Node.blender_import(self) # Attach faces to self.faceLs
|
|
|
|
if self.isMesh:
|
|
# Add all my faces into the mesh at once
|
|
self.blender_import_my_faces()
|
|
|
|
if self.matrix:
|
|
self.object.setMatrix(self.matrix)
|
|
|
|
# Attach properties
|
|
#for name, value in self.props.items():
|
|
# self.object.addProperty(name, value)
|
|
|
|
def parse_face(self):
|
|
child = Face(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_group(self):
|
|
child = Group(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def move_to_next_layer(self):
|
|
global current_layer
|
|
current_layer = current_layer << 1
|
|
if current_layer > 0x80000:
|
|
current_layer = 1
|
|
|
|
def parse_lod(self):
|
|
child = LOD(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_unhandled(self):
|
|
child = Unhandled(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_object(self):
|
|
child = Object(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_xref(self):
|
|
child = XRef(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_indexed_light_point(self):
|
|
child = IndexedLightPoint(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_inline_light_point(self):
|
|
child = InlineLightPoint(self)
|
|
child.parse()
|
|
return True
|
|
|
|
def parse_matrix(self):
|
|
m = list()
|
|
for i in xrange(4):
|
|
m.append([])
|
|
for j in xrange(4):
|
|
f = self.header.fw.read_float()
|
|
m[i].append(f)
|
|
self.matrix = Blender.Mathutils.Matrix(m[0], m[1], m[2], m[3])
|
|
|
|
EDGE_FGON= Blender.Mesh.EdgeFlags['FGON']
|
|
FACE_TEX= Blender.Mesh.FaceModes['TEX']
|
|
|
|
class Face(Node):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
self.root_handler.set_handler({31: self.parse_comment,
|
|
10: self.parse_push})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({72: self.parse_vertex_list,
|
|
10: self.parse_push,
|
|
11: self.parse_pop})
|
|
|
|
if parent:
|
|
parent.isMesh = True
|
|
|
|
self.indices = list() # face verts here
|
|
|
|
self.comment = ''
|
|
self.props = dict.fromkeys(['ir color', 'priority',
|
|
'draw type', 'texture white', 'template billboard',
|
|
'smc', 'fid', 'ir material', 'lod generation control',
|
|
'flags', 'light mode'])
|
|
|
|
self.header.fw.read_ahead(8) # face id
|
|
# Load face.
|
|
self.props['ir color'] = self.header.fw.read_int()
|
|
self.props['priority'] = self.header.fw.read_short()
|
|
self.props['draw type'] = self.header.fw.read_char()
|
|
self.props['texture white'] = self.header.fw.read_char()
|
|
self.header.fw.read_ahead(4) # color name indices
|
|
self.header.fw.read_ahead(1) # reserved
|
|
self.props['template billboard'] = self.header.fw.read_uchar()
|
|
self.detail_tex_index = self.header.fw.read_short()
|
|
self.tex_index = self.header.fw.read_short()
|
|
self.mat_index = self.header.fw.read_short()
|
|
self.props['smc'] = self.header.fw.read_short()
|
|
self.props['fid'] = self.header.fw.read_short()
|
|
self.props['ir material'] = self.header.fw.read_int()
|
|
self.alpha = 1.0 - float(self.header.fw.read_ushort()) / 65535.0
|
|
self.props['lod generation control'] = self.header.fw.read_uchar()
|
|
self.header.fw.read_ahead(1) # line style index
|
|
self.props['flags'] = self.header.fw.read_int()
|
|
self.props['light mode'] = self.header.fw.read_uchar()
|
|
self.header.fw.read_ahead(7)
|
|
a = self.header.fw.read_uchar()
|
|
b = self.header.fw.read_uchar()
|
|
g = self.header.fw.read_uchar()
|
|
r = self.header.fw.read_uchar()
|
|
self.packed_color = [r, g, b, a]
|
|
a = self.header.fw.read_uchar()
|
|
b = self.header.fw.read_uchar()
|
|
g = self.header.fw.read_uchar()
|
|
r = self.header.fw.read_uchar()
|
|
self.alt_packed_color = [r, g, b, a]
|
|
self.tex_map_index = self.header.fw.read_short()
|
|
self.header.fw.read_ahead(2)
|
|
self.color_index = self.header.fw.read_uint()
|
|
self.alt_color_index = self.header.fw.read_uint()
|
|
#self.header.fw.read_ahead(2)
|
|
#self.shader_index = self.header.fw.read_short()
|
|
|
|
|
|
"""
|
|
def blender_import_face(self, material_index, image):
|
|
|
|
|
|
mesh = self.parent.mesh
|
|
face_len= len(self.indices)
|
|
|
|
mesh_vert_len_orig= len(mesh.verts)
|
|
mesh.verts.extend([ self.header.vert_pal.blender_verts[i] for i in self.indices])
|
|
|
|
# Exception for an edge
|
|
if face_len==2:
|
|
mesh.edges.extend((mesh.verts[-1], mesh.verts[-2]))
|
|
return
|
|
|
|
|
|
mesh_face_indicies = range(mesh_vert_len_orig, mesh_vert_len_orig+face_len)
|
|
|
|
#print mesh_face_indicies , 'mesh_face_indicies '
|
|
|
|
# First we need to triangulate NGONS
|
|
if face_len>4:
|
|
tri_indicies = [[i+mesh_vert_len_orig for i in t] for t in BPyMesh.ngon(mesh, mesh_face_indicies) ] # use range because the verts are in order.
|
|
else:
|
|
tri_indicies= [mesh_face_indicies] # can be a quad but thats ok
|
|
|
|
# Extend face or ngon
|
|
|
|
mesh.faces.extend(tri_indicies)
|
|
#print mesh.faces, 'mesh.faces'
|
|
mesh.faceUV= True
|
|
|
|
# Now set UVs
|
|
for i in xrange(len(mesh.faces)-len(tri_indicies), len(mesh.faces)):
|
|
f= mesh.faces[i]
|
|
f_v= f.v
|
|
for j, uv in enumerate(f.uv):
|
|
vertex_index_flt= self.indices[f_v[j].index - mesh_vert_len_orig]
|
|
|
|
vert_desc = self.header.vert_pal.vert_desc_lst[vertex_index_flt]
|
|
uv.x, uv.y= vert_desc.u, vert_desc.v
|
|
|
|
# Only a bug in 2.42, fixed in cvs
|
|
for c in f.col:
|
|
c.r=c.g=c.b= 255
|
|
|
|
f.mat = material_index
|
|
if image:
|
|
f.image = image
|
|
else:
|
|
f.mode &= ~FACE_TEX
|
|
|
|
# FGon
|
|
|
|
if face_len>4:
|
|
# Add edges we know are not fgon
|
|
end_index= len(mesh.verts)
|
|
start_index= end_index - len(self.indices)
|
|
edge_dict= dict([ ((i, i+1), None) for i in xrange(start_index, end_index-1)])
|
|
edge_dict[(start_index, end_index)]= None # wish this was a set
|
|
|
|
fgon_edges= {}
|
|
for tri in tri_indicies:
|
|
for i in (0,1,2):
|
|
i1= tri[i]
|
|
i2= tri[i-1]
|
|
|
|
# Sort
|
|
if i1>i2:
|
|
i1,i2= i2,i1
|
|
|
|
if not edge_dict.has_key( (i1,i2) ): # if this works its an edge vert
|
|
fgon_edges[i1,i2]= None
|
|
|
|
|
|
# Now set fgon flags
|
|
for ed in mesh.edges:
|
|
i1= ed.v1.index
|
|
i2= ed.v2.index
|
|
if i1>i2:
|
|
i1,i2= i2,i1
|
|
|
|
if fgon_edges.has_key( (i1,i2) ):
|
|
# This is an edge tagged for fgonning?
|
|
fgon_edges[i1, i2]
|
|
ed.flag |= EDGE_FGON
|
|
del fgon_edges[i1, i2] # make later searches faster?
|
|
|
|
if not fgon_edges:
|
|
break
|
|
"""
|
|
|
|
def parse_comment(self):
|
|
self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
|
|
return True
|
|
|
|
# returns a tuple (material, image) where material is the blender material and
|
|
# image is the blender image or None.
|
|
def create_blender_material(self):
|
|
# Create face material.
|
|
mat_desc = MaterialDesc()
|
|
|
|
if self.mat_index != -1:
|
|
if not self.mat_index in self.header.mat_desc_pal:
|
|
if global_prefs['verbose'] >= 1:
|
|
#print 'Warning: Material index', self.mat_index, 'not in material palette.'
|
|
pass
|
|
else:
|
|
mat_pal_desc = self.header.mat_desc_pal[self.mat_index]
|
|
mat_desc.alpha = mat_pal_desc.alpha * self.alpha # combine face and mat alphas
|
|
mat_desc.ambient = mat_pal_desc.ambient
|
|
mat_desc.diffuse = mat_pal_desc.diffuse
|
|
mat_desc.specular = mat_pal_desc.specular
|
|
mat_desc.emissive = mat_pal_desc.emissive
|
|
mat_desc.shininess = mat_pal_desc.shininess
|
|
else:
|
|
# if no material get alpha from just face.
|
|
mat_desc.alpha = self.alpha
|
|
|
|
# Color.
|
|
if global_prefs['color_from_face']:
|
|
color = None
|
|
if not self.props['flags'] & 0x40000000:
|
|
if self.props['flags'] & 0x10000000: # packed color
|
|
color = self.packed_color
|
|
else:
|
|
color = self.header.get_color(self.color_index)
|
|
|
|
if color:
|
|
r = float(color[0])/255.0
|
|
g = float(color[1])/255.0
|
|
b = float(color[2])/255.0
|
|
mat_desc.diffuse = [r, g, b]
|
|
|
|
# Texture
|
|
image = None
|
|
if self.tex_index != -1 and self.tex_index in self.header.bl_tex_pal:
|
|
mat_desc.tex0 = self.header.bl_tex_pal[self.tex_index]
|
|
if mat_desc.tex0:
|
|
mat_desc.name = FF.strip_path(self.header.tex_pal[self.tex_index])
|
|
image = mat_desc.tex0.image
|
|
|
|
# OpenFlight Face Attributes
|
|
mat_desc.face_props = self.props
|
|
|
|
# Get material.
|
|
mat = GRR.request_mat(mat_desc)
|
|
|
|
# Add material to mesh.
|
|
mesh = self.parent.mesh
|
|
|
|
# Return where it is in the mesh for faces.
|
|
mesh_materials= mesh.materials
|
|
|
|
material_index= -1
|
|
for i,m in enumerate(mesh_materials):
|
|
if m.name==mat.name:
|
|
material_index= i
|
|
break
|
|
|
|
if material_index==-1:
|
|
material_index= len(mesh_materials)
|
|
if material_index==16:
|
|
material_index= 15
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'Warning: Too many materials per mesh object. Only a maximum of 16 ' + \
|
|
'allowed. Using 16th material instead.'
|
|
|
|
else:
|
|
mesh_materials.append(mat)
|
|
mesh.materials= mesh_materials
|
|
|
|
return (material_index, image)
|
|
|
|
|
|
def blender_import(self):
|
|
vert_count = len(self.indices)
|
|
if vert_count < 3:
|
|
if global_prefs['verbose'] >= 2:
|
|
print 'Warning: Ignoring face with no vertices.'
|
|
return
|
|
|
|
# Assign material and image
|
|
|
|
self.parent.faceLs.append(self)
|
|
self.blen_mat_idx, self.blen_image= self.create_blender_material()
|
|
|
|
|
|
|
|
|
|
# Store comment info in parent.
|
|
if self.comment != '':
|
|
if self.parent.props['comment'] != '':
|
|
self.parent.props['comment'] += '\n\nFrom Face:\n' + self.comment
|
|
else:
|
|
self.parent.props['comment'] = self.comment
|
|
|
|
def parse_vertex_list(self):
|
|
length = self.header.fw.get_length()
|
|
fw = self.header.fw
|
|
vert_pal = self.header.vert_pal
|
|
|
|
count = (length-4)/4
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
'''
|
|
for i in xrange(count):
|
|
byte_offset = fw.read_int()
|
|
if byte_offset in vert_pal.index:
|
|
index = vert_pal.index[byte_offset]
|
|
self.indices.append(index)
|
|
elif global_prefs['verbose'] >= 1:
|
|
print 'Warning: Unable to map byte offset %s' + \
|
|
' to vertex index.' % byte_offset
|
|
'''
|
|
return True
|
|
|
|
|
|
class Object(InterNode):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({5: self.parse_face,
|
|
#130: self.parse_indexed_light_point,
|
|
#111: self.parse_inline_light_point,
|
|
10: self.parse_push,
|
|
11: self.parse_pop})
|
|
|
|
self.props['type'] = 'Object'
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
|
|
|
|
|
|
class Group(InterNode):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({5: self.parse_face,
|
|
#130: self.parse_indexed_light_point,
|
|
#111: self.parse_inline_light_point,
|
|
2: self.parse_group,
|
|
73: self.parse_lod,
|
|
4: self.parse_object,
|
|
10: self.parse_push,
|
|
11: self.parse_pop,
|
|
96: self.parse_unhandled,
|
|
14: self.parse_unhandled,
|
|
91: self.parse_unhandled,
|
|
98: self.parse_unhandled,
|
|
63: self.parse_xref})
|
|
self.props = dict.fromkeys(['type', 'id', 'comment', 'priority', 'flags', 'special1',
|
|
'special2', 'significance', 'layer code', 'loop count',
|
|
'loop duration', 'last frame duration'])
|
|
|
|
self.props['type'] = 'Group'
|
|
self.props['comment'] = ''
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
self.props['priority'] = self.header.fw.read_short()
|
|
self.header.fw.read_ahead(2)
|
|
self.props['flags'] = self.header.fw.read_int()
|
|
self.props['special1'] = self.header.fw.read_short()
|
|
self.props['special2'] = self.header.fw.read_short()
|
|
self.props['significance'] = self.header.fw.read_short()
|
|
self.props['layer code'] = self.header.fw.read_char()
|
|
self.header.fw.read_ahead(5)
|
|
self.props['loop count'] = self.header.fw.read_int()
|
|
self.props['loop duration'] = self.header.fw.read_float()
|
|
self.props['last frame duration'] = self.header.fw.read_float()
|
|
|
|
class XRef(InterNode):
|
|
def parse(self):
|
|
if self.xref:
|
|
self.xref.parse()
|
|
Node.parse(self)
|
|
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
xref_filename = self.header.fw.read_string(200)
|
|
filename = FF.find(xref_filename)
|
|
|
|
self.props['type'] = 'XRef'
|
|
|
|
if filename != None:
|
|
self.xref = Database(filename, self)
|
|
self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(filename))[0]
|
|
else:
|
|
self.xref = None
|
|
self.props['id'] = 'X: broken'
|
|
|
|
class LOD(InterNode):
|
|
def blender_import(self):
|
|
self.move_to_next_layer()
|
|
InterNode.blender_import(self)
|
|
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({2: self.parse_group,
|
|
73: self.parse_lod,
|
|
4: self.parse_object,
|
|
10: self.parse_push,
|
|
11: self.parse_pop,
|
|
96: self.parse_unhandled, # switch
|
|
14: self.parse_unhandled, # DOF
|
|
91: self.parse_unhandled, # sound
|
|
98: self.parse_unhandled, # clip
|
|
63: self.parse_xref})
|
|
|
|
self.props['type'] = 'LOD'
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
|
|
class InlineLightPoint(InterNode):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({72: self.parse_vertex_list,
|
|
10: self.parse_push,
|
|
11: self.parse_pop})
|
|
|
|
self.indices = list()
|
|
|
|
self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance'])
|
|
self.app_props = dict()
|
|
|
|
self.props['comment'] = ''
|
|
self.props['type'] = 'Light Point'
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
|
|
self.app_props.update({'smc': self.header.fw.read_short()})
|
|
self.app_props.update({'fid': self.header.fw.read_short()})
|
|
self.app_props.update({'back color: a': self.header.fw.read_uchar()})
|
|
self.app_props.update({'back color: b': self.header.fw.read_uchar()})
|
|
self.app_props.update({'back color: g': self.header.fw.read_uchar()})
|
|
self.app_props.update({'back color: r': self.header.fw.read_uchar()})
|
|
self.app_props.update({'display mode': self.header.fw.read_int()})
|
|
self.app_props.update({'intensity': self.header.fw.read_float()})
|
|
self.app_props.update({'back intensity': self.header.fw.read_float()})
|
|
self.app_props.update({'minimum defocus': self.header.fw.read_float()})
|
|
self.app_props.update({'maximum defocus': self.header.fw.read_float()})
|
|
self.app_props.update({'fading mode': self.header.fw.read_int()})
|
|
self.app_props.update({'fog punch mode': self.header.fw.read_int()})
|
|
self.app_props.update({'directional mode': self.header.fw.read_int()})
|
|
self.app_props.update({'range mode': self.header.fw.read_int()})
|
|
self.app_props.update({'min pixel size': self.header.fw.read_float()})
|
|
self.app_props.update({'max pixel size': self.header.fw.read_float()})
|
|
self.app_props.update({'actual size': self.header.fw.read_float()})
|
|
self.app_props.update({'trans falloff pixel size': self.header.fw.read_float()})
|
|
self.app_props.update({'trans falloff exponent': self.header.fw.read_float()})
|
|
self.app_props.update({'trans falloff scalar': self.header.fw.read_float()})
|
|
self.app_props.update({'trans falloff clamp': self.header.fw.read_float()})
|
|
self.app_props.update({'fog scalar': self.header.fw.read_float()})
|
|
self.app_props.update({'fog intensity': self.header.fw.read_float()})
|
|
self.app_props.update({'size threshold': self.header.fw.read_float()})
|
|
self.app_props.update({'directionality': self.header.fw.read_int()})
|
|
self.app_props.update({'horizontal lobe angle': self.header.fw.read_float()})
|
|
self.app_props.update({'vertical lobe angle': self.header.fw.read_float()})
|
|
self.app_props.update({'lobe roll angle': self.header.fw.read_float()})
|
|
self.app_props.update({'dir falloff exponent': self.header.fw.read_float()})
|
|
self.app_props.update({'dir ambient intensity': self.header.fw.read_float()})
|
|
self.header.fw.read_ahead(12) # Animation settings.
|
|
self.app_props.update({'significance': self.header.fw.read_float()})
|
|
self.props['draw order'] = self.header.fw.read_int()
|
|
self.app_props.update({'flags': self.header.fw.read_int()})
|
|
#self.fw.read_ahead(12) # More animation settings.
|
|
|
|
# return dictionary: lp_app name => index list
|
|
def group_points(self, props):
|
|
|
|
name_to_indices = {}
|
|
|
|
for i in self.indices:
|
|
vert_desc = self.header.vert_pal.vert_desc_lst[i]
|
|
app_desc = LightPointAppDesc()
|
|
app_desc.props.update(props)
|
|
# add vertex normal and color
|
|
app_desc.props.update({'nx': vert_desc.nx})
|
|
app_desc.props.update({'ny': vert_desc.ny})
|
|
app_desc.props.update({'nz': vert_desc.nz})
|
|
|
|
app_desc.props.update({'r': vert_desc.r})
|
|
app_desc.props.update({'g': vert_desc.g})
|
|
app_desc.props.update({'b': vert_desc.b})
|
|
app_desc.props.update({'a': vert_desc.a})
|
|
|
|
app_name = GRR.request_lightpoint_app(app_desc)
|
|
|
|
if name_to_indices.get(app_name):
|
|
name_to_indices[app_name].append(i)
|
|
else:
|
|
name_to_indices.update({app_name: [i]})
|
|
|
|
return name_to_indices
|
|
|
|
def blender_import(self):
|
|
name = '%s: %s' % (self.props['type'], self.props['id'])
|
|
|
|
name_to_indices = self.group_points(self.app_props)
|
|
|
|
for app_name, indices in name_to_indices.iteritems():
|
|
self.object = Blender.Object.New('Mesh', name)
|
|
#self.mesh = self.object.getData()
|
|
self.mesh= Blender.Mesh.New()
|
|
self.mesh.verts.extend( Vector() ) # DUMMYVERT
|
|
self.object.link(self.mesh)
|
|
|
|
if self.parent:
|
|
self.parent.object.makeParent([self.object])
|
|
|
|
for i in indices:
|
|
vert = self.header.vert_pal.blender_verts[i]
|
|
self.mesh.verts.append(vert)
|
|
|
|
scene.link(self.object)
|
|
self.object.Layer = current_layer
|
|
self.object.sel= 1
|
|
|
|
if self.matrix:
|
|
self.object.setMatrix(self.matrix)
|
|
|
|
# Import comment.
|
|
if self.props['comment'] != '':
|
|
name = 'COMMENT: ' + self.props['id']
|
|
t = Blender.Text.New(name)
|
|
t.write(self.props['comment'])
|
|
self.props['comment'] = name
|
|
|
|
# Attach properties.
|
|
self.props.update({'appearance': app_name})
|
|
for name, value in self.props.iteritems():
|
|
self.object.addProperty(name, value)
|
|
|
|
self.mesh.update()
|
|
|
|
def parse_vertex_list(self):
|
|
length = self.header.fw.get_length()
|
|
fw = self.header.fw
|
|
vert_pal = self.header.vert_pal
|
|
|
|
count = (length-4)/4
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
|
|
'''
|
|
for i in xrange(count):
|
|
byte_offset = fw.read_int()
|
|
if byte_offset in vert_pal.index:
|
|
index = vert_pal.index[byte_offset]
|
|
self.indices.append(index)
|
|
elif global_prefs['verbose'] >= 1:
|
|
print 'Warning: Unable to map byte offset %s' + \
|
|
' to vertex index.' % byte_offset
|
|
'''
|
|
|
|
return True
|
|
|
|
|
|
|
|
class IndexedLightPoint(InterNode):
|
|
# return dictionary: lp_app name => index list
|
|
def group_points(self, props):
|
|
|
|
name_to_indices = {}
|
|
|
|
for i in self.indices:
|
|
vert_desc = self.header.vert_pal.vert_desc_lst[i]
|
|
app_desc = LightPointAppDesc()
|
|
app_desc.props.update(props)
|
|
# add vertex normal and color
|
|
app_desc.props.update({'nx': vert_desc.nx})
|
|
app_desc.props.update({'ny': vert_desc.ny})
|
|
app_desc.props.update({'nz': vert_desc.nz})
|
|
|
|
app_desc.props.update({'r': vert_desc.r})
|
|
app_desc.props.update({'g': vert_desc.g})
|
|
app_desc.props.update({'b': vert_desc.b})
|
|
app_desc.props.update({'a': vert_desc.a})
|
|
|
|
app_name = GRR.request_lightpoint_app(app_desc)
|
|
|
|
if name_to_indices.get(app_name):
|
|
name_to_indices[app_name].append(i)
|
|
else:
|
|
name_to_indices.update({app_name: [i]})
|
|
|
|
return name_to_indices
|
|
|
|
def blender_import(self):
|
|
name = self.props['type'] + ': ' + self.props['id']
|
|
|
|
name_to_indices = self.group_points(self.header.lightpoint_appearance_pal[self.index])
|
|
|
|
for app_name, indices in name_to_indices.iteritems():
|
|
self.object = Blender.Object.New('Mesh', name)
|
|
#self.mesh = self.object.getData()
|
|
self.mesh= Blender.Mesh.New()
|
|
self.mesh.verts.extend( Vector() ) # DUMMYVERT
|
|
self.object.link(self.mesh)
|
|
|
|
if self.parent:
|
|
self.parent.object.makeParent([self.object])
|
|
|
|
for i in indices:
|
|
vert = self.header.vert_pal.blender_verts[i]
|
|
self.mesh.verts.append(vert)
|
|
|
|
scene.link(self.object)
|
|
|
|
self.object.Layer = current_layer
|
|
|
|
if self.matrix:
|
|
self.object.setMatrix(self.matrix)
|
|
|
|
# Import comment.
|
|
if self.props['comment'] != '':
|
|
name = 'COMMENT: ' + self.props['id']
|
|
t = Blender.Text.New(name)
|
|
t.write(self.props['comment'])
|
|
self.props['comment'] = name
|
|
|
|
# Attach properties.
|
|
self.props.update({'appearance': app_name})
|
|
for name, value in self.props.iteritems():
|
|
self.object.addProperty(name, value)
|
|
|
|
self.mesh.update()
|
|
|
|
def parse_vertex_list(self):
|
|
length = self.header.fw.get_length()
|
|
fw = self.header.fw
|
|
vert_pal = self.header.vert_pal
|
|
|
|
count = (length-4)/4
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
|
|
'''
|
|
for i in xrange(count):
|
|
byte_offset = fw.read_int()
|
|
if byte_offset in vert_pal.index:
|
|
index = vert_pal.index[byte_offset]
|
|
self.indices.append(index)
|
|
elif global_prefs['verbose'] >= 1:
|
|
print 'Warning: Unable to map byte offset %s' + \
|
|
' to vertex index.' % byte_offset
|
|
'''
|
|
return True
|
|
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({72: self.parse_vertex_list,
|
|
10: self.parse_push,
|
|
11: self.parse_pop})
|
|
|
|
self.indices = list()
|
|
|
|
self.props = dict.fromkeys(['id', 'type', 'comment', 'draw order', 'appearance'])
|
|
self.props['comment'] = ''
|
|
self.props['type'] = 'Light Point'
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
self.index = self.header.fw.read_int()
|
|
self.header.fw.read_ahead(4) # animation index
|
|
self.props['draw order'] = self.header.fw.read_int()
|
|
|
|
class Unhandled(InterNode):
|
|
def __init__(self, parent):
|
|
Node.__init__(self, parent, parent.header)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
10: self.parse_push,
|
|
49: self.parse_matrix})
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({2: self.parse_group,
|
|
73: self.parse_lod,
|
|
4: self.parse_object,
|
|
10: self.parse_push,
|
|
11: self.parse_pop,
|
|
96: self.parse_unhandled, # switch
|
|
14: self.parse_unhandled, # DOF
|
|
91: self.parse_unhandled, # sound
|
|
98: self.parse_unhandled, # clip
|
|
63: self.parse_xref})
|
|
|
|
self.props['id'] = self.header.fw.read_string(8)
|
|
|
|
class Database(InterNode):
|
|
def blender_import(self):
|
|
self.tex_pal = dict(self.tex_pal_lst)
|
|
del self.tex_pal_lst
|
|
|
|
# Setup Textures
|
|
bl_tex_pal_lst = list()
|
|
for i in self.tex_pal.iterkeys():
|
|
path_filename = FF.find(self.tex_pal[i])
|
|
if path_filename != None:
|
|
img = GRR.request_image(path_filename)
|
|
if img:
|
|
tex = GRR.request_texture(img)
|
|
tex.setName(FF.strip_path(self.tex_pal[i]))
|
|
bl_tex_pal_lst.append( (i, tex) )
|
|
else:
|
|
bl_tex_pal_lst.append( (i, None) )
|
|
elif global_prefs['verbose'] >= 1:
|
|
print 'Warning: Unable to find', self.tex_pal[i]
|
|
|
|
self.bl_tex_pal = dict(bl_tex_pal_lst)
|
|
|
|
# Setup Materials
|
|
self.mat_desc_pal = dict(self.mat_desc_pal_lst)
|
|
|
|
InterNode.blender_import(self)
|
|
|
|
def parse_appearance_palette(self):
|
|
props = dict()
|
|
self.fw.read_ahead(4) # reserved
|
|
props.update({'id': self.fw.read_string(256)})
|
|
index = self.fw.read_int()
|
|
props.update({'smc': self.fw.read_short()})
|
|
props.update({'fid': self.fw.read_short()})
|
|
props.update({'back color: a': self.fw.read_uchar()})
|
|
props.update({'back color: b': self.fw.read_uchar()})
|
|
props.update({'back color: g': self.fw.read_uchar()})
|
|
props.update({'back color: r': self.fw.read_uchar()})
|
|
props.update({'display mode': self.fw.read_int()})
|
|
props.update({'intensity': self.fw.read_float()})
|
|
props.update({'back intensity': self.fw.read_float()})
|
|
props.update({'minimum defocus': self.fw.read_float()})
|
|
props.update({'maximum defocus': self.fw.read_float()})
|
|
props.update({'fading mode': self.fw.read_int()})
|
|
props.update({'fog punch mode': self.fw.read_int()})
|
|
props.update({'directional mode': self.fw.read_int()})
|
|
props.update({'range mode': self.fw.read_int()})
|
|
props.update({'min pixel size': self.fw.read_float()})
|
|
props.update({'max pixel size': self.fw.read_float()})
|
|
props.update({'actual size': self.fw.read_float()})
|
|
props.update({'trans falloff pixel size': self.fw.read_float()})
|
|
props.update({'trans falloff exponent': self.fw.read_float()})
|
|
props.update({'trans falloff scalar': self.fw.read_float()})
|
|
props.update({'trans falloff clamp': self.fw.read_float()})
|
|
props.update({'fog scalar': self.fw.read_float()})
|
|
props.update({'fog intensity': self.fw.read_float()})
|
|
props.update({'size threshold': self.fw.read_float()})
|
|
props.update({'directionality': self.fw.read_int()})
|
|
props.update({'horizontal lobe angle': self.fw.read_float()})
|
|
props.update({'vertical lobe angle': self.fw.read_float()})
|
|
props.update({'lobe roll angle': self.fw.read_float()})
|
|
props.update({'dir falloff exponent': self.fw.read_float()})
|
|
props.update({'dir ambient intensity': self.fw.read_float()})
|
|
props.update({'significance': self.fw.read_float()})
|
|
props.update({'flags': self.fw.read_int()})
|
|
props.update({'visibility range': self.fw.read_float()})
|
|
props.update({'fade range ratio': self.fw.read_float()})
|
|
props.update({'fade in duration': self.fw.read_float()})
|
|
props.update({'fade out duration': self.fw.read_float()})
|
|
props.update({'LOD range ratio': self.fw.read_float()})
|
|
props.update({'LOD scale': self.fw.read_float()})
|
|
|
|
self.lightpoint_appearance_pal.update({index: props})
|
|
|
|
def parse_header(self):
|
|
self.props['type'] = 'Header'
|
|
self.props['comment'] = ''
|
|
self.props['id'] = self.fw.read_string(8)
|
|
self.props['version'] = self.fw.read_int()
|
|
self.fw.read_ahead(46)
|
|
self.props['units'] = self.fw.read_char()
|
|
self.props['set white'] = bool(self.fw.read_char())
|
|
self.props['flags'] = self.fw.read_int()
|
|
self.fw.read_ahead(24)
|
|
self.props['projection type'] = self.fw.read_int()
|
|
self.fw.read_ahead(36)
|
|
self.props['sw x'] = self.fw.read_double()
|
|
self.props['sw y'] = self.fw.read_double()
|
|
self.props['dx'] = self.fw.read_double()
|
|
self.props['dy'] = self.fw.read_double()
|
|
self.fw.read_ahead(24)
|
|
self.props['sw lat'] = self.fw.read_double()
|
|
self.props['sw lon'] = self.fw.read_double()
|
|
self.props['ne lat'] = self.fw.read_double()
|
|
self.props['ne lon'] = self.fw.read_double()
|
|
self.props['origin lat'] = self.fw.read_double()
|
|
self.props['origin lon'] = self.fw.read_double()
|
|
self.props['lambert lat1'] = self.fw.read_double()
|
|
self.props['lambert lat2'] = self.fw.read_double()
|
|
self.fw.read_ahead(16)
|
|
self.props['ellipsoid model'] = self.fw.read_int()
|
|
self.fw.read_ahead(4)
|
|
self.props['utm zone'] = self.fw.read_short()
|
|
self.fw.read_ahead(6)
|
|
self.props['dz'] = self.fw.read_double()
|
|
self.props['radius'] = self.fw.read_double()
|
|
self.fw.read_ahead(8)
|
|
self.props['major axis'] = self.fw.read_double()
|
|
self.props['minor axis'] = self.fw.read_double()
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'OpenFlight Version:', float(self.props['version']) / 100.0
|
|
print
|
|
|
|
return True
|
|
|
|
def parse_mat_palette(self):
|
|
mat_desc = MaterialDesc()
|
|
index = self.fw.read_int()
|
|
|
|
name = self.fw.read_string(12)
|
|
if len(mat_desc.name) > 0:
|
|
mat_desc.name = name
|
|
|
|
flag = self.fw.read_int()
|
|
# skip material if not used
|
|
if not flag & 0x80000000:
|
|
return True
|
|
|
|
ambient_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
|
|
mat_desc.diffuse = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
|
|
mat_desc.specular = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
|
|
emissive_col = [self.fw.read_float(), self.fw.read_float(), self.fw.read_float()]
|
|
|
|
mat_desc.shininess = self.fw.read_float() / 64.0 # [0.0, 128.0] => [0.0, 2.0]
|
|
mat_desc.alpha = self.fw.read_float()
|
|
|
|
# Convert ambient and emissive colors into intensitities.
|
|
mat_desc.ambient = col_to_gray(ambient_col)
|
|
mat_desc.emissive = col_to_gray(emissive_col)
|
|
|
|
self.mat_desc_pal_lst.append( (index, mat_desc) )
|
|
|
|
return True
|
|
|
|
def get_color(self, color_index):
|
|
index = color_index / 128
|
|
intensity = float(color_index - 128.0 * index) / 127.0
|
|
|
|
if index >= 0 and index <= 1023:
|
|
brightest = self.col_pal[index]
|
|
r = int(brightest[0] * intensity)
|
|
g = int(brightest[1] * intensity)
|
|
b = int(brightest[2] * intensity)
|
|
a = int(brightest[3])
|
|
|
|
color = [r, g, b, a]
|
|
|
|
return color
|
|
|
|
def parse_color_palette(self):
|
|
self.header.fw.read_ahead(128)
|
|
for i in xrange(1024):
|
|
a = self.header.fw.read_uchar()
|
|
b = self.header.fw.read_uchar()
|
|
g = self.header.fw.read_uchar()
|
|
r = self.header.fw.read_uchar()
|
|
self.col_pal.append((r, g, b, a))
|
|
return True
|
|
|
|
def parse_vertex_palette(self):
|
|
self.vert_pal = VertexPalette(self)
|
|
self.vert_pal.parse()
|
|
return True
|
|
|
|
def parse_texture_palette(self):
|
|
name = self.fw.read_string(200)
|
|
index = self.fw.read_int()
|
|
self.tex_pal_lst.append( (index, name) )
|
|
return True
|
|
|
|
def __init__(self, filename, parent=None):
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'Parsing:', filename
|
|
print
|
|
|
|
self.fw = flt_filewalker.FltIn(filename)
|
|
Node.__init__(self, parent, self)
|
|
InterNode.__init__(self)
|
|
|
|
self.root_handler.set_handler({1: self.parse_header,
|
|
67: self.parse_vertex_palette,
|
|
33: self.parse_long_id,
|
|
31: self.parse_comment,
|
|
64: self.parse_texture_palette,
|
|
32: self.parse_color_palette,
|
|
113: self.parse_mat_palette,
|
|
128: self.parse_appearance_palette,
|
|
10: self.parse_push})
|
|
if parent:
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
self.child_handler.set_handler({#130: self.parse_indexed_light_point,
|
|
#111: self.parse_inline_light_point,
|
|
2: self.parse_group,
|
|
73: self.parse_lod,
|
|
4: self.parse_object,
|
|
10: self.parse_push,
|
|
11: self.parse_pop,
|
|
96: self.parse_unhandled,
|
|
14: self.parse_unhandled,
|
|
91: self.parse_unhandled,
|
|
98: self.parse_unhandled,
|
|
63: self.parse_xref})
|
|
|
|
self.vert_pal = None
|
|
self.lightpoint_appearance_pal = dict()
|
|
self.tex_pal = dict()
|
|
self.tex_pal_lst = list()
|
|
self.bl_tex_pal = dict()
|
|
self.col_pal = list()
|
|
self.mat_desc_pal_lst = list()
|
|
self.mat_desc_pal = dict()
|
|
self.props = dict.fromkeys(['id', 'type', 'comment', 'version', 'units', 'set white',
|
|
'flags', 'projection type', 'sw x', 'sw y', 'dx', 'dy', 'dz', 'sw lat',
|
|
'sw lon', 'ne lat', 'ne lon', 'origin lat', 'origin lon', 'lambert lat1',
|
|
'lambert lat2', 'ellipsoid model', 'utm zone', 'radius', 'major axis', 'minor axis'])
|
|
|
|
def select_file(filename):
|
|
if not Blender.sys.exists(filename):
|
|
msg = 'Error: File ' + filename + ' does not exist.'
|
|
Blender.Draw.PupMenu(msg)
|
|
return
|
|
|
|
if not filename.lower().endswith('.flt'):
|
|
msg = 'Error: Not a flight file.'
|
|
Blender.Draw.PupMenu(msg)
|
|
print msg
|
|
print
|
|
return
|
|
|
|
global_prefs['fltfile']= filename
|
|
global_prefs['verbose']= 1
|
|
global_prefs['get_texture'] = True
|
|
global_prefs['get_diffuse'] = True
|
|
global_prefs['get_specular'] = False
|
|
global_prefs['get_emissive'] = False
|
|
global_prefs['get_alpha'] = True
|
|
global_prefs['get_ambient'] = False
|
|
global_prefs['get_shininess'] = True
|
|
global_prefs['color_from_face'] = True
|
|
|
|
# Start loading the file,
|
|
# first set the context
|
|
Blender.Window.WaitCursor(True)
|
|
Blender.Window.EditMode(0)
|
|
for ob in scene.objects:
|
|
ob.sel=0
|
|
|
|
|
|
FF.add_file_to_search_path(filename)
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'Pass 1: Loading.'
|
|
print
|
|
|
|
load_time = Blender.sys.time()
|
|
db = Database(filename)
|
|
db.parse()
|
|
load_time = Blender.sys.time() - load_time
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
print
|
|
print 'Pass 2: Importing to Blender.'
|
|
print
|
|
|
|
import_time = Blender.sys.time()
|
|
db.blender_import()
|
|
import_time = Blender.sys.time() - import_time
|
|
|
|
Blender.Window.ViewLayer(range(1,21))
|
|
|
|
# FIX UP AFTER DUMMY VERT AND REMOVE DOUBLES
|
|
Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
|
|
for ob in scene.objects.context:
|
|
if ob.type=='Mesh':
|
|
me=ob.getData(mesh=1)
|
|
me.verts.delete(0) # remove the dummy vert
|
|
me.sel= 1
|
|
me.remDoubles(0.0001)
|
|
|
|
|
|
|
|
Blender.Window.RedrawAll()
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
print 'Done.'
|
|
print
|
|
print 'Time to parse file: %.3f seconds' % load_time
|
|
print 'Time to import to blender: %.3f seconds' % import_time
|
|
print 'Total time: %.3f seconds' % (load_time + import_time)
|
|
|
|
Blender.Window.WaitCursor(False)
|
|
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
print
|
|
print 'OpenFlight Importer'
|
|
print 'Version:', __version__
|
|
print 'Author: Greg MacDonald'
|
|
print __url__[2]
|
|
print
|
|
|
|
|
|
if __name__ == '__main__':
|
|
Blender.Window.FileSelector(select_file, "Import OpenFlight", "*.flt")
|
|
#select_file('/fe/flt/helnwsflt/helnws.flt')
|
|
#select_file('/fe/flt/Container_006.flt')
|
|
#select_file('/fe/flt/NaplesORIGINALmesh.flt')
|
|
#select_file('/Anti_tank_D30.flt')
|
|
#select_file('/metavr/file_examples/flt/cherrypoint/CherryPoint_liter_runway.flt')
|
|
|
|
|
|
"""
|
|
TIME= Blender.sys.time()
|
|
import os
|
|
PATH= 'c:\\flt_test'
|
|
for FNAME in os.listdir(PATH):
|
|
if FNAME.lower().endswith('.flt'):
|
|
FPATH= os.path.join(PATH, FNAME)
|
|
newScn= Blender.Scene.New(FNAME)
|
|
newScn.makeCurrent()
|
|
scene= newScn
|
|
select_file(FPATH)
|
|
|
|
print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
|
|
"""
|
|
|