9633c94355eeed87d1e6ab881b819e82fd2ea775
[blender.git] / release / scripts / wings_import.py
1 #!BPY
2
3 """
4 Name: 'Wings3D (.wings)...'
5 Blender: 232
6 Group: 'Import'
7 Tooltip: 'Import Wings3D File Format (.wings)'
8 """
9
10 __author__ = "Anthony D'Agostino (Scorpius)"
11 __url__ = ("blender", "elysiun",
12 "Author's homepage, http://www.redrival.com/scorpius",
13 "Wings 3D, http://www.wings3d.com")
14 __version__ = "Part of IOSuite 0.5"
15
16 __bpydoc__ = """\
17 This script imports Wings 3d files to Blender.
18
19 Usage:
20
21 Execute this script from the "File->Import" menu and choose a Wings file to
22 open.
23 """
24
25 # $Id$
26 #
27 # +---------------------------------------------------------+
28 # | Copyright (c) 2002 Anthony D'Agostino                   |
29 # | http://www.redrival.com/scorpius                        |
30 # | scorpius@netzero.com                                    |
31 # | Feb 19, 2002                                            |
32 # | Released under the Blender Artistic Licence (BAL)       |
33 # | Import Export Suite v0.5                                |
34 # +---------------------------------------------------------+
35 # | Read and write Wings3D File Format (*.wings)            |
36 # +---------------------------------------------------------+
37
38 import Blender, mod_meshtools
39 import struct, time, sys, os, zlib, cStringIO
40
41 # ==============================================
42 # === Read The 'Header' Common To All Chunks ===
43 # ==============================================
44 def read_chunkheader(data):
45         data.read(2) #version, tag = struct.unpack(">BB", data.read(2))
46         misc, namelen = struct.unpack(">BH", data.read(3))
47         name = data.read(namelen)
48         return name
49
50 # ==============================
51 # === Read The Material Mode ===
52 # ==============================
53 def read_mode(data):
54         data.read(5)                    # BL
55         read_chunkheader(data)  # "mode"
56         misc, namelen = struct.unpack(">BH", data.read(3))
57         data.read(namelen)
58         data.read(1)                    # 6A
59
60 # =======================
61 # === Read Hard Edges ===
62 # =======================
63 def read_hardedges(data):
64         tag = data.read(1)
65         if tag == '\x6A':
66                 return # There are no hard edges
67         elif tag == '\x6B':
68                 numhardedges, = struct.unpack(">H", data.read(2))
69                 print "numhardedges:", numhardedges
70                 for i in range(numhardedges):
71                         data.read(1)
72         elif tag == '\x6C':
73                 numhardedges, = struct.unpack(">L", data.read(4))
74                 print "numhardedges:", numhardedges
75                 for i in range(numhardedges):
76                         misc = data.read(1)
77                         if misc == '\x61':    # next value is stored as a byte
78                                 data.read(1)
79                         elif misc == '\x62':  # next value is stored as a long
80                                 data.read(4)
81                 data.read(1) # 6A
82         else:
83                 print tag
84
85 # ==================
86 # === Read Edges ===
87 # ==================
88 def read_edges(data):
89         misc, numedges = struct.unpack(">BL", data.read(5))
90         edge_table = {}  # the winged-edge table
91         for i in range(numedges):
92                 if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Reading Edges")
93                 misc, etype = struct.unpack(">BL", data.read(5))
94                 if etype == 2:                          # Vertex Colors
95                         data.read(10)                   # or read_chunkheader(data)  # "color"
96                         data.read(5)                    # BL
97                         r1,g1,b1,r2,g2,b2 = struct.unpack(">dddddd", data.read(48))
98                         #print "%3d %3d %3d | %3d %3d %3d" % (r1*255,g1*255,b1*255,r2*255,g2*255,b2*255),
99                         #print "%f %f %f | %f %f %f" % (r1, g1, b1, r2, g2, b2)
100                 data.read(9) # or read_chunkheader(data)  # "edge"
101                 edge = []                       # the eight entries for this edge
102                 for e in range(8):      # Sv Ev | Lf Rf | Lp Ls | Rp Rs
103                         misc = data.read(1)
104                         if misc == '\x61':    # next value is stored as a byte
105                                 entry, = struct.unpack(">B", data.read(1))
106                                 edge.append(entry)
107                         elif misc == '\x62':  # next value is stored as a long
108                                 entry, = struct.unpack(">L", data.read(4))
109                                 edge.append(entry)
110                 edge_table[i] = edge
111                 data.read(1) # 6A
112         data.read(1) # 6A
113         return edge_table
114
115 # ==================
116 # === Read Faces ===
117 # ==================
118 def read_faces(data):
119         misc, numfaces = struct.unpack(">BL", data.read(5))
120         for i in range(numfaces):
121                 if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Reading Faces")
122                 if data.read(1) == '\x6C':  # a material follows
123                         data.read(4)
124                         read_chunkheader(data)
125                         misc, namelen = struct.unpack(">BH", data.read(3))
126                         materialname = data.read(namelen)
127                         data.read(1)
128         data.read(1) # 6A
129         return numfaces
130
131 # ==================
132 # === Read Verts ===
133 # ==================
134 def read_verts(data):
135         misc, numverts = struct.unpack(">BL", data.read(5))
136         verts = []      # a list of verts
137         for i in range(numverts):
138                 if not i%100 and mod_meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
139                 data.read(10)
140                 x, y, z = struct.unpack(">ddd", data.read(24))  # double precision
141                 verts.append((x, -z, y))
142                 data.read(1) # 6A
143         data.read(1) # 6A
144         return verts
145
146 # =======================
147 # === Make Face Table ===
148 # =======================
149 def make_face_table(edge_table): # For Wings
150         face_table = {}
151         for i in range(len(edge_table)):
152                 Lf = edge_table[i][2]
153                 Rf = edge_table[i][3]
154                 face_table[Lf] = i
155                 face_table[Rf] = i
156         return face_table
157
158 # =======================
159 # === Make Vert Table ===
160 # =======================
161 def make_vert_table(edge_table): # For Wings
162         vert_table = {}
163         for i in range(len(edge_table)):
164                 Sv = edge_table[i][0]
165                 Ev = edge_table[i][1]
166                 vert_table[Sv] = i
167                 vert_table[Ev] = i
168         return vert_table
169
170 # ==================
171 # === Make Faces ===
172 # ==================
173 def make_faces(edge_table): # For Wings
174         face_table = make_face_table(edge_table)
175         faces=[]
176         for i in range(len(face_table)):
177                 face_verts = []
178                 current_edge = face_table[i]
179                 while(1):
180                         if i == edge_table[current_edge][3]:
181                                 next_edge = edge_table[current_edge][7] # Right successor edge
182                                 next_vert = edge_table[current_edge][0]
183                         else:
184                                 next_edge = edge_table[current_edge][5] # Left successor edge
185                                 next_vert = edge_table[current_edge][1]
186                         face_verts.append(next_vert)
187                         current_edge = next_edge
188                         if current_edge == face_table[i]: break
189                 face_verts.reverse()
190                 faces.append(face_verts)
191         return faces
192
193 # =======================
194 # === Dump Wings File ===
195 # =======================
196 def dump_wings(filename):
197         import pprint
198         start = time.clock()
199         file = open(filename, "rb")
200         header = file.read(15)
201         fsize, = struct.unpack(">L",  file.read(4))   # file_size - 19
202         misc,  = struct.unpack(">H",  file.read(2))
203         dsize, = struct.unpack(">L",  file.read(4))   # uncompressed data size
204         data   = file.read(fsize-6)
205         file.close()
206         data = zlib.decompress(data)
207         if dsize != len(data): print "ERROR: uncompressed size does not match."
208         data = cStringIO.StringIO(data)
209         print "header:", header
210         print read_chunkheader(data)  # === wings chunk ===
211         data.read(4) # misc bytes
212         misc, numobjs, = struct.unpack(">BL", data.read(5))
213         print "filename:", filename
214         print "numobjs :", numobjs
215         for obj in range(numobjs):
216                 print read_chunkheader(data) # === object chunk ===
217                 misc, namelen = struct.unpack(">BH", data.read(3))
218                 objname = data.read(namelen)
219                 print read_chunkheader(data) # === winged chunk ===
220                 edge_table = read_edges(data)
221                 numfaces = read_faces(data)
222                 verts = read_verts(data)
223                 read_hardedges(data)
224
225                 face_table = {}  # contains an incident edge
226                 vert_table = {}  # contains an incident edge
227                 for i in range(len(edge_table)):
228                         face_table[edge_table[i][2]] = i  # generate face_table
229                         face_table[edge_table[i][3]] = i
230                         vert_table[edge_table[i][0]] = i  # generate vert_table
231                         vert_table[edge_table[i][1]] = i
232
233                 print "objname :", objname
234                 print "numedges:", len(edge_table)
235                 print "numfaces:", numfaces
236                 print "numverts:", len(verts)
237                 print
238                 print "Ä"*79
239                 print "edge_table:"
240                 pprint.pprint(edge_table)
241                 #for i in range(len(edge_table)): print "%2d" % (i), edge_table[i]
242                 print
243                 print "face_table:"
244                 pprint.pprint(face_table)
245                 #for i in range(len(face_table)): print "%2d %2d" % (i, face_table[i])
246                 print
247                 print "vert_table:"
248                 pprint.pprint(vert_table)
249                 #for i in range(len(vert_table)): print "%2d %2d" % (i, vert_table[i])
250         file.close()
251         end = time.clock()
252         print '\a\r',
253         sys.stderr.write("\nDone in %.2f %s" % (end-start, "seconds"))
254
255 # =========================
256 # === Read Wings Format ===
257 # =========================
258 def read(filename):
259         start = time.clock()
260         file = open(filename, "rb")
261         header = file.read(15)
262         fsize, = struct.unpack(">L",  file.read(4))   # file_size - 19
263         misc,  = struct.unpack(">H",  file.read(2))
264         dsize, = struct.unpack(">L",  file.read(4))   # uncompressed data size
265         data   = file.read(fsize-6)
266         #print file.tell(), "bytes"
267         file.close()
268         Blender.Window.DrawProgressBar(1.0, "Decompressing Data")
269         data = zlib.decompress(data)
270         data = cStringIO.StringIO(data)
271         read_chunkheader(data) # wings chunk
272         data.read(4)               # misc bytes
273         misc, numobjs = struct.unpack(">BL", data.read(5))
274         message = "Successfully imported " + os.path.basename(filename) + '\n\n'
275         message += "%s %8s %8s %8s\n" % ("Object".ljust(15), "faces", "edges", "verts")
276         message += "%s %8s %8s %8s\n" % ("ÄÄÄÄÄÄ".ljust(15), "ÄÄÄÄÄ", "ÄÄÄÄÄ", "ÄÄÄÄÄ")
277
278         for obj in range(numobjs):
279                 read_chunkheader(data) # object chunk
280                 misc, namelen = struct.unpack(">BH", data.read(3))
281                 objname = data.read(namelen)
282                 read_chunkheader(data) # winged chunk
283                 edge_table = read_edges(data)
284                 numfaces = read_faces(data)
285                 verts = read_verts(data)
286                 read_hardedges(data)
287                 read_mode(data)
288                 faces = make_faces(edge_table)
289                 message += "%s %8s %8s %8s\n" % (objname.ljust(15), len(faces), len(edge_table), len(verts))
290                 mod_meshtools.create_mesh(verts, faces, objname)
291
292         material = data.read()
293         #for i in material[0:6]: print "%02X" % ord(i),
294         #print
295         Blender.Window.DrawProgressBar(1.0, "Done")    # clear progressbar
296         data.close()
297         end = time.clock()
298         seconds = "\nDone in %.2f %s" % (end-start, "seconds")
299         message += seconds
300         mod_meshtools.print_boxed(message)
301
302 def fs_callback(filename):
303         read(filename)
304
305 Blender.Window.FileSelector(fs_callback, "Import Wings3D")