]> git.tdb.fi Git - libs/gl.git/blobdiff - blender/io_mesh_mspgl/mesh.py
Improve smoothing in blender exporter
[libs/gl.git] / blender / io_mesh_mspgl / mesh.py
index 5af8578720d10bbe78759f995d72ab6912b79311..e3405f9f8e055490b71bf7a4323abcfc1475c752 100644 (file)
@@ -23,8 +23,7 @@ class Edge:
                        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
+               self.smooth = ((d>limit and self.faces[0].use_smooth and self.faces[1].use_smooth) or d>0.99995)
 
        def other_face(self, f):
                if f.index==self.faces[0].index:
@@ -41,10 +40,10 @@ class Vertex:
                if mv.__class__==Vertex:
                        self._mvert = mv._mvert
                        self.normal = mv.normal
-                       self.uv = mv.uv
+                       self.uvs = mv.uvs[:]
                else:
                        self._mvert = mv
-                       self.uv = None
+                       self.uvs = []
                self.flag = False
                self.faces = []
                self.tan = None
@@ -64,7 +63,7 @@ class Face:
                self._mface = mf
                self.edges = []
                self.vertices = mf.vertices[:]
-               self.uv = None
+               self.uvs = []
                self.flag = False
                self.material = None
 
@@ -98,27 +97,34 @@ class Line:
                self.flag = False
 
 
+def uvtex_unit_number(uvtex):
+       dot = uvtex.name.find('.')
+       if dot!=-1 and uvtex.name[dot+1:dot+5]=="unit" and uvtex.name[dot+5:].isdigit():
+               return int(uvtex.name[dot+5])
+       else:
+               return 1000
+
 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
+               self.vertices = [Vertex(v) for v in self.vertices]
+               self.faces = [Face(f) for f in self.faces]
+
+               self.materials = self.materials[:]
+
+               self.uv_textures = [u for u in self.uv_textures if not u.name.endswith(".hidden")]
+               self.uv_textures.sort(key=uvtex_unit_number)
 
                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)
+                       for u in self.uv_textures:
+                               r = u.data[f.index].uv_raw;
+                               f.uvs.append([(r[i], r[i+1]) for i in range(0, 8, 2)])
 
-               self.edges = dict([(e.key, Edge(e)) for e in m.edges])
+               self.edges = dict([(e.key, Edge(e)) for e in self.edges])
                for f in self.faces:
                        for k in f.edge_keys:
                                e = self.edges[k]
@@ -127,8 +133,8 @@ class Mesh:
 
                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)
+               if self.use_auto_smooth:
+                       smooth_limit = math.cos(self.auto_smooth_angle*math.pi/180)
                else:
                        smooth_limit = -1
 
@@ -164,13 +170,20 @@ class Mesh:
                        self.edges[e.key] = e
 
                self.lines += other.lines
-       
+
+       def flatten_faces(self):
+               for f in self.faces:
+                       f.use_smooth = False
+
+               for e in self.edges.values():
+                       e.check_smooth(1)
+
        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):
+       def split_vertices(self, find_group_func, progress, *args):
                groups = []
                for i in range(len(self.vertices)):
                        v = self.vertices[i]
@@ -180,7 +193,7 @@ class Mesh:
                        vg = []
                        for f in v.faces:
                                if not f.flag:
-                                       vg.append(find_group_func(v, f))
+                                       vg.append(find_group_func(v, f, *args))
 
                        groups.append(vg)
 
@@ -204,7 +217,6 @@ class Mesh:
                                                        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
@@ -227,8 +239,8 @@ class Mesh:
        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 split_uv(self, index, progress = None):
+               self.split_vertices(self.find_uv_group, progress, index)
 
        def find_smooth_group(self, vertex, face):
                face.flag = True
@@ -237,7 +249,6 @@ class Mesh:
                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
 
@@ -248,12 +259,12 @@ class Mesh:
 
                return queue
 
-       def find_uv_group(self, vertex, face):
-               uv = face.uv[face.vertices.index(vertex)]
+       def find_uv_group(self, vertex, face, index):
+               uv = face.uvs[index][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:
+                       if not f.flag and f.uvs[index][f.vertices.index(vertex)]==uv:
                                f.flag = True
                                group.append(f)
                return group
@@ -263,7 +274,15 @@ class Mesh:
                        if v.faces:
                                v.normal = mathutils.Vector()
                                for f in v.faces:
-                                       v.normal += f.normal
+                                       fv = f.pivot_vertices(v)
+                                       edge1 = fv[1].co-fv[0].co
+                                       edge2 = fv[-1].co-fv[0].co
+                                       weight = 1
+                                       if len(f.get_edge(fv[0], fv[1]).faces)==1:
+                                               weight += 1
+                                       if len(f.get_edge(fv[0], fv[-1]).faces)==1:
+                                               weight += 1
+                                       v.normal += f.normal*edge1.angle(edge2)*weight
                                v.normal.normalize()
                        else:
                                # XXX Should use edges to compute normal
@@ -272,26 +291,40 @@ class Mesh:
        def compute_uv(self):
                for v in self.vertices:
                        if v.faces:
-                               v.uv = v.faces[0].uv[v.faces[0].vertices.index(v)]
+                               f = v.faces[0]
+                               i = f.vertices.index(v)
+                               v.uvs = [u[i] for u in f.uvs]
+
+       def compute_tbn(self, uvtex):
+               if not self.uv_textures:
+                       return
+
+               uvtex_names = [u.name for u in self.uv_textures]
+               if uvtex in uvtex_names:
+                       uvtex_index = uvtex_names.index(uvtex)
+               else:
+                       uvtex_index = 0
 
-       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
+                               fv = f.pivot_vertices(v)
+                               uv0 = fv[0].uvs[uvtex_index]
+                               uv1 = fv[1].uvs[uvtex_index]
+                               uv2 = fv[-1].uvs[uvtex_index]
+                               du1 = uv1[0]-uv0[0]
+                               du2 = uv2[0]-uv0[0]
+                               dv1 = uv1[1]-uv0[1]
+                               dv2 = uv2[1]-uv0[1]
                                edge1 = fv[1].co-fv[0].co
                                edge2 = fv[-1].co-fv[0].co
+                               div = (du1*dv2-du2*dv1)
                                if div:
-                                       v.tan += (edge1*dv2-edge2*dv1)/div
-                                       v.bino += (edge2*du1-edge1*du2)/div
+                                       mul = edge1.angle(edge2)/div
+                                       v.tan += (edge1*dv2-edge2*dv1)*mul
+                                       v.bino += (edge2*du1-edge1*du2)*mul
+
                        if v.tan.length:
                                v.tan.normalize()
                        if v.bino.length: