source: OGRE/trunk/ogrenew/Tools/Wings3DExporter/io3d_wings.py @ 657

Revision 657, 8.4 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1
2#
3# TODO:
4#   parse vertex colors and UV coordinates
5#   remove faces with the hole material
6#
7
8from erlang_ext import *
9import types
10import pprint
11
12import mesh
13
14try:
15        import Image
16except:
17        pass
18
19def safe_append(ctr, key, value):
20        if ctr.has_key(key):
21                ctr[key].append(value)
22        else:
23                ctr[key] = [value]
24
25class wings_reader:
26
27        dump = __name__ == '__main__'
28
29        def __init__(self, raw_data, writeImages, keepRotation):
30                self.data = raw_data
31                self.writeImages = writeImages
32                self.keepRotation = keepRotation
33                # read and check
34                a, self.ver, wingsdata = self.data
35                if a != erlang_atom("wings") or self.ver != 2:
36                        raise IOError("Unknown wings version")
37
38                #if self.dump:
39                #       pp = pprint.PrettyPrinter(indent=4,width=78)
40                #       pp.pprint(wingsdata)
41
42                self.raw_objects, self.raw_materials, self.raw_props = wingsdata
43       
44        def parse(self):
45                return self.parse_2()
46
47        def parse_2(self):
48                scene = mesh.Mesh()
49                scene.name = "wings_object"
50                self.materials = scene.materials
51                self.mat_images = {}
52                for raw_mat in self.raw_materials:
53                        wmat = self.parse_2_material(raw_mat)
54                        scene.materials.append(wmat)
55                self.parse_2_images()
56                for raw_obj in self.raw_objects:
57                        wobj = self.parse_2_object(raw_obj)
58                        scene.merge(wobj)
59                self.postprocess(scene)
60                return scene
61
62        def parse_2_image(self, index, raw_image):
63                w, h, spp = 0, 0, 0
64                pixels = None
65                filename = None
66                for elem in raw_image:
67                        if elem[0] == erlang_atom("width"):
68                                w = elem[1]
69                        if elem[0] == erlang_atom("height"):
70                                h = elem[1]
71                        if elem[0] == erlang_atom("samples_per_pixel"):
72                                spp = elem[1]
73                        if elem[0] == erlang_atom("pixels"):
74                                pixels = elem[1]
75
76                if not pixels:
77                        return None
78
79                if spp == 3: mode = 'RGB'
80                else: mode = 'L'
81                im = Image.new(mode, (w, h))
82
83                print "processing image"
84                print mode, spp, w, h, len(pixels)
85
86                pixels = map(lambda x: ord(x), pixels)
87                for x in range(w):
88                        for y in range(h):
89                                i = (x + y * w) * 3
90                                yy = h - 1 - y # huh?
91                                im.putpixel((x, yy), tuple(pixels[i:i+3]))
92                #bands = [tuple(pixels[i*3:i*3+3]) for i in range(w * h)]
93
94                #print pixels
95                #print bands
96
97                #im.putdata(bands)
98
99                if self.mat_images.has_key(index):
100                        filename = self.mat_images[index]
101                        im.save(filename)
102                return im
103
104        def parse_2_images(self):
105                if not self.writeImages:
106                        return
107                images = []
108                if self.raw_props:
109                        for elem in self.raw_props:
110                                if elem[0] == erlang_atom('images'):
111                                        images = elem[1]
112
113                        for raw_im_data in images:
114                                index, raw_im = raw_im_data[:2]
115                                self.parse_2_image(index, raw_im)
116
117        def parse_2_material(self, raw_mat):
118
119                atom, data = raw_mat
120
121                #pp = pprint.PrettyPrinter(indent=4,width=78)
122                #pp.pprint(data)
123
124                #raw_maps, raw_gl = data[:2]
125
126                mat = mesh.Material(str(atom))
127
128                for tag in data:
129                        a, elem_data = tag
130                        if a == erlang_atom('openg'):
131                                for elem in elem_data:
132                                        if elem[0] == erlang_atom('ambient'):
133                                                mat.ambient = elem[1]
134                                        if elem[0] == erlang_atom('diffuse'):
135                                                mat.diffuse = elem[1]
136                                        if elem[0] == erlang_atom('specular'):
137                                                mat.specular = elem[1]
138                                        if elem[0] == erlang_atom('shininess'):
139                                                mat.shininess = elem[1]
140                        elif a == erlang_atom('maps') and elem_data:
141                                filename = str(atom) + '.png'
142                                mat.textures.append(filename)
143                                self.mat_images[elem_data[0][1]] = filename
144
145                return mat
146
147
148        def check_atom(self, atom, name):
149                if atom != erlang_atom(name):
150                        raise IOError("Unexpected atom: %s expected, %s found" %
151                                        (erlang_atom(name), atom))
152
153        def parse_2_edges(self, wobj, raw_edges, hard_edges):
154                faces = {}
155                for edge_index in range(len(raw_edges)):
156                        raw_edge = raw_edges[edge_index]
157                        LSp, LEp = None, None
158                        for elem in raw_edge:
159
160                                if elem[0] == erlang_atom('edge'):
161                                        edgedata = elem
162
163                                #
164                                # the color data for the face on the sides of this
165                                # edge, rgb1/uv1 is for Lf:Sv, rgb2/uv2 is for Rf:Ev
166                                #
167                                if elem[0] == erlang_atom('uv'):
168                                        uvdata = struct.unpack('>dddd', elem[1])
169                                        u1, v1, u2, v2 = uvdata
170                                        LSp = mesh.ColorProp((u1, v1))
171                                        LEp = mesh.ColorProp((u2, v2))
172
173                                # new UV packing for Wings3D 0.98.16b?
174                                # I leave the old code in for older mesh files
175                                if elem[0] == erlang_atom('uv_lt'):
176                                        uvdata = struct.unpack('>dd', elem[1])
177                                        u1, v1 = uvdata
178                                        LSp = mesh.ColorProp((u1, v1))
179
180                                if elem[0] == erlang_atom('uv_rt'):
181                                        uvdata = struct.unpack('>dd', elem[1])
182                                        u2, v2 = uvdata
183                                        LEp = mesh.ColorProp((u2, v2))
184
185                                if elem[0] == erlang_atom('color'):
186                                        colordata = struct.unpack('>dddddd', elem[1])
187                                        r1, g1, b1, r2, g2, b2 = colordata
188                                        LSp = mesh.ColorProp((r1, g1, b1, 1))
189                                        LEp = mesh.ColorProp((r2, g2, b2, 1))
190
191                        # read winged data
192                        a, Sv, Ev, Lf, Rf, LP, LS, RP, RS = edgedata
193                        self.check_atom(a, "edge")
194
195                        minf, maxf = min(Lf, Rf), max(Lf, Rf)
196                        wobj.edges.append((minf, maxf, Sv, Ev))
197
198                        # store color info here if any
199                        if LSp and LEp:
200                                if wobj.face_vert_colors.has_key((Lf, Sv)) or \
201                                                wobj.face_vert_colors.has_key((Rf, Ev)):
202                                        print "hey!"
203                                wobj.face_vert_colors[(Lf, Sv)] = LSp
204                                wobj.face_vert_colors[(Rf, Ev)] = LEp
205
206                        # store hardness info
207                        if edge_index in hard_edges:
208                                wobj.hard_edges.append((minf, maxf))
209
210                        # store left and right face
211                        safe_append(faces, Lf, (Sv, Ev))
212                        safe_append(faces, Rf, (Ev, Sv))
213
214                # === put edges (Sv & Ev) in correct order ===
215                # === faces{} now contains a sorted list of edges (Sv & Ev) for each face
216                for i in range(len(faces)):
217                        face = faces[i]
218                        swaps = 1
219                        while swaps:
220                                swaps = 0
221                                for j in range(len(face)-2):
222                                        if face[j][1] != face[j+1][0]:
223                                                face[j+1], face[j+2] = face[j+2], face[j+1] # swap them
224                                                swaps = 1
225
226                # replace tuples with vertex indices, also convert the map to sequence
227                # s is a sequence of edges, e is an edge
228                wobj.faces = map(lambda s: map(lambda e: e[0], s), faces.values())
229
230                if self.dump:
231                        print "*** Edges parsed"
232                        pp = pprint.PrettyPrinter(indent=4,width=78)
233                        pp.pprint(wobj.faces)
234                        pp.pprint(wobj.face_vert_colors)
235                        pp.pprint(wobj.hard_edges)
236
237        def parse_2_faces(self, wobj, raw_faces):
238               
239                for face in range(len(raw_faces)):
240                        raw_face = raw_faces[face]
241                        if raw_face:
242                                for elem in raw_face:
243                                        if elem[0] == erlang_atom('material'):
244                                                mat_name = str(elem[1])
245                                                mat_id = wobj.find_material(mat_name)
246                        else:
247                                try:
248                                        mat_id = wobj.find_material("default")
249                                except:
250                                        mat_id = 0
251                        wobj.face_materials.append(mat_id)
252
253                if self.dump:
254                        print "*** Faces parsed"
255                        pp = pprint.PrettyPrinter(indent=4,width=78)
256                        pp.pprint(wobj.face_materials)
257
258
259        def parse_2_verts(self, wobj, raw_verts):
260                wobj.verts = []
261
262                for vertdata in raw_verts:
263                        x, y, z = struct.unpack(">ddd", vertdata[0])  # double precision
264                        if self.keepRotation:
265                                wobj.verts.append((x, -z, y))
266                        else:
267                                wobj.verts.append((x, y, z))
268
269        def parse_2_object(self, obj):
270                a, name, winged, mode = obj
271                self.check_atom(a, "object")
272
273                # if mode is invisible, skip this
274
275                a, raw_edges, raw_faces, raw_verts, raw_edge_htable = winged
276                self.check_atom(a, "winged")
277
278                print "reading object '%s' (%d faces, %d edges, %d vertices)" % (name,
279                                len(raw_faces), len(raw_edges), len(raw_verts))
280
281                # raw_edge_htable lists hard edges
282                # (edges are soft by default, so this table may be empty, thus None)
283                if raw_edge_htable == None: raw_edge_htable = []
284
285                if type(raw_edge_htable) == types.StringType:
286                        raw_edge_htable = map(ord, raw_edge_htable)
287                #print raw_edge_htable
288
289                wobj = mesh.Mesh()
290                wobj.materials = self.materials
291                wobj.name = name
292                self.parse_2_edges(wobj, raw_edges, raw_edge_htable)
293                self.parse_2_faces(wobj, raw_faces)
294                self.parse_2_verts(wobj, raw_verts)
295
296                return wobj
297
298        def postprocess(self, wobj):
299                wobj.make_face_normals()
300                wobj.make_vert_normals(1)
301                wobj.flatten()
302                wobj.triangulate()
303                wobj.submeshize()
304
305                if self.dump:
306                        wobj.dump()
307
308def read_wings(filename, writeImages, keepRotation):
309        e = erlang_ext_reader(filename)
310        raw_data = e.read()
311
312        ob = wings_reader(raw_data, writeImages, keepRotation)
313        scene = ob.parse()
314
315        return scene
316
317if __name__ == '__main__':
318        try:
319                e = erlang_ext_reader("C:/projects/3d/erpy/uv-cube.wings")
320                #e = erlang_ext_reader("C:/projects/3d/erpy/mycar.wings")
321                #e = erlang_ext_reader("/home/attis/src/erpy/cube-colored.wings")
322                #e = erlang_ext_reader("/home/attis/src/erpy/tank1w.wings")
323                raw_data = e.read()
324
325                print "read"
326
327                ob = wings_reader(raw_data)
328                ob.parse()
329
330                print "done"
331
332                #pp = pprint.PrettyPrinter(indent=4,width=78)
333                #file = open("log1.txt", "w")
334                #file.write(pp.pformat(raw_data))
335                #file.write('\n')
336
337                print "ok"
338
339        finally:
340                pp = pprint.PrettyPrinter(indent=4,width=78)
341                pp.pprint(raw_data)
342
Note: See TracBrowser for help on using the repository browser.