diff options
Diffstat (limited to 'release/scripts/lightwave_import.py')
-rw-r--r-- | release/scripts/lightwave_import.py | 1705 |
1 files changed, 0 insertions, 1705 deletions
diff --git a/release/scripts/lightwave_import.py b/release/scripts/lightwave_import.py deleted file mode 100644 index 6d02467cef8..00000000000 --- a/release/scripts/lightwave_import.py +++ /dev/null @@ -1,1705 +0,0 @@ -#!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 - -# python 2.3 has no reversed() iterator. this will only work on lists and tuples -try: - reversed -except: - def reversed(l): return l[::-1] - -### # 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()) - data_str = data.read(4) - if len(data_str) < 4: # can be zero also??? :/ - # Should not happen but lw can import so we should too - return - - image_index, = struct.unpack(">L", data_str) - 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 'XREF' in clip_dict: # has_key - ###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=False) - 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=False) - - ###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 - # all are dictionaries - so testing keys - if not('g_IMAG' in my_dict) and ('CHAN' in rr) and ('OPAC' in rr) and ('IMAG' in rr): - 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 - -# ========================= -# === 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 'SMAN' in surf: # has_key - #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 = (('UVNAME' in surf) and (surf['UVNAME'] in uvcoords_dict)) - - ###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: - try: - uvs.append(uvcoords_dict_context[ vi ]) - except: - ###if DEBUG: print '\tWarning, Corrupt UVs' - uvs.append(default_uv) - - return uvs - cur_face - 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 or numfaceverts == 4: - rev_face = [__i for __i in reversed(cur_face)] - 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 > 4: - meta_faces= BPyMesh.ngon(complete_vertlist, cur_face, PREF_FIX_LOOPS= True) - edge_face_count = {} - for mf in meta_faces: - # These will always be tri's since they are scanfill faces - 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 j in xrange(3): - v1= mf[j] - v2= mf[j-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 - - - - if edge_face_count: - edges_fgon.extend( [vert_key for vert_key, count in edge_face_count.iteritems() if count] ) - - if edges: - msh.edges.extend(edges) - - face_mapping_removed = msh.faces.extend(face_data, indexList=True) - if 'TRAN' in surf 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 'XREF' in ii: # has_key - #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('IMAG' in blok): # has_key - ###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 'CHAN' in blok: # has_key - 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 'WRAP' in blok: # has_key - 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 'CHAN' in blok: # has_key - if blok['CHAN'] == 'COLR' and 'OPACVAL' in blok: # has_key - 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 'OPACVAL' in blok: norfac = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> Nor = %.3f" % norfac - if blok['CHAN'] == 'LUMI': - mapflag = Blender.Texture.MapTo.EMIT - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'DIFF': - mapflag = Blender.Texture.MapTo.REF - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'SPEC': - mapflag = Blender.Texture.MapTo.SPEC - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - if blok['CHAN'] == 'TRAN': - mapflag = Blender.Texture.MapTo.ALPHA - if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key - ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar - alphaflag = 1 - nega = True - if 'NEGA' in blok: # has_key - ###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 'OPAC' in blok: # has_key - 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 'PROJ' in blok: # has_key - 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 'COLR' in surf: # has_key - mat.rgbCol = surf['COLR'] - if 'LUMI' in surf: - mat.setEmit(surf['LUMI']) - if 'GVAL' in surf: # has_key - mat.setAdd(surf['GVAL']) - if 'SPEC' in surf: # has_key - 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 'DIFF' in surf: # has_key - mat.setRef(surf['DIFF']) #lwo [0.0, 1.0] - blender [0.0, 1.0] - if 'GLOS' in surf: # has_key #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 'TRNL' in surf: # has_key - mat.setTranslucency(surf['TRNL']) #NOT SURE ABOUT THIS lwo [0.0, 1.0] - blender [0.0, 1.0] - - mm = mat.mode - mm |= Blender.Material.Modes.TRANSPSHADOW - if 'REFL' in surf: # has_key - mat.setRayMirr(surf['REFL']) #lwo [0.0, 1.0] - blender [0.0, 1.0] - mm |= Blender.Material.Modes.RAYMIRROR - if 'TRAN' in surf: # has_key - mat.setAlpha(1.0-surf['TRAN']) #lwo [0.0, 1.0] - blender [1.0, 0.0] - mm |= Blender.Material.Modes.RAYTRANSP - if 'RIND' in surf: # has_key - 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 'BLOK' in surf 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.mode = 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/lwo/Objects/ -follow -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() - -# sort by filesize for faster testing -lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines] -lines_size.sort() -lines = [f[1] for f in lines_size] - -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 i>141: - #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) -"""
\ No newline at end of file |