3 # aof2obj - convert Artlantis Object Format files to Wavefront OBJ
5 # Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 from lxml import etree
27 sys.stdout.write("usage: %s <aof file>\n" % name)
30 def aof2obj(aof_filename, obj_filename, basename):
32 f = open(aof_filename, "r")
34 # Use recover mode, because the xml format is ill-specified:
35 # there is at least one element with the name starting with a number
36 # <3D.Paths>, in violation to the XML spec.
37 # And there is some elements with the UUID attribute specified multiple
39 parser = etree.XMLParser(recover=True)
40 tree = etree.parse(f, parser)
42 # The preview image could be some bitmap format, don't know yet
43 preview = tree.find("Preview.Image")
44 if preview is not None:
45 heximage = preview.text.rstrip("\t\n")
47 preview_file = open(basename + ".prw", "w")
48 preview_file.write(binascii.unhexlify(heximage))
51 obj_file = open(obj_filename, "w")
53 obj_file.write("# obj file created with aof2obj\n")
54 obj_file.write("# by Antonio Ospite\n\n")
57 points = tree.find('Points')
58 points_data = points.text.strip("\t\n").split("\n")
60 for p in points_data[1:]:
61 obj_file.write("v %s\n" % p.rstrip(' '))
63 obj_file.write("# %d vertices\n\n" % int(points_data[0]))
66 polygons = tree.find('Polygons')
67 polygons_data = polygons.text.strip("\t\n").split("\n")
71 for p in polygons_data[1:]:
72 ptype, pdata = p.split("\t")
73 if ptype != 'o' and ptype != 'p':
74 sys.stderr.write("Unsupported polygon type")
77 # If there is a M in pdata discard the line
78 # don't know how to handle that
80 sys.stdout.write("Warning, ignored M element\n")
83 # Don't know what the 'I' stands for yet, for now just ignore it
84 pdata = pdata.replace(' I ', ' ').strip(' ')
86 pdata_list = pdata.split(' ')
88 obj_number = int(pdata_list[0])
89 num_verts = int(pdata_list[1])
91 # Vert indices start from 1 in .obj files
92 verts_data = " ".join([str(int(i) + 1) for i in pdata_list[2:]])
94 if obj_number != current_object:
95 obj_file.write("\n# defining Object_%d\n" % obj_number)
96 obj_file.write("g Object_%d\n" % obj_number)
97 current_object = obj_number
99 obj_file.write("f %s\n" % verts_data)
101 obj_file.write("# %d faces\n\n" % int(polygons_data[0]))
106 if __name__ == "__main__":
108 if len(sys.argv) < 2:
112 aof_filename = sys.argv[1]
113 basename_no_ext = os.path.splitext(aof_filename)[0]
114 obj_filename = basename_no_ext + ".obj"
116 aof2obj(aof_filename, obj_filename, basename_no_ext)