X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=blender%2Fio_mspgl%2Fmesh.py;h=3a24db96a07f29a8cd9aacff8e6ede446f7cc81a;hb=e196a09d1df1e8504ff037d1701b7159c4f04e84;hp=fb568ec416fb04739ef7b49c8b2bbd0a1f9f972e;hpb=308dc6b8f5ee1aa3bb8f205e2ed6464749eebbe5;p=libs%2Fgl.git diff --git a/blender/io_mspgl/mesh.py b/blender/io_mspgl/mesh.py index fb568ec4..3a24db96 100644 --- a/blender/io_mspgl/mesh.py +++ b/blender/io_mspgl/mesh.py @@ -1,4 +1,3 @@ -import bpy import math import mathutils import itertools @@ -76,6 +75,13 @@ class VertexGroup: self.weight = 0.0 +class Batch: + def __init__(self, pt): + self.primitive_type = pt + self.patch_size = 0 + self.vertices = [] + + class Face: def __init__(self, face): self.index = face.index @@ -155,11 +161,12 @@ 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_patches = mesh.use_patches + self.use_lines = mesh.use_lines self.vertex_groups = mesh.vertex_groups # Clone basic data @@ -181,7 +188,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 +200,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 = [] @@ -206,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] @@ -224,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 = [] @@ -244,7 +251,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 +266,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 +302,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 @@ -306,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] @@ -413,30 +423,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 @@ -656,10 +642,28 @@ 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) + subtask = task.task("Building sequence", 1.0) + self.build_patch_sequence(subtask) + else: + 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() + + self.reorder_vertices() + + def build_tristrip_sequence(self, task): sequence = None for i, f in enumerate(self.faces): if sequence: @@ -683,12 +687,35 @@ 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 - subtask.set_progress(i/len(self.faces)) + task.set_progress(i/len(self.faces)) - self.reorder_vertices() + 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) + + 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 @@ -708,7 +735,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 = [] @@ -772,24 +800,57 @@ 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 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 +873,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 +895,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)