X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=mesh_export.py;h=41ceb90a7baed794eaf7fa1cf6cc6d0276efb5e2;hb=119d9819ac9e9a8d274d2410beffe54e470485a3;hp=fbb282281e3dce09e3ef3af62d14ec264a69f65b;hpb=05e003962916b3c1b8c0ecfd2d4fb7ce0c2e45ca;p=libs%2Fgl.git diff --git a/mesh_export.py b/mesh_export.py index fbb28228..41ceb90a 100644 --- a/mesh_export.py +++ b/mesh_export.py @@ -20,6 +20,8 @@ class Edge: def __init__(self, me): if me.__class__==Edge: self._medge=me._medge + self.v1=me.v1 + self.v2=me.v2 self.smooth=me.smooth else: self._medge=me @@ -54,6 +56,7 @@ class Vertex: def __init__(self, mv): if mv.__class__==Vertex: self._mvert=mv._mvert + self.no=mv.no self.uv=mv.uv else: self._mvert=mv @@ -61,11 +64,15 @@ class Vertex: self.orig_index=self._mvert.index self.flag=False self.faces=[] + self.tan=None + self.bino=None def __getattr__(self, attr): return getattr(self._mvert, attr) def __cmp__(self, other): + if other is None: + return 1 return cmp(self.index, other.index) def __str__(self): @@ -85,6 +92,8 @@ class Face: return getattr(self._mface, attr) def __cmp__(self, other): + if other is None: + return 1 return cmp(self.index, other.index) def __str__(self): @@ -92,12 +101,11 @@ class Face: __repr__=__str__ - def get_vertices_from(self, reverse, *vt): + def pivot_vertices(self, reverse, *vt): verts=self.verts[:] if reverse: verts.reverse() - indices=[u.index for u in vt] - flags=[(v.index in indices) for v in verts] + flags=[(v in vt) for v in verts] l=len(verts) for i in range(l): if flags[i] and not flags[(i+l-1)%l]: @@ -108,6 +116,7 @@ class Face: for e in self.edges: if e.key==key: return e + raise KeyError, "No edge %s"%(key,) class Line: @@ -151,7 +160,7 @@ class Mesh: def __getattr__(self, attr): return getattr(self._mesh, attr) - def split_vertices(self, debug=False): + def split_vertices(self, find_group_func, debug): groups=[] for v in self.verts: for f in v.faces: @@ -160,7 +169,7 @@ class Mesh: vg=[] for f in v.faces: if not f.flag: - vg.append(self.find_group(v, f)) + vg.append(find_group_func(v, f)) groups.append(vg) @@ -177,7 +186,7 @@ class Mesh: self.verts.append(v) if debug: - print " -> %d"%v.index + print " -> %d %s"%(v.index, [f.index for f in g]) for f in g: for j in range(len(f.edges)): @@ -189,15 +198,14 @@ class Mesh: if debug: print " Splitting edge %s with faces %s"%(e.key, e.faces) - if not e.smooth: - if len(e.faces)>=2: - k=e.faces.index(f) - e.faces.remove(f) - e=Edge(e) - f.edges[j]=e - e.faces.append(f) - else: - del self.edges[e.key] + if e.other_face(f) not in g and len(e.faces)>=2: + k=e.faces.index(f) + e.faces.remove(f) + e=Edge(e) + f.edges[j]=e + e.faces.append(f) + else: + del self.edges[e.key] if e.v1==self.verts[i]: e.v1=v @@ -205,23 +213,27 @@ class Mesh: e.v2=v e.key=make_edge_key(e.v1.index, e.v2.index) - if not e.smooth: - self.edges[e.key]=e + self.edges[e.key]=e self.verts[i].faces.remove(f) f.verts[f.verts.index(self.verts[i])]=v v.faces.append(f) - def find_group(self, vert, face): - face_indices=[f.index for f in vert.faces] + def split_smooth(self, debug=False): + self.split_vertices(self.find_smooth_group, debug) + + def split_uv(self, debug=False): + self.split_vertices(self.find_uv_group, debug) + def find_smooth_group(self, vert, face): face.flag=True queue=[face] for f in queue: for e in f.edges: other=e.other_face(f) - if not other or other.index not in face_indices: + #if not other or other.index not in face_indices: + if other not in vert.faces: continue if e.smooth: @@ -231,6 +243,16 @@ class Mesh: return queue + def find_uv_group(self, vert, face): + uv=face.uv[face.verts.index(vert)] + face.flag=True + group=[face] + for f in vert.faces: + if not f.flag and f.uv[f.verts.index(vert)]==uv: + f.flag=True + group.append(f) + return group + def compute_normals(self): for v in self.verts: if v.faces: @@ -242,6 +264,31 @@ class Mesh: # XXX Should use edges to compute normal v.no=Blender.Mathutils.Vector(0, 0, 1) + def compute_uv(self): + for v in self.verts: + if v.faces: + v.uv=v.faces[0].uv[v.faces[0].verts.index(v)] + + def compute_tbn(self): + for v in self.verts: + v.tan=Blender.Mathutils.Vector() + v.bino=Blender.Mathutils.Vector() + for f in v.faces: + fverts=f.pivot_vertices(False, v) + v1=fverts[1] + v2=fverts[-1] + du1=v1.uv[0]-v.uv[0] + du2=v2.uv[0]-v.uv[0] + dv1=v1.uv[1]-v.uv[1] + dv2=v2.uv[1]-v.uv[1] + div=du1*dv2-du2*dv1 + edge1=fverts[1].co-fverts[0].co + edge2=fverts[-1].co-fverts[0].co + v.tan+=(edge1*dv2-edge2*dv1)/div + v.bino+=(edge2*du1-edge1*du2)/div + v.tan.normalize() + v.bino.normalize() + def create_strip(self, face, reverse, debug): edge=None for e in face.edges: @@ -256,14 +303,14 @@ class Mesh: if debug: print "Starting strip from %s, edge %s, reverse=%s"%([v.index for v in face.verts], (edge.v1.index, edge.v2.index), reverse) - verts=face.get_vertices_from(reverse, edge.v1, edge.v2) + verts=face.pivot_vertices(reverse, edge.v1, edge.v2) if len(verts)==3: result=[verts[-1], verts[0]] else: result=[verts[-2], verts[-1]] while 1: - verts=face.get_vertices_from(reverse, *result[-2:]) + verts=face.pivot_vertices(reverse, *result[-2:]) k=len(result)%2 if debug: print " Adding %s"%face @@ -302,9 +349,10 @@ class Exporter: self.use_degen_tris=True self.optimize_locality=True self.export_lines=True + self.tbn_vecs=False self.debug=False self.strip_debug=False - self.smooth_debug=False + self.split_debug=False def get_locality(self, strip): total=0 @@ -340,14 +388,22 @@ class Exporter: ntris=sum([len(f.verts)-2 for f in mesh.faces]) print "Starting with %d vertices, %d faces (%d triangles) and %d edges"%(len(mesh.verts), len(mesh.faces), ntris, len(mesh.edges)) - mesh.split_vertices(self.smooth_debug) + mesh.split_smooth(self.split_debug) if self.debug: - ntris=sum([len(f.verts)-2 for f in mesh.faces]) - print "After splitting %d vertices, %d faces (%d triangles) and %d edges"%(len(mesh.verts), len(mesh.faces), ntris, len(mesh.edges)) + print "After smooth splitting %d vertices and %d edges"%(len(mesh.verts), len(mesh.edges)) mesh.compute_normals() + if mesh.faceUV: + mesh.split_uv(self.split_debug) + if self.debug: + print "After UV splitting %d vertices and %d edges"%(len(mesh.verts), len(mesh.edges)) + + mesh.compute_uv() + if self.tbn_vecs: + mesh.compute_tbn() + strips=[] if self.use_strips: for f in mesh.faces: @@ -452,9 +508,13 @@ class Exporter: self.out_file.write("vertices NORMAL3") if mesh.faceUV: self.out_file.write("_TEXCOORD2") + if self.tbn_vecs: + self.out_file.write("_ATTRIB33_ATTRIB34") self.out_file.write("_VERTEX3\n{\n") norm=None uv=None + tan=None + bino=None for v in mesh.verts: if v.no!=norm: self.out_file.write("\tnormal3 %f %f %f;\n"%tuple(v.no)) @@ -462,6 +522,12 @@ class Exporter: if v.uv!=uv: self.out_file.write("\ttexcoord2 %f %f;\n"%tuple(v.uv)) uv=v.uv + if v.tan!=tan: + self.out_file.write("\tattrib3 3 %f %f %f;\n"%tuple(v.tan)) + tan=v.tan + if v.bino!=bino: + self.out_file.write("\tattrib3 4 %f %f %f;\n"%tuple(v.bino)) + bino=v.bino self.out_file.write("\tvertex3 %f %f %f;\n"%tuple(v.co)) self.out_file.write("};\n") for s in strips: @@ -502,18 +568,20 @@ class FrontEnd: self.use_degen_tris=Blender.Draw.Create(self.config.get('use_degen_tris', True)) self.optimize_locality=Blender.Draw.Create(self.config.get('optimize_locality', True)) self.export_lines=Blender.Draw.Create(self.config.get('export_lines', False)) + self.tbn_vecs=Blender.Draw.Create(self.config.get('tbn_vecs', False)) self.debug=Blender.Draw.Create(self.config.get('debug', False)) self.strip_debug=Blender.Draw.Create(self.config.get('strip_debug', False)) - self.smooth_debug=Blender.Draw.Create(self.config.get('smooth_debug', False)) + self.split_debug=Blender.Draw.Create(self.config.get('split_debug', False)) ret=Blender.Draw.PupBlock("Export MSP GL mesh", [("Use strips", self.use_strips, "Generage OpenGL triangle strips"), ("Use degen tris", self.use_degen_tris, "Use degenerate triangles to combine triangle strips"), ("Optimize locality", self.optimize_locality), - ("Export lines", self.export_lines), + ("Export lines", self.export_lines, "Export lone edges as lines"), + ("Compute T/B vecs", self.tbn_vecs, "Compute tangent/binormal vectors for bumpmapping"), ("Debugging options"), ("Debug", self.debug), ("Debug strips", self.strip_debug), - ("Debug smoothing", self.smooth_debug)]) + ("Debug splitting", self.split_debug)]) if ret: dirname=self.temp_config.get("dirname", Blender.sys.dirname(Blender.Get("filename"))) obj=bpy.data.scenes.active.objects.active @@ -527,9 +595,10 @@ class FrontEnd: self.config['use_degen_tris']=self.use_degen_tris.val self.config['optimize_locality']=self.optimize_locality.val self.config['export_lines']=self.export_lines.val + self.config['tbn_vecs']=self.tbn_vecs.val self.config['debug']=self.debug.val self.config['strip_debug']=self.strip_debug.val - self.config['smooth_debug']=self.smooth_debug.val + self.config['split_debug']=self.split_debug.val Blender.Registry.SetKey('mspgl_export', self.config, True) import os @@ -541,9 +610,10 @@ class FrontEnd: exp.use_degen_tris=self.use_degen_tris.val exp.optimize_locality=self.optimize_locality.val exp.export_lines=self.export_lines.val + exp.tbn_vecs=self.tbn_vecs.val exp.debug=self.debug.val exp.strip_debug=self.strip_debug.val - exp.smooth_debug=self.smooth_debug.val + exp.split_debug=self.split_debug.val exp.export()