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