diff options
Diffstat (limited to 'release/scripts/wings_import.py')
-rw-r--r-- | release/scripts/wings_import.py | 191 |
1 files changed, 160 insertions, 31 deletions
diff --git a/release/scripts/wings_import.py b/release/scripts/wings_import.py index 70f124b3bac..8bba6f52de7 100644 --- a/release/scripts/wings_import.py +++ b/release/scripts/wings_import.py @@ -11,7 +11,7 @@ __author__ = "Anthony D'Agostino (Scorpius)" __url__ = ("blender", "elysiun", "Author's homepage, http://www.redrival.com/scorpius", "Wings 3D, http://www.wings3d.com") -__version__ = "Part of IOSuite 0.5" +__version__ = "Update on version from IOSuite 0.5" __bpydoc__ = """\ This script imports Wings3D files to Blender. @@ -37,7 +37,8 @@ fanning algorithm. Convex polygons (i.e., shaped like the letter "U") require a different algorithm, and will be triagulated incorrectly. Notes:<br> - Last tested with Wings 3D 0.98.25 & Blender 2.35a. + Last tested with Wings 3D 0.98.25 & Blender 2.35a.<br> + This version has improvements made by Adam Saltsman (AdamAtomic) and Toastie. """ # $Id$ @@ -47,15 +48,29 @@ Notes:<br> # | http://www.redrival.com/scorpius | # | scorpius@netzero.com | # | Feb 19, 2002 | -# | Released under the Blender Artistic Licence (BAL) | -# | Import Export Suite v0.5 | -# +---------------------------------------------------------+ -# | Read and write Wings3D File Format (*.wings) | -# +---------------------------------------------------------+ + +# ***** BEGIN 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. +# +# ***** END GPL LICENCE BLOCK ***** + import Blender, meshtools import struct, time, sys, os, zlib, cStringIO - + # ============================================== # === Read The 'Header' Common To All Chunks === # ============================================== @@ -79,26 +94,28 @@ def read_mode(data): # === Read Hard Edges === # ======================= def read_hardedges(data): + hardedge_table = {} # hard edges table tag = data.read(1) if tag == '\x6A': - return # There are no hard edges + return hardedge_table # There are no hard edges elif tag == '\x6B': numhardedges, = struct.unpack(">H", data.read(2)) - print "numhardedges:", numhardedges + #print "numhardedges:", numhardedges for i in range(numhardedges): - data.read(1) + hardedge_table[i] = struct.unpack(">B", data.read(1))[0] elif tag == '\x6C': numhardedges, = struct.unpack(">L", data.read(4)) - print "numhardedges:", numhardedges + #print "numhardedges:", numhardedges for i in range(numhardedges): misc = data.read(1) if misc == '\x61': # next value is stored as a byte - data.read(1) + hardedge_table[i] = struct.unpack(">B", data.read(1))[0] elif misc == '\x62': # next value is stored as a long - data.read(4) + hardedge_table[i] = struct.unpack(">L", data.read(4))[0] data.read(1) # 6A else: print tag + return hardedge_table # ================== # === Read Edges === @@ -134,6 +151,7 @@ def read_edges(data): # === Read Faces === # ================== def read_faces(data): + mat_table = {} #list of faces and material names misc, numfaces = struct.unpack(">BL", data.read(5)) for i in range(numfaces): if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces") @@ -141,10 +159,10 @@ def read_faces(data): data.read(4) read_chunkheader(data) misc, namelen = struct.unpack(">BH", data.read(3)) - materialname = data.read(namelen) - data.read(1) + mat_table[i] = data.read(namelen) + data.read(1) # 6A? data.read(1) # 6A - return numfaces + return mat_table # ================== # === Read Verts === @@ -169,8 +187,10 @@ def make_face_table(edge_table): # For Wings for i in range(len(edge_table)): Lf = edge_table[i][2] Rf = edge_table[i][3] - face_table[Lf] = i - face_table[Rf] = i + if Lf >= 0: + face_table[Lf] = i + if Rf >= 0: + face_table[Rf] = i return face_table # ======================= @@ -198,14 +218,17 @@ def make_faces(edge_table): # For Wings if i == edge_table[current_edge][3]: next_edge = edge_table[current_edge][7] # Right successor edge next_vert = edge_table[current_edge][0] - else: + elif i == edge_table[current_edge][2]: next_edge = edge_table[current_edge][5] # Left successor edge next_vert = edge_table[current_edge][1] + else: + break face_verts.append(next_vert) current_edge = next_edge if current_edge == face_table[i]: break - face_verts.reverse() - faces.append(face_verts) + if len(face_verts) > 0: + face_verts.reverse() + faces.append(face_verts) return faces # ======================= @@ -223,7 +246,7 @@ def dump_wings(filename): file.close() data = zlib.decompress(data) if dsize != len(data): print "ERROR: uncompressed size does not match." - data = cStringIO.StringIO(data) + data = cStringIO.StringIO(data) print "header:", header print read_chunkheader(data) # === wings chunk === data.read(4) # misc bytes @@ -236,9 +259,10 @@ def dump_wings(filename): objname = data.read(namelen) print read_chunkheader(data) # === winged chunk === edge_table = read_edges(data) - numfaces = read_faces(data) + mat_table = read_faces(data) + numfaces = len(mat_table) verts = read_verts(data) - read_hardedges(data) + hardedge_table = read_hardedges(data) face_table = {} # contains an incident edge vert_table = {} # contains an incident edge @@ -255,25 +279,26 @@ def dump_wings(filename): print print "Ä"*79 print "edge_table:" - pprint.pprint(edge_table) + #pprint.pprint(edge_table) #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i] print print "face_table:" - pprint.pprint(face_table) + #pprint.pprint(face_table) #for i in range(len(face_table)): print "%2d %2d" % (i, face_table[i]) print print "vert_table:" - pprint.pprint(vert_table) + #pprint.pprint(vert_table) #for i in range(len(vert_table)): print "%2d %2d" % (i, vert_table[i]) file.close() end = time.clock() print '\a\r', - sys.stderr.write("\nDone in %.2f %s" % (end-start, "seconds")) + sys.stderr.write("\nDone in %.2f %s\a\r" % (end-start, "seconds")) # ========================= # === Read Wings Format === # ========================= def read(filename): + start = time.clock() file = open(filename, "rb") header = file.read(15) @@ -299,9 +324,113 @@ def read(filename): objname = data.read(namelen) read_chunkheader(data) # winged chunk edge_table = read_edges(data) - numfaces = read_faces(data) + mat_table = read_faces(data) + numfaces = len(mat_table) verts = read_verts(data) - read_hardedges(data) + hardedge_table = read_hardedges(data) + + # Manually split hard edges + # TODO: Handle the case where there are 2+ edges on a face + duped = {} + processed = [] + cleanup = [] + oldedgecount = len(edge_table) + for i in range(len(verts)): + duped[i] = -1 + for j in range(len(hardedge_table)): + hardedge = hardedge_table[j] + oldedge = edge_table[hardedge] + newedge = [] # Copy old edge into a new list + for k in range(len(oldedge)): + newedge.append(oldedge[k]) + + # Duplicate start vert if not duped already + sv = newedge[0] + if duped[sv] == -1: + verts.append(verts[sv]) + duped[sv] = len(verts)-1 + newedge[0] = duped[sv] + + # Duplicate end vert if not duped already + ev = newedge[1] + if duped[ev] == -1: + verts.append(verts[ev]) + duped[ev] = len(verts)-1 + newedge[1] = duped[ev] + + # Decide which way to cut the edge + flip = 0 + for v in range(len(processed)): + if processed[v][0] == oldedge[0]: + flip = 1 + elif processed[v][1] == oldedge[1]: + flip = 1 + if flip == 0: + of = 3 + oe1 = 6 + oe2 = 7 + nf = 2 + ne1 = 4 + ne2 = 5 + else: + of = 2 + oe1 = 4 + oe2 = 5 + nf = 3 + ne1 = 6 + ne2 = 7 + + # Fix up side-specific edge fields + oldedge[of] = -1 + oldedge[oe1] = -1 + oldedge[oe2] = -1 + newedge[nf] = -1 + newedge[ne1] = -1 + newedge[ne2] = -1 + + # Store new edge's neighbors for cleanup later + cleanup.append(edge_table[newedge[oe1]]) + cleanup.append(edge_table[newedge[oe2]]) + + #DEBUG + # Sv Ev | Lf Rf | Lp Ls | Rp Rs + #print "Old Edge:",hardedge,oldedge + #print "New Edge:",len(edge_table),newedge + + # Add this new edge to the edge table + edge_table[len(edge_table)] = newedge + if flip == 0: + processed.append(oldedge) # mark it off as processed + + # Cycle through cleanup list and fix it up + for c in range(len(cleanup)): + cleanupedge = cleanup[c] + + # Fix up their verts in case they were duped + sv = cleanupedge[0] + if sv < len(duped): + if duped[sv] >= 0: + cleanupedge[0] = duped[sv] + ev = cleanupedge[1] + if ev < len(duped): + if duped[ev] >= 0: + cleanupedge[1] = duped[ev] + + # Fix up edge info (in case a hard edge was replaced with a new one) + edgecount = c/2 + hardedge = hardedge_table[edgecount] # look up what edge we were replacing + newedgenum = oldedgecount+edgecount # calculate new edge's index + if cleanupedge[4] == hardedge: + cleanupedge[4] = newedgenum + if cleanupedge[5] == hardedge: + cleanupedge[5] = newedgenum + if cleanupedge[6] == hardedge: + cleanupedge[6] = newedgenum + if cleanupedge[7] == hardedge: + cleanupedge[7] = newedgenum + + #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i] + read_mode(data) faces = make_faces(edge_table) message += "%s %8s %8s %8s\n" % (objname.ljust(15), len(faces), len(edge_table), len(verts)) |