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