]> git.tdb.fi Git - libs/gl.git/blob - mesh_export.py
Add projection functions
[libs/gl.git] / mesh_export.py
1 #!BPY
2 # $Id$
3
4 """
5 Name: 'MSP GL Mesh (.mesh)...'
6 Blender: 244
7 Group: 'Export'
8 """
9
10 import sys
11 import math
12 import bpy
13 import Blender
14
15 class Edge:
16         def __init__(self, me):
17                 self._medge=me
18                 self.faces=[]
19                 self.smooth=False
20
21         def __getattr__(self, attr):
22                 return getattr(self._medge, attr)
23
24         def check_smooth(self, limit):
25                 if len(self.faces)!=2:
26                         return
27
28                 d=Blender.Mathutils.DotVecs(self.faces[0].no, self.faces[1].no)
29                 if (d>limit and self.faces[0].smooth and self.faces[1].smooth) or d>0.999:
30                         self.smooth=1
31
32         def other_face(self, f):
33                 if f.index==self.faces[0].index:
34                         if len(self.faces)>=2:
35                                 return self.faces[1]
36                         else:
37                                 return None
38                 else:
39                         return self.faces[0]
40
41
42 class Vertex:
43         def __init__(self, mv):
44                 if mv.__class__==Vertex:
45                         self._mvert=mv._mvert
46                 else:
47                         self._mvert=mv
48
49         def __getattr__(self, attr):
50                 return getattr(self._mvert, attr)
51
52
53 class Face:
54         def __init__(self, mf):
55                 self._mface=mf
56                 self.smooth_group=None
57                 self.edges=[]
58                 self.verts=[v for v in mf.verts]
59                 self.flag=False
60
61         def __getattr__(self, attr):
62                 return getattr(self._mface, attr)
63
64         def get_following_vertex(self, *vt):
65                 seen=False
66                 indices=[v.index for v in vt]
67                 for v in self.verts:
68                         if v.index in indices:
69                                 seen=True
70                         elif seen:
71                                 return v
72
73                 if seen:
74                         return self.verts[0]
75
76                 return None
77
78
79 class SmoothGroup:
80         def __init__(self, index):
81                 self.index=index
82                 self.faces=[]
83                 self.verts=[]
84
85         def find_vertices(self):
86                 vert_map={}
87                 for f in self.faces:
88                         for i in range(len(f.verts)):
89                                 v=f.verts[i]
90                                 if v.index not in vert_map:
91                                         vt=Vertex(v)
92                                         if not f.smooth:
93                                                 vt.no=f.no
94                                         self.verts.append(vt)
95                                         vert_map[v.index]=vt
96                                         f.verts[i]=vt
97                                 else:
98                                         f.verts[i]=vert_map[v.index]
99
100
101 class Exporter:
102         def __init__(self, fn):
103                 self.filename=fn
104                 if fn==None:
105                         self.out_file=sys.stdout
106                 else:
107                         self.out_file=file(fn, "w")
108                 self.use_strips=True
109                 self.use_degen_tris=True
110
111         def find_smooth_group(self, face, sg):
112                 face.smooth_group=sg
113                 sg.faces.append(face)
114                 queue=[face]
115                 while queue:
116                         cur=queue.pop(0)
117                         for e in cur.edges:
118                                 if e.smooth:
119                                         other=e.other_face(cur)
120                                         if other and not other.smooth_group:
121                                                 other.smooth_group=sg
122                                                 sg.faces.append(other)
123                                                 queue.append(other)
124
125         def create_strip(self, face):
126                 edge=None
127                 for e in face.edges:
128                         other=e.other_face(face)
129                         if other and other.smooth_group.index==face.smooth_group.index and not other.flag:
130                                 edge=e
131                                 break
132
133                 if not edge:
134                         return None
135
136                 v1=face.get_following_vertex(edge.v1, edge.v2)
137                 v2=face.get_following_vertex(v1)
138                 if len(face.verts)==4:
139                         result=[v2, v1]
140                 else:
141                         result=[v1, v2]
142
143                 while 1:
144                         face.flag=True
145                         for i in range(2, len(face.verts)):
146                                 v=face.get_following_vertex(result[-2], result[-1])
147                                 result.append(v)
148
149                         i1=result[-2].index
150                         i2=result[-1].index
151                         ekey=(min(i1, i2), max(i1, i2))
152                         for e in face.edges:
153                                 if e.key==ekey:
154                                         edge=e
155                                         break
156
157                         next=edge.other_face(face)
158                         if next.smooth_group.index!=face.smooth_group.index or next.flag:
159                                 break
160                         face=next
161
162                 return result
163
164         def export(self):
165                 scene=bpy.data.scenes.active
166
167                 obj=scene.objects.active
168                 if obj.getType()!="Mesh":
169                         raise Exception, "Can only export Mesh data"
170
171                 mesh=obj.getData(mesh=True)
172
173                 faces=[Face(f) for f in mesh.faces]
174
175                 edges=dict([(e.key, Edge(e)) for e in mesh.edges])
176                 for f in faces:
177                         for e in f.edge_keys:
178                                 edges[e].faces.append(f)
179                                 f.edges.append(edges[e])
180
181                 smooth_limit=math.cos(mesh.degr*math.pi/180)
182                 for e in edges.itervalues():
183                         e.check_smooth(smooth_limit)
184
185                 smooth_groups=[]
186                 for f in faces:
187                         if not f.smooth_group:
188                                 sg=SmoothGroup(len(smooth_groups))
189                                 smooth_groups.append(sg)
190                                 self.find_smooth_group(f, sg)
191
192                 for sg in smooth_groups:
193                         sg.find_vertices()
194
195                 strips=[]
196                 if self.use_strips:
197                         for sg in smooth_groups:
198                                 for f in sg.faces:
199                                         if not f.flag:
200                                                 strip=self.create_strip(f)
201                                                 if strip:
202                                                         strips.append(strip)
203
204                         if self.use_degen_tris:
205                                 big_strip=[]
206                                 for s in strips:
207                                         if big_strip:
208                                                 big_strip+=[big_strip[-1], s[0]]
209                                         big_strip+=s
210
211                                 for f in faces:
212                                         if not f.flag:
213                                                 if big_strip:
214                                                         big_strip+=[big_strip[-1], f.verts[0]]
215                                                 big_strip+=[f.verts[i] for i in (0, 1, -1)]
216                                                 if len(f.verts)==4:
217                                                         big_strip.append(f.verts[-2])
218                                                 f.flag=True
219
220                                 strips=[big_strip]
221
222                 verts=[]
223                 for sg in smooth_groups:
224                         for v in sg.verts:
225                                 v.index=len(verts)
226                                 verts.append(v)
227
228                 self.out_file.write("vertices NORMAL3_VERTEX3\n{\n")
229                 for v in verts:
230                         self.out_file.write("\tnormal3 %f %f %f;\n"%tuple(v.no))
231                         self.out_file.write("\tvertex3 %f %f %f;\n"%tuple(v.co))
232                 self.out_file.write("};\n")
233                 for s in strips:
234                         self.out_file.write("batch TRIANGLE_STRIP\n{\n\tindices")
235                         n=0
236                         for v in s:
237                                 self.out_file.write(" %u"%v.index)
238                                 n+=1;
239                                 if n%32==0:
240                                         self.out_file.write(";\n\tindices")
241                         self.out_file.write(";\n};\n")
242
243                 first=True
244                 for f in faces:
245                         if not f.flag:
246                                 if first:
247                                         self.out_file.write("batch TRIANGLES\n{\n")
248                                         first=False
249                                 for i in range(2, len(f.verts)):
250                                         self.out_file.write("\tindices %u %u %u;\n"%(f.verts[0].index, f.verts[i-1].index, f.verts[i].index))
251                 if not first:
252                         self.out_file.write("};\n")
253
254
255 class FrontEnd:
256         def run(self):
257                 #self.export(None)
258                 Blender.Window.FileSelector(self.export, "Export MSP GL mesh", Blender.sys.makename(ext='.mesh'))
259
260         def export(self, fn):
261                 exp=Exporter(fn)
262                 exp.export()
263
264
265 if __name__=="__main__":
266         fe=FrontEnd()
267         fe.run()