2006-01-10 13:42:20 +00:00
|
|
|
#!BPY
|
|
|
|
""" Registration info for Blender menus:
|
|
|
|
Name: 'OpenFlight (.flt)...'
|
2007-11-22 01:43:24 +00:00
|
|
|
Blender: 245
|
2006-01-10 13:42:20 +00:00
|
|
|
Group: 'Import'
|
|
|
|
Tip: 'Import OpenFlight (.flt)'
|
|
|
|
"""
|
|
|
|
|
2008-03-18 23:16:47 +00:00
|
|
|
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
__author__ = "Greg MacDonald, Campbell Barton, Geoffrey Bantle"
|
|
|
|
__version__ = "2.0 11/21/07"
|
2008-04-23 14:04:05 +00:00
|
|
|
__url__ = ("blender", "blenderartists.org", "Author's homepage, http://sourceforge.net/projects/blight/")
|
2006-01-10 13:42:20 +00:00
|
|
|
__bpydoc__ = """\
|
|
|
|
This script imports OpenFlight files into Blender. OpenFlight is a
|
|
|
|
registered trademark of MultiGen-Paradigm, Inc.
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
Feature overview and more availible at:
|
2008-05-24 18:43:02 +00:00
|
|
|
http://wiki.blender.org/index.php/Scripts/Manual/Import/openflight_fltss
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
Note: This file is a grab-bag of old and new code. It needs some cleanup still.
|
2006-01-10 13:42:20 +00:00
|
|
|
"""
|
|
|
|
|
2007-02-14 01:03:32 +00:00
|
|
|
# flt_import.py is an OpenFlight importer for blender.
|
2007-11-22 01:43:24 +00:00
|
|
|
# Copyright (C) 2005 Greg MacDonald, 2007 Blender Foundation
|
2007-02-14 01:03:32 +00:00
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
import Blender
|
|
|
|
import os
|
2006-07-28 08:17:04 +00:00
|
|
|
import BPyMesh
|
|
|
|
import BPyImage
|
|
|
|
import flt_filewalker
|
2007-11-22 01:43:24 +00:00
|
|
|
import flt_properties
|
2008-05-24 18:43:02 +00:00
|
|
|
import sys
|
2007-11-22 01:43:24 +00:00
|
|
|
reload(flt_properties)
|
|
|
|
from flt_properties import *
|
2006-01-10 13:42:20 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#Globals. Should Clean these up and minimize their usage.
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
typecodes = ['c','C','s','S','i','I','f','d','t']
|
|
|
|
records = dict()
|
|
|
|
|
|
|
|
FLTBaseLabel = None
|
|
|
|
FLTBaseString = None
|
|
|
|
FLTBaseChooser = None
|
|
|
|
FLTExport = None
|
|
|
|
FLTClose = None
|
|
|
|
FLTDoXRef = None
|
|
|
|
FLTScale = None
|
|
|
|
FLTShadeImport = None
|
|
|
|
FLTAttrib = None
|
2008-05-15 19:35:17 +00:00
|
|
|
FLTWarn = None
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
Vector= Blender.Mathutils.Vector
|
|
|
|
FLOAT_TOLERANCE = 0.01
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
FF = flt_filewalker.FileFinder()
|
|
|
|
current_layer = 0x01
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
global_prefs = dict()
|
2007-11-22 01:43:24 +00:00
|
|
|
global_prefs['verbose']= 4
|
2006-07-28 08:17:04 +00:00
|
|
|
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']= ''
|
2007-11-22 01:43:24 +00:00
|
|
|
global_prefs['smoothshading'] = 1
|
|
|
|
global_prefs['doxrefs'] = 1
|
|
|
|
global_prefs['scale'] = 1.0
|
|
|
|
global_prefs['attrib'] = 0
|
2006-01-10 13:42:20 +00:00
|
|
|
msg_once = False
|
|
|
|
|
2008-03-28 23:06:00 +00:00
|
|
|
reg = Blender.Registry.GetKey('flt_import',1)
|
|
|
|
if reg:
|
|
|
|
for key in global_prefs:
|
|
|
|
if reg.has_key(key):
|
|
|
|
global_prefs[key] = reg[key]
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
throw_back_opcodes = [2, 73, 4, 11, 96, 14, 91, 98, 63,111] # Opcodes that indicate its time to return control to parent.
|
2008-03-28 00:08:41 +00:00
|
|
|
do_not_report_opcodes = [76, 78, 79, 80, 81, 82, 94, 83, 33, 112, 101, 102, 97, 31, 103, 104, 117, 118, 120, 121, 124, 125]
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
#Process FLT record definitions
|
|
|
|
for record in FLT_Records:
|
|
|
|
props = dict()
|
|
|
|
for prop in FLT_Records[record]:
|
|
|
|
position = ''
|
|
|
|
slice = 0
|
|
|
|
(format,name) = prop.split('!')
|
|
|
|
for i in format:
|
|
|
|
if i not in typecodes:
|
|
|
|
position = position + i
|
|
|
|
slice = slice + 1
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
type = format[slice:]
|
|
|
|
length = type[1:]
|
|
|
|
if len(length) == 0:
|
|
|
|
length = 1
|
|
|
|
else:
|
|
|
|
type = type[0]
|
|
|
|
length = int(length)
|
|
|
|
|
|
|
|
props[int(position)] = (type,length,prop)
|
|
|
|
records[record] = props
|
|
|
|
|
|
|
|
def col_to_gray(c):
|
|
|
|
return 0.3*c[0] + 0.59*c[1] + 0.11*c[2]
|
2006-01-10 13:42:20 +00:00
|
|
|
class MaterialDesc:
|
2006-07-28 08:17:04 +00:00
|
|
|
# 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])
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
# key.extend(self.face_props.values())
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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'])
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class VertexDesc:
|
2006-07-28 08:17:04 +00:00
|
|
|
def make_key(self):
|
2006-07-28 19:09:09 +00:00
|
|
|
return round(self.x, 6), round(self.y, 6), round(self.z, 6)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
def __init__(self):
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# Assign later, save memory, all verts have a loc
|
2006-07-28 08:17:04 +00:00
|
|
|
self.x = 0.0
|
|
|
|
self.y = 0.0
|
|
|
|
self.z = 0.0
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.nx = 0.0
|
2007-11-22 01:43:24 +00:00
|
|
|
self.ny = 0.0
|
2006-07-28 08:17:04 +00:00
|
|
|
self.nz = 0.0
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
self.uv= Vector(0,0)
|
2007-11-22 01:43:24 +00:00
|
|
|
self.cindex = 127 #default/lowest
|
|
|
|
self.cnorm = False
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class LightPointAppDesc:
|
2006-07-28 08:17:04 +00:00
|
|
|
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})
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class GlobalResourceRepository:
|
2007-11-22 01:43:24 +00:00
|
|
|
def request_lightpoint_app(self, desc, scene):
|
2006-07-28 08:17:04 +00:00
|
|
|
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)
|
2007-11-22 01:43:24 +00:00
|
|
|
scene.objects.link(object)
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# Dont use request_vert - faster to make it from the vector direct.
|
|
|
|
"""
|
2006-07-28 08:17:04 +00:00
|
|
|
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)
|
2006-07-28 19:09:09 +00:00
|
|
|
''' IGNORE_NORMALS
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
"""
|
2006-07-28 08:17:04 +00:00
|
|
|
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.
|
2006-01-10 13:42:20 +00:00
|
|
|
# t = Blender.Text.New('FACE: ' + mat.getName())
|
|
|
|
#
|
|
|
|
# for name, value in mat_desc.face_props.items():
|
|
|
|
# t.write(name + '\n' + str(value) + '\n\n')
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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):
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
#list of scenes xrefs belong to.
|
|
|
|
self.xrefs = dict()
|
2006-07-28 08:17:04 +00:00
|
|
|
# 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
|
2006-07-28 19:09:09 +00:00
|
|
|
# self.vert_dict = dict()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
# light point
|
|
|
|
self.light_point_app = dict()
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class Handler:
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class Node:
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
for child in self.children:
|
|
|
|
child.blender_import()
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
# Import comment.
|
2006-01-10 13:42:20 +00:00
|
|
|
# if self.props['comment'] != '':
|
|
|
|
# name = 'COMMENT: ' + self.props['id']
|
|
|
|
# t = Blender.Text.New(name)
|
|
|
|
# t.write(self.props['comment'])
|
|
|
|
# self.props['comment'] = name
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
# 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'
|
2007-11-22 01:43:24 +00:00
|
|
|
elif global_prefs['verbose'] >= 1 and not opcode in do_not_report_opcodes and opcode in opcode_name:
|
|
|
|
print 'not handled'
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2008-03-28 00:08:41 +00:00
|
|
|
def parse_extension(self):
|
|
|
|
extension = dict()
|
|
|
|
props = records[100]
|
|
|
|
propkeys = props.keys()
|
|
|
|
propkeys.sort()
|
|
|
|
for position in propkeys:
|
|
|
|
(type,length,name) = props[position]
|
|
|
|
extension[name] = read_prop(self.header.fw,type,length)
|
|
|
|
#read extension data.
|
|
|
|
dstring = list()
|
|
|
|
for i in xrange(self.header.fw.get_length()-24):
|
|
|
|
dstring.append(self.header.fw.read_char())
|
|
|
|
extension['data'] = dstring
|
|
|
|
self.extension = extension
|
2007-11-22 01:43:24 +00:00
|
|
|
def parse_record(self):
|
|
|
|
self.props['type'] = self.opcode
|
|
|
|
props = records[self.opcode]
|
|
|
|
propkeys = props.keys()
|
|
|
|
propkeys.sort()
|
|
|
|
for position in propkeys:
|
|
|
|
(type,length,name) = props[position]
|
|
|
|
self.props[name] = read_prop(self.header.fw,type,length)
|
|
|
|
try: #remove me!
|
|
|
|
self.props['id'] = self.props['3t8!id']
|
|
|
|
except:
|
|
|
|
pass
|
2006-07-28 08:17:04 +00:00
|
|
|
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'}
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class VertexPalette(Node):
|
2006-07-28 19:09:09 +00:00
|
|
|
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()
|
|
|
|
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
def blender_import(self):
|
2006-07-28 19:09:09 +00:00
|
|
|
self.blender_verts.extend([Vector(vert_desc.x, vert_desc.y, vert_desc.z) for vert_desc in self.vert_desc_lst ])
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
def parse_vertex_common(self):
|
|
|
|
# Add this vertex to an offset to index dictionary.
|
2006-07-28 19:09:09 +00:00
|
|
|
#self.index_lst.append( (self.offset, self.next_index) )
|
|
|
|
self.index[self.offset]= len(self.index)
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
# 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):
|
2007-11-22 01:43:24 +00:00
|
|
|
#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) #skip packed color
|
|
|
|
v.cindex = self.header.fw.read_uint()
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
2007-11-22 01:43:24 +00:00
|
|
|
v.cnorm = True
|
2006-07-28 08:17:04 +00:00
|
|
|
v.nx = self.header.fw.read_float()
|
|
|
|
v.ny = self.header.fw.read_float()
|
|
|
|
v.nz = self.header.fw.read_float()
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def parse_vertex_cuv(self):
|
|
|
|
v = self.parse_vertex_common()
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def parse_vertex_cnuv(self):
|
|
|
|
v = self.parse_vertex_common()
|
2007-11-22 01:43:24 +00:00
|
|
|
v.cnorm = True
|
2006-07-28 08:17:04 +00:00
|
|
|
v.nx = self.header.fw.read_float()
|
|
|
|
v.ny = self.header.fw.read_float()
|
|
|
|
v.nz = self.header.fw.read_float()
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
v.uv[:] = self.header.fw.read_float(), self.header.fw.read_float()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
self.parse_vertex_post_common(v)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
def parse(self): # Run once per import
|
2006-07-28 08:17:04 +00:00
|
|
|
Node.parse(self)
|
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class InterNode(Node):
|
2006-07-28 19:09:09 +00:00
|
|
|
def __init__(self):
|
|
|
|
self.object = None
|
|
|
|
self.mesh = None
|
2008-03-26 15:59:56 +00:00
|
|
|
self.swapmesh = None
|
2007-11-22 01:43:24 +00:00
|
|
|
self.hasMesh = False
|
2006-07-28 19:09:09 +00:00
|
|
|
self.faceLs= []
|
|
|
|
self.matrix = None
|
2007-11-22 01:43:24 +00:00
|
|
|
self.vis = True
|
|
|
|
self.hasmtex = False
|
|
|
|
self.uvlayers = dict()
|
|
|
|
self.blayernames = dict()
|
|
|
|
self.subfacelevel = 0
|
2008-03-28 00:08:41 +00:00
|
|
|
self.extension = None
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
mask = 2147483648
|
|
|
|
for i in xrange(7):
|
|
|
|
self.uvlayers[mask] = False
|
|
|
|
mask = mask / 2
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
#######################################################
|
|
|
|
## Begin Remove Doubles Replacement ##
|
|
|
|
#######################################################
|
|
|
|
def __xvertsort(self,__a,__b):
|
|
|
|
(__vert, __x1) = __a
|
|
|
|
(__vert2,__x2) = __b
|
|
|
|
|
|
|
|
if __x1 > __x2:
|
|
|
|
return 1
|
|
|
|
elif __x1 < __x2:
|
|
|
|
return -1
|
|
|
|
return 0
|
|
|
|
def __calcFaceNorm(self,__face):
|
|
|
|
if len(__face) == 3:
|
|
|
|
return Blender.Mathutils.TriangleNormal(__face[0].co, __face[1].co, __face[2].co)
|
|
|
|
elif len(__face) == 4:
|
|
|
|
return Blender.Mathutils.QuadNormal(__face[0].co, __face[1].co, __face[2].co, __face[3].co)
|
|
|
|
|
|
|
|
def __replaceFaceVert(self,__weldface, __oldvert, __newvert):
|
|
|
|
__index = None
|
|
|
|
for __i, __v in enumerate(__weldface):
|
|
|
|
if __v == __oldvert:
|
|
|
|
__index = __i
|
|
|
|
break
|
|
|
|
__weldface[__index] = __newvert
|
|
|
|
|
|
|
|
def __matchEdge(self,__weldmesh, __edge1, __edge2):
|
|
|
|
if __edge1[0] in __weldmesh['Vertex Disk'][__edge2[1]] and __edge1[1] in __weldmesh['Vertex Disk'][__edge2[0]]:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
#have to compare original faces!
|
|
|
|
def __faceWinding(self, __weldmesh, __face1, __face2):
|
|
|
|
|
|
|
|
__f1edges = list()
|
|
|
|
__f2edges = list()
|
|
|
|
|
|
|
|
__f1edges.append((__face1.verts[0], __face1.verts[1]))
|
|
|
|
__f1edges.append((__face1.verts[1], __face1.verts[2]))
|
|
|
|
if len(__face1.verts) == 3:
|
|
|
|
__f1edges.append((__face1.verts[2], __face1.verts[0]))
|
|
|
|
else:
|
|
|
|
__f1edges.append((__face1.verts[2], __face1.verts[3]))
|
|
|
|
__f1edges.append((__face1.verts[3], __face1.verts[0]))
|
|
|
|
|
|
|
|
__f2edges.append((__face2.verts[0], __face2.verts[1]))
|
|
|
|
__f2edges.append((__face2.verts[1], __face2.verts[2]))
|
|
|
|
if len(__face2.verts) == 3:
|
|
|
|
__f2edges.append((__face2.verts[2], __face2.verts[0]))
|
|
|
|
else:
|
|
|
|
__f2edges.append((__face2.verts[2], __face2.verts[3]))
|
|
|
|
__f2edges.append((__face2.verts[3], __face2.verts[0]))
|
|
|
|
|
|
|
|
|
|
|
|
#find a matching edge
|
|
|
|
for __edge1 in __f1edges:
|
|
|
|
for __edge2 in __f2edges:
|
|
|
|
if self.__matchEdge(__weldmesh, __edge1, __edge2): #no more tests nessecary
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
def __floatcompare(self, __f1, __f2):
|
2008-03-26 16:45:18 +00:00
|
|
|
epsilon = 0.1
|
2008-03-26 15:59:56 +00:00
|
|
|
if ((__f1 + epsilon) > __f2) and ((__f1 - epsilon) < __f2):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
def __testFace(self,__weldmesh,__v1face, __v2face, __v1bface, __v2bface):
|
|
|
|
limit = 0.01
|
|
|
|
__matchvert = None
|
|
|
|
#frst test (for real this time!). Are the faces the same face?
|
|
|
|
if __v1face == __v2face:
|
|
|
|
return False
|
|
|
|
|
|
|
|
#first test: Do the faces possibly geometrically share more than two vertices? we should be comparing original faces for this? - Yes.....
|
|
|
|
__match = 0
|
|
|
|
for __vert in __v1bface.verts:
|
|
|
|
for __vert2 in __v2bface.verts:
|
2008-03-26 16:45:18 +00:00
|
|
|
#if (abs(__vert.co[0] - __vert2.co[0]) <= limit) and (abs(__vert.co[1] - __vert2.co[1]) <= limit) and (abs(__vert.co[2] - __vert2.co[2]) <= limit): #this needs to be fixed!
|
|
|
|
if __vert2 in __weldmesh['Vertex Disk'][__vert] or __vert == __vert2:
|
2008-03-26 15:59:56 +00:00
|
|
|
__match += 1
|
|
|
|
__matchvert = __vert2
|
|
|
|
#avoid faces sharing more than two verts
|
|
|
|
if __match > 2:
|
|
|
|
return False
|
|
|
|
|
|
|
|
#consistent winding for face normals
|
2008-03-26 16:45:18 +00:00
|
|
|
if __match == 2:
|
|
|
|
if not self.__faceWinding(__weldmesh, __v1bface, __v2bface):
|
|
|
|
return False
|
2008-03-26 15:59:56 +00:00
|
|
|
|
|
|
|
#second test: Compatible normals.Anything beyond almost exact opposite is 'ok'
|
|
|
|
__v1facenorm = self.__calcFaceNorm(__v1face)
|
|
|
|
__v2facenorm = self.__calcFaceNorm(__v2face)
|
|
|
|
|
|
|
|
#dont even mess with zero length faces
|
|
|
|
if __v1facenorm.length < limit:
|
|
|
|
return False
|
|
|
|
if __v2facenorm.length < limit:
|
|
|
|
return False
|
|
|
|
|
|
|
|
__v1facenorm.normalize()
|
|
|
|
__v2facenorm.normalize()
|
2008-03-26 16:45:18 +00:00
|
|
|
|
|
|
|
if __match == 1:
|
|
|
|
#special case, look for comparison of normals angle
|
|
|
|
__angle = Blender.Mathutils.AngleBetweenVecs(__v1facenorm, __v2facenorm)
|
|
|
|
if __angle > 70.0:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
__v2facenorm = __v2facenorm.negate()
|
|
|
|
|
|
|
|
if self.__floatcompare(__v1facenorm[0], __v2facenorm[0]) and self.__floatcompare(__v1facenorm[1], __v2facenorm[1]) and self.__floatcompare(__v1facenorm[2], __v2facenorm[2]):
|
|
|
|
return False
|
|
|
|
|
|
|
|
#next test: dont weld a subface to a non-subface!
|
|
|
|
if __v1bface.getProperty("FLT_SFLEVEL") != __v2bface.getProperty("FLT_SFLEVEL"):
|
|
|
|
return False
|
|
|
|
|
|
|
|
#final test: edge test - We dont want to create a non-manifold edge through our weld operation
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def __copyFaceData(self, __source, __target):
|
|
|
|
#copy vcolor layers.
|
|
|
|
__actColLayer = self.mesh.activeColorLayer
|
|
|
|
for __colorlayer in self.mesh.getColorLayerNames():
|
|
|
|
self.mesh.activeColorLayer = __colorlayer
|
|
|
|
for __i, __col in enumerate(__source.col):
|
|
|
|
__target.col[__i].r = __col.r
|
|
|
|
__target.col[__i].g = __col.g
|
|
|
|
__target.col[__i].b = __col.b
|
|
|
|
|
|
|
|
self.mesh.activeColorLayer = __actColLayer
|
|
|
|
#copy uv layers.
|
|
|
|
__actUVLayer = self.mesh.activeUVLayer
|
|
|
|
for __uvlayer in self.mesh.getUVLayerNames():
|
|
|
|
self.mesh.activeUVLayer = __uvlayer
|
|
|
|
__target.image = __source.image
|
|
|
|
__target.mode = __source.mode
|
|
|
|
__target.smooth = __source.smooth
|
|
|
|
__target.transp = __source.transp
|
|
|
|
for __i, __uv in enumerate(__source.uv):
|
|
|
|
__target.uv[__i][0] = __uv[0]
|
|
|
|
__target.uv[__i][1] = __uv[1]
|
|
|
|
|
|
|
|
self.mesh.activeUVLayer = __actUVLayer
|
|
|
|
#copy property layers
|
|
|
|
for __property in self.mesh.faces.properties:
|
|
|
|
__target.setProperty(__property, __source.getProperty(__property))
|
|
|
|
|
|
|
|
def findDoubles(self):
|
|
|
|
limit = 0.01
|
|
|
|
sortblock = list()
|
|
|
|
double = dict()
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
double[vert] = None
|
|
|
|
sortblock.append((vert, vert.co[0] + vert.co[1] + vert.co[2]))
|
|
|
|
sortblock.sort(self.__xvertsort)
|
|
|
|
|
|
|
|
a = 0
|
|
|
|
while a < len(self.mesh.verts):
|
|
|
|
(vert,xsort) = sortblock[a]
|
|
|
|
b = a+1
|
|
|
|
if not double[vert]:
|
|
|
|
while b < len(self.mesh.verts):
|
|
|
|
(vert2, xsort2) = sortblock[b]
|
|
|
|
if not double[vert2]:
|
|
|
|
#first test, simple distance
|
|
|
|
if (xsort2 - xsort) > limit:
|
|
|
|
break
|
|
|
|
#second test, more expensive
|
|
|
|
if (abs(vert.co[0] - vert2.co[0]) <= limit) and (abs(vert.co[1] - vert2.co[1]) <= limit) and (abs(vert.co[2] - vert2.co[2]) <= limit):
|
|
|
|
double[vert2] = vert
|
|
|
|
b+=1
|
|
|
|
a+=1
|
|
|
|
|
|
|
|
return double
|
|
|
|
|
|
|
|
def buildWeldMesh(self):
|
|
|
|
|
|
|
|
weldmesh = dict()
|
|
|
|
weldmesh['Vertex Disk'] = dict() #this is geometric adjacency
|
|
|
|
weldmesh['Vertex Faces'] = dict() #topological adjacency
|
|
|
|
|
|
|
|
#find the doubles for this mesh
|
|
|
|
double = self.findDoubles()
|
|
|
|
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
weldmesh['Vertex Faces'][vert] = list()
|
|
|
|
|
|
|
|
#create weld faces
|
|
|
|
weldfaces = list()
|
|
|
|
originalfaces = list()
|
|
|
|
for face in self.mesh.faces:
|
|
|
|
weldface = list()
|
|
|
|
for vert in face.verts:
|
|
|
|
weldface.append(vert)
|
|
|
|
weldfaces.append(weldface)
|
|
|
|
originalfaces.append(face)
|
|
|
|
for i, weldface in enumerate(weldfaces):
|
|
|
|
for vert in weldface:
|
|
|
|
weldmesh['Vertex Faces'][vert].append(i)
|
|
|
|
weldmesh['Weld Faces'] = weldfaces
|
|
|
|
weldmesh['Original Faces'] = originalfaces
|
|
|
|
|
|
|
|
#Now we need to build the vertex disk data. first we do just the 'target' vertices
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
if not double[vert]: #its a target
|
|
|
|
weldmesh['Vertex Disk'][vert] = list()
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
if double[vert]: #its a double
|
|
|
|
weldmesh['Vertex Disk'][double[vert]].append(vert)
|
|
|
|
|
|
|
|
#Now we need to create the disk information for the remaining vertices
|
|
|
|
targets = weldmesh['Vertex Disk'].keys()
|
|
|
|
for target in targets:
|
|
|
|
for doublevert in weldmesh['Vertex Disk'][target]:
|
|
|
|
weldmesh['Vertex Disk'][doublevert] = [target]
|
|
|
|
for othervert in weldmesh['Vertex Disk'][target]:
|
|
|
|
if othervert != doublevert:
|
|
|
|
weldmesh['Vertex Disk'][doublevert].append(othervert)
|
|
|
|
|
|
|
|
return weldmesh
|
|
|
|
|
|
|
|
def weldFuseFaces(self,weldmesh):
|
2008-05-15 19:35:17 +00:00
|
|
|
|
|
|
|
#retain original loose vertices
|
|
|
|
looseverts = dict()
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
looseverts[vert] = 0
|
|
|
|
for edge in self.mesh.edges:
|
|
|
|
looseverts[edge.v1] += 1
|
|
|
|
looseverts[edge.v2] += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
#slight modification here: we need to walk around the mesh as many times as it takes to have no more matches
|
|
|
|
done = 0
|
|
|
|
while not done:
|
|
|
|
done = 1
|
|
|
|
for windex, weldface in enumerate(weldmesh['Weld Faces']):
|
|
|
|
for vertex in weldface:
|
|
|
|
#we walk around the faces of the doubles of this vertex and if possible, we weld them.
|
|
|
|
for doublevert in weldmesh['Vertex Disk'][vertex]:
|
|
|
|
removeFaces = list() #list of faces to remove from doubleverts face list
|
|
|
|
for doublefaceindex in weldmesh['Vertex Faces'][doublevert]:
|
|
|
|
doubleface = weldmesh['Weld Faces'][doublefaceindex]
|
|
|
|
oface1 = self.mesh.faces[windex]
|
|
|
|
oface2 = self.mesh.faces[doublefaceindex]
|
|
|
|
ok = self.__testFace(weldmesh, weldface, doubleface, oface1, oface2)
|
|
|
|
if ok:
|
|
|
|
done = 0
|
|
|
|
removeFaces.append(doublefaceindex)
|
|
|
|
self.__replaceFaceVert(doubleface, doublevert, vertex)
|
|
|
|
for doublefaceindex in removeFaces:
|
|
|
|
weldmesh['Vertex Faces'][doublevert].remove(doublefaceindex)
|
|
|
|
#old faces first
|
|
|
|
oldindices = list()
|
|
|
|
for face in self.mesh.faces:
|
|
|
|
oldindices.append(face.index)
|
|
|
|
#make our new faces.
|
|
|
|
newfaces = list()
|
|
|
|
for weldface in weldmesh['Weld Faces']:
|
|
|
|
newfaces.append(weldface)
|
|
|
|
newindices = self.mesh.faces.extend(newfaces, indexList=True, ignoreDups=True)
|
|
|
|
#copy custom data over
|
|
|
|
for i, newindex in enumerate(newindices):
|
|
|
|
try:
|
|
|
|
self.__copyFaceData(self.mesh.faces[oldindices[i]], self.mesh.faces[newindex])
|
|
|
|
except:
|
|
|
|
print "warning, could not copy face data!"
|
|
|
|
#delete the old faces
|
|
|
|
self.mesh.faces.delete(1, oldindices)
|
|
|
|
|
|
|
|
#Clean up stray vertices
|
|
|
|
vertuse = dict()
|
|
|
|
for vert in self.mesh.verts:
|
|
|
|
vertuse[vert] = 0
|
|
|
|
for face in self.mesh.faces:
|
|
|
|
for vert in face.verts:
|
|
|
|
vertuse[vert] += 1
|
|
|
|
delverts = list()
|
|
|
|
for vert in self.mesh.verts:
|
2008-05-15 19:35:17 +00:00
|
|
|
if not vertuse[vert] and vert.index != 0 and looseverts[vert]:
|
2008-03-26 15:59:56 +00:00
|
|
|
delverts.append(vert)
|
|
|
|
|
|
|
|
self.mesh.verts.delete(delverts)
|
|
|
|
|
2008-03-26 16:45:18 +00:00
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
#######################################################
|
|
|
|
## End Remove Doubles Replacement ##
|
|
|
|
#######################################################
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
def blender_import_my_faces(self):
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
# Add the verts onto the mesh
|
|
|
|
blender_verts= self.header.vert_pal.blender_verts
|
|
|
|
vert_desc_lst= self.header.vert_pal.vert_desc_lst
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
vert_list= [ i for flt_face in self.faceLs for i in flt_face.indices] #splitting faces apart. Is this a good thing?
|
|
|
|
face_edges= []
|
|
|
|
face_verts= []
|
|
|
|
self.mesh.verts.extend([blender_verts[i] for i in vert_list])
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
new_faces= []
|
|
|
|
new_faces_props= []
|
|
|
|
ngon= BPyMesh.ngon
|
|
|
|
vert_index= 1
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
#add vertex color layer for baked face colors.
|
|
|
|
self.mesh.addColorLayer("FLT_Fcol")
|
|
|
|
self.mesh.activeColorLayer = "FLT_Fcol"
|
|
|
|
|
|
|
|
FLT_OrigIndex = 0
|
2006-07-28 19:09:09 +00:00
|
|
|
for flt_face in self.faceLs:
|
2007-11-22 01:43:24 +00:00
|
|
|
if flt_face.tex_index != -1:
|
|
|
|
try:
|
|
|
|
image= self.header.tex_pal[flt_face.tex_index][1]
|
|
|
|
except KeyError:
|
|
|
|
image= None
|
|
|
|
else:
|
|
|
|
image= None
|
2006-07-28 19:09:09 +00:00
|
|
|
face_len= len(flt_face.indices)
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#create dummy uvert dicts
|
|
|
|
if len(flt_face.uverts) == 0:
|
|
|
|
for i in xrange(face_len):
|
|
|
|
flt_face.uverts.append(dict())
|
|
|
|
#May need to patch up MTex info
|
|
|
|
if self.hasmtex:
|
|
|
|
#For every layer in mesh, there should be corresponding layer in the face
|
|
|
|
for mask in self.uvlayers.keys():
|
|
|
|
if self.uvlayers[mask]:
|
|
|
|
if not flt_face.uvlayers.has_key(mask): #Does the face have this layer?
|
|
|
|
#Create Layer info for this face
|
|
|
|
flt_face.uvlayers[mask] = dict()
|
|
|
|
flt_face.uvlayers[mask]['texture index'] = -1
|
|
|
|
flt_face.uvlayers[mask]['texture enviorment'] = 3
|
|
|
|
flt_face.uvlayers[mask]['texture mapping'] = 0
|
|
|
|
flt_face.uvlayers[mask]['texture data'] = 0
|
|
|
|
|
|
|
|
#now go through and create dummy uvs for this layer
|
|
|
|
for uvert in flt_face.uverts:
|
|
|
|
uv = Vector(0.0,0.0)
|
|
|
|
uvert[mask] = uv
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
# Get the indicies in reference to the mesh.
|
|
|
|
uvs= [vert_desc_lst[j].uv for j in flt_face.indices]
|
2007-11-22 01:43:24 +00:00
|
|
|
if face_len == 1:
|
|
|
|
pass
|
|
|
|
elif face_len == 2:
|
|
|
|
face_edges.append((vert_index, vert_index+1))
|
|
|
|
elif flt_face.props['draw type'] == 2 or flt_face.props['draw type'] == 3:
|
|
|
|
i = 0
|
|
|
|
while i < (face_len-1):
|
|
|
|
face_edges.append((vert_index + i, vert_index + i + 1))
|
|
|
|
i = i + 1
|
|
|
|
if flt_face.props['draw type'] == 2:
|
|
|
|
face_edges.append((vert_index + i,vert_index))
|
|
|
|
elif face_len == 3 or face_len == 4: # tri or quad
|
|
|
|
#if face_len == 1:
|
|
|
|
# pass
|
|
|
|
#if face_len == 2:
|
|
|
|
# face_edges.append((vert_index, vert_index+1))
|
2006-07-28 19:09:09 +00:00
|
|
|
new_faces.append( [i+vert_index for i in xrange(face_len)] )
|
2007-11-22 01:43:24 +00:00
|
|
|
new_faces_props.append((None, image, uvs, flt_face.uverts, flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,0, flt_face.subfacelevel))
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
else: # fgon
|
|
|
|
mesh_face_indicies = [i+vert_index for i in xrange(face_len)]
|
2007-11-22 01:43:24 +00:00
|
|
|
tri_ngons= ngon(self.mesh, mesh_face_indicies)
|
2008-05-24 18:43:02 +00:00
|
|
|
if len(tri_ngons) != 1:
|
|
|
|
new_faces.extend([ [mesh_face_indicies[t] for t in tri] for tri in tri_ngons])
|
|
|
|
new_faces_props.extend( [ (None, image, (uvs[tri[0]], uvs[tri[1]], uvs[tri[2]]), [flt_face.uverts[tri[0]], flt_face.uverts[tri[1]], flt_face.uverts[tri[2]]], flt_face.uvlayers, flt_face.color_index, flt_face.props,FLT_OrigIndex,1, flt_face.subfacelevel) for tri in tri_ngons ])
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
vert_index+= face_len
|
2007-11-22 01:43:24 +00:00
|
|
|
FLT_OrigIndex+=1
|
|
|
|
|
|
|
|
self.mesh.faces.extend(new_faces)
|
|
|
|
self.mesh.edges.extend(face_edges)
|
|
|
|
|
|
|
|
#add in the FLT_ORIGINDEX layer
|
|
|
|
if len(self.mesh.faces):
|
|
|
|
try: self.mesh.faceUV= True
|
|
|
|
except: pass
|
|
|
|
|
|
|
|
if self.mesh.faceUV == True:
|
|
|
|
self.mesh.renameUVLayer(self.mesh.activeUVLayer, 'Layer0')
|
|
|
|
|
|
|
|
#create name layer for faces
|
|
|
|
self.mesh.faces.addPropertyLayer("FLT_ID",Blender.Mesh.PropertyTypes["STRING"])
|
|
|
|
#create layer for face color indices
|
|
|
|
self.mesh.faces.addPropertyLayer("FLT_COL",Blender.Mesh.PropertyTypes["INT"])
|
|
|
|
#create index layer for faces. This is needed by both FGONs and subfaces
|
|
|
|
self.mesh.faces.addPropertyLayer("FLT_ORIGINDEX",Blender.Mesh.PropertyTypes["INT"])
|
|
|
|
#create temporary FGON flag layer. Delete after remove doubles
|
|
|
|
self.mesh.faces.addPropertyLayer("FLT_FGON",Blender.Mesh.PropertyTypes["INT"])
|
|
|
|
self.mesh.faces.addPropertyLayer("FLT_SFLEVEL", Blender.Mesh.PropertyTypes["INT"])
|
|
|
|
|
|
|
|
for i, f in enumerate(self.mesh.faces):
|
|
|
|
props = new_faces_props[i]
|
2008-01-09 19:51:22 +00:00
|
|
|
if props[6]['template billboard'] > 0:
|
|
|
|
f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
|
|
|
|
if props[6]['template billboard'] == 2:
|
|
|
|
f.mode |= Blender.Mesh.FaceModes["BILLBOARD"]
|
|
|
|
f.mode |= Blender.Mesh.FaceModes["LIGHT"]
|
2008-03-28 00:26:48 +00:00
|
|
|
if props[6]['draw type'] == 1:
|
|
|
|
f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
|
2008-01-09 19:51:22 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#f.mat = props[0]
|
|
|
|
f.image = props[1]
|
|
|
|
f.uv = props[2]
|
|
|
|
#set vertex colors
|
|
|
|
color = self.header.get_color(props[5])
|
|
|
|
if not color:
|
|
|
|
color = [255,255,255,255]
|
|
|
|
for mcol in f.col:
|
|
|
|
mcol.a = color[3]
|
|
|
|
mcol.r = color[0]
|
|
|
|
mcol.g = color[1]
|
|
|
|
mcol.b = color[2]
|
|
|
|
|
|
|
|
f.setProperty("FLT_SFLEVEL", props[9])
|
|
|
|
f.setProperty("FLT_ORIGINDEX",i)
|
|
|
|
f.setProperty("FLT_ID",props[6]['id'])
|
|
|
|
#if props[5] > 13199:
|
|
|
|
# print "Warning, invalid color index read in! Using default!"
|
|
|
|
# f.setProperty("FLT_COL",127)
|
|
|
|
#else:
|
|
|
|
if(1): #uh oh....
|
|
|
|
value = struct.unpack('>i',struct.pack('>I',props[5]))[0]
|
|
|
|
f.setProperty("FLT_COL",value)
|
|
|
|
|
|
|
|
#if props[8]:
|
|
|
|
# f.setProperty("FLT_FGON",1)
|
|
|
|
#else:
|
|
|
|
# f.setProperty("FLT_FGON",0)
|
|
|
|
|
|
|
|
|
|
|
|
#Create multitex layers, if present.
|
|
|
|
actuvlayer = self.mesh.activeUVLayer
|
|
|
|
if(self.hasmtex):
|
|
|
|
#For every multi-tex layer, we have to add a new UV layer to the mesh
|
|
|
|
for i,mask in enumerate(reversed(sorted(self.uvlayers))):
|
|
|
|
if self.uvlayers[mask]:
|
|
|
|
self.blayernames[mask] = "Layer" + str(i+1)
|
|
|
|
self.mesh.addUVLayer(self.blayernames[mask])
|
|
|
|
|
|
|
|
#Cycle through availible multi-tex layers and add face UVS
|
|
|
|
for mask in self.uvlayers:
|
|
|
|
if self.uvlayers[mask]:
|
|
|
|
self.mesh.activeUVLayer = self.blayernames[mask]
|
|
|
|
for j, f in enumerate(self.mesh.faces):
|
2008-03-28 00:26:48 +00:00
|
|
|
if props[6]['draw type'] == 1:
|
|
|
|
f.mode |= Blender.Mesh.FaceModes["TWOSIDE"]
|
2007-11-22 01:43:24 +00:00
|
|
|
f.transp |= Blender.Mesh.FaceTranspModes["ALPHA"]
|
|
|
|
f.mode |= Blender.Mesh.FaceModes["LIGHT"]
|
|
|
|
props = new_faces_props[j]
|
|
|
|
uvlayers = props[4]
|
|
|
|
if uvlayers.has_key(mask): #redundant
|
|
|
|
uverts = props[3]
|
|
|
|
for k, uv in enumerate(f.uv):
|
|
|
|
uv[0] = uverts[k][mask][0]
|
|
|
|
uv[1] = uverts[k][mask][1]
|
|
|
|
|
|
|
|
uvlayer = uvlayers[mask]
|
|
|
|
tex_index = uvlayer['texture index']
|
|
|
|
if tex_index != -1:
|
|
|
|
try:
|
|
|
|
f.image = self.header.tex_pal[tex_index][1]
|
|
|
|
except KeyError:
|
|
|
|
f.image = None
|
|
|
|
|
|
|
|
if global_prefs['smoothshading'] == True and len(self.mesh.faces):
|
|
|
|
#We need to store per-face vertex normals in the faces as UV layers and delete them later.
|
|
|
|
self.mesh.addUVLayer("FLTNorm1")
|
|
|
|
self.mesh.addUVLayer("FLTNorm2")
|
|
|
|
self.mesh.activeUVLayer = "FLTNorm1"
|
|
|
|
for f in self.mesh.faces:
|
|
|
|
f.smooth = 1
|
|
|
|
#grab the X and Y components of normal and store them in UV
|
|
|
|
for i, uv in enumerate(f.uv):
|
|
|
|
vert = f.v[i].index
|
|
|
|
vert_desc = vert_desc_lst[vert_list[vert-1]]
|
|
|
|
if vert_desc.cnorm:
|
|
|
|
uv[0] = vert_desc.nx
|
|
|
|
uv[1] = vert_desc.ny
|
|
|
|
else:
|
|
|
|
uv[0] = 0.0
|
|
|
|
uv[1] = 0.0
|
|
|
|
|
|
|
|
#Now go through and populate the second UV Layer with the z component
|
|
|
|
self.mesh.activeUVLayer = "FLTNorm2"
|
|
|
|
for f in self.mesh.faces:
|
|
|
|
for i, uv in enumerate(f.uv):
|
|
|
|
vert = f.v[i].index
|
|
|
|
vert_desc = vert_desc_lst[vert_list[vert-1]]
|
|
|
|
if vert_desc.cnorm:
|
|
|
|
uv[0] = vert_desc.nz
|
|
|
|
uv[1] = 0.0
|
|
|
|
else:
|
|
|
|
uv[0] = 0.0
|
|
|
|
uv[1] = 0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#Finally, go through, remove dummy vertex, remove doubles and add edgesplit modifier.
|
|
|
|
Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX'])
|
|
|
|
self.mesh.sel= 1
|
|
|
|
self.header.scene.update(1) #slow!
|
2008-03-26 16:45:18 +00:00
|
|
|
|
2008-03-26 15:59:56 +00:00
|
|
|
#self.mesh.remDoubles(0.0001)
|
|
|
|
weldmesh = self.buildWeldMesh()
|
2008-03-26 16:45:18 +00:00
|
|
|
welded = self.weldFuseFaces(weldmesh)
|
2008-03-26 15:59:56 +00:00
|
|
|
self.mesh.verts.delete(0) # remove the dummy vert
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
edgeHash = dict()
|
|
|
|
|
|
|
|
for edge in self.mesh.edges:
|
|
|
|
edgeHash[edge.key] = edge.index
|
|
|
|
|
|
|
|
|
|
|
|
if global_prefs['smoothshading'] == True and len(self.mesh.faces):
|
|
|
|
|
|
|
|
#rip out the custom vertex normals from the mesh and place them in a face aligned list. Easier to compare this way.
|
|
|
|
facenorms = []
|
|
|
|
self.mesh.activeUVLayer = "FLTNorm1"
|
|
|
|
for face in self.mesh.faces:
|
|
|
|
facenorm = []
|
|
|
|
for uv in face.uv:
|
|
|
|
facenorm.append(Vector(uv[0],uv[1],0.0))
|
|
|
|
facenorms.append(facenorm)
|
|
|
|
self.mesh.activeUVLayer = "FLTNorm2"
|
|
|
|
for i, face in enumerate(self.mesh.faces):
|
|
|
|
facenorm = facenorms[i]
|
|
|
|
for j, uv in enumerate(face.uv):
|
|
|
|
facenorm[j][2] = uv[0]
|
|
|
|
self.mesh.removeUVLayer("FLTNorm1")
|
|
|
|
self.mesh.removeUVLayer("FLTNorm2")
|
|
|
|
|
|
|
|
#find hard edges
|
|
|
|
#store edge data for lookup by faces
|
|
|
|
#edgeHash = dict()
|
|
|
|
#for edge in self.mesh.edges:
|
|
|
|
# edgeHash[edge.key] = edge.index
|
|
|
|
|
|
|
|
edgeNormHash = dict()
|
|
|
|
#make sure to align the edgenormals to key value!
|
|
|
|
for i, face in enumerate(self.mesh.faces):
|
|
|
|
|
|
|
|
facenorm = facenorms[i]
|
|
|
|
faceEdges = []
|
|
|
|
faceEdges.append((face.v[0].index,face.v[1].index,facenorm[0],facenorm[1],face.edge_keys[0]))
|
|
|
|
faceEdges.append((face.v[1].index,face.v[2].index,facenorm[1],facenorm[2],face.edge_keys[1]))
|
|
|
|
if len(face.v) == 3:
|
|
|
|
faceEdges.append((face.v[2].index,face.v[0].index,facenorm[2],facenorm[0],face.edge_keys[2]))
|
|
|
|
elif len(face.v) == 4:
|
|
|
|
faceEdges.append((face.v[2].index,face.v[3].index,facenorm[2],facenorm[3],face.edge_keys[2]))
|
|
|
|
faceEdges.append((face.v[3].index,face.v[0].index,facenorm[3],facenorm[0],face.edge_keys[3]))
|
|
|
|
|
|
|
|
#check to see if edgeNormal has been placed in the edgeNormHash yet
|
|
|
|
#this is a redundant test, and should be optimized to not be called as often as it is.
|
|
|
|
for j, faceEdge in enumerate(faceEdges):
|
|
|
|
#the value we are looking for is (faceEdge[2],faceEdge[3])
|
|
|
|
hashvalue = (faceEdge[2],faceEdge[3])
|
|
|
|
if (faceEdge[0],faceEdge[1]) != faceEdge[4]:
|
|
|
|
hashvalue = (hashvalue[1],hashvalue[0])
|
|
|
|
assert (faceEdge[1],faceEdge[0]) == faceEdge[4]
|
|
|
|
if edgeNormHash.has_key(faceEdge[4]):
|
|
|
|
#compare value in the hash, if different, mark as sharp
|
|
|
|
edgeNorm = edgeNormHash[faceEdge[4]]
|
|
|
|
if\
|
|
|
|
abs(hashvalue[0][0] - edgeNorm[0][0]) > FLOAT_TOLERANCE or\
|
|
|
|
abs(hashvalue[0][1] - edgeNorm[0][1]) > FLOAT_TOLERANCE or\
|
|
|
|
abs(hashvalue[0][2] - edgeNorm[0][2]) > FLOAT_TOLERANCE or\
|
|
|
|
abs(hashvalue[1][0] - edgeNorm[1][0]) > FLOAT_TOLERANCE or\
|
|
|
|
abs(hashvalue[1][1] - edgeNorm[1][1]) > FLOAT_TOLERANCE or\
|
|
|
|
abs(hashvalue[1][2] - edgeNorm[1][2]) > FLOAT_TOLERANCE:
|
|
|
|
edge = self.mesh.edges[edgeHash[faceEdge[4]]]
|
|
|
|
edge.flag |= Blender.Mesh.EdgeFlags.SHARP
|
|
|
|
|
|
|
|
else:
|
|
|
|
edgeNormHash[faceEdge[4]] = hashvalue
|
|
|
|
|
|
|
|
#add in edgesplit modifier
|
|
|
|
mod = self.object.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
|
|
|
|
mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = True
|
|
|
|
mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = False
|
|
|
|
|
|
|
|
if(actuvlayer):
|
|
|
|
self.mesh.activeUVLayer = actuvlayer
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
def blender_import(self):
|
2008-03-28 21:04:27 +00:00
|
|
|
if self.vis and self.parent.object:
|
2007-11-22 01:43:24 +00:00
|
|
|
self.vis = self.parent.vis
|
2006-07-28 08:17:04 +00:00
|
|
|
name = self.props['id']
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2008-03-28 00:08:41 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.hasMesh:
|
2006-07-28 08:17:04 +00:00
|
|
|
self.mesh = Blender.Mesh.New()
|
2007-11-22 01:43:24 +00:00
|
|
|
self.mesh.name = 'FLT_FaceList'
|
|
|
|
self.mesh.fakeUser = True
|
|
|
|
self.mesh.verts.extend( Vector()) #DUMMYVERT
|
|
|
|
self.object = self.header.scene.objects.new(self.mesh)
|
2006-07-28 08:17:04 +00:00
|
|
|
else:
|
2007-11-22 01:43:24 +00:00
|
|
|
self.object = self.header.scene.objects.new('Empty')
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.object.name = name
|
|
|
|
self.header.group.objects.link(self.object)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#id props import
|
|
|
|
self.object.properties['FLT'] = dict()
|
|
|
|
for key in self.props:
|
|
|
|
try:
|
|
|
|
self.object.properties['FLT'][key] = self.props[key]
|
|
|
|
except: #horrible...
|
|
|
|
pass
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2008-03-18 23:16:47 +00:00
|
|
|
|
2008-03-28 00:08:41 +00:00
|
|
|
if self.extension:
|
|
|
|
self.object.properties['FLT']['EXT'] = dict()
|
|
|
|
for key in self.extension:
|
|
|
|
self.object.properties['FLT']['EXT'][key] = self.extension[key]
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.parent and self.parent.object and (self.header.scene == self.parent.header.scene):
|
2008-03-18 23:16:47 +00:00
|
|
|
self.parent.object.makeParent([self.object],1)
|
|
|
|
|
|
|
|
if self.matrix:
|
|
|
|
self.object.setMatrix(self.matrix)
|
2008-03-28 21:04:27 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.vis == False:
|
|
|
|
self.object.restrictDisplay = True
|
|
|
|
self.object.restrictRender = True
|
|
|
|
|
|
|
|
else: #check for LOD children and set the proper flags
|
|
|
|
lodlist = list()
|
|
|
|
for child in self.children:
|
|
|
|
if child.props.has_key('type') and child.props['type'] == 73:
|
2008-03-28 21:04:27 +00:00
|
|
|
if child.props['6d!switch out'] != 0.0:
|
2008-03-28 00:30:46 +00:00
|
|
|
child.vis = False
|
|
|
|
#lodlist.append(child)
|
|
|
|
|
|
|
|
#def LODmin(a,b):
|
|
|
|
# if a.props['5d!switch in'] < b.props['5d!switch in']:
|
|
|
|
# return a
|
|
|
|
# return b
|
|
|
|
|
|
|
|
#min= None
|
|
|
|
#if len(lodlist) > 1:
|
|
|
|
# for lod in lodlist:
|
|
|
|
# lod.vis = False
|
|
|
|
# min = lodlist[0]
|
|
|
|
# for i in xrange(len(lodlist)):
|
|
|
|
# min= LODmin(min,lodlist[i])
|
|
|
|
# min.vis = True
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
Node.blender_import(self) # Attach faces to self.faceLs
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.hasMesh:
|
2006-07-28 19:09:09 +00:00
|
|
|
# Add all my faces into the mesh at once
|
|
|
|
self.blender_import_my_faces()
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
def parse_face(self):
|
2007-11-22 01:43:24 +00:00
|
|
|
child = Face(self, self.subfacelevel)
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def parse_dof(self):
|
|
|
|
child = DOF(self)
|
|
|
|
child.parse()
|
|
|
|
return True
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
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])
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def parse_subpush(self):
|
|
|
|
self.parse_push()
|
|
|
|
self.subfacelevel+= 1
|
|
|
|
return True
|
|
|
|
def parse_subpop(self):
|
|
|
|
self.parse_pop()
|
|
|
|
self.subfacelevel -= 1
|
|
|
|
return True
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class Face(Node):
|
2007-11-22 01:43:24 +00:00
|
|
|
def __init__(self, parent,subfacelevel):
|
2006-07-28 19:09:09 +00:00
|
|
|
Node.__init__(self, parent, parent.header)
|
|
|
|
self.root_handler.set_handler({31: self.parse_comment,
|
2007-11-22 01:43:24 +00:00
|
|
|
10: self.parse_push,
|
|
|
|
52: self.parse_multitex})
|
2006-07-28 19:09:09 +00:00
|
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
|
|
|
|
self.child_handler.set_handler({72: self.parse_vertex_list,
|
|
|
|
10: self.parse_push,
|
2007-11-22 01:43:24 +00:00
|
|
|
11: self.parse_pop,
|
|
|
|
53: self.parse_uvlist})
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
if parent:
|
2007-11-22 01:43:24 +00:00
|
|
|
parent.hasMesh = True
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.subfacelevel = subfacelevel
|
|
|
|
self.indices = list() # face verts here
|
|
|
|
self.uvlayers = dict() # MultiTexture layers keyed to layer bitmask.
|
|
|
|
self.uverts = list() # Vertex aligned list of dictionaries keyed to layer bitmask.
|
|
|
|
self.uvmask = 0 # Bitfield read from MTex record
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
self.comment = ''
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
|
|
|
self.props['id'] = self.header.fw.read_string(8)
|
2006-07-28 19:09:09 +00:00
|
|
|
# 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()
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
def parse_comment(self):
|
|
|
|
self.comment = self.header.fw.read_string(self.header.fw.get_length()-4)
|
|
|
|
return True
|
|
|
|
|
|
|
|
def blender_import(self):
|
|
|
|
vert_count = len(self.indices)
|
2007-11-22 01:43:24 +00:00
|
|
|
if vert_count < 1:
|
2006-07-28 08:17:04 +00:00
|
|
|
if global_prefs['verbose'] >= 2:
|
|
|
|
print 'Warning: Ignoring face with no vertices.'
|
|
|
|
return
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# Assign material and image
|
|
|
|
|
|
|
|
self.parent.faceLs.append(self)
|
2007-11-22 01:43:24 +00:00
|
|
|
#need to store comment in mesh prop layer!
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
# Store comment info in parent.
|
2007-11-22 01:43:24 +00:00
|
|
|
#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
|
|
|
|
|
|
|
|
if self.uvlayers:
|
|
|
|
#Make sure that the mesh knows about the layers that this face uses
|
|
|
|
self.parent.hasmtex = True
|
|
|
|
for mask in self.uvlayers.keys():
|
|
|
|
self.parent.uvlayers[mask] = True
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
return True
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
def parse_multitex(self):
|
|
|
|
#Parse MultiTex Record.
|
|
|
|
length = self.header.fw.get_length()
|
|
|
|
fw = self.header.fw
|
|
|
|
#num layers == (length - 8) / 4
|
|
|
|
uvmask = fw.read_uint()
|
|
|
|
mask = 2147483648
|
|
|
|
for i in xrange(7):
|
|
|
|
if mask & uvmask:
|
|
|
|
uvlayer = dict()
|
|
|
|
self.uvlayers[mask] = uvlayer
|
|
|
|
mask = mask / 2
|
|
|
|
|
|
|
|
#read in record for each individual layer.
|
|
|
|
for key in reversed(sorted(self.uvlayers)):
|
|
|
|
uvlayer = self.uvlayers[key]
|
|
|
|
uvlayer['texture index'] = fw.read_ushort()
|
|
|
|
uvlayer['texture enviorment'] = fw.read_ushort()
|
|
|
|
uvlayer['texture mapping'] = fw.read_ushort()
|
|
|
|
uvlayer['texture data'] = fw.read_ushort()
|
|
|
|
|
|
|
|
self.uvmask = uvmask
|
|
|
|
|
|
|
|
def parse_uvlist(self):
|
|
|
|
#for each uvlayer, add uv vertices
|
|
|
|
length = self.header.fw.get_length()
|
|
|
|
fw = self.header.fw
|
|
|
|
uvmask = fw.read_uint()
|
|
|
|
if uvmask != self.uvmask: #This should never happen!
|
|
|
|
fw.read_ahead(self.length - 4) #potentially unnessecary?
|
|
|
|
else:
|
|
|
|
#need to store in uvverts dictionary for each vertex.
|
|
|
|
totverts = len(self.indices)
|
|
|
|
for i in xrange(totverts):
|
|
|
|
uvert = dict()
|
|
|
|
for key in reversed(sorted(self.uvlayers)):
|
|
|
|
uv = Vector(0.0,0.0)
|
|
|
|
uv[0] = fw.read_float()
|
|
|
|
uv[1] = fw.read_float()
|
|
|
|
uvert[key] = uv
|
|
|
|
self.uverts.append(uvert)
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class Object(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
def __init__(self, parent):
|
|
|
|
Node.__init__(self, parent, parent.header)
|
|
|
|
InterNode.__init__(self)
|
|
|
|
|
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
2008-03-28 00:08:41 +00:00
|
|
|
21: self.parse_push_extension,
|
|
|
|
31: self.parse_comment,
|
|
|
|
10: self.parse_push,
|
|
|
|
49: self.parse_matrix})
|
2006-07-28 08:17:04 +00:00
|
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
|
|
|
|
self.child_handler.set_handler({5: self.parse_face,
|
2007-11-22 01:43:24 +00:00
|
|
|
19: self.parse_subpush,
|
|
|
|
20: self.parse_subpop,
|
|
|
|
111: self.parse_inline_light_point,
|
2006-07-28 08:17:04 +00:00
|
|
|
10: self.parse_push,
|
|
|
|
11: self.parse_pop})
|
2008-03-28 00:08:41 +00:00
|
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension,
|
|
|
|
100: self.parse_extension})
|
|
|
|
|
|
|
|
self.extension = dict()
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
|
|
|
self.props['comment'] = ''
|
|
|
|
self.parse_record()
|
2006-07-28 08:59:44 +00:00
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class Group(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
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,
|
2008-03-28 00:08:41 +00:00
|
|
|
49: self.parse_matrix,
|
|
|
|
21: self.parse_push_extension})
|
2006-07-28 08:17:04 +00:00
|
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
|
|
|
|
self.child_handler.set_handler({5: self.parse_face,
|
2007-11-22 01:43:24 +00:00
|
|
|
19: self.parse_subpush,
|
|
|
|
20: self.parse_subpop,
|
|
|
|
111: self.parse_inline_light_point,
|
2006-07-28 08:17:04 +00:00
|
|
|
2: self.parse_group,
|
|
|
|
73: self.parse_lod,
|
|
|
|
4: self.parse_object,
|
|
|
|
10: self.parse_push,
|
|
|
|
11: self.parse_pop,
|
|
|
|
96: self.parse_unhandled,
|
2007-11-22 01:43:24 +00:00
|
|
|
14: self.parse_dof,
|
2006-07-28 08:17:04 +00:00
|
|
|
91: self.parse_unhandled,
|
|
|
|
98: self.parse_unhandled,
|
|
|
|
63: self.parse_xref})
|
2008-03-28 00:08:41 +00:00
|
|
|
|
|
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension,
|
|
|
|
100: self.parse_extension})
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.props = dict.fromkeys(['type', 'id', 'comment', 'priority', 'flags', 'special1',
|
|
|
|
'special2', 'significance', 'layer code', 'loop count',
|
|
|
|
'loop duration', 'last frame duration'])
|
|
|
|
|
|
|
|
self.props['comment'] = ''
|
2007-11-22 01:43:24 +00:00
|
|
|
self.parse_record()
|
|
|
|
|
|
|
|
#self.props['type'] = str(self.opcode) + ':' + opcode_name[self.opcode]
|
|
|
|
#props = records[self.opcode]
|
|
|
|
#propkeys = props.keys()
|
|
|
|
#propkeys.sort()
|
|
|
|
#for position in propkeys:
|
|
|
|
# (type,length,name) = props[position]
|
|
|
|
# self.props[name] = read_prop(self.header.fw,type,length)
|
|
|
|
#self.props['id'] = self.props['3t8!id']
|
|
|
|
|
|
|
|
class DOF(InterNode):
|
|
|
|
def blender_import(self):
|
|
|
|
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,
|
2008-03-28 00:08:41 +00:00
|
|
|
49: self.parse_matrix,
|
|
|
|
21: self.parse_push_extension})
|
2007-11-22 01:43:24 +00:00
|
|
|
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_dof,
|
|
|
|
91: self.parse_unhandled,
|
|
|
|
98: self.parse_unhandled,
|
|
|
|
63: self.parse_xref})
|
2008-03-28 00:08:41 +00:00
|
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension,
|
|
|
|
100: self.parse_extension})
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
|
|
|
self.props['comment'] = ''
|
|
|
|
self.parse_record()
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class XRef(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
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)
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.root_handler.set_handler({49: self.parse_matrix})
|
|
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
|
|
|
self.props['comment'] = ''
|
|
|
|
self.parse_record()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2008-03-19 19:23:42 +00:00
|
|
|
xref_filename = self.props['3t200!filename'] #I dont even think there is a reason to keep this around...
|
|
|
|
|
|
|
|
if not os.path.isabs(xref_filename):
|
|
|
|
absname = os.path.join(os.path.dirname(self.header.filename), xref_filename)
|
|
|
|
else:
|
|
|
|
absname = xref_filename
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props['id'] = 'X: ' + Blender.sys.splitext(Blender.sys.basename(xref_filename))[0] #this is really wrong as well....
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2008-03-19 19:23:42 +00:00
|
|
|
if global_prefs['doxrefs'] and os.path.exists(absname) and not self.header.grr.xrefs.has_key(xref_filename):
|
|
|
|
self.xref = Database(absname, self.header.grr, self)
|
2007-11-22 01:43:24 +00:00
|
|
|
self.header.grr.xrefs[xref_filename] = self.xref
|
2006-07-28 08:17:04 +00:00
|
|
|
else:
|
|
|
|
self.xref = None
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
def blender_import(self):
|
|
|
|
#name = self.props['type'] + ': ' + self.props['id']
|
|
|
|
name = self.props['id']
|
|
|
|
self.object = self.header.scene.objects.new('Empty')
|
|
|
|
self.object.name = name
|
|
|
|
self.object.enableDupGroup = True
|
|
|
|
self.header.group.objects.link(self.object)
|
|
|
|
|
|
|
|
#for broken links its ok to leave this empty! they purely for visual purposes anyway.....
|
|
|
|
try:
|
|
|
|
self.object.DupGroup = self.header.grr.xrefs[self.props['3t200!filename']].group
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2008-03-18 23:16:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.parent and self.parent.object:
|
2008-03-18 23:16:47 +00:00
|
|
|
self.parent.object.makeParent([self.object],1)
|
|
|
|
|
|
|
|
if self.matrix:
|
|
|
|
self.object.setMatrix(self.matrix)
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#id props import
|
|
|
|
self.object.properties['FLT'] = dict()
|
|
|
|
for key in self.props:
|
|
|
|
try:
|
|
|
|
self.object.properties['FLT'][key] = self.props[key]
|
|
|
|
except: #horrible...
|
|
|
|
pass
|
|
|
|
|
|
|
|
self.object.Layer = current_layer
|
|
|
|
self.object.sel = 1
|
2008-03-18 23:16:47 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
Node.blender_import(self)
|
|
|
|
|
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class LOD(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
def blender_import(self):
|
2007-11-22 01:43:24 +00:00
|
|
|
#self.move_to_next_layer()
|
2006-07-28 08:17:04 +00:00
|
|
|
InterNode.blender_import(self)
|
2007-11-22 01:43:24 +00:00
|
|
|
#self.object.properties['FLT'] = self.props.copy()
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
def __init__(self, parent):
|
|
|
|
Node.__init__(self, parent, parent.header)
|
|
|
|
InterNode.__init__(self)
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.root_handler.set_handler({33: self.parse_long_id,
|
|
|
|
31: self.parse_comment,
|
|
|
|
10: self.parse_push,
|
2008-03-28 00:08:41 +00:00
|
|
|
49: self.parse_matrix,
|
|
|
|
21: self.parse_push_extension})
|
2006-07-28 08:17:04 +00:00
|
|
|
self.root_handler.set_throw_back_lst(throw_back_opcodes)
|
|
|
|
|
|
|
|
self.child_handler.set_handler({2: self.parse_group,
|
2007-11-22 01:43:24 +00:00
|
|
|
111: self.parse_inline_light_point,
|
2006-07-28 08:17:04 +00:00
|
|
|
73: self.parse_lod,
|
|
|
|
4: self.parse_object,
|
|
|
|
10: self.parse_push,
|
|
|
|
11: self.parse_pop,
|
|
|
|
96: self.parse_unhandled, # switch
|
2007-11-22 01:43:24 +00:00
|
|
|
14: self.parse_dof, # DOF
|
2006-07-28 08:17:04 +00:00
|
|
|
91: self.parse_unhandled, # sound
|
|
|
|
98: self.parse_unhandled, # clip
|
|
|
|
63: self.parse_xref})
|
2008-03-28 00:08:41 +00:00
|
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension,
|
|
|
|
100: self.parse_extension})
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
|
|
|
self.props['comment'] = ''
|
|
|
|
self.parse_record()
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class InlineLightPoint(InterNode):
|
2006-07-28 19:09:09 +00:00
|
|
|
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,
|
2008-03-28 00:08:41 +00:00
|
|
|
21: self.parse_push_extension,
|
2006-07-28 19:09:09 +00:00
|
|
|
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})
|
2008-03-28 00:08:41 +00:00
|
|
|
self.extension_handler.set_handler({22: self.parse_pop_extension,
|
|
|
|
100: self.parse_extension})
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
self.indices = list()
|
2007-11-22 01:43:24 +00:00
|
|
|
self.props = dict()
|
2006-07-28 19:09:09 +00:00
|
|
|
self.props['comment'] = ''
|
2007-11-22 01:43:24 +00:00
|
|
|
self.parse_record()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
def blender_import(self):
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
name = self.props['id']
|
|
|
|
self.mesh= Blender.Mesh.New()
|
|
|
|
self.mesh.name = 'FLT_LP'
|
|
|
|
self.object = self.header.scene.objects.new(self.mesh)
|
|
|
|
self.object.name = name
|
|
|
|
#self.mesh.verts.extend(Vector() ) # DUMMYVERT
|
|
|
|
self.object.Layer = current_layer
|
|
|
|
self.object.sel= 1
|
|
|
|
|
|
|
|
self.object.properties['FLT'] = dict()
|
|
|
|
for key in self.props:
|
|
|
|
try:
|
|
|
|
self.object.properties['FLT'][key] = self.props[key]
|
|
|
|
except: #horrible...
|
|
|
|
pass
|
|
|
|
|
2008-03-28 00:08:41 +00:00
|
|
|
if self.extension:
|
|
|
|
self.object.properties['FLT']['EXT'] = dict()
|
|
|
|
for key in self.extension:
|
|
|
|
self.object.properties['FLT']['EXT'][key] = self.extension[key]
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.parent and self.parent.object and self.header.scene == self.parent.header.scene:
|
|
|
|
self.parent.object.makeParent([self.object])
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if self.matrix:
|
|
|
|
self.object.setMatrix(self.matrix)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.mesh.verts.extend([self.header.vert_pal.blender_verts[i] for i in self.indices])
|
|
|
|
|
|
|
|
#add color index information.
|
|
|
|
self.mesh.verts.addPropertyLayer("FLT_VCOL",Blender.Mesh.PropertyTypes["INT"])
|
|
|
|
for i, vindex in enumerate(self.indices):
|
|
|
|
vdesc = self.header.vert_pal.vert_desc_lst[vindex]
|
|
|
|
v = self.mesh.verts[i]
|
|
|
|
v.setProperty("FLT_VCOL",vdesc.cindex)
|
|
|
|
#for i, v in enumerate(self.mesh.verts):
|
|
|
|
# vdesc = self.header.vert_pal.vert_desc_lst[i]
|
|
|
|
# v.setProperty("FLT_VCOL",vdesc.cindex)
|
|
|
|
self.mesh.update()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
|
|
|
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2006-01-10 13:42:20 +00:00
|
|
|
class IndexedLightPoint(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
# 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})
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
app_name = self.header.grr.request_lightpoint_app(app_desc, self.header.scene)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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= Blender.Mesh.New()
|
2006-07-28 19:09:09 +00:00
|
|
|
self.mesh.verts.extend( Vector() ) # DUMMYVERT
|
2006-07-28 08:17:04 +00:00
|
|
|
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)
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.header.scene.objects.link(self.object)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
|
|
|
|
# If this ever fails the chunk below does error checking
|
|
|
|
self.indices= [vert_pal.index[fw.read_int()] for i in xrange(count)]
|
|
|
|
|
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2006-07-28 19:09:09 +00:00
|
|
|
'''
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class Unhandled(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2007-11-22 01:43:24 +00:00
|
|
|
14: self.parse_dof, # DOF
|
2006-07-28 08:17:04 +00:00
|
|
|
91: self.parse_unhandled, # sound
|
|
|
|
98: self.parse_unhandled, # clip
|
|
|
|
63: self.parse_xref})
|
|
|
|
|
|
|
|
self.props['id'] = self.header.fw.read_string(8)
|
2006-01-10 13:42:20 +00:00
|
|
|
|
|
|
|
class Database(InterNode):
|
2006-07-28 08:17:04 +00:00
|
|
|
def blender_import(self):
|
2007-11-22 01:43:24 +00:00
|
|
|
for key in self.tex_pal.keys():
|
|
|
|
path_filename= FF.find(self.tex_pal[key][0])
|
2006-07-28 08:17:04 +00:00
|
|
|
if path_filename != None:
|
2007-11-22 01:43:24 +00:00
|
|
|
img = self.grr.request_image(path_filename)
|
2006-07-28 08:17:04 +00:00
|
|
|
if img:
|
2007-11-22 01:43:24 +00:00
|
|
|
self.tex_pal[key][1] = img
|
2006-07-28 08:17:04 +00:00
|
|
|
elif global_prefs['verbose'] >= 1:
|
2007-11-22 01:43:24 +00:00
|
|
|
print 'Warning: Unable to find', self.tex_pal[key][0]
|
|
|
|
|
|
|
|
self.scene.properties['FLT'] = dict()
|
|
|
|
for key in self.props:
|
|
|
|
try:
|
|
|
|
self.scene.properties['FLT'][key] = self.props[key]
|
|
|
|
except: #horrible...
|
|
|
|
pass
|
|
|
|
|
|
|
|
self.scene.properties['FLT']['Main'] = 0
|
|
|
|
self.scene.properties['FLT']['Filename'] = self.bname
|
|
|
|
|
2008-03-28 21:04:27 +00:00
|
|
|
for child in self.children:
|
|
|
|
if child.props.has_key('type') and child.props['type'] == 73:
|
|
|
|
if child.props['6d!switch out'] != 0.0:
|
|
|
|
child.vis = False
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#import color palette
|
|
|
|
carray = list()
|
|
|
|
for color in self.col_pal:
|
|
|
|
carray.append(struct.unpack('>i',struct.pack('>BBBB',color[0],color[1],color[2],color[3]))[0])
|
|
|
|
self.scene.properties['FLT']['Color Palette'] = carray
|
|
|
|
Node.blender_import(self)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
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):
|
2007-11-22 01:43:24 +00:00
|
|
|
color = None
|
2006-07-28 08:17:04 +00:00
|
|
|
index = color_index / 128
|
|
|
|
intensity = float(color_index - 128.0 * index) / 127.0
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
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]
|
2007-11-22 01:43:24 +00:00
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
2007-11-22 01:43:24 +00:00
|
|
|
self.tex_pal[index]= [name, None]
|
2006-07-28 08:17:04 +00:00
|
|
|
return True
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
def read_attribute_files(self):
|
|
|
|
for tex in self.tex_pal.keys():
|
|
|
|
[name,image] = self.tex_pal[tex]
|
|
|
|
basename = os.path.basename(name)
|
|
|
|
if(image):
|
|
|
|
basename = basename + ".attr"
|
|
|
|
dirname = os.path.dirname(Blender.sys.expandpath(image.getFilename())) #can't rely on original info stored in pallette since it might be relative link
|
|
|
|
newpath = os.path.join(dirname, basename)
|
|
|
|
if os.path.exists(newpath) and not image.properties.has_key('FLT'):
|
|
|
|
fw = flt_filewalker.FltIn(newpath)
|
|
|
|
fw.read_ahead(8) #We dont care what the attribute file says about x/y dimensions
|
|
|
|
image.properties['FLT']={}
|
|
|
|
|
|
|
|
#need to steal code from parse records....
|
|
|
|
props = records['Image']
|
|
|
|
propkeys = props.keys()
|
|
|
|
propkeys.sort()
|
|
|
|
for position in propkeys:
|
|
|
|
(type,length,name) = props[position]
|
|
|
|
image.properties['FLT'][name] = read_prop(fw,type,length)
|
|
|
|
fw.close_file()
|
|
|
|
|
|
|
|
#copy clamp settings
|
|
|
|
wrap = image.properties['FLT']['10i!Wrap']
|
|
|
|
wrapu = image.properties['FLT']['11i!WrapU']
|
|
|
|
wrapv = image.properties['FLT']['12i!WrapV']
|
|
|
|
|
|
|
|
if wrapu == 3 or wrapv == 3:
|
|
|
|
wrapuv = (wrap,wrap)
|
|
|
|
else:
|
|
|
|
wrapuv = (wrapu, wrapv)
|
|
|
|
image.clampX = wrapuv[0]
|
|
|
|
image.clampY = wrapuv[1]
|
|
|
|
|
|
|
|
elif not os.path.exists(newpath):
|
|
|
|
print "Cannot read attribute file:" + newpath
|
|
|
|
|
|
|
|
def __init__(self, filename, grr, parent=None):
|
2006-07-28 08:17:04 +00:00
|
|
|
if global_prefs['verbose'] >= 1:
|
|
|
|
print 'Parsing:', filename
|
|
|
|
print
|
|
|
|
|
2008-03-19 19:23:42 +00:00
|
|
|
#check to see if filename is a relative path
|
|
|
|
#filename = os.path.abspath(filename)
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.fw = flt_filewalker.FltIn(filename)
|
2007-11-22 01:43:24 +00:00
|
|
|
self.filename = filename
|
|
|
|
self.bname = os.path.splitext(os.path.basename(filename))[0]
|
|
|
|
self.grr = grr
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
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,
|
2007-11-22 01:43:24 +00:00
|
|
|
111: self.parse_inline_light_point,
|
2006-07-28 08:17:04 +00:00
|
|
|
2: self.parse_group,
|
|
|
|
73: self.parse_lod,
|
|
|
|
4: self.parse_object,
|
|
|
|
10: self.parse_push,
|
|
|
|
11: self.parse_pop,
|
|
|
|
96: self.parse_unhandled,
|
2007-11-22 01:43:24 +00:00
|
|
|
14: self.parse_dof,
|
2006-07-28 08:17:04 +00:00
|
|
|
91: self.parse_unhandled,
|
|
|
|
98: self.parse_unhandled,
|
|
|
|
63: self.parse_xref})
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
self.scene = Blender.Scene.New(self.bname)
|
|
|
|
self.group = Blender.Group.New(self.bname)
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
self.vert_pal = None
|
|
|
|
self.lightpoint_appearance_pal = dict()
|
|
|
|
self.tex_pal = dict()
|
2007-11-22 01:43:24 +00:00
|
|
|
#self.tex_pal_lst = list()
|
|
|
|
#self.bl_tex_pal = dict()
|
2006-07-28 08:17:04 +00:00
|
|
|
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'])
|
2006-01-10 13:42:20 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
|
|
|
|
def clearparent(root,childhash):
|
|
|
|
for child in childhash[root]:
|
|
|
|
clearparent(child,childhash)
|
|
|
|
root.clrParent(2,0)
|
|
|
|
|
|
|
|
def fixscale(root,childhash):
|
|
|
|
for child in childhash[root]:
|
|
|
|
fixscale(child,childhash)
|
|
|
|
location = Blender.Mathutils.Vector(root.getLocation('worldspace'))
|
2008-03-18 23:16:47 +00:00
|
|
|
if location[0] != 0.0 or location[1] != 0.0 or location[2] != 0.0:
|
2007-11-22 01:43:24 +00:00
|
|
|
#direction = Blender.Mathutils.Vector(0-location[0],0-location[1],0-location[2]) #reverse vector
|
|
|
|
smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
|
|
|
|
root.setLocation(location * smat)
|
|
|
|
#if its a mesh, we need to scale all of its vertices too
|
|
|
|
if root.type == 'Mesh':
|
|
|
|
smat = Blender.Mathutils.ScaleMatrix(global_prefs['scale'],4)
|
|
|
|
rmesh = root.getData(mesh=True)
|
|
|
|
for v in rmesh.verts:
|
|
|
|
v.co = v.co * smat
|
|
|
|
|
|
|
|
def reparent(root,childhash,sce):
|
|
|
|
for child in childhash[root]:
|
|
|
|
reparent(child,childhash,sce)
|
|
|
|
|
|
|
|
root.makeParent(childhash[root])
|
|
|
|
sce.update(1)
|
|
|
|
|
|
|
|
def update_scene(root,sdone):
|
|
|
|
for object in root.objects:
|
|
|
|
if object.DupGroup:
|
|
|
|
try:
|
|
|
|
child = Blender.Scene.Get(object.DupGroup.name)
|
|
|
|
except:
|
|
|
|
child = None
|
|
|
|
if child and child not in sdone:
|
|
|
|
update_scene(child,sdone)
|
|
|
|
root.makeCurrent()
|
|
|
|
#create a list of children for each object
|
|
|
|
childhash = dict()
|
|
|
|
for object in root.objects:
|
|
|
|
childhash[object] = list()
|
|
|
|
|
|
|
|
for object in root.objects:
|
|
|
|
if object.parent:
|
|
|
|
childhash[object.parent].append(object)
|
|
|
|
|
|
|
|
for object in root.objects:
|
|
|
|
if not object.parent:
|
|
|
|
#recursivley go through and clear all the children of their transformation, starting at deepest level first.
|
|
|
|
clearparent(object,childhash)
|
|
|
|
#now fix the location of everything
|
|
|
|
fixscale(object,childhash)
|
|
|
|
#now fix the parenting
|
|
|
|
reparent(object,childhash,root)
|
|
|
|
|
|
|
|
for object in root.objects:
|
|
|
|
object.makeDisplayList()
|
|
|
|
root.update(1)
|
|
|
|
sdone.append(root)
|
|
|
|
|
|
|
|
|
|
|
|
def select_file(filename, grr):
|
2006-07-28 08:17:04 +00:00
|
|
|
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
|
2007-11-22 01:43:24 +00:00
|
|
|
global_prefs['log to blender'] = True
|
|
|
|
|
|
|
|
|
2006-07-28 08:17:04 +00:00
|
|
|
|
|
|
|
Blender.Window.WaitCursor(True)
|
|
|
|
Blender.Window.EditMode(0)
|
|
|
|
|
|
|
|
|
|
|
|
FF.add_file_to_search_path(filename)
|
|
|
|
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
|
|
print 'Pass 1: Loading.'
|
|
|
|
print
|
|
|
|
|
|
|
|
load_time = Blender.sys.time()
|
2007-11-22 01:43:24 +00:00
|
|
|
db = Database(filename,grr)
|
2006-07-28 08:17:04 +00:00
|
|
|
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()
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
if global_prefs['attrib']:
|
|
|
|
print "reading attribute files"
|
|
|
|
db.read_attribute_files()
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
Blender.Window.ViewLayer(range(1,21))
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
update_scene(db.scene,[])
|
|
|
|
import_time = Blender.sys.time() - import_time
|
2006-07-28 08:17:04 +00:00
|
|
|
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)
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def setimportscale(ID,val):
|
|
|
|
global global_prefs
|
|
|
|
global_prefs['scale'] = val
|
|
|
|
def setBpath(fname):
|
|
|
|
global_prefs['fltfile'] = fname
|
2008-03-28 23:06:00 +00:00
|
|
|
d = dict()
|
|
|
|
for key in global_prefs:
|
|
|
|
d[key] = global_prefs[key]
|
|
|
|
Blender.Registry.SetKey('flt_import', d, 1)
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def event(evt,val):
|
|
|
|
pass
|
2008-05-15 19:35:17 +00:00
|
|
|
|
|
|
|
from Blender.BGL import *
|
|
|
|
from Blender import Draw
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def but_event(evt):
|
|
|
|
|
|
|
|
global FLTBaseLabel
|
|
|
|
global FLTBaseString
|
|
|
|
global FLTBaseChooser
|
2006-07-28 08:17:04 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
global FLTExport
|
|
|
|
global FLTClose
|
|
|
|
|
|
|
|
global FLTDoXRef
|
|
|
|
global FLTShadeImport
|
|
|
|
global FLTAttrib
|
|
|
|
|
2008-05-15 19:35:17 +00:00
|
|
|
global FLTWarn
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#Import DB
|
|
|
|
if evt == 1:
|
|
|
|
if global_prefs['verbose'] >= 1:
|
|
|
|
print
|
|
|
|
print 'OpenFlight Importer'
|
|
|
|
print 'Version:', __version__
|
|
|
|
print 'Author: Greg MacDonald, Campbell Barton, Geoffrey Bantle'
|
|
|
|
print __url__[2]
|
|
|
|
print
|
|
|
|
|
|
|
|
GRR = GlobalResourceRepository()
|
2008-05-15 19:35:17 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
select_file(global_prefs['fltfile'], GRR)
|
|
|
|
except:
|
|
|
|
import traceback
|
2008-05-24 18:43:02 +00:00
|
|
|
FLTWarn = Draw.PupBlock("Ixport Error", ["See console for output!"])
|
2008-05-15 19:35:17 +00:00
|
|
|
traceback.print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)
|
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
#choose base path for export
|
|
|
|
if evt == 4:
|
|
|
|
Blender.Window.FileSelector(setBpath, "DB Root", global_prefs['fltfile'])
|
|
|
|
#Import custom shading?
|
|
|
|
if evt == 9:
|
|
|
|
global_prefs['smoothshading'] = FLTShadeImport.val
|
|
|
|
#Import Image attribute files
|
|
|
|
if evt == 10:
|
|
|
|
global_prefs['attrib'] = FLTAttrib.val
|
|
|
|
#export XRefs
|
|
|
|
if evt == 13:
|
|
|
|
global_prefs['doxrefs'] = FLTDoXRef.val
|
|
|
|
|
|
|
|
if evt == 2:
|
|
|
|
Draw.Exit()
|
|
|
|
|
2008-03-28 23:06:00 +00:00
|
|
|
d = dict()
|
|
|
|
for key in global_prefs:
|
|
|
|
d[key] = global_prefs[key]
|
|
|
|
Blender.Registry.SetKey('flt_import', d, 1)
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
def gui():
|
|
|
|
|
|
|
|
global FLTBaseLabel
|
|
|
|
global FLTBaseString
|
|
|
|
global FLTBaseChooser
|
2006-07-28 19:09:09 +00:00
|
|
|
|
2007-11-22 01:43:24 +00:00
|
|
|
global FLTExport
|
|
|
|
global FLTClose
|
|
|
|
|
|
|
|
global FLTDoXRef
|
|
|
|
global FLTShadeImport
|
|
|
|
|
|
|
|
global FLTAttrib
|
|
|
|
|
|
|
|
|
|
|
|
glClearColor(0.772,0.832,0.847,1.0)
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT)
|
|
|
|
|
|
|
|
areas = Blender.Window.GetScreenInfo()
|
|
|
|
curarea = Blender.Window.GetAreaID()
|
|
|
|
curRect = None
|
|
|
|
|
|
|
|
for area in areas:
|
|
|
|
if area['id'] == curarea:
|
|
|
|
curRect = area['vertices']
|
|
|
|
break
|
|
|
|
|
|
|
|
width = curRect[2] - curRect[0]
|
|
|
|
height = curRect[3] - curRect[1]
|
|
|
|
cx = 50
|
|
|
|
cy = height - 80
|
|
|
|
|
|
|
|
FLTBaseLabel = Draw.Label("Base file:",cx,cy,100,20)
|
|
|
|
FLTBaseString = Draw.String("",3,cx+100,cy,300,20,global_prefs['fltfile'],255,"Root DB file")
|
|
|
|
FLTBaseChooser = Draw.PushButton("...",4,cx+400,cy,20,20,"Choose Folder")
|
|
|
|
|
|
|
|
cy = cy-40
|
|
|
|
FLTScale = Draw.Number("Import Scale",14,cx,cy,220,20,global_prefs['scale'],0.0,100.0,"Export scaleing factor",setimportscale)
|
|
|
|
|
|
|
|
cy = cy-40
|
|
|
|
FLTDoXRef = Draw.Toggle("Import XRefs", 13,cx,cy,220,20,global_prefs['doxrefs'],"Import External references")
|
|
|
|
|
|
|
|
cy = cy-40
|
|
|
|
FLTShadeImport = Draw.Toggle("Import Custom Shading",9,cx,cy,220,20,global_prefs['smoothshading'],"Import custom shading via edgesplit modifiers")
|
|
|
|
|
|
|
|
cy = cy-40
|
|
|
|
FLTAttrib = Draw.Toggle("Import Attribute Files", 10,cx,cy,220,20,global_prefs['attrib'],"Import Image Attribute files")
|
|
|
|
|
|
|
|
cy = cy - 40
|
|
|
|
FLTExport = Draw.PushButton("Import",1,cx,20,100,20,"Import FLT Database")
|
|
|
|
FLTClose = Draw.PushButton("Close",2,cx+120,20,100,20,"Close Window")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Draw.Register(gui,event,but_event)
|