]> git.tdb.fi Git - libs/gl.git/blob - mesh_export.py
Blender export: Add support for smoothing
[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         
59         def __getattr__(self, attr):
60                 return getattr(self._mface, attr)
61
62
63 class SmoothGroup:
64         def __init__(self):
65                 self.faces=[]
66                 self.verts=[]
67
68         def find_vertices(self):
69                 vert_map={}
70                 for f in self.faces:
71                         for i in range(len(f.verts)):
72                                 v=f.verts[i]
73                                 if v.index not in vert_map:
74                                         vt=Vertex(v)
75                                         if not f.smooth:
76                                                 vt.no=f.no
77                                         self.verts.append(vt)
78                                         vert_map[v.index]=vt
79                                         f.verts[i]=vt
80                                 else:
81                                         f.verts[i]=vert_map[v.index]
82
83
84 class Exporter:
85         def __init__(self, fn):
86                 self.filename=fn
87                 if fn==None:
88                         self.out_file=sys.stdout
89                 else:
90                         self.out_file=file(fn, "w")
91
92         def find_smooth_group(self, face, sg):
93                 face.smooth_group=sg
94                 sg.faces.append(face)
95                 queue=[face]
96                 while queue:
97                         f=queue.pop(0)
98                         for e in f.edges:
99                                 if e.smooth:
100                                         f2=e.other_face(f)
101                                         if f2 and not f2.smooth_group:
102                                                 f2.smooth_group=sg
103                                                 sg.faces.append(f2)
104                                                 queue.append(f2)
105
106         def export(self):
107                 scene=Blender.Scene.GetCurrent()
108
109                 obj=scene.getActiveObject()
110                 if obj.getType()!="Mesh":
111                         raise Exception, "Can only export Mesh data"
112
113                 mesh=obj.getData(mesh=True)
114
115                 faces=[Face(f) for f in mesh.faces]
116
117                 edges=dict([(e.key, Edge(e)) for e in mesh.edges])
118                 for f in faces:
119                         for e in f.edge_keys:
120                                 edges[e].faces.append(f)
121                                 f.edges.append(edges[e])
122
123                 smooth_limit=math.cos(mesh.degr*math.pi/180)
124                 for e in edges.itervalues():
125                         e.check_smooth(smooth_limit)
126
127                 smooth_groups=[]
128                 for f in faces:
129                         if not f.smooth_group:
130                                 sg=SmoothGroup()
131                                 smooth_groups.append(sg)
132                                 self.find_smooth_group(f, sg)
133
134                 verts=[]
135                 for sg in smooth_groups:
136                         sg.find_vertices()
137                         for v in sg.verts:
138                                 v.index=len(verts)
139                                 verts.append(v)
140
141                 self.out_file.write("vertices NORMAL3_VERTEX3\n{\n")
142                 for v in verts:
143                         self.out_file.write("\tnormal3 %g %g %g;\n"%tuple(v.no))
144                         self.out_file.write("\tvertex3 %g %g %g;\n"%tuple(v.co))
145                 self.out_file.write("};\n")
146                 self.out_file.write("batch TRIANGLES\n{\n")
147                 for f in faces:
148                         for i in range(2, len(f.verts)):
149                                 self.out_file.write("\tindices %u %u %u;\n"%(f.verts[0].index, f.verts[i-1].index, f.verts[i].index))
150                 self.out_file.write("};\n")
151
152
153 class FrontEnd:
154         def run(self):
155                 #self.export(None)
156                 Blender.Window.FileSelector(self.export, "Export MSP GL mesh", Blender.sys.makename(ext='.mesh'))
157
158         def export(self, fn):
159                 exp=Exporter(fn)
160                 exp.export()
161
162
163 if __name__=="__main__":
164         fe=FrontEnd()
165         fe.run()