From 2bf43ec60f148fe2c9a4ed2a322118860be3b25c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 3 Sep 2022 16:40:35 +0300 Subject: [PATCH] Support exporting meshes from Blender using patch primitives --- blender/io_mspgl/export_mesh.py | 2 + blender/io_mspgl/mesh.py | 72 ++++++++++++++++++++++++++++----- blender/io_mspgl/properties.py | 8 +++- 3 files changed, 69 insertions(+), 13 deletions(-) diff --git a/blender/io_mspgl/export_mesh.py b/blender/io_mspgl/export_mesh.py index 3f5acf9e..b0f186db 100644 --- a/blender/io_mspgl/export_mesh.py +++ b/blender/io_mspgl/export_mesh.py @@ -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) diff --git a/blender/io_mspgl/mesh.py b/blender/io_mspgl/mesh.py index ba9db802..3a24db96 100644 --- a/blender/io_mspgl/mesh.py +++ b/blender/io_mspgl/mesh.py @@ -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 diff --git a/blender/io_mspgl/properties.py b/blender/io_mspgl/properties.py index b21f45a2..6e1df641 100644 --- a/blender/io_mspgl/properties.py +++ b/blender/io_mspgl/properties.py @@ -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", -- 2.45.2