moved bpy into bpy.data and bpy will be eventually replace the root level 'Blender' module. currently we have bpy.library bpy.config and bpy.data
1723 lines
62 KiB
Python
1723 lines
62 KiB
Python
#!BPY
|
|
"""
|
|
Name: 'LightWave (.lwo)...'
|
|
Blender: 239
|
|
Group: 'Import'
|
|
Tooltip: 'Import LightWave Object File Format'
|
|
"""
|
|
|
|
__author__ = ["Alessandro Pirovano, Anthony D'Agostino (Scorpius)", "Campbell Barton (ideasman42)", "ZanQdo"]
|
|
__url__ = ("www.blender.org", "blenderartist.org",
|
|
"Anthony's homepage, http://www.redrival.com/scorpius", "Alessandro's homepage, http://uaraus.altervista.org")
|
|
|
|
importername = "lwo_import 0.4.0"
|
|
|
|
# +---------------------------------------------------------+
|
|
# | Save your work before and after use. |
|
|
# | Please report any useful comment to: |
|
|
# | uaraus-dem@yahoo.it |
|
|
# | Thanks |
|
|
# +---------------------------------------------------------+
|
|
# +---------------------------------------------------------+
|
|
# | Copyright (c) 2002 Anthony D'Agostino |
|
|
# | http://www.redrival.com/scorpius |
|
|
# | scorpius@netzero.com |
|
|
# | April 21, 2002 |
|
|
# | Import Export Suite v0.5 |
|
|
# +---------------------------------------------------------+
|
|
# | Read and write LightWave Object File Format (*.lwo) |
|
|
# +---------------------------------------------------------+
|
|
# +---------------------------------------------------------+
|
|
# | Alessandro Pirovano tweaked starting on March 2005 |
|
|
# | http://uaraus.altervista.org |
|
|
# +---------------------------------------------------------+
|
|
# +----------------------------------------------------------
|
|
# | GPL license block
|
|
# |
|
|
# | 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
# +----------------------------------------------------------
|
|
# +---------------------------------------------------------+
|
|
# | Release log: |
|
|
# | 0.4.0 : Updated for blender 2.44 |
|
|
# | ZanQdo - made the mesh import the right way up |
|
|
# | Ideasman42 - Updated functions for the bew API |
|
|
# | as well as removing the text object class |
|
|
# | 0.2.2 : This code works with Blender 2.42 RC3 |
|
|
# | Added a new PolyFill function for BPYMesh's |
|
|
# | ngon() to use, checked compatibility |
|
|
# | lightwaves ngons are imported as fgons |
|
|
# | Checked compatibility against 1711 lwo files |
|
|
# | 0.2.1 : This code works with Blender 2.40 RC1 |
|
|
# | modified material mode assignment to deal with |
|
|
# | Python API modification |
|
|
# | Changed script license to GNU GPL |
|
|
# | 0.2.0: This code works with Blender 2.40a2 or up |
|
|
# | Major rewrite to deal with large meshes |
|
|
# | - 2 pass file parsing |
|
|
# | - lower memory foot###if DEBUG: print |
|
|
# | (as long as python gc allows) |
|
|
# | 2.40a2 - Removed subsurf settings patches=poly |
|
|
# | 2.40a2 - Edge generation instead of 2vert faces |
|
|
# | 0.1.16: fixed (try 2) texture offset calculations |
|
|
# | added hint on axis mapping |
|
|
# | added hint on texture blending mode |
|
|
# | added hint on texture transparency setting |
|
|
# | search images in original directory first |
|
|
# | fixed texture order application |
|
|
# | 0.1.15: added release log |
|
|
# | fixed texture offset calculations (non-UV) |
|
|
# | fixed reverting vertex order in face generation |
|
|
# | associate texture on game-engine settings |
|
|
# | vector math definitely based on mathutils |
|
|
# | search images in "Images" and "../Images" dir |
|
|
# | revised logging facility |
|
|
# | fixed subsurf texture and material mappings |
|
|
# | 0.1.14: patched missing mod_vector (not definitive) |
|
|
# | 0.1.13: first public release |
|
|
# +---------------------------------------------------------+
|
|
|
|
#blender related import
|
|
import Blender
|
|
import bpy
|
|
|
|
# use for comprehensiveImageLoad
|
|
import BPyImage
|
|
|
|
# Use this ngon function
|
|
import BPyMesh
|
|
|
|
import BPyMessages
|
|
|
|
#python specific modules import
|
|
try:
|
|
import struct, chunk, cStringIO
|
|
except:
|
|
struct= chunk= cStringIO= None
|
|
|
|
### # Debuggin disabled in release.
|
|
### # do a search replace to enabe debug prints
|
|
### DEBUG = False
|
|
|
|
# ===========================================================
|
|
# === Utility Preamble ======================================
|
|
# ===========================================================
|
|
|
|
textname = None
|
|
#uncomment the following line to enable logging facility to the named text object
|
|
#textname = "lwo_log"
|
|
|
|
TXMTX = Blender.Mathutils.Matrix(\
|
|
[1, 0, 0, 0],\
|
|
[0, 0, 1, 0],\
|
|
[0, 1, 0, 0],\
|
|
[0, 0, 0, 1])
|
|
|
|
# ===========================================================
|
|
# === Make sure it is a string ... deal with strange chars ==
|
|
# ===========================================================
|
|
def safestring(st):
|
|
myst = ""
|
|
for ll in xrange(len(st)):
|
|
if st[ll] < " ":
|
|
myst += "#"
|
|
else:
|
|
myst += st[ll]
|
|
return myst
|
|
|
|
# ===========================================================
|
|
# === Main read functions ===================================
|
|
# ===========================================================
|
|
|
|
# =============================
|
|
# === Read LightWave Format ===
|
|
# =============================
|
|
def read(filename):
|
|
if BPyMessages.Error_NoFile(filename):
|
|
return
|
|
|
|
print "This is: %s" % importername
|
|
print "Importing file:", filename
|
|
bpy.data.scenes.active.objects.selected = []
|
|
|
|
start = Blender.sys.time()
|
|
file = open(filename, "rb")
|
|
|
|
editmode = Blender.Window.EditMode() # are we in edit mode? If so ...
|
|
if editmode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh # === LWO header ===
|
|
|
|
try:
|
|
form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12))
|
|
except:
|
|
Blender.Draw.PupMenu('Error%t|This is not a lightwave file')
|
|
return
|
|
|
|
if (form_type == "LWOB"):
|
|
read_lwob(file, filename)
|
|
elif (form_type == "LWO2"):
|
|
read_lwo2(file, filename)
|
|
else:
|
|
print "Can't read a file with the form_type: %s" % form_type
|
|
return
|
|
|
|
Blender.Window.DrawProgressBar(1.0, "") # clear progressbar
|
|
file.close()
|
|
end = Blender.sys.time()
|
|
seconds = " in %.2f %s" % (end-start, "seconds")
|
|
if form_type == "LWO2": fmt = " (v6.0 Format)"
|
|
if form_type == "LWOB": fmt = " (v5.5 Format)"
|
|
print "Successfully imported " + filename.split('\\')[-1].split('/')[-1] + fmt + seconds
|
|
|
|
if editmode: Blender.Window.EditMode(1) # optional, just being nice
|
|
Blender.Redraw()
|
|
|
|
# enddef read
|
|
|
|
|
|
# =================================
|
|
# === Read LightWave 5.5 format ===
|
|
# =================================
|
|
def read_lwob(file, filename):
|
|
#This function is directly derived from the LWO2 import routine
|
|
#dropping all the material analysis parts
|
|
|
|
###if DEBUG: print "LightWave 5.5 format"
|
|
|
|
dir_part = Blender.sys.dirname(filename)
|
|
fname_part = Blender.sys.basename(filename)
|
|
#ask_weird = 1
|
|
|
|
#first initialization of data structures
|
|
defaultname = Blender.sys.splitext(fname_part)[0]
|
|
tag_list = [] #tag list: global for the whole file?
|
|
surf_list = [] #surf list: global for the whole file?
|
|
clip_list = [] #clip list: global for the whole file?
|
|
object_index = 0
|
|
object_list = None
|
|
objspec_list = None
|
|
|
|
#add default material for orphaned faces, if any
|
|
surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")})
|
|
|
|
#pass 2: effectively generate objects
|
|
###if DEBUG: print "Pass 1: dry import"
|
|
file.seek(0)
|
|
objspec_list = ["imported", {}, [], [], {}, {}, 0, {}, {}]
|
|
# === LWO header ===
|
|
form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12))
|
|
if (form_type != "LWOB"):
|
|
###if DEBUG: print "??? Inconsistent file type: %s" % form_type
|
|
return
|
|
while 1:
|
|
try:
|
|
lwochunk = chunk.Chunk(file)
|
|
except EOFError:
|
|
break
|
|
###if DEBUG: print ' ',
|
|
if lwochunk.chunkname == "LAYR":
|
|
###if DEBUG: print "---- LAYR",
|
|
objname = read_layr(lwochunk)
|
|
###if DEBUG: print objname
|
|
if objspec_list != None: #create the object
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
|
|
object_index += 1
|
|
elif lwochunk.chunkname == "PNTS": # Verts
|
|
###if DEBUG: print "---- PNTS",
|
|
verts = read_verts(lwochunk)
|
|
objspec_list[2] = verts
|
|
elif lwochunk.chunkname == "POLS": # Faces v5.5
|
|
###if DEBUG: print "-------- POLS(5.5)"
|
|
faces = read_faces_5(lwochunk)
|
|
flag = 0
|
|
#flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
|
|
if flag<2:
|
|
if objspec_list[3] != []:
|
|
#create immediately the object
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
#update with new data
|
|
objspec_list = [objspec_list[0], #update name
|
|
{}, #init
|
|
objspec_list[2], #same vertexes
|
|
faces, #give it the new faces
|
|
{}, #no need to copy - filled at runtime
|
|
{}, #polygon tagging will follow
|
|
flag, #patch flag
|
|
objspec_list[7], #same uvcoords
|
|
{}] #no vmad mapping
|
|
object_index += 1
|
|
#end if already has a face list
|
|
objspec_list[3] = faces
|
|
objname = objspec_list[0]
|
|
if objname == None:
|
|
objname = defaultname
|
|
#end if processing a valid poly type
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname
|
|
lwochunk.skip()
|
|
#uncomment here to log data structure as it is built
|
|
# ###if DEBUG: print object_list
|
|
#last object read
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
objspec_list = None
|
|
surf_list = None
|
|
clip_list = None
|
|
|
|
|
|
###if DEBUG: print "\nFound %d objects:" % object_index
|
|
|
|
# enddef read_lwob
|
|
|
|
|
|
# =============================
|
|
# === Read LightWave Format ===
|
|
# =============================
|
|
def read_lwo2(file, filename, typ="LWO2"):
|
|
|
|
###if DEBUG: print "LightWave 6 (and above) format"
|
|
|
|
dir_part = Blender.sys.dirname(filename)
|
|
fname_part = Blender.sys.basename(filename)
|
|
ask_weird = 1
|
|
|
|
#first initialization of data structures
|
|
defaultname = Blender.sys.splitext(fname_part)[0]
|
|
tag_list = [] #tag list: global for the whole file?
|
|
surf_list = [] #surf list: global for the whole file?
|
|
clip_list = [] #clip list: global for the whole file?
|
|
object_index = 0
|
|
object_list = None
|
|
objspec_list = None
|
|
# init value is: object_list = [[None, {}, [], [], {}, {}, 0, {}, {}]]
|
|
#0 - objname #original name
|
|
#1 - obj_dict = {TAG} #objects created
|
|
#2 - verts = [] #object vertexes
|
|
#3 - faces = [] #object faces (associations poly -> vertexes)
|
|
#4 - obj_dim_dict = {TAG} #tuples size and pos in local object coords - used for NON-UV mappings
|
|
#5 - polytag_dict = {TAG} #tag to polygons mapping
|
|
#6 - patch_flag #0 = surf; 1 = patch (subdivision surface) - it was the image list
|
|
#7 - uvcoords_dict = {name} #uvmap coordinates (mixed mode per vertex/per face)
|
|
#8 - facesuv_dict = {name} #vmad only coordinates associations poly & vertex -> uv tuples
|
|
|
|
#pass 1: look in advance for materials
|
|
###if DEBUG: print "Starting Pass 1: hold on tight"
|
|
while 1:
|
|
try:
|
|
lwochunk = chunk.Chunk(file)
|
|
except EOFError:
|
|
break
|
|
###if DEBUG: print ' ',
|
|
if lwochunk.chunkname == "TAGS": # Tags
|
|
###if DEBUG: print "---- TAGS"
|
|
tag_list.extend(read_tags(lwochunk))
|
|
elif lwochunk.chunkname == "SURF": # surfaces
|
|
###if DEBUG: print "---- SURF"
|
|
surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
|
|
elif lwochunk.chunkname == "CLIP": # texture images
|
|
###if DEBUG: print "---- CLIP"
|
|
clip_list.append(read_clip(lwochunk, dir_part))
|
|
###if DEBUG: print "read total %s clips up to now" % len(clip_list)
|
|
else: # Misc Chunks
|
|
if ask_weird:
|
|
ckname = safestring(lwochunk.chunkname)
|
|
if "#" in ckname:
|
|
choice = Blender.Draw.PupMenu("WARNING: file could be corrupted.%t|Import anyway|Give up")
|
|
if choice != 1:
|
|
###if DEBUG: print "---- %s: Maybe file corrupted. Terminated by user" % lwochunk.chunkname
|
|
return
|
|
ask_weird = 0
|
|
###if DEBUG: print "---- %s: skipping (maybe later)" % lwochunk.chunkname
|
|
lwochunk.skip()
|
|
|
|
#add default material for orphaned faces, if any
|
|
surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")})
|
|
|
|
#pass 2: effectively generate objects
|
|
###if DEBUG: print "Pass 2: now for the hard part"
|
|
file.seek(0)
|
|
# === LWO header ===
|
|
form_id, form_size, form_type = struct.unpack(">4s1L4s", file.read(12))
|
|
if (form_type != "LWO2"):
|
|
###if DEBUG: print "??? Inconsistent file type: %s" % form_type
|
|
return
|
|
while 1:
|
|
try:
|
|
lwochunk = chunk.Chunk(file)
|
|
except EOFError:
|
|
break
|
|
###if DEBUG: print ' ',
|
|
if lwochunk.chunkname == "LAYR":
|
|
###if DEBUG: print "---- LAYR"
|
|
objname = read_layr(lwochunk)
|
|
###if DEBUG: print objname
|
|
if objspec_list != None: #create the object
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
|
|
object_index += 1
|
|
elif lwochunk.chunkname == "PNTS": # Verts
|
|
###if DEBUG: print "---- PNTS"
|
|
verts = read_verts(lwochunk)
|
|
objspec_list[2] = verts
|
|
elif lwochunk.chunkname == "VMAP": # MAPS (UV)
|
|
###if DEBUG: print "---- VMAP"
|
|
#objspec_list[7] = read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
|
|
read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
|
|
elif lwochunk.chunkname == "VMAD": # MAPS (UV) per-face
|
|
###if DEBUG: print "---- VMAD"
|
|
#objspec_list[7], objspec_list[8] = read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
|
|
read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
|
|
elif lwochunk.chunkname == "POLS": # Faces v6.0
|
|
###if DEBUG: print "-------- POLS(6)"
|
|
faces, flag = read_faces_6(lwochunk)
|
|
#flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
|
|
if flag<2:
|
|
if objspec_list[3] != []:
|
|
#create immediately the object
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
#update with new data
|
|
objspec_list = [objspec_list[0], #update name
|
|
{}, #init
|
|
objspec_list[2], #same vertexes
|
|
faces, #give it the new faces
|
|
{}, #no need to copy - filled at runtime
|
|
{}, #polygon tagging will follow
|
|
flag, #patch flag
|
|
objspec_list[7], #same uvcoords
|
|
{}] #no vmad mapping
|
|
object_index += 1
|
|
#end if already has a face list
|
|
objspec_list[3] = faces
|
|
objname = objspec_list[0]
|
|
if objname == None:
|
|
objname = defaultname
|
|
#end if processing a valid poly type
|
|
elif lwochunk.chunkname == "PTAG": # PTags
|
|
###if DEBUG: print "---- PTAG"
|
|
polytag_dict = read_ptags(lwochunk, tag_list)
|
|
for kk, polytag_dict_val in polytag_dict.iteritems(): objspec_list[5][kk] = polytag_dict_val
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname
|
|
lwochunk.skip()
|
|
#uncomment here to log data structure as it is built
|
|
|
|
#last object read
|
|
create_objects(clip_list, objspec_list, surf_list)
|
|
update_material(clip_list, objspec_list, surf_list) #give it all the object
|
|
objspec_list = None
|
|
surf_list = None
|
|
clip_list = None
|
|
|
|
###if DEBUG: print "\nFound %d objects:" % object_index
|
|
# enddef read_lwo2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================
|
|
# === File reading routines =================================
|
|
# ===========================================================
|
|
# ==================
|
|
# === Read Verts ===
|
|
# ==================
|
|
def read_verts(lwochunk):
|
|
#data = cStringIO.StringIO(lwochunk.read())
|
|
numverts = lwochunk.chunksize/12
|
|
return [struct.unpack(">fff", lwochunk.read(12)) for i in xrange(numverts)]
|
|
# enddef read_verts
|
|
|
|
|
|
# =================
|
|
# === Read Name ===
|
|
# =================
|
|
# modified to deal with odd lenght strings
|
|
def read_name(file):
|
|
name = ""
|
|
while 1:
|
|
char = file.read(1)
|
|
if char == "\0": break
|
|
else: name += char
|
|
len_name = len(name) + 1 #count the trailing zero
|
|
if len_name%2==1:
|
|
char = file.read(1) #remove zero padding to even lenght
|
|
len_name += 1
|
|
return name, len_name
|
|
|
|
|
|
# ==================
|
|
# === Read Layer ===
|
|
# ==================
|
|
def read_layr(lwochunk):
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
idx, flags = struct.unpack(">hh", data.read(4))
|
|
pivot = struct.unpack(">fff", data.read(12))
|
|
layer_name, discard = read_name(data)
|
|
if not layer_name: layer_name = "NoName"
|
|
return layer_name
|
|
# enddef read_layr
|
|
|
|
|
|
# ======================
|
|
# === Read Faces 5.5 ===
|
|
# ======================
|
|
def read_faces_5(lwochunk):
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
faces = []
|
|
i = 0
|
|
while i < lwochunk.chunksize:
|
|
#if not i%1000 and my_meshtools.show_progress:
|
|
# Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
|
|
|
|
numfaceverts, = struct.unpack(">H", data.read(2))
|
|
facev = [struct.unpack(">H", data.read(2))[0] for j in xrange(numfaceverts)]
|
|
facev.reverse()
|
|
faces.append(facev)
|
|
surfaceindex, = struct.unpack(">H", data.read(2))
|
|
if surfaceindex < 0:
|
|
###if DEBUG: print "***Error. Referencing uncorrect surface index"
|
|
return
|
|
i += (4+numfaceverts*2)
|
|
return faces
|
|
|
|
|
|
# ==================================
|
|
# === Read Variable-Length Index ===
|
|
# ==================================
|
|
def read_vx(data):
|
|
byte1, = struct.unpack(">B", data.read(1))
|
|
if byte1 != 0xFF: # 2-byte index
|
|
byte2, = struct.unpack(">B", data.read(1))
|
|
index = byte1*256 + byte2
|
|
index_size = 2
|
|
else: # 4-byte index
|
|
byte2, byte3, byte4 = struct.unpack(">3B", data.read(3))
|
|
index = byte2*65536 + byte3*256 + byte4
|
|
index_size = 4
|
|
return index, index_size
|
|
|
|
|
|
# ======================
|
|
# === Read uvmapping ===
|
|
# ======================
|
|
def read_vmap(uvcoords_dict, maxvertnum, lwochunk):
|
|
if maxvertnum == 0:
|
|
###if DEBUG: print "Found VMAP but no vertexes to map!"
|
|
return uvcoords_dict
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
map_type = data.read(4)
|
|
if map_type != "TXUV":
|
|
###if DEBUG: print "Reading VMAP: No Texture UV map Were Found. Map Type: %s" % map_type
|
|
return uvcoords_dict
|
|
dimension, = struct.unpack(">H", data.read(2))
|
|
name, i = read_name(data) #i initialized with string lenght + zeros
|
|
###if DEBUG: print "TXUV %d %s" % (dimension, name)
|
|
#note if there is already a VMAD it will be lost
|
|
#it is assumed that VMAD will follow the corresponding VMAP
|
|
Vector = Blender.Mathutils.Vector
|
|
try: #if uvcoords_dict.has_key(name):
|
|
my_uv_dict = uvcoords_dict[name] #update existing
|
|
except: #else:
|
|
my_uv_dict = {} #start a brand new: this could be made more smart
|
|
while (i < lwochunk.chunksize - 6): #4+2 header bytes already read
|
|
vertnum, vnum_size = read_vx(data)
|
|
uv = struct.unpack(">ff", data.read(8))
|
|
if vertnum >= maxvertnum:
|
|
###if DEBUG: print "Hem: more uvmap than vertexes? ignoring uv data for vertex %d" % vertnum
|
|
pass
|
|
else:
|
|
my_uv_dict[vertnum] = Vector(uv)
|
|
i += 8 + vnum_size
|
|
#end loop on uv pairs
|
|
uvcoords_dict[name] = my_uv_dict
|
|
#this is a per-vertex mapping AND the uv tuple is vertex-ordered, so faces_uv is the same as faces
|
|
#return uvcoords_dict
|
|
return
|
|
|
|
# ========================
|
|
# === Read uvmapping 2 ===
|
|
# ========================
|
|
def read_vmad(uvcoords_dict, facesuv_dict, maxfacenum, maxvertnum, lwochunk):
|
|
if maxvertnum == 0 or maxfacenum == 0:
|
|
###if DEBUG: print "Found VMAD but no vertexes to map!"
|
|
return uvcoords_dict, facesuv_dict
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
map_type = data.read(4)
|
|
if map_type != "TXUV":
|
|
###if DEBUG: print "Reading VMAD: No Texture UV map Were Found. Map Type: %s" % map_type
|
|
return uvcoords_dict, facesuv_dict
|
|
dimension, = struct.unpack(">H", data.read(2))
|
|
name, i = read_name(data) #i initialized with string lenght + zeros
|
|
###if DEBUG: print "TXUV %d %s" % (dimension, name)
|
|
try: #if uvcoords_dict.has_key(name):
|
|
my_uv_dict = uvcoords_dict[name] #update existing
|
|
except: #else:
|
|
my_uv_dict = {} #start a brand new: this could be made more smart
|
|
my_facesuv_list = []
|
|
newindex = maxvertnum + 10 #why +10? Why not?
|
|
#end variable initialization
|
|
Vector = Blender.Mathutils.Vector
|
|
while (i < lwochunk.chunksize - 6): #4+2 header bytes already read
|
|
vertnum, vnum_size = read_vx(data)
|
|
i += vnum_size
|
|
polynum, vnum_size = read_vx(data)
|
|
i += vnum_size
|
|
uv = struct.unpack(">ff", data.read(8))
|
|
if polynum >= maxfacenum or vertnum >= maxvertnum:
|
|
###if DEBUG: print "Hem: more uvmap than vertexes? ignorig uv data for vertex %d" % vertnum
|
|
pass
|
|
else:
|
|
my_uv_dict[newindex] = Vector(uv)
|
|
my_facesuv_list.append([polynum, vertnum, newindex])
|
|
newindex += 1
|
|
i += 8
|
|
#end loop on uv pairs
|
|
uvcoords_dict[name] = my_uv_dict
|
|
facesuv_dict[name] = my_facesuv_list
|
|
###if DEBUG: print "updated %d vertexes data" % (newindex-maxvertnum-10)
|
|
return
|
|
|
|
|
|
# =================
|
|
# === Read tags ===
|
|
# =================
|
|
def read_tags(lwochunk):
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
tag_list = []
|
|
current_tag = ""
|
|
i = 0
|
|
while i < lwochunk.chunksize:
|
|
char = data.read(1)
|
|
if char == "\0":
|
|
tag_list.append(current_tag)
|
|
if (len(current_tag) % 2 == 0): char = data.read(1)
|
|
current_tag = ""
|
|
else:
|
|
current_tag += char
|
|
i += 1
|
|
###if DEBUG: print "read %d tags, list follows: %s" % (len(tag_list), tag_list)
|
|
return tag_list
|
|
|
|
|
|
# ==================
|
|
# === Read Ptags ===
|
|
# ==================
|
|
def read_ptags(lwochunk, tag_list):
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
polygon_type = data.read(4)
|
|
if polygon_type != "SURF":
|
|
###if DEBUG: print "No Surf Were Found. Polygon Type: %s" % polygon_type
|
|
return {}
|
|
ptag_dict = {}
|
|
i = 0
|
|
while(i < lwochunk.chunksize-4): #4 bytes polygon type already read
|
|
#if not i%1000 and my_meshtools.show_progress:
|
|
# Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading PTAGS")
|
|
poln, poln_size = read_vx(data)
|
|
i += poln_size
|
|
tag_index, = struct.unpack(">H", data.read(2))
|
|
if tag_index > (len(tag_list)):
|
|
###if DEBUG: print "Reading PTAG: Surf belonging to undefined TAG: %d. Skipping" % tag_index
|
|
return {}
|
|
i += 2
|
|
tag_key = tag_list[tag_index]
|
|
try:
|
|
ptag_dict[tag_list[tag_index]].append(poln)
|
|
except: #if not(ptag_dict.has_key(tag_key)):
|
|
ptag_dict[tag_list[tag_index]] = [poln]
|
|
|
|
###if DEBUG: for i, ptag_dict_val in ptag_dict.iteritems(): print "read %d polygons belonging to TAG %s" % (len(ptag_dict_val ), i)
|
|
return ptag_dict
|
|
|
|
|
|
|
|
# ==================
|
|
# === Read Clips ===
|
|
# ==================
|
|
def read_clip(lwochunk, dir_part):
|
|
# img, IMG, g_IMG refers to blender image objects
|
|
# ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf
|
|
clip_dict = {}
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
image_index, = struct.unpack(">L", data.read(4))
|
|
clip_dict['ID'] = image_index
|
|
i = 4
|
|
while(i < lwochunk.chunksize):
|
|
subchunkname, = struct.unpack("4s", data.read(4))
|
|
subchunklen, = struct.unpack(">H", data.read(2))
|
|
if subchunkname == "STIL":
|
|
###if DEBUG: print "-------- STIL"
|
|
clip_name, k = read_name(data)
|
|
#now split text independently from platform
|
|
#depend on the system where image was saved. NOT the one where the script is run
|
|
no_sep = "\\"
|
|
if Blender.sys.sep == no_sep: no_sep ="/"
|
|
if (no_sep in clip_name):
|
|
clip_name = clip_name.replace(no_sep, Blender.sys.sep)
|
|
short_name = Blender.sys.basename(clip_name)
|
|
if clip_name == "" or short_name == "":
|
|
###if DEBUG: print "Reading CLIP: Empty clip name not allowed. Skipping"
|
|
discard = data.read(subchunklen-k)
|
|
clip_dict['NAME'] = clip_name
|
|
clip_dict['BASENAME'] = short_name
|
|
elif subchunkname == "XREF": #cross reference another image
|
|
###if DEBUG: print "-------- XREF"
|
|
image_index, = struct.unpack(">L", data.read(4))
|
|
clip_name, k = read_name(data)
|
|
clip_dict['NAME'] = clip_name
|
|
clip_dict['XREF'] = image_index
|
|
elif subchunkname == "NEGA": #negate texture effect
|
|
###if DEBUG: print "-------- NEGA"
|
|
n, = struct.unpack(">H", data.read(2))
|
|
clip_dict['NEGA'] = n
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "-------- CLIP:%s: skipping" % subchunkname
|
|
discard = data.read(subchunklen)
|
|
i = i + 6 + subchunklen
|
|
#end loop on surf chunks
|
|
###if DEBUG: print "read image:%s" % clip_dict
|
|
if clip_dict.has_key('XREF'):
|
|
###if DEBUG: print "Cross-reference: no image pre-allocated."
|
|
return clip_dict
|
|
#look for images
|
|
#img = load_image("",clip_dict['NAME'])
|
|
NAME= BASENAME= None
|
|
|
|
try:
|
|
NAME= clip_dict['NAME']
|
|
BASENAME= clip_dict['BASENAME']
|
|
except:
|
|
clip_dict['g_IMG'] = None
|
|
return
|
|
# ###if DEBUG: print 'test', NAME, BASENAME
|
|
img = BPyImage.comprehensiveImageLoad(NAME, dir_part, PLACE_HOLDER= False, RECURSIVE= True)
|
|
if not img:
|
|
###if DEBUG: print "***No image %s found: trying LWO file subdir" % NAME
|
|
img = BPyImage.comprehensiveImageLoad(BASENAME, dir_part, PLACE_HOLDER= False, RECURSIVE= True)
|
|
|
|
###if DEBUG: if not img: print "***No image %s found: giving up" % BASENAME
|
|
#lucky we are: we have an image
|
|
###if DEBUG: print "Image pre-allocated."
|
|
clip_dict['g_IMG'] = img
|
|
|
|
return clip_dict
|
|
|
|
|
|
# ===========================
|
|
# === Read Surfaces Block ===
|
|
# ===========================
|
|
def read_surfblok(subchunkdata):
|
|
lenght = len(subchunkdata)
|
|
my_dict = {}
|
|
my_uvname = ""
|
|
data = cStringIO.StringIO(subchunkdata)
|
|
##############################################################
|
|
# blok header sub-chunk
|
|
##############################################################
|
|
subchunkname, = struct.unpack("4s", data.read(4))
|
|
subchunklen, = struct.unpack(">h", data.read(2))
|
|
accumulate_i = subchunklen + 6
|
|
if subchunkname != 'IMAP':
|
|
###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname
|
|
return {}, ""
|
|
###if DEBUG: print "---------- IMAP"
|
|
ordinal, i = read_name(data)
|
|
my_dict['ORD'] = ordinal
|
|
#my_dict['g_ORD'] = -1
|
|
my_dict['ENAB'] = True
|
|
while(i < subchunklen): # ---------left 6------------------------- loop on header parameters
|
|
sub2chunkname, = struct.unpack("4s", data.read(4))
|
|
sub2chunklen, = struct.unpack(">h", data.read(2))
|
|
i = i + 6 + sub2chunklen
|
|
if sub2chunkname == "CHAN":
|
|
###if DEBUG: print "------------ CHAN"
|
|
sub2chunkname, = struct.unpack("4s", data.read(4))
|
|
my_dict['CHAN'] = sub2chunkname
|
|
sub2chunklen -= 4
|
|
elif sub2chunkname == "ENAB": #only present if is to be disabled
|
|
###if DEBUG: print "------------ ENAB"
|
|
ena, = struct.unpack(">h", data.read(2))
|
|
my_dict['ENAB'] = ena
|
|
sub2chunklen -= 2
|
|
elif sub2chunkname == "NEGA": #only present if is to be enabled
|
|
###if DEBUG: print "------------ NEGA"
|
|
ena, = struct.unpack(">h", data.read(2))
|
|
if ena == 1:
|
|
my_dict['NEGA'] = ena
|
|
sub2chunklen -= 2
|
|
elif sub2chunkname == "OPAC": #only present if is to be disabled
|
|
###if DEBUG: print "------------ OPAC"
|
|
opa, = struct.unpack(">h", data.read(2))
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['OPAC'] = opa
|
|
my_dict['OPACVAL'] = s
|
|
sub2chunklen -= 6
|
|
elif sub2chunkname == "AXIS":
|
|
###if DEBUG: print "------------ AXIS"
|
|
ena, = struct.unpack(">h", data.read(2))
|
|
my_dict['DISPLAXIS'] = ena
|
|
sub2chunklen -= 2
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "------------ SURF: BLOK: IMAP: %s: skipping" % sub2chunkname
|
|
discard = data.read(sub2chunklen)
|
|
#end loop on blok header subchunks
|
|
##############################################################
|
|
# blok attributes sub-chunk
|
|
##############################################################
|
|
subchunkname, = struct.unpack("4s", data.read(4))
|
|
subchunklen, = struct.unpack(">h", data.read(2))
|
|
accumulate_i += subchunklen + 6
|
|
if subchunkname != 'TMAP':
|
|
###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname
|
|
return {}, ""
|
|
###if DEBUG: print "---------- TMAP"
|
|
i = 0
|
|
while(i < subchunklen): # -----------left 6----------------------- loop on header parameters
|
|
sub2chunkname, = struct.unpack("4s", data.read(4))
|
|
sub2chunklen, = struct.unpack(">h", data.read(2))
|
|
i = i + 6 + sub2chunklen
|
|
if sub2chunkname == "CNTR":
|
|
###if DEBUG: print "------------ CNTR"
|
|
x, y, z = struct.unpack(">fff", data.read(12))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['CNTR'] = [x, y, z]
|
|
sub2chunklen -= (12+env_size)
|
|
elif sub2chunkname == "SIZE":
|
|
###if DEBUG: print "------------ SIZE"
|
|
x, y, z = struct.unpack(">fff", data.read(12))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['SIZE'] = [x, y, z]
|
|
sub2chunklen -= (12+env_size)
|
|
elif sub2chunkname == "ROTA":
|
|
###if DEBUG: print "------------ ROTA"
|
|
x, y, z = struct.unpack(">fff", data.read(12))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['ROTA'] = [x, y, z]
|
|
sub2chunklen -= (12+env_size)
|
|
elif sub2chunkname == "CSYS":
|
|
###if DEBUG: print "------------ CSYS"
|
|
ena, = struct.unpack(">h", data.read(2))
|
|
my_dict['CSYS'] = ena
|
|
sub2chunklen -= 2
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "------------ SURF: BLOK: TMAP: %s: skipping" % sub2chunkname
|
|
pass
|
|
if sub2chunklen > 0:
|
|
discard = data.read(sub2chunklen)
|
|
#end loop on blok attributes subchunks
|
|
##############################################################
|
|
# ok, now other attributes without sub_chunks
|
|
##############################################################
|
|
while(accumulate_i < lenght): # ---------------------------------- loop on header parameters: lenght has already stripped the 6 bypes header
|
|
subchunkname, = struct.unpack("4s", data.read(4))
|
|
subchunklen, = struct.unpack(">H", data.read(2))
|
|
accumulate_i = accumulate_i + 6 + subchunklen
|
|
if subchunkname == "PROJ":
|
|
###if DEBUG: print "---------- PROJ"
|
|
p, = struct.unpack(">h", data.read(2))
|
|
my_dict['PROJ'] = p
|
|
subchunklen -= 2
|
|
elif subchunkname == "AXIS":
|
|
###if DEBUG: print "---------- AXIS"
|
|
a, = struct.unpack(">h", data.read(2))
|
|
my_dict['MAJAXIS'] = a
|
|
subchunklen -= 2
|
|
elif subchunkname == "IMAG":
|
|
###if DEBUG: print "---------- IMAG"
|
|
i, i_size = read_vx(data)
|
|
my_dict['IMAG'] = i
|
|
subchunklen -= i_size
|
|
elif subchunkname == "WRAP":
|
|
###if DEBUG: print "---------- WRAP"
|
|
ww, wh = struct.unpack(">hh", data.read(4))
|
|
#reduce width and height to just 1 parameter for both
|
|
my_dict['WRAP'] = max([ww,wh])
|
|
#my_dict['WRAPWIDTH'] = ww
|
|
#my_dict['WRAPHEIGHT'] = wh
|
|
subchunklen -= 4
|
|
elif subchunkname == "WRPW":
|
|
###if DEBUG: print "---------- WRPW"
|
|
w, = struct.unpack(">f", data.read(4))
|
|
my_dict['WRPW'] = w
|
|
envelope, env_size = read_vx(data)
|
|
subchunklen -= (env_size+4)
|
|
elif subchunkname == "WRPH":
|
|
###if DEBUG: print "---------- WRPH"
|
|
w, = struct.unpack(">f", data.read(4))
|
|
my_dict['WRPH'] = w
|
|
envelope, env_size = read_vx(data)
|
|
subchunklen -= (env_size+4)
|
|
elif subchunkname == "VMAP":
|
|
###if DEBUG: print "---------- VMAP"
|
|
vmp, i = read_name(data)
|
|
my_dict['VMAP'] = vmp
|
|
my_uvname = vmp
|
|
subchunklen -= i
|
|
else: # Misc Chunks
|
|
###if DEBUG: print "---------- SURF: BLOK: %s: skipping" % subchunkname
|
|
pass
|
|
if subchunklen > 0:
|
|
discard = data.read(subchunklen)
|
|
#end loop on blok subchunks
|
|
return my_dict, my_uvname
|
|
|
|
|
|
# =====================
|
|
# === Read Surfaces ===
|
|
# =====================
|
|
def read_surfs(lwochunk, surf_list, tag_list):
|
|
my_dict = {}
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
surf_name, i = read_name(data)
|
|
parent_name, j = read_name(data)
|
|
i += j
|
|
if (surf_name == "") or not(surf_name in tag_list):
|
|
###if DEBUG: print "Reading SURF: Actually empty surf name not allowed. Skipping"
|
|
return {}
|
|
if (parent_name != ""):
|
|
parent_index = [x['NAME'] for x in surf_list].count(parent_name)
|
|
if parent_index >0:
|
|
my_dict = surf_list[parent_index-1]
|
|
my_dict['NAME'] = surf_name
|
|
###if DEBUG: print "Surface data for TAG %s" % surf_name
|
|
while(i < lwochunk.chunksize):
|
|
subchunkname, = struct.unpack("4s", data.read(4))
|
|
subchunklen, = struct.unpack(">H", data.read(2))
|
|
i = i + 6 + subchunklen #6 bytes subchunk header
|
|
if subchunkname == "COLR": #color: mapped on color
|
|
###if DEBUG: print "-------- COLR"
|
|
r, g, b = struct.unpack(">fff", data.read(12))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['COLR'] = [r, g, b]
|
|
subchunklen -= (12+env_size)
|
|
elif subchunkname == "DIFF": #diffusion: mapped on reflection (diffuse shader)
|
|
###if DEBUG: print "-------- DIFF"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['DIFF'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "SPEC": #specularity: mapped to specularity (spec shader)
|
|
###if DEBUG: print "-------- SPEC"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['SPEC'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "REFL": #reflection: mapped on raymirror
|
|
###if DEBUG: print "-------- REFL"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['REFL'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "TRNL": #translucency: mapped on same param
|
|
###if DEBUG: print "-------- TRNL"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['TRNL'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "GLOS": #glossiness: mapped on specularity hardness (spec shader)
|
|
###if DEBUG: print "-------- GLOS"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['GLOS'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "TRAN": #transparency: inverted and mapped on alpha channel
|
|
###if DEBUG: print "-------- TRAN"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['TRAN'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "LUMI": #luminosity: mapped on emit channel
|
|
###if DEBUG: print "-------- LUMI"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['LUMI'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "GVAL": #glow: mapped on add channel
|
|
###if DEBUG: print "-------- GVAL"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['GVAL'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "SMAN": #smoothing angle
|
|
###if DEBUG: print "-------- SMAN"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
my_dict['SMAN'] = s
|
|
subchunklen -= 4
|
|
elif subchunkname == "SIDE": #double sided?
|
|
###if DEBUG: print "-------- SIDE" #if 1 side do not define key
|
|
s, = struct.unpack(">H", data.read(2))
|
|
if s == 3:
|
|
my_dict['SIDE'] = s
|
|
subchunklen -= 2
|
|
elif subchunkname == "RIND": #Refraction: mapped on IOR
|
|
###if DEBUG: print "-------- RIND"
|
|
s, = struct.unpack(">f", data.read(4))
|
|
envelope, env_size = read_vx(data)
|
|
my_dict['RIND'] = s
|
|
subchunklen -= (4+env_size)
|
|
elif subchunkname == "BLOK": #blocks
|
|
###if DEBUG: print "-------- BLOK"
|
|
rr, uvname = read_surfblok(data.read(subchunklen))
|
|
#paranoia setting: preventing adding an empty dict
|
|
if rr: # != {}
|
|
try:
|
|
my_dict['BLOK'].append(rr)
|
|
except:
|
|
my_dict['BLOK'] = [rr]
|
|
|
|
if uvname: # != "":
|
|
my_dict['UVNAME'] = uvname #theoretically there could be a number of them: only one used per surf
|
|
if not(my_dict.has_key('g_IMAG')) and (rr.has_key('CHAN')) and (rr.has_key('OPAC')) and (rr.has_key('IMAG')):
|
|
if (rr['CHAN'] == 'COLR') and (rr['OPAC'] == 0):
|
|
my_dict['g_IMAG'] = rr['IMAG'] #do not set anything, just save image object for later assignment
|
|
subchunklen = 0 #force ending
|
|
else: # Misc Chunks
|
|
pass
|
|
###if DEBUG: print "-------- SURF:%s: skipping" % subchunkname
|
|
if subchunklen > 0:
|
|
discard = data.read(subchunklen)
|
|
#end loop on surf chunks
|
|
try:#if my_dict.has_key('BLOK'):
|
|
my_dict['BLOK'].reverse() #texture applied in reverse order with respect to reading from lwo
|
|
except:
|
|
pass
|
|
|
|
#uncomment this if material pre-allocated by read_surf
|
|
my_dict['g_MAT'] = bpy.data.materials.new(my_dict['NAME'])
|
|
###if DEBUG: print "-> Material pre-allocated."
|
|
return my_dict
|
|
|
|
|
|
|
|
def reduce_face(verts, face):
|
|
TriangleArea= Blender.Mathutils.TriangleArea
|
|
Vector= Blender.Mathutils.Vector
|
|
####if DEBUG: print len(face), face
|
|
# wants indicies local to the face
|
|
len_face= len(face)
|
|
if len_face==3:
|
|
return [face]
|
|
elif len_face==4:
|
|
vecs= [Vector(verts[i]) for i in face]
|
|
# Get the convave quad area
|
|
a1= TriangleArea(vecs[0], vecs[1], vecs[2])
|
|
a2= TriangleArea(vecs[0], vecs[2], vecs[3])
|
|
|
|
a3= TriangleArea(vecs[0], vecs[1], vecs[3])
|
|
a4= TriangleArea(vecs[1], vecs[2], vecs[3])
|
|
|
|
if abs((a1+a2) - (a3+a4)) < (a1+a2+a3+a4)/100: # Not convace
|
|
####if DEBUG: print 'planer'
|
|
return [[0,1,2,3]]
|
|
if a1+a2<a3+a4:
|
|
return [[0,1,2], [0,2,3]]
|
|
else:
|
|
return [[0,1,3], [1,2,3]]
|
|
|
|
else: # 5+
|
|
####if DEBUG: print 'SCANFILL...', len(face)
|
|
ngons= BPyMesh.ngon(verts, face, PREF_FIX_LOOPS= True)
|
|
return ngons
|
|
|
|
|
|
|
|
# =========================
|
|
# === Recalculate Faces ===
|
|
# =========================
|
|
|
|
def get_uvface(complete_list, facenum):
|
|
# extract from the complete list only vertexes of the desired polygon
|
|
'''
|
|
my_facelist = []
|
|
for elem in complete_list:
|
|
if elem[0] == facenum:
|
|
my_facelist.append(elem)
|
|
return my_facelist
|
|
'''
|
|
return [elem for elem in complete_list if elem[0] == facenum]
|
|
|
|
def get_newindex(polygon_list, vertnum):
|
|
# extract from the polygon list the new index associated to a vertex
|
|
if not polygon_list: # == []
|
|
return -1
|
|
for elem in polygon_list:
|
|
if elem[1] == vertnum:
|
|
return elem[2]
|
|
# ###if DEBUG: print "WARNING: expected vertex %s for polygon %s. Polygon_list dump follows" % (vertnum, polygon_list[0][0])
|
|
# ###if DEBUG: print polygon_list
|
|
return -1
|
|
|
|
def get_surf(surf_list, cur_tag):
|
|
for elem in surf_list: # elem can be None
|
|
if elem and elem['NAME'] == cur_tag:
|
|
return elem
|
|
return {}
|
|
|
|
|
|
|
|
# ====================================
|
|
# === Modified Create Blender Mesh ===
|
|
# ====================================
|
|
def my_create_mesh(clip_list, surf, objspec_list, current_facelist, objname, not_used_faces):
|
|
#take the needed faces and update the not-used face list
|
|
complete_vertlist = objspec_list[2]
|
|
complete_facelist = objspec_list[3]
|
|
uvcoords_dict = objspec_list[7]
|
|
facesuv_dict = objspec_list[8]
|
|
vertex_map = {} #implementation as dict
|
|
cur_ptag_faces = []
|
|
cur_ptag_faces_indexes = []
|
|
maxface = len(complete_facelist)
|
|
for ff in current_facelist:
|
|
if ff >= maxface:
|
|
###if DEBUG: print "Non existent face addressed: Giving up with this object"
|
|
return None, not_used_faces #return the created object
|
|
cur_face = complete_facelist[ff]
|
|
cur_ptag_faces_indexes.append(ff)
|
|
if not_used_faces: # != []
|
|
not_used_faces[ff] = -1
|
|
for vv in cur_face: vertex_map[vv] = 1
|
|
#end loop on faces
|
|
store_edge = 0
|
|
|
|
scn= bpy.data.scenes.active
|
|
msh = bpy.data.meshes.new()
|
|
obj = scn.objects.new(msh)
|
|
|
|
mat = None
|
|
try:
|
|
msh.materials = [surf['g_MAT']]
|
|
except:
|
|
pass
|
|
|
|
msh.mode |= Blender.Mesh.Modes.AUTOSMOOTH #smooth it anyway
|
|
if surf.has_key('SMAN'):
|
|
#not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle)
|
|
#only one smoothing angle will be active! => take the max one
|
|
msh.degr = min(80, int(surf['SMAN']/3.1415926535897932384626433832795*180.0)) #lwo in radians - blender in degrees
|
|
|
|
try:
|
|
img= lookup_imag(clip_list, surf['g_IMAG'])['g_IMG']
|
|
except:
|
|
img= None
|
|
|
|
|
|
#uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])) and (img != None))
|
|
uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])))
|
|
|
|
|
|
|
|
|
|
###if DEBUG: print "\n#===================================================================#"
|
|
###if DEBUG: print "Processing Object: %s" % objname
|
|
###if DEBUG: print "#===================================================================#"
|
|
|
|
if uv_flag:
|
|
msh.verts.extend([(0.0,0.0,0.0),])
|
|
j = 1
|
|
else:
|
|
j = 0
|
|
|
|
def tmp_get_vert(k, i):
|
|
vertex_map[k] = i+j # j is the dummy vert
|
|
# ###if DEBUG: print complete_vertlist[i]
|
|
return complete_vertlist[k]
|
|
|
|
|
|
|
|
msh.verts.extend([tmp_get_vert(k, i) for i, k in enumerate(vertex_map.iterkeys())])
|
|
msh.transform(TXMTX) # faster then applying while reading.
|
|
#end sweep over vertexes
|
|
|
|
#append faces
|
|
FACE_TEX= Blender.Mesh.FaceModes.TEX
|
|
FACE_ALPHA= Blender.Mesh.FaceTranspModes.ALPHA
|
|
EDGE_DRAW_FLAG= Blender.Mesh.EdgeFlags.EDGEDRAW | Blender.Mesh.EdgeFlags.EDGERENDER
|
|
|
|
|
|
edges = []
|
|
face_data = [] # [(indicies, material, uvs, image), ]
|
|
face_uvs = []
|
|
edges_fgon = []
|
|
|
|
if uv_flag:
|
|
uvcoords_dict_context = uvcoords_dict[surf['UVNAME']]
|
|
try: current_uvdict = facesuv_dict[surf['UVNAME']]
|
|
except: current_uvdict = None
|
|
|
|
default_uv = Blender.Mathutils.Vector(0,0)
|
|
def tmp_get_face_uvs(cur_face, i):
|
|
uvs = []
|
|
if current_uvdict:
|
|
uvface = get_uvface(current_uvdict,i)
|
|
for vi in cur_face:
|
|
ni = get_newindex(uvface, vi)
|
|
if ni == -1: ni = vi
|
|
|
|
try:
|
|
uvs.append(uvcoords_dict_context[ ni ])
|
|
except:
|
|
###if DEBUG: print '\tWarning, Corrupt UVs'
|
|
uvs.append(default_uv)
|
|
else:
|
|
for vi in cur_face:
|
|
uvs.append(uvcoords_dict_context[ vi ])
|
|
|
|
return uvs
|
|
|
|
for i in cur_ptag_faces_indexes:
|
|
cur_face = complete_facelist[i]
|
|
numfaceverts = len(cur_face)
|
|
|
|
if numfaceverts == 2: edges.append((vertex_map[cur_face[0]], vertex_map[cur_face[1]]))
|
|
elif numfaceverts == 3:
|
|
rev_face = (cur_face[2], cur_face[1], cur_face[0])
|
|
face_data.append( [vertex_map[j] for j in rev_face] )
|
|
if uv_flag: face_uvs.append(tmp_get_face_uvs(rev_face, i))
|
|
|
|
elif numfaceverts > 3:
|
|
meta_faces= reduce_face(complete_vertlist, cur_face) # Indices of triangles
|
|
edge_face_count = {}
|
|
for mf in meta_faces:
|
|
# ###if DEBUG: print meta_faces
|
|
|
|
if len(mf) == 3: #triangle
|
|
mf = cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]]
|
|
face_data.append( [vertex_map[j] for j in mf] )
|
|
|
|
if uv_flag: face_uvs.append(tmp_get_face_uvs(mf, i))
|
|
|
|
#if USE_FGON:
|
|
if len(meta_faces) > 1:
|
|
mf = face_data[-1] # reuse mf
|
|
for i in xrange(3):
|
|
v1= mf[i]
|
|
v2= mf[i-1]
|
|
if v1!=v2:
|
|
if v1>v2:
|
|
v2,v1= v1,v2
|
|
try:
|
|
edge_face_count[v1,v2]+= 1
|
|
except:
|
|
edge_face_count[v1,v2]= 0
|
|
|
|
else: #quads
|
|
mf= cur_face[mf[3]], cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]]
|
|
face_data.append( [vertex_map[j] for j in mf] )
|
|
if uv_flag: face_uvs.append(tmp_get_face_uvs(mf, i))
|
|
|
|
if edge_face_count:
|
|
edges_fgon.extend( [vert_key for vert_key, count in edge_face_count.iteritems() if count] )
|
|
|
|
|
|
msh.edges.extend(edges)
|
|
face_mapping_removed = msh.faces.extend(face_data, indexList=True)
|
|
if surf.has_key('TRAN') or (mat and mat.alpha<1.0): # incase mat is null
|
|
transp_flag = True
|
|
else:
|
|
transp_flag = False
|
|
|
|
if uv_flag:
|
|
msh.faceUV = True
|
|
msh_faces= msh.faces
|
|
for i, uvs in enumerate(face_uvs):
|
|
i_mapped = face_mapping_removed[i]
|
|
if i_mapped != None:
|
|
f = msh_faces[i_mapped]
|
|
f.uv = uvs
|
|
if img:
|
|
f.image = img
|
|
|
|
if transp_flag: f.transp |= FACE_ALPHA
|
|
|
|
if edges_fgon:
|
|
msh_edges = msh.edges
|
|
FGON= Blender.Mesh.EdgeFlags.FGON
|
|
edges_fgon = msh.findEdges( edges_fgon )
|
|
if type(edges_fgon) != list: edges_fgon = [edges_fgon]
|
|
for ed in edges_fgon:
|
|
if ed!=None:
|
|
msh_edges[ed].flag |= FGON
|
|
|
|
if not(uv_flag): #clear eventual UV data
|
|
msh.faceUV = False
|
|
|
|
if uv_flag:
|
|
msh.verts.delete([0,])
|
|
|
|
return obj, not_used_faces #return the created object
|
|
|
|
|
|
# ============================================
|
|
# === Set Subsurf attributes on given mesh ===
|
|
# ============================================
|
|
def set_subsurf(obj):
|
|
mods = obj.modifiers # get the object's modifiers
|
|
mod = mods.append(Blender.Modifier.Type.SUBSURF) # add a new subsurf modifier
|
|
mod[Blender.Modifier.Settings.LEVELS] = 2 # set subsurf subdivision levels to 2
|
|
mod[Blender.Modifier.Settings.RENDLEVELS] = 2 # set subsurf rendertime subdivision levels to 2
|
|
obj.makeDisplayList()
|
|
|
|
|
|
# =================================
|
|
# === object size and dimension ===
|
|
# =================================
|
|
def obj_size_pos(obj):
|
|
bbox = obj.getBoundBox()
|
|
bbox_min = map(lambda *row: min(row), *bbox) #transpose & get min
|
|
bbox_max = map(lambda *row: max(row), *bbox) #transpose & get max
|
|
obj_size = (bbox_max[0]-bbox_min[0], bbox_max[1]-bbox_min[1], bbox_max[2]-bbox_min[2])
|
|
obj_pos = ( (bbox_max[0]+bbox_min[0]) / 2, (bbox_max[1]+bbox_min[1]) / 2, (bbox_max[2]+bbox_min[2]) / 2)
|
|
return (obj_size, obj_pos)
|
|
|
|
|
|
# =========================
|
|
# === Create the object ===
|
|
# =========================
|
|
def create_objects(clip_list, objspec_list, surf_list):
|
|
nf = len(objspec_list[3])
|
|
not_used_faces = range(nf)
|
|
ptag_dict = objspec_list[5]
|
|
obj_dict = {} #links tag names to object, used for material assignments
|
|
obj_dim_dict = {}
|
|
obj_list = [] #have it handy for parent association
|
|
middlechar = "+"
|
|
endchar = ""
|
|
if (objspec_list[6] == 1):
|
|
middlechar = endchar = "#"
|
|
for cur_tag, ptag_dict_val in ptag_dict.iteritems():
|
|
if ptag_dict_val != []:
|
|
cur_surf = get_surf(surf_list, cur_tag)
|
|
cur_obj, not_used_faces= my_create_mesh(clip_list, cur_surf, objspec_list, ptag_dict_val, objspec_list[0][:9]+middlechar+cur_tag[:9], not_used_faces)
|
|
# Works now with new modifiers
|
|
if objspec_list[6] == 1:
|
|
set_subsurf(cur_obj)
|
|
if cur_obj: # != None
|
|
obj_dict[cur_tag] = cur_obj
|
|
obj_dim_dict[cur_tag] = obj_size_pos(cur_obj)
|
|
obj_list.append(cur_obj)
|
|
#end loop on current group
|
|
#and what if some faces not used in any named PTAG? get rid of unused faces
|
|
orphans = []
|
|
for tt in not_used_faces:
|
|
if tt > -1: orphans.append(tt)
|
|
#end sweep on unused face list
|
|
not_used_faces = None
|
|
if orphans: # != []
|
|
cur_surf = get_surf(surf_list, "_Orphans")
|
|
cur_obj, not_used_faces = my_create_mesh(clip_list, cur_surf, objspec_list, orphans, objspec_list[0][:9]+middlechar+"Orphans", [])
|
|
if cur_obj: # != None
|
|
if objspec_list[6] == 1:
|
|
set_subsurf(cur_obj)
|
|
obj_dict["_Orphans"] = cur_obj
|
|
obj_dim_dict["_Orphans"] = obj_size_pos(cur_obj)
|
|
obj_list.append(cur_obj)
|
|
objspec_list[1]= obj_dict
|
|
objspec_list[4]= obj_dim_dict
|
|
|
|
return
|
|
|
|
|
|
|
|
# ===========================================
|
|
# === Lookup for image index in clip_list ===
|
|
# ===========================================
|
|
def lookup_imag(clip_list, ima_id):
|
|
for ii in clip_list:
|
|
if ii and ii['ID'] == ima_id:
|
|
if ii.has_key('XREF'):
|
|
#cross reference - recursively look for images
|
|
return lookup_imag(clip_list, ii['XREF'])
|
|
else:
|
|
return ii
|
|
return None
|
|
|
|
|
|
# ===================================================
|
|
# === Create and assign image mapping to material ===
|
|
# ===================================================
|
|
def create_blok(surf, mat, clip_list, obj_size, obj_pos):
|
|
|
|
def output_size_ofs(size, pos, blok):
|
|
#just automate repetitive task
|
|
# 0 == X, 1 == Y, 2 == Z
|
|
size_default = [1.0] * 3
|
|
size2 = [1.0] * 3
|
|
ofs_default = [0.0] * 3
|
|
offset = [1.0] * 3
|
|
axis_default = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z]
|
|
axis = [1.0] * 3
|
|
c_map_txt = [" X--", " -Y-", " --Z"]
|
|
c_map = [0,1,2] # standard, good for Z axis projection
|
|
if blok['MAJAXIS'] == 0:
|
|
c_map = [1,2,0] # X axis projection
|
|
if blok['MAJAXIS'] == 2:
|
|
c_map = [0,2,1] # Y axis projection
|
|
|
|
###if DEBUG: print "!!!axis mapping:"
|
|
#this is the smart way
|
|
###if DEBUG: for mp in c_map: print c_map_txt[mp]
|
|
|
|
if blok['SIZE'][0] != 0.0: #paranoia controls
|
|
size_default[0] = (size[0]/blok['SIZE'][0])
|
|
ofs_default[0] = ((blok['CNTR'][0]-pos[0])/blok['SIZE'][0])
|
|
if blok['SIZE'][1] != 0.0:
|
|
size_default[2] = (size[2]/blok['SIZE'][1])
|
|
ofs_default[2] = ((blok['CNTR'][1]-pos[2])/blok['SIZE'][1])
|
|
if blok['SIZE'][2] != 0.0:
|
|
size_default[1] = (size[1]/blok['SIZE'][2])
|
|
ofs_default[1] = ((blok['CNTR'][2]-pos[1])/blok['SIZE'][2])
|
|
|
|
for mp in xrange(3):
|
|
axis[mp] = axis_default[c_map[mp]]
|
|
size2[mp] = size_default[c_map[mp]]
|
|
offset[mp] = ofs_default[c_map[mp]]
|
|
if offset[mp]>10.0: offset[mp]-10.0
|
|
if offset[mp]<-10.0: offset[mp]+10.0
|
|
# size = [size_default[mp] for mp in c_map]
|
|
|
|
###if DEBUG: print "!!!texture size and offsets:"
|
|
###if DEBUG: print " sizeX = %.5f; sizeY = %.5f; sizeZ = %.5f" % (size[0],size[1],size[2])
|
|
###if DEBUG: print " ofsX = %.5f; ofsY = %.5f; ofsZ = %.5f" % (offset[0],offset[1],offset[2])
|
|
return axis, size2, offset
|
|
|
|
ti = 0
|
|
alphaflag = 0 #switched to 1 if some tex in this block is using alpha
|
|
lastimag = 0 #experimental ....
|
|
for blok in surf['BLOK']:
|
|
###if DEBUG: print "#...................................................................#"
|
|
###if DEBUG: print "# Processing texture block no.%s for surf %s" % (ti,surf['NAME'])
|
|
###if DEBUG: print "#...................................................................#"
|
|
# tobj.pdict (blok)
|
|
if ti > 9: break #only 8 channels 0..7 allowed for texture mapping
|
|
#if not blok['ENAB']:
|
|
# ###if DEBUG: print "***Image is not ENABled! Quitting this block"
|
|
# break
|
|
if not(blok.has_key('IMAG')):
|
|
###if DEBUG: print "***No IMAGE for this block? Quitting"
|
|
break #extract out the image index within the clip_list
|
|
if blok['IMAG'] == 0: blok['IMAG'] = lastimag #experimental ....
|
|
###if DEBUG: print "looking for image number %d" % blok['IMAG']
|
|
ima = lookup_imag(clip_list, blok['IMAG'])
|
|
if ima == None:
|
|
###if DEBUG: print "***Block index image not within CLIP list? Quitting Block"
|
|
break #safety check (paranoia setting)
|
|
img = ima['g_IMG']
|
|
lastimag = blok['IMAG'] #experimental ....
|
|
if img == None:
|
|
###if DEBUG: print "***Failed to pre-allocate image %s found: giving up" % ima['BASENAME']
|
|
break
|
|
tname = str(ima['ID'])
|
|
if blok['ENAB']:
|
|
tname += "+"
|
|
else:
|
|
tname += "x" #let's signal when should not be enabled
|
|
if blok.has_key('CHAN'):
|
|
tname += blok['CHAN']
|
|
newtex = bpy.data.textures.new(tname)
|
|
newtex.setType('Image') # make it anu image texture
|
|
newtex.image = img
|
|
#how does it extends beyond borders
|
|
if blok.has_key('WRAP'):
|
|
if (blok['WRAP'] == 3) or (blok['WRAP'] == 2):
|
|
newtex.setExtend('Extend')
|
|
elif (blok['WRAP'] == 1):
|
|
newtex.setExtend('Repeat')
|
|
elif (blok['WRAP'] == 0):
|
|
newtex.setExtend('Clip')
|
|
###if DEBUG: print "generated texture %s" % tname
|
|
|
|
#MapTo is determined by CHAN parameter
|
|
#assign some defaults
|
|
colfac = 1.0
|
|
dvar = 1.0
|
|
norfac = 0.5
|
|
nega = False
|
|
mapflag = Blender.Texture.MapTo.COL #default to color
|
|
maptype = Blender.Texture.Mappings.FLAT
|
|
if blok.has_key('CHAN'):
|
|
if blok['CHAN'] == 'COLR' and blok.has_key('OPACVAL'):
|
|
colfac = blok['OPACVAL']
|
|
# Blender needs this to be clamped
|
|
colfac = max(0.0, min(1.0, colfac))
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> Col = %.3f" % colfac
|
|
if blok['CHAN'] == 'BUMP':
|
|
mapflag = Blender.Texture.MapTo.NOR
|
|
if blok.has_key('OPACVAL'): norfac = blok['OPACVAL']
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> Nor = %.3f" % norfac
|
|
if blok['CHAN'] == 'LUMI':
|
|
mapflag = Blender.Texture.MapTo.EMIT
|
|
if blok.has_key('OPACVAL'): dvar = blok['OPACVAL']
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
|
|
if blok['CHAN'] == 'DIFF':
|
|
mapflag = Blender.Texture.MapTo.REF
|
|
if blok.has_key('OPACVAL'): dvar = blok['OPACVAL']
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
|
|
if blok['CHAN'] == 'SPEC':
|
|
mapflag = Blender.Texture.MapTo.SPEC
|
|
if blok.has_key('OPACVAL'): dvar = blok['OPACVAL']
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
|
|
if blok['CHAN'] == 'TRAN':
|
|
mapflag = Blender.Texture.MapTo.ALPHA
|
|
if blok.has_key('OPACVAL'): dvar = blok['OPACVAL']
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
|
|
alphaflag = 1
|
|
nega = True
|
|
if blok.has_key('NEGA'):
|
|
###if DEBUG: print "!!!Watch-out: effect of this texture channel must be INVERTED!"
|
|
nega = not nega
|
|
|
|
blendmode_list = ['Mix',
|
|
'Subtractive',
|
|
'Difference',
|
|
'Multiply',
|
|
'Divide',
|
|
'Mix with calculated alpha layer and stencil flag',
|
|
'Texture Displacement',
|
|
'Additive']
|
|
set_blendmode = 7 #default additive
|
|
if blok.has_key('OPAC'):
|
|
set_blendmode = blok['OPAC']
|
|
if set_blendmode == 5: #transparency
|
|
newtex.imageFlags |= Blender.Texture.ImageFlags.CALCALPHA
|
|
if nega: newtex.flags |= Blender.Texture.Flags.NEGALPHA
|
|
###if DEBUG: print "!!!Set Texture -> MapTo -> Blending Mode = %s" % blendmode_list[set_blendmode]
|
|
|
|
#the TexCo flag is determined by PROJ parameter
|
|
axis = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z]
|
|
size = [1.0] * 3
|
|
ofs = [0.0] * 3
|
|
if blok.has_key('PROJ'):
|
|
if blok['PROJ'] == 0: #0 - Planar
|
|
###if DEBUG: print "!!!Flat projection"
|
|
coordflag = Blender.Texture.TexCo.ORCO
|
|
maptype = Blender.Texture.Mappings.FLAT
|
|
elif blok['PROJ'] == 1: #1 - Cylindrical
|
|
###if DEBUG: print "!!!Cylindrical projection"
|
|
coordflag = Blender.Texture.TexCo.ORCO
|
|
maptype = Blender.Texture.Mappings.TUBE
|
|
elif blok['PROJ'] == 2: #2 - Spherical
|
|
###if DEBUG: print "!!!Spherical projection"
|
|
coordflag = Blender.Texture.TexCo.ORCO
|
|
maptype = Blender.Texture.Mappings.SPHERE
|
|
elif blok['PROJ'] == 3: #3 - Cubic
|
|
###if DEBUG: print "!!!Cubic projection"
|
|
coordflag = Blender.Texture.TexCo.ORCO
|
|
maptype = Blender.Texture.Mappings.CUBE
|
|
elif blok['PROJ'] == 4: #4 - Front Projection
|
|
###if DEBUG: print "!!!Front projection"
|
|
coordflag = Blender.Texture.TexCo.ORCO
|
|
maptype = Blender.Texture.Mappings.FLAT # ??? could it be a FLAT with some other TexCo type?
|
|
elif blok['PROJ'] == 5: #5 - UV
|
|
###if DEBUG: print "UVMapped"
|
|
coordflag = Blender.Texture.TexCo.UV
|
|
maptype = Blender.Texture.Mappings.FLAT #in case of UV default to FLAT mapping => effectively not used
|
|
if blok['PROJ'] != 5: #This holds for any projection map except UV
|
|
axis, size, ofs = output_size_ofs(obj_size, obj_pos, blok)
|
|
|
|
# Clamp ofs and size else blender will raise an error
|
|
for ii in xrange(3):
|
|
ofs[ii]= min(10.0, max(-10, ofs[ii]))
|
|
size[ii]= min(100, max(-100, size[ii]))
|
|
|
|
mat.setTexture(ti, newtex, coordflag, mapflag)
|
|
current_mtex = mat.getTextures()[ti]
|
|
current_mtex.mapping = maptype
|
|
current_mtex.colfac = colfac
|
|
current_mtex.dvar = dvar
|
|
current_mtex.norfac = norfac
|
|
current_mtex.neg = nega
|
|
current_mtex.xproj = axis[0]
|
|
current_mtex.yproj = axis[1]
|
|
current_mtex.zproj = axis[2]
|
|
current_mtex.size = tuple(size)
|
|
current_mtex.ofs = tuple(ofs)
|
|
if (set_blendmode == 5): #transparency
|
|
current_mtex.stencil = not (nega)
|
|
|
|
ti += 1
|
|
#end loop over bloks
|
|
return alphaflag
|
|
|
|
|
|
# ========================================
|
|
# === Create and assign a new material ===
|
|
# ========================================
|
|
#def update_material(surf_list, ptag_dict, obj, clip_list, uv_dict, dir_part):
|
|
def update_material(clip_list, objspec, surf_list):
|
|
if (surf_list == []) or (objspec[5] == {}) or (objspec[1] == {}):
|
|
###if DEBUG: print "something getting wrong in update_material: dump follows ..."
|
|
###if DEBUG: print surf_list
|
|
###if DEBUG: print objspec[5]
|
|
###if DEBUG: print objspec[1]
|
|
return
|
|
obj_dict = objspec[1]
|
|
all_faces = objspec[3]
|
|
obj_dim_dict = objspec[4]
|
|
ptag_dict = objspec[5]
|
|
uvcoords_dict = objspec[7]
|
|
facesuv_dict = objspec[8]
|
|
for surf in surf_list:
|
|
if surf and surf['NAME'] in ptag_dict: # in ptag_dict.keys()
|
|
###if DEBUG: print "#-------------------------------------------------------------------#"
|
|
###if DEBUG: print "Processing surface (material): %s" % surf['NAME']
|
|
###if DEBUG: print "#-------------------------------------------------------------------#"
|
|
#material set up
|
|
facelist = ptag_dict[surf['NAME']]
|
|
#bounding box and position
|
|
cur_obj = obj_dict[surf['NAME']]
|
|
obj_size = obj_dim_dict[surf['NAME']][0]
|
|
obj_pos = obj_dim_dict[surf['NAME']][1]
|
|
###if DEBUG: print surf
|
|
#uncomment this if material pre-allocated by read_surf
|
|
mat = surf['g_MAT']
|
|
if mat == None:
|
|
###if DEBUG: print "Sorry, no pre-allocated material to update. Giving up for %s." % surf['NAME']
|
|
break
|
|
#mat = Blender.Material.New(surf['NAME'])
|
|
#surf['g_MAT'] = mat
|
|
if surf.has_key('COLR'):
|
|
mat.rgbCol = surf['COLR']
|
|
if surf.has_key('LUMI'):
|
|
mat.setEmit(surf['LUMI'])
|
|
if surf.has_key('GVAL'):
|
|
mat.setAdd(surf['GVAL'])
|
|
if surf.has_key('SPEC'):
|
|
mat.setSpec(surf['SPEC']) #it should be * 2 but seems to be a bit higher lwo [0.0, 1.0] - blender [0.0, 2.0]
|
|
if surf.has_key('DIFF'):
|
|
mat.setRef(surf['DIFF']) #lwo [0.0, 1.0] - blender [0.0, 1.0]
|
|
if surf.has_key('GLOS'): #lwo [0.0, 1.0] - blender [0, 255]
|
|
glo = int(371.67 * surf['GLOS'] - 42.334) #linear mapping - seems to work better than exp mapping
|
|
if glo <32: glo = 32 #clamped to 32-255
|
|
if glo >255: glo = 255
|
|
mat.setHardness(glo)
|
|
if surf.has_key('TRNL'):
|
|
mat.setTranslucency(surf['TRNL']) #NOT SURE ABOUT THIS lwo [0.0, 1.0] - blender [0.0, 1.0]
|
|
|
|
mm = mat.getMode()
|
|
mm |= Blender.Material.Modes.TRANSPSHADOW
|
|
if surf.has_key('REFL'):
|
|
mat.setRayMirr(surf['REFL']) #lwo [0.0, 1.0] - blender [0.0, 1.0]
|
|
mm |= Blender.Material.Modes.RAYMIRROR
|
|
if surf.has_key('TRAN'):
|
|
mat.setAlpha(1.0-surf['TRAN']) #lwo [0.0, 1.0] - blender [1.0, 0.0]
|
|
mm |= Blender.Material.Modes.RAYTRANSP
|
|
if surf.has_key('RIND'):
|
|
s = surf['RIND']
|
|
if s < 1.0: s = 1.0
|
|
if s > 3.0: s = 3.0
|
|
mat.setIOR(s) #clipped to blender [1.0, 3.0]
|
|
mm |= Blender.Material.Modes.RAYTRANSP
|
|
if surf.has_key('BLOK') and surf['BLOK'] != []:
|
|
#update the material according to texture.
|
|
alphaflag = create_blok(surf, mat, clip_list, obj_size, obj_pos)
|
|
if alphaflag:
|
|
mm |= Blender.Material.Modes.RAYTRANSP
|
|
mat.setMode(mm)
|
|
#finished setting up the material
|
|
#end if exist SURF
|
|
#end loop on materials (SURFs)
|
|
return
|
|
|
|
|
|
# ======================
|
|
# === Read Faces 6.0 ===
|
|
# ======================
|
|
def read_faces_6(lwochunk):
|
|
data = cStringIO.StringIO(lwochunk.read())
|
|
faces = []
|
|
polygon_type = data.read(4)
|
|
subsurf = 0
|
|
if polygon_type != "FACE" and polygon_type != "PTCH":
|
|
###if DEBUG: print "No FACE/PATCH Were Found. Polygon Type: %s" % polygon_type
|
|
return "", 2
|
|
if polygon_type == 'PTCH': subsurf = 1
|
|
i = 0
|
|
while(i < lwochunk.chunksize-4):
|
|
#if not i%1000 and my_meshtools.show_progress:
|
|
# Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
|
|
facev = []
|
|
numfaceverts, = struct.unpack(">H", data.read(2))
|
|
i += 2
|
|
|
|
for j in xrange(numfaceverts):
|
|
index, index_size = read_vx(data)
|
|
i += index_size
|
|
facev.append(index)
|
|
faces.append(facev)
|
|
###if DEBUG: print "read %s faces; type of block %d (0=FACE; 1=PATCH)" % (len(faces), subsurf)
|
|
return faces, subsurf
|
|
|
|
def main():
|
|
if not struct:
|
|
Blender.Draw.PupMenu('This importer requires a full python install')
|
|
return
|
|
|
|
Blender.Window.FileSelector(read, "Import LWO", '*.lwo')
|
|
|
|
if __name__=='__main__':
|
|
main()
|
|
|
|
# Cams debugging lwo loader
|
|
"""
|
|
TIME= Blender.sys.time()
|
|
import os
|
|
print 'Searching for files'
|
|
os.system('find /fe/ -iname "*.lwo" > /tmp/templwo_list')
|
|
# os.system('find /storage/ -iname "*.lwo" > /tmp/templwo_list')
|
|
print '...Done'
|
|
file= open('/tmp/templwo_list', 'r')
|
|
lines= file.readlines()
|
|
file.close()
|
|
|
|
def between(v,a,b):
|
|
if v <= max(a,b) and v >= min(a,b):
|
|
return True
|
|
|
|
return False
|
|
size= 0.0
|
|
for i, _lwo in enumerate(lines):
|
|
#if i==425: # SCANFILL
|
|
#if 1:
|
|
#if i==520: # SCANFILL CRASH
|
|
#if i==47: # SCANFILL CRASH
|
|
#if between(i, 525, 550):
|
|
#if i > 1635:
|
|
#if i != 1519: # 730
|
|
if 1:
|
|
_lwo= _lwo[:-1]
|
|
print 'Importing', _lwo, '\nNUMBER', i, 'of', len(lines)
|
|
_lwo_file= _lwo.split('/')[-1].split('\\')[-1]
|
|
newScn= bpy.data.scenes.new(_lwo_file)
|
|
bpy.data.scenes.active = newScn
|
|
size += ((os.path.getsize(_lwo)/1024.0))/ 1024.0
|
|
read(_lwo)
|
|
# Remove objects to save memory?
|
|
'''
|
|
for ob in newScn.objects:
|
|
if ob.type=='Mesh':
|
|
me= ob.getData(mesh=1)
|
|
me.verts= None
|
|
newScn.unlink(ob)
|
|
'''
|
|
print 'mb size so far', size
|
|
|
|
print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
|
|
""" |