From 87b86b7553bbee0f60122ce4d2c29116efb18ab5 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 20 Oct 2015 15:33:54 -1000 Subject: [PATCH] Much more optimal mesh optimizer --- hecl/blender/hecl/hmdl/HMDLMesh.py | 176 ++++++++--------------------- hecl/blender/hecl/hmdl/__init__.py | 29 +---- hecl/extern/Athena | 2 +- 3 files changed, 56 insertions(+), 151 deletions(-) diff --git a/hecl/blender/hecl/hmdl/HMDLMesh.py b/hecl/blender/hecl/hmdl/HMDLMesh.py index d5534d3ae..a0812c9ec 100644 --- a/hecl/blender/hecl/hmdl/HMDLMesh.py +++ b/hecl/blender/hecl/hmdl/HMDLMesh.py @@ -216,103 +216,15 @@ def recursive_faces_islands(dlay, list_out, rem_list, skin_slot_set, skin_slot_c next_faces.append(f) return next_faces -def find_opposite_edge(face, boot_edge, boot_edge2, last_edge, last_edge_2): - if last_edge_2: - for e in face.edges: - if e.verts[0] in last_edge_2.verts or e.verts[1] in last_edge_2.verts: - continue - return e - elif last_edge: - return boot_edge2 +def strip_next_loop(prev_loop, out_count): + if out_count & 1: + radial_loop = prev_loop.link_loop_radial_next + loop = radial_loop.link_loop_prev + return loop, loop else: - return boot_edge - -def recursive_faces_strip(list_out, rem_list, face, boot_edge, boot_edge_2, last_edge, last_edge_2): - if face not in rem_list: - return None, None, None - list_out.append(face) - rem_list.remove(face) - edge = find_opposite_edge(face, boot_edge, boot_edge_2, last_edge, last_edge_2) - if not edge: - return None, None, None - edge.select = True - for f in edge.link_faces: - if f == face: - continue - return f, edge, last_edge - return None, None, None - -def count_contiguous_edges(face): - retval = 0 - for e in face.edges: - if e.is_contiguous: - retval += 1 - return retval - -def find_loop_opposite_from_other_face(face, other_face): - for e in face.edges: - if e in other_face.edges: - edge = e - break - for l in face.loops: - if l.vert in edge.verts: - continue - return l - -def stripify_primitive(writebuf, vert_pool, prim_faces, last_loop, next_idx): - if last_loop: - vert_pool.loop_out(writebuf, last_loop) - next_idx += 1 - - if len(prim_faces) == 1: - loop = prim_faces[0].loops[0] - if last_loop: - vert_pool.loop_out(writebuf, loop) - next_idx += 1 - if next_idx & 1: - rev = True - else: - rev = False - for i in range(3): - vert_pool.loop_out(writebuf, loop) - last_loop = loop - next_idx += 1 - if rev: - loop = loop.link_loop_prev - else: - loop = loop.link_loop_next - return last_loop, next_idx - - loop = find_loop_opposite_from_other_face(prim_faces[0], prim_faces[1]) - if last_loop: - vert_pool.loop_out(writebuf, loop) - next_idx += 1 - if next_idx & 1: - rev = True - else: - rev = False - for i in range(3): - vert_pool.loop_out(writebuf, loop) - last_loop = loop - next_idx += 1 - if rev: - loop = loop.link_loop_prev - else: - loop = loop.link_loop_next - - for i in range(1, len(prim_faces)): - if prim_faces[i].index == 688: - print(prim_faces[i], prim_faces[i-1], prim_faces[i-2]) - #prim_faces[i].select = True - #prim_faces[i-1].select = True - #prim_faces[i-2].select = True - loop = find_loop_opposite_from_other_face(prim_faces[i], prim_faces[i-1]) - vert_pool.loop_out(writebuf, loop) - last_loop = loop - next_idx += 1 - - return last_loop, next_idx - + radial_loop = prev_loop.link_loop_radial_prev + loop = radial_loop.link_loop_next + return loop.link_loop_next, loop def write_out_surface(writebuf, vert_pool, island_faces, mat_idx): @@ -350,43 +262,53 @@ def write_out_surface(writebuf, vert_pool, island_faces, mat_idx): writebuf(struct.pack('I', len(island_faces) * 3)) # Verts themselves - last_loop = None - next_idx = 0 + prev_loop_emit = None + out_count = 0 while len(island_faces): sel_lists_local = [] + restore_out_count = out_count for start_face in island_faces: - for e in start_face.edges: - next_edges = [] - for f in e.link_faces: - if f == start_face: - continue - for eg in f.edges: - if eg == e: - continue - next_edges.append(eg) - break - if len(next_edges) == 0: - next_edges.append(None) - for e2 in next_edges: - island_local = list(island_faces) - sel_list = [] - next_face = start_face - last_edge = None - last_edge_2 = None - while next_face is not None: - next_face, last_edge, last_edge_2 = recursive_faces_strip(sel_list, island_local, next_face, - e, e2, last_edge, last_edge_2) - if len(sel_list): - sel_lists_local.append(sel_list) + for l in start_face.loops: + out_count = restore_out_count + island_local = list(island_faces) + if out_count & 1: + prev_loop = l.link_loop_prev + loop = prev_loop.link_loop_prev + sel_list = [l, prev_loop, loop] + prev_loop = loop + else: + prev_loop = l.link_loop_next + loop = prev_loop.link_loop_next + sel_list = [l, prev_loop, loop] + out_count += 3 + island_local.remove(start_face) + while True: + if not prev_loop.edge.is_contiguous or prev_loop.edge.tag: + break + loop, prev_loop = strip_next_loop(prev_loop, out_count) + face = loop.face + if face not in island_local: + break + sel_list.append(loop) + island_local.remove(face) + out_count += 1 + sel_lists_local.append((sel_list, island_local, out_count)) max_count = 0 max_sl = None + max_island_faces = None for sl in sel_lists_local: - if len(sl) > max_count: - max_count = len(sl) - max_sl = sl - for f in max_sl: - island_faces.remove(f) - last_loop, next_idx = stripify_primitive(writebuf, vert_pool, max_sl, last_loop, next_idx) + if len(sl[0]) > max_count: + max_count = len(sl[0]) + max_sl = sl[0] + max_island_faces = sl[1] + out_count = sl[2] + island_faces = max_island_faces + if prev_loop_emit: + vert_pool.loop_out(writebuf, prev_loop_emit) + vert_pool.loop_out(writebuf, max_sl[0]) + for loop in max_sl: + vert_pool.loop_out(writebuf, loop) + prev_loop_emit = loop writebuf(struct.pack('B', 0)) diff --git a/hecl/blender/hecl/hmdl/__init__.py b/hecl/blender/hecl/hmdl/__init__.py index 9512ce360..a5f0b7eaa 100644 --- a/hecl/blender/hecl/hmdl/__init__.py +++ b/hecl/blender/hecl/hmdl/__init__.py @@ -128,25 +128,10 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): bm_master.from_mesh(copy_mesh) vert_pool = HMDLMesh.VertPool(bm_master, rna_loops) - # Split edges where there are distinctive loops + # Tag edges where there are distinctive loops splittable_edges = [] for e in bm_master.edges: - if vert_pool.splitable_edge(e): - #splittable_edges.append(e) - e.seam = True - #bmesh.ops.split(bm_master, geom=splittable_edges) - bm_master.to_mesh(copy_mesh) - - bpy.context.scene.objects.active = copy_obj - return - - if copy_mesh.has_custom_normals: - copy_mesh.calc_normals_split() - rna_loops = copy_mesh.loops - bpy.ops.object.mode_set(mode='EDIT') - bm_master = bmesh.from_edit_mesh(copy_mesh) - vert_pool = HMDLMesh.VertPool(bm_master, rna_loops) - + e.tag = vert_pool.splitable_edge(e) # Sort materials by pass index first sorted_material_idxs = [] @@ -262,12 +247,10 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): writebuf(struct.pack('B', 0)) # Delete copied mesh from scene - #bm_master.free() - #bpy.context.scene.objects.unlink(copy_obj) - #bpy.data.objects.remove(copy_obj) - #bpy.data.meshes.remove(copy_mesh) - - bpy.context.scene.objects.active = copy_obj + bm_master.free() + bpy.context.scene.objects.unlink(copy_obj) + bpy.data.objects.remove(copy_obj) + bpy.data.meshes.remove(copy_mesh) def draw(layout, context): diff --git a/hecl/extern/Athena b/hecl/extern/Athena index 1601abcc7..e86169148 160000 --- a/hecl/extern/Athena +++ b/hecl/extern/Athena @@ -1 +1 @@ -Subproject commit 1601abcc7a4261ca0d6822729aec683fb39f2c9e +Subproject commit e8616914801e274155bfe8d9fe3353448f0ec219