]> git.tdb.fi Git - libs/gl.git/blobdiff - blender/io_mesh_mspgl/mesh.py
Add a Blender 2.5 port of the exporter
[libs/gl.git] / blender / io_mesh_mspgl / mesh.py
diff --git a/blender/io_mesh_mspgl/mesh.py b/blender/io_mesh_mspgl/mesh.py
new file mode 100644 (file)
index 0000000..5af8578
--- /dev/null
@@ -0,0 +1,338 @@
+import math
+import mathutils
+
+def make_edge_key(i1, i2):
+       return (min(i1, i2), max(i1, i2))
+
+class Edge:
+       def __init__(self, me):
+               if me.__class__==Edge:
+                       self._medge = me._medge
+                       self.vertices = me.vertices[:]
+                       self.smooth = me.smooth
+               else:
+                       self._medge = me
+                       self.smooth = False
+               self.faces = []
+
+       def __getattr__(self, attr):
+               return getattr(self._medge, attr)
+
+       def check_smooth(self, limit):
+               if len(self.faces)!=2:
+                       return
+
+               d = self.faces[0].normal.dot(self.faces[1].normal)
+               if (d>limit and self.faces[0].use_smooth and self.faces[1].use_smooth) or d>0.999:
+                       self.smooth = True
+
+       def other_face(self, f):
+               if f.index==self.faces[0].index:
+                       if len(self.faces)>=2:
+                               return self.faces[1]
+                       else:
+                               return None
+               else:
+                       return self.faces[0]
+
+
+class Vertex:
+       def __init__(self, mv):
+               if mv.__class__==Vertex:
+                       self._mvert = mv._mvert
+                       self.normal = mv.normal
+                       self.uv = mv.uv
+               else:
+                       self._mvert = mv
+                       self.uv = None
+               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)
+
+
+class Face:
+       def __init__(self, mf):
+               self._mface = mf
+               self.edges = []
+               self.vertices = mf.vertices[:]
+               self.uv = None
+               self.flag = False
+               self.material = None
+
+       def __getattr__(self, attr):
+               return getattr(self._mface, attr)
+
+       def __cmp__(self, other):
+               if other is None:
+                       return 1
+               return cmp(self.index, other.index)
+
+       def pivot_vertices(self, *vt):
+               flags = [(v in vt) for v in self.vertices]
+               l = len(self.vertices)
+               for i in range(l):
+                       if flags[i] and not flags[(i+l-1)%l]:
+                               return self.vertices[i:]+self.vertices[:i]
+
+       def get_edge(self, v1, v2):     
+               key = make_edge_key(v1.index, v2.index)
+               for e in self.edges:
+                       if e.key==key:
+                               return e
+               raise KeyError("No edge %s"%(key,))
+
+
+class Line:
+       def __init__(self, e):
+               self.edge = e
+               self.vertices = e.vertices[:]
+               self.flag = False
+
+
+class Mesh:
+       def __init__(self, m):
+               self._mesh = m
+               self.vertices = [Vertex(v) for v in m.vertices]
+               self.faces = [Face(f) for f in m.faces]
+               self.materials = m.materials[:]
+               self.has_uv = False
+
+               uvtex = None
+               if m.uv_textures:
+                       uvtex = self.uv_textures[0]
+                       self.has_uv = True
+
+               for f in self.faces:
+                       f.vertices = [self.vertices[i] for i in f.vertices]
+                       if uvtex:
+                               f.uv = uvtex.data[f.index].uv
+                       for v in f.vertices:
+                               v.faces.append(f)
+
+               self.edges = dict([(e.key, Edge(e)) for e in m.edges])
+               for f in self.faces:
+                       for k in f.edge_keys:
+                               e = self.edges[k]
+                               e.faces.append(self.faces[f.index])
+                               f.edges.append(e)
+
+               self.lines = [Line(e) for e in self.edges.values() if not e.faces]
+
+               if m.use_auto_smooth:
+                       smooth_limit = math.cos(m.auto_smooth_angle*math.pi/180)
+               else:
+                       smooth_limit = -1
+
+               for e in self.edges.values():
+                       e.vertices = [self.vertices[i] for i in e.vertices]
+                       e.check_smooth(smooth_limit)
+
+       def __getattr__(self, attr):
+               return getattr(self._mesh, attr)
+
+       def splice(self, other):
+               material_map = []
+               for m in other.materials:
+                       if m in self.materials:
+                               material_map.append(self.materials.index(m))
+                       else:
+                               material_map.append(len(self.materials))
+                               self.materials.append(m)
+
+               offset = len(self.vertices)
+               for v in other.vertices:
+                       v.index += offset
+                       self.vertices.append(v)
+
+               offset = len(self.faces)
+               for f in other.faces:
+                       f.index += offset
+                       f.material = material_map[f.material_index]
+                       self.faces.append(f)
+
+               for e in other.edges.values():
+                       e.key = make_edge_key(e.vertices[0].index, e.vertices[1].index)
+                       self.edges[e.key] = e
+
+               self.lines += other.lines
+       
+       def generate_material_uv(self):
+               for f in self.faces:
+                       f.uv = ([(f.material_index+0.5)/len(self.materials), 0.5],)*len(f.vertices)
+               self.has_uv = True
+
+       def split_vertices(self, find_group_func, progress = None):
+               groups = []
+               for i in range(len(self.vertices)):
+                       v = self.vertices[i]
+                       for f in v.faces:
+                               f.flag = False
+
+                       vg = []
+                       for f in v.faces:
+                               if not f.flag:
+                                       vg.append(find_group_func(v, f))
+
+                       groups.append(vg)
+
+                       if progress:
+                               progress.set_progress(i*0.5/len(self.vertices))
+
+               for i in range(len(self.vertices)):
+                       if len(groups[i])==1:
+                               continue
+
+                       for g in groups[i][1:]:
+                               v = Vertex(self.vertices[i])
+                               v.index = len(self.vertices)
+                               self.vertices.append(v)
+
+                               for f in g:
+                                       for j in range(len(f.edges)):
+                                               e = f.edges[j]
+
+                                               if self.vertices[i] not in e.vertices:
+                                                       continue
+
+                                               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]
+
+                                               e.vertices[e.vertices.index(self.vertices[i])] = v
+
+                                               e.key = make_edge_key(e.vertices[0].index, e.vertices[1].index)
+                                               self.edges[e.key] = e
+
+                                       self.vertices[i].faces.remove(f)
+                                       f.vertices[f.vertices.index(self.vertices[i])] = v
+                                       v.faces.append(f)
+
+                       if progress:
+                               progress.set_progress(0.5+i*0.5/len(self.vertices))
+
+       def split_smooth(self, progress = None):
+               self.split_vertices(self.find_smooth_group, progress)
+
+       def split_uv(self, progress = None):
+               self.split_vertices(self.find_uv_group, progress)
+
+       def find_smooth_group(self, vertex, 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 other not in vertex.faces:
+                                       continue
+
+                               if e.smooth:
+                                       if not other.flag:
+                                               other.flag = True
+                                               queue.append(other)
+
+               return queue
+
+       def find_uv_group(self, vertex, face):
+               uv = face.uv[face.vertices.index(vertex)]
+               face.flag = True
+               group = [face]
+               for f in vertex.faces:
+                       if not f.flag and f.uv[f.vertices.index(vertex)]==uv:
+                               f.flag = True
+                               group.append(f)
+               return group
+
+       def compute_normals(self):
+               for v in self.vertices:
+                       if v.faces:
+                               v.normal = mathutils.Vector()
+                               for f in v.faces:
+                                       v.normal += f.normal
+                               v.normal.normalize()
+                       else:
+                               # XXX Should use edges to compute normal
+                               v.normal = mathutils.Vector(0, 0, 1)
+
+       def compute_uv(self):
+               for v in self.vertices:
+                       if v.faces:
+                               v.uv = v.faces[0].uv[v.faces[0].vertices.index(v)]
+
+       def compute_tbn(self):
+               for v in self.vertices:
+                       v.tan = mathutils.Vector()
+                       v.bino = mathutils.Vector()
+                       for f in v.faces:
+                               fv = f.pivot_vertices(False, v)
+                               v1 = fv[1]
+                               v2 = fv[-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 = fv[1].co-fv[0].co
+                               edge2 = fv[-1].co-fv[0].co
+                               if div:
+                                       v.tan += (edge1*dv2-edge2*dv1)/div
+                                       v.bino += (edge2*du1-edge1*du2)/div
+                       if v.tan.length:
+                               v.tan.normalize()
+                       if v.bino.length:
+                               v.bino.normalize()
+
+       def create_strip(self, face, max_len):
+               edge = None
+               for e in face.edges:
+                       other = e.other_face(face)
+                       if other and not other.flag:
+                               edge = e
+                               break
+
+               if not edge:
+                       return None
+
+               vertices = face.pivot_vertices(*edge.vertices)
+               if len(vertices)==3:
+                       result = [vertices[-1], vertices[0]]
+               else:
+                       result = [vertices[-2], vertices[-1]]
+
+               while 1:
+                       vertices = face.pivot_vertices(*result[-2:])
+                       k = len(result)%2
+
+                       face.flag = True
+                       if len(vertices)==4 and not k:
+                               result.append(vertices[3])
+                       result.append(vertices[2])
+                       if len(vertices)==4 and k:
+                               result.append(vertices[3])
+
+                       if len(result)>=max_len:
+                               break
+
+                       edge = face.get_edge(*result[-2:])
+
+                       next = edge.other_face(face)
+                       if not next or next.flag:
+                               break
+                       face = next
+
+               return result