]> git.tdb.fi Git - libs/gl.git/blobdiff - blender/io_mspgl/mesh.py
Refactor creation of batches in the Blender exporter
[libs/gl.git] / blender / io_mspgl / mesh.py
index fb568ec416fb04739ef7b49c8b2bbd0a1f9f972e..ba9db8022c7e50652e5ed6258fab1821e1b7f229 100644 (file)
@@ -1,4 +1,3 @@
-import bpy
 import math
 import mathutils
 import itertools
@@ -76,6 +75,12 @@ class VertexGroup:
                        self.weight = 0.0
 
 
+class Batch:
+       def __init__(self, pt):
+               self.primitive_type = pt
+               self.vertices = []
+
+
 class Face:
        def __init__(self, face):
                self.index = face.index
@@ -155,11 +160,11 @@ class Mesh:
        def __init__(self, mesh):
                self.name = mesh.name
 
-               self.winding_test = mesh.winding_test
                self.smoothing = mesh.smoothing
                self.use_uv = mesh.use_uv
                self.tangent_uvtex = mesh.tangent_uvtex
                self.use_strips = mesh.use_strips
+               self.use_lines = mesh.use_lines
                self.vertex_groups = mesh.vertex_groups
 
                # Clone basic data
@@ -181,7 +186,7 @@ class Mesh:
                if mesh.use_uv=='NONE' or not mesh.uv_layers:
                        self.uv_layers = []
                else:
-                       self.uv_layers = [UvLayer(u) for u in mesh.uv_layers]
+                       self.uv_layers = [UvLayer(u) for u in mesh.uv_layers if u.data]
 
                        # Assign texture unit numbers to UV layers that lack one
                        missing_unit = [u for u in self.uv_layers if u.unit is None]
@@ -193,7 +198,7 @@ class Mesh:
 
                        self.uv_layers = sorted(self.uv_layers, key=(lambda u: u.unit))
 
-                       if mesh.use_uv=='UNIT0':
+                       if mesh.use_uv=='UNIT0' and self.uv_layers:
                                self.uv_layers = [self.uv_layers[0]]
                                if self.uv_layers[0].unit!=0:
                                        self.uv_layers = []
@@ -244,7 +249,7 @@ class Mesh:
                                        if normal_prop and normal_prop.texture:
                                                self.tangent_vecs = True
 
-               self.vertex_sequence = []
+               self.batches = []
 
        def transform(self, matrix):
                for v in self.vertices:
@@ -259,12 +264,12 @@ class Mesh:
 
                # Merge materials and form a lookup from source material indices to the
                # merged material list
-               material_atlas = []
+               material_lookup = []
                for m in other.materials:
                        if m in self.materials:
-                               material_atlas.append(self.materials.index(m))
+                               material_lookup.append(self.materials.index(m))
                        else:
-                               material_atlas.append(len(self.materials))
+                               material_lookup.append(len(self.materials))
                                self.materials.append(m)
 
                # Append data and adjust indices where necessary.  Since the data is
@@ -295,7 +300,7 @@ class Mesh:
                        f.index += offset
                        f.loop_indices = range(f.loop_indices.start+offset, f.loop_indices.stop+offset)
                        if other.materials:
-                               f.material_index = material_atlas[f.material_index]
+                               f.material_index = material_lookup[f.material_index]
 
                offset = len(self.edges)
                self.edges += other.edges
@@ -413,30 +418,6 @@ class Mesh:
                                for g in v.groups:
                                        g.group = group_index_map[g.group]
 
-       def apply_material_atlas(self, material_atlas):
-               for m in self.materials:
-                       if m.name not in material_atlas.material_names:
-                               raise Exception("Material atlas {} is not compatible with Mesh {}".format(material_atlas.name, self.name))
-
-               if self.use_uv=='NONE':
-                       return
-
-               layer = UvLayer("material_atlas")
-               if self.use_uv=='UNIT0':
-                       self.uv_layers = [layer]
-                       layer.unit = 0
-               else:
-                       self.uv_layers.append(layer)
-                       used_units = [u.unit for u in self.uv_layers]
-                       layer.unit = next(i for i in itertools.count() if i not in used_units)
-                       self.uv_layers.sort(key=lambda u: u.unit)
-
-               layer.uvs = [(0.0, 0.0)]*len(self.loops)
-               for f in self.faces:
-                       uv = material_atlas.get_material_uv(self.materials[f.material_index])
-                       for i in f.loop_indices:
-                               layer.uvs[i] = uv
-
        def prepare_uv(self, task):
                # Form a list of UV layers referenced by materials with the array atlas
                # property set
@@ -660,6 +641,17 @@ class Mesh:
                self.reorder_faces(subtask)
 
                subtask = task.task("Building sequence", 1.0)
+               if self.use_strips:
+                       self.build_tristrip_sequence(subtask)
+               else:
+                       self.build_triangle_sequence(subtask)
+
+               if self.use_lines:
+                       self.build_line_sequence()
+
+               self.reorder_vertices()
+
+       def build_tristrip_sequence(self, task):
                sequence = None
                for i, f in enumerate(self.faces):
                        if sequence:
@@ -683,10 +675,23 @@ class Mesh:
                                        sequence += to_add
 
                        if not sequence:
-                               sequence = f.vertices[:]
-                               self.vertex_sequence.append(sequence)
+                               self.batches.append(Batch("TRIANGLE_STRIP"))
+                               sequence = self.batches[-1].vertices
+                               sequence += f.vertices
+
+                       task.set_progress(i/len(self.faces))
 
-                       subtask.set_progress(i/len(self.faces))
+       def build_triangle_sequence(self, task):
+               batch = Batch("TRIANGLES")
+               for f in self.faces:
+                       batch.vertices += f.vertices
+               self.batches.append(batch)
+
+       def build_line_sequence(self):
+               batch = Batch("LINES")
+               for l in self.lines:
+                       batch.vertices += l.vertices
+               self.batches.append(batch)
 
                self.reorder_vertices()
 
@@ -708,7 +713,8 @@ class Mesh:
                # Keep track of the score and number of unused faces for each vertex
                vertex_info = [[0, len(v.faces)] for v in self.vertices]
                for vi in vertex_info:
-                       vi[0] = valence_boost_scale*(vi[1]**valence_boost_power)
+                       if vi[1]:
+                               vi[0] = valence_boost_scale*(vi[1]**valence_boost_power)
 
                face = None
                reordered_faces = []
@@ -777,19 +783,24 @@ class Mesh:
                        v.index = -1
 
                reordered_vertices = []
-               for s in self.vertex_sequence:
-                       for v in s:
+               for b in self.batches:
+                       for v in b.vertices:
                                if v.index<0:
                                        v.index = len(reordered_vertices)
                                        reordered_vertices.append(v)
 
+               for v in self.vertices:
+                       if v.index<0:
+                               v.index = len(reordered_vertices)
+                               reordered_vertices.append(v)
+
                self.vertices = reordered_vertices
 
                for e in self.edges:
                        e.key = make_edge_key(e.vertices[0].index, e.vertices[1].index)
 
 
-def create_mesh_from_object(ctx, obj, material_atlas):
+def create_mesh_from_object(ctx, obj):
        if obj.type!="MESH":
                raise Exception("Object {} is not a mesh".format(obj.name))
 
@@ -812,7 +823,6 @@ def create_mesh_from_object(ctx, obj, material_atlas):
                bmesh = eval_obj.to_mesh()
 
                # Object.to_mesh does not copy custom properties
-               bmesh.winding_test = o.data.winding_test
                bmesh.smoothing = o.data.smoothing
                bmesh.use_lines = o.data.use_lines
                bmesh.vertex_groups = o.data.vertex_groups
@@ -835,9 +845,6 @@ def create_mesh_from_object(ctx, obj, material_atlas):
 
        mesh.name = obj.data.name
 
-       if material_atlas:
-               mesh.apply_material_atlas(material_atlas)
-
        task = ctx.task("Triangulating", 0.3)
        mesh.prepare_triangles(task)
        task = ctx.task("Smoothing", 0.5)