From 5900c39ea0d8439ba20c8395f20a8b342ce756b5 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 19 Oct 2015 19:02:30 -1000 Subject: [PATCH] Work on mesh generation --- hecl/blender/hecl/hmdl/HMDLMesh.py | 37 ++++++++++++++++ hecl/blender/hecl/hmdl/__init__.py | 69 +++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/hecl/blender/hecl/hmdl/HMDLMesh.py b/hecl/blender/hecl/hmdl/HMDLMesh.py index d7e3abae8..d5534d3ae 100644 --- a/hecl/blender/hecl/hmdl/HMDLMesh.py +++ b/hecl/blender/hecl/hmdl/HMDLMesh.py @@ -11,6 +11,7 @@ class VertPool: # Initialize hash-unique index for each available attribute def __init__(self, bm, rna_loops): + self.bm = bm self.rna_loops = rna_loops self.pos = {} self.norm = {} @@ -123,6 +124,36 @@ class VertPool: uf = loop[self.ulays[uidx]].uv.copy().freeze() return self.uv[uf] + def loops_contiguous(self, la, lb): + if la.vert != lb.vert: + return False + if self.get_norm_idx(la) != self.get_norm_idx(lb): + return False + for cl in range(len(self.clays)): + if self.get_color_idx(la, cl) != self.get_color_idx(lb, cl): + return False + for ul in range(len(self.ulays)): + if self.get_uv_idx(la, ul) != self.get_uv_idx(lb, ul): + return False + return True + + def splitable_edge(self, edge): + if len(edge.link_faces) < 2: + return False + for v in edge.verts: + found = None + for f in edge.link_faces: + for l in f.loops: + if l.vert == v: + if not found: + found = l + break + else: + if not self.loops_contiguous(found, l): + return True + break + return False + def loop_out(self, writebuf, loop): writebuf(struct.pack('B', 1)) writebuf(struct.pack('II', self.get_pos_idx(loop.vert), self.get_norm_idx(loop))) @@ -204,6 +235,7 @@ def recursive_faces_strip(list_out, rem_list, face, boot_edge, boot_edge_2, last 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 @@ -269,6 +301,11 @@ def stripify_primitive(writebuf, vert_pool, prim_faces, last_loop, next_idx): 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 diff --git a/hecl/blender/hecl/hmdl/__init__.py b/hecl/blender/hecl/hmdl/__init__.py index 7acbf7968..9512ce360 100644 --- a/hecl/blender/hecl/hmdl/__init__.py +++ b/hecl/blender/hecl/hmdl/__init__.py @@ -109,6 +109,7 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_all(action='SELECT') bpy.ops.mesh.quads_convert_to_tris() + bpy.ops.mesh.select_all(action='DESELECT') bpy.context.scene.update() bpy.ops.object.mode_set(mode='OBJECT') rna_loops = None @@ -124,9 +125,29 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): # Create master BMesh and VertPool bm_master = bmesh.new() - bm_master.from_mesh(copy_obj.data) + bm_master.from_mesh(copy_mesh) vert_pool = HMDLMesh.VertPool(bm_master, rna_loops) + # Split 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) + + # Sort materials by pass index first sorted_material_idxs = [] source_mat_set = set(range(len(mesh_obj.data.materials))) @@ -143,20 +164,23 @@ def cook(writebuf, mesh_obj, max_skin_banks, max_octant_length=None): if mesh_obj.data.hecl_material_count > 0: writebuf(struct.pack('I', mesh_obj.data.hecl_material_count)) for grp_idx in range(mesh_obj.data.hecl_material_count): - writebuf(struct.pack('I', len(sorted_material_idxs))) - for mat_idx in sorted_material_idxs: + writebuf(struct.pack('I', len(mesh_obj.data.materials))) + for ref_mat in mesh_obj.data.materials: + ref_mat_split = ref_mat.name.split('_') + if len(ref_mat_split) != 3: + raise RuntimeError('material names must follow MAT_%u_%u format') + ref_mat_idx = int(ref_mat_split[2]) found = False for mat in bpy.data.materials: - if mat.name.endswith('_%u_%u' % (grp_idx, mat_idx)): + if mat.name.endswith('_%u_%u' % (grp_idx, ref_mat_idx)): write_out_material(writebuf, mat, mesh_obj) found = True break if not found: raise RuntimeError('uneven material set %d in %s' % (grp_idx, mesh_obj.name)) else: - writebuf(struct.pack('II', 1, len(sorted_material_idxs))) - for mat_idx in sorted_material_idxs: - mat = mesh_obj.data.materials[mat_idx] + writebuf(struct.pack('II', 1, len(mesh_obj.data.materials))) + for mat in mesh_obj.data.materials: write_out_material(writebuf, mat, mesh_obj) # Output vert pool @@ -238,10 +262,12 @@ 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) + #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 def draw(layout, context): @@ -268,6 +294,25 @@ def material_update(self, context): if mat.name.endswith('_%u_%u' % (target_idx, mat_idx)): self.materials[mat_idx] = mat + +def fake_writebuf(by): + pass + +# DEBUG operator +import bpy +class hecl_mesh_operator(bpy.types.Operator): + bl_idname = "scene.hecl_mesh" + bl_label = "DEBUG HECL mesh maker" + bl_description = "Test mesh generation utility" + + @classmethod + def poll(cls, context): + return context.object and context.object.type == 'MESH' + + def execute(self, context): + cook(fake_writebuf, context.object, -1) + return {'FINISHED'} + import bpy def register(): bpy.types.Scene.hecl_mesh_obj = bpy.props.StringProperty( @@ -279,7 +324,9 @@ def register(): bpy.types.Mesh.hecl_material_count = bpy.props.IntProperty(name='HECL Material Count', default=0, min=0) bpy.types.Mesh.hecl_active_material = bpy.props.IntProperty(name='HECL Active Material', default=0, min=0, update=material_update) bpy.utils.register_class(HMDLShader.hecl_shader_operator) + bpy.utils.register_class(hecl_mesh_operator) pass def unregister(): bpy.utils.unregister_class(HMDLShader.hecl_shader_operator) + bpy.utils.unregister_class(hecl_mesh_operator) pass