]> git.tdb.fi Git - libs/gl.git/commitdiff
Support exporting meshes from Blender using patch primitives
authorMikko Rasa <tdb@tdb.fi>
Sat, 3 Sep 2022 13:40:35 +0000 (16:40 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sat, 3 Sep 2022 13:40:35 +0000 (16:40 +0300)
blender/io_mspgl/export_mesh.py
blender/io_mspgl/mesh.py
blender/io_mspgl/properties.py

index 3f5acf9ed35f5cdd8e9c0a32eee6f0faa0dd406b..b0f186dbc04f6d65b850871169fe1db2e13e2e38 100644 (file)
@@ -92,6 +92,8 @@ class MeshExporter:
 
                for b in mesh.batches:
                        st = Statement("batch", Token(b.primitive_type))
+                       if b.primitive_type=="PATCHES":
+                               st.sub.append(Statement("patch_size", b.patch_size))
                        for i in range(0, len(b.vertices), 32):
                                st.sub.append(Statement("indices", *(v.index for v in b.vertices[i:i+32])))
                        statements.append(st)
index ba9db8022c7e50652e5ed6258fab1821e1b7f229..3a24db96a07f29a8cd9aacff8e6ede446f7cc81a 100644 (file)
@@ -78,6 +78,7 @@ class VertexGroup:
 class Batch:
        def __init__(self, pt):
                self.primitive_type = pt
+               self.patch_size = 0
                self.vertices = []
 
 
@@ -164,6 +165,7 @@ class Mesh:
                self.use_uv = mesh.use_uv
                self.tangent_uvtex = mesh.tangent_uvtex
                self.use_strips = mesh.use_strips
+               self.use_patches = mesh.use_patches
                self.use_lines = mesh.use_lines
                self.vertex_groups = mesh.vertex_groups
 
@@ -211,7 +213,7 @@ class Mesh:
                # where they don't exist
                edge_map = {e.key: e for e in self.edges}
                for f in self.faces:
-                       if len(f.vertices)>4:
+                       if len(f.vertices)>4 and not mesh.use.patches:
                                raise ValueError("Unsupported face on mesh {}: N-gon".format(self.name))
 
                        f.vertices = [self.vertices[i] for i in f.vertices]
@@ -229,7 +231,7 @@ class Mesh:
                                v.edges.append(e)
 
                # Store loose edges as lines
-               if mesh.use_lines:
+               if mesh.use_lines and not mesh.use_patches:
                        self.lines = [Line(e) for e in self.edges if not e.faces]
                else:
                        self.lines = []
@@ -311,6 +313,9 @@ class Mesh:
                self.lines += other.lines
 
        def prepare_triangles(self, task):
+               if self.use_patches:
+                       return
+
                face_count = len(self.faces)
                for i in range(face_count):
                        f = self.faces[i]
@@ -637,17 +642,24 @@ class Mesh:
                        task.set_progress(i/len(self.vertices))
 
        def prepare_sequence(self, task):
-               subtask = task.task("Reordering faces", 0.5)
-               self.reorder_faces(subtask)
+               if self.use_patches:
+                       subtask = task.task("Reordering patches", 0.5)
+                       self.reorder_patches(subtask)
 
-               subtask = task.task("Building sequence", 1.0)
-               if self.use_strips:
-                       self.build_tristrip_sequence(subtask)
+                       subtask = task.task("Building sequence", 1.0)
+                       self.build_patch_sequence(subtask)
                else:
-                       self.build_triangle_sequence(subtask)
+                       subtask = task.task("Reordering faces", 0.5)
+                       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()
+                       if self.use_lines:
+                               self.build_line_sequence()
 
                self.reorder_vertices()
 
@@ -693,7 +705,17 @@ class Mesh:
                        batch.vertices += l.vertices
                self.batches.append(batch)
 
-               self.reorder_vertices()
+       def build_patch_sequence(self, task):
+               current_size = 0
+               sequence = None
+               for f in self.faces:
+                       if len(f.vertices)!=current_size:
+                               current_size = len(f.vertices)
+                               self.batches.append(Batch("PATCHES"))
+                               self.batches[-1].patch_size = current_size
+                               sequence = self.batches[-1].vertices
+
+                       sequence += f.vertices
 
        def reorder_faces(self, task):
                # Tom Forsyth's vertex cache optimization algorithm
@@ -778,6 +800,34 @@ class Mesh:
                for i, f in enumerate(self.faces):
                        f.index = i
 
+       def reorder_patches(self, task):
+               for f in self.faces:
+                       f.flag = False
+
+               reordered_faces = []
+               n_processed = 0
+
+               while 1:
+                       current_size = 0
+
+                       for f in self.faces:
+                               if f.flag:
+                                       continue
+
+                               if not current_size:
+                                       current_size = len(f.vertices)
+                               elif len(f.vertices)!=current_size:
+                                       continue
+
+                               reordered_faces.append(f)
+                               f.flag = True
+
+                               n_processed += 1
+                               task.set_progress(n_processed/len(self.faces))
+
+                       if not current_size:
+                               break
+
        def reorder_vertices(self):
                for v in self.vertices:
                        v.index = -1
index b21f45a2bfdc103ec2d130174cbb5fe87e54ba8a..6e1df6416b974ecb731d47d65c7fb7c53814a7b8 100644 (file)
@@ -43,13 +43,16 @@ class MspGLMeshProperties(bpy.types.Panel):
                mesh = context.active_object.data
 
                self.layout.prop(mesh, "smoothing")
-               self.layout.prop(mesh, "use_strips")
+               self.layout.prop(mesh, "use_patches")
+               if not mesh.use_patches:
+                       self.layout.prop(mesh, "use_strips")
 
                self.layout.separator()
 
                col = self.layout.column()
                col.label(text="Data selection")
-               col.prop(mesh, "use_lines")
+               if not mesh.use_patches:
+                       col.prop(mesh, "use_lines")
                col.prop(mesh, "vertex_groups")
                col.prop(mesh, "max_groups_per_vertex")
 
@@ -244,6 +247,7 @@ def register_properties():
                        ("MSPGL", "MspGL", "Compute vertex normals internally")))
        bpy.types.Mesh.use_lines = bpy.props.BoolProperty(name="Include lines", description="Include edges without faces as lines", default=False)
        bpy.types.Mesh.use_strips = bpy.props.BoolProperty(name="Use strips", description="Combine the mesh's triangles into triangle strips", default=True)
+       bpy.types.Mesh.use_patches = bpy.props.BoolProperty(name="Export as patches", description="Export faces as patches, suitable for tessellation", default=False)
        bpy.types.Mesh.vertex_groups = bpy.props.BoolProperty(name="Vertex groups", description="Include vertex groups and weights", default=False)
        bpy.types.Mesh.max_groups_per_vertex = bpy.props.IntProperty(name="Max groups", description="Maximum amount of groups per vertex", min=1, max=4, default=2)
        bpy.types.Mesh.use_uv = bpy.props.EnumProperty(name="Use UV", description="Use UV coordinates", default="UNIT0",