X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=blender%2Fio_mesh_mspgl%2Fmesh.py;fp=blender%2Fio_mesh_mspgl%2Fmesh.py;h=5af8578720d10bbe78759f995d72ab6912b79311;hb=5028e8accde81677fc4a50c771b955cf324851b2;hp=0000000000000000000000000000000000000000;hpb=cd460f42d4468b80d3929aad5b93674fa0b2897c;p=libs%2Fgl.git diff --git a/blender/io_mesh_mspgl/mesh.py b/blender/io_mesh_mspgl/mesh.py new file mode 100644 index 00000000..5af85787 --- /dev/null +++ b/blender/io_mesh_mspgl/mesh.py @@ -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