def import_skin(ni_block, b_obj): """Import a NiSkinInstance and its contents as vertex groups""" skininst = ni_block.skin_instance if skininst: skindata = skininst.data bones = skininst.bones # the usual case if skindata.has_vertex_weights: bone_weights = skindata.bone_list for idx, n_bone in enumerate(bones): # skip empty bones (see pyffi issue #3114079) if not n_bone: continue vertex_weights = bone_weights[idx].vertex_weights group_name = block_store.import_name(n_bone) if group_name not in b_obj.vertex_groups: v_group = b_obj.vertex_groups.new(name=group_name) for skinWeight in vertex_weights: vert = skinWeight.index weight = skinWeight.weight v_group.add([vert], weight, 'REPLACE') # WLP2 - hides the weights in the partition else: skin_partition = skininst.skin_partition for block in skin_partition.skin_partition_blocks: # create all vgroups for this block's bones block_bone_names = [block_store.import_name(bones[i]) for i in block.bones] for group_name in block_bone_names: b_obj.vertex_groups.new(name=group_name) # go over each vert in this block for vert, vertex_weights, bone_indices in zip(block.vertex_map, block.vertex_weights, block.bone_indices): # assign this vert's 4 weights to its 4 vgroups (at max) for w, b_i in zip(vertex_weights, bone_indices): if w > 0: group_name = block_bone_names[b_i] v_group = b_obj.vertex_groups[group_name] v_group.add([vert], w, 'REPLACE') # import body parts as face maps # get faces (triangles) as map of tuples to index tri_map = {frozenset(polygon.vertices): polygon.index for polygon in b_obj.data.polygons} if isinstance(skininst, NifFormat.BSDismemberSkinInstance): skinpart = ni_block.get_skin_partition() for bodypart, skinpartblock in zip(skininst.partitions, skinpart.skin_partition_blocks): bodypart_wrap = NifFormat.BSDismemberBodyPartType() bodypart_wrap.set_value(bodypart.body_part) group_name = bodypart_wrap.get_detail_display() # create face map if it did not exist yet if group_name not in b_obj.face_maps: f_group = b_obj.face_maps.new(name=group_name) # add the triangles to the face map f_group.add([tri_map[frozenset(vertices)] for vertices in skinpartblock.get_mapped_triangles()])
def get_body_part_groups(self, b_obj, b_mesh): """Returns a set of vertices (no dupes) for each body part""" bodypartgroups = [] for bodypartgroupname in NifFormat.BSDismemberBodyPartType( ).get_editor_keys(): vertex_group = b_obj.vertex_groups.get(bodypartgroupname) vertices_list = set() if vertex_group: for b_vert in b_mesh.vertices: for b_groupname in b_vert.groups: if b_groupname.group == vertex_group.index: vertices_list.add(b_vert.index) NifLog.debug(f"Found body part {bodypartgroupname}") bodypartgroups.append([ bodypartgroupname, getattr(NifFormat.BSDismemberBodyPartType, bodypartgroupname), vertices_list ]) return bodypartgroups
def get_polygon_parts(self, b_obj, b_mesh): """Returns the body part indices of the mesh polygons. -1 is either not assigned to a face map or not a valid body part""" index_group_map = {-1: -1} for bodypartgroupname in NifFormat.BSDismemberBodyPartType( ).get_editor_keys(): face_map = b_obj.face_maps.get(bodypartgroupname) if face_map: index_group_map[face_map.index] = getattr( NifFormat.BSDismemberBodyPartType, bodypartgroupname) if len(index_group_map) <= 1: # there were no valid face maps return [] bm = bmesh.new() bm.from_mesh(b_mesh) bm.faces.ensure_lookup_table() fm = bm.faces.layers.face_map.verify() polygon_parts = [ index_group_map.get(face[fm], -1) for face in bm.faces ] bm.free() return polygon_parts
def import_skin(ni_block, b_obj): """Import a NiSkinInstance and its contents as vertex groups""" skininst = ni_block.skin_instance if skininst: skindata = skininst.data bones = skininst.bones # the usual case if skindata.has_vertex_weights: bone_weights = skindata.bone_list for idx, n_bone in enumerate(bones): # skip empty bones (see pyffi issue #3114079) if not n_bone: continue vertex_weights = bone_weights[idx].vertex_weights group_name = block_store.import_name(n_bone) if group_name not in b_obj.vertex_groups: v_group = b_obj.vertex_groups.new(name=group_name) for skinWeight in vertex_weights: vert = skinWeight.index weight = skinWeight.weight v_group.add([vert], weight, 'REPLACE') # WLP2 - hides the weights in the partition else: skin_partition = skininst.skin_partition for block in skin_partition.skin_partition_blocks: # create all vgroups for this block's bones block_bone_names = [ block_store.import_name(bones[i]) for i in block.bones ] for group_name in block_bone_names: b_obj.vertex_groups.new(name=group_name) # go over each vert in this block for vert, vertex_weights, bone_indices in zip( block.vertex_map, block.vertex_weights, block.bone_indices): # assign this vert's 4 weights to its 4 vgroups (at max) for w, b_i in zip(vertex_weights, bone_indices): if w > 0: group_name = block_bone_names[b_i] v_group = b_obj.vertex_groups[group_name] v_group.add([vert], w, 'REPLACE') # import body parts as vertex groups if isinstance(skininst, NifFormat.BSDismemberSkinInstance): skinpart_list = [] bodypart_flag = [] skinpart = ni_block.get_skin_partition() for bodypart, skinpartblock in zip(skininst.partitions, skinpart.skin_partition_blocks): bodypart_wrap = NifFormat.BSDismemberBodyPartType() bodypart_wrap.set_value(bodypart.body_part) group_name = bodypart_wrap.get_detail_display() # create vertex group if it did not exist yet if group_name not in b_obj.vertex_groups: v_group = b_obj.vertex_groups.new(name=group_name) skinpart_index = len(skinpart_list) skinpart_list.append((skinpart_index, group_name)) bodypart_flag.append(bodypart.part_flag) # find vertex indices of this group groupverts = [v_index for v_index in skinpartblock.vertex_map] # create the group v_group.add(groupverts, 1, 'ADD') b_obj.niftools_part_flags_panel.pf_partcount = len(skinpart_list) for i, pl_name in skinpart_list: b_obj_partflag = b_obj.niftools_part_flags.add() # b_obj.niftools_part_flags.pf_partint = (i) b_obj_partflag.name = pl_name b_obj_partflag.pf_editorflag = bodypart_flag[ i].pf_editor_visible b_obj_partflag.pf_startflag = bodypart_flag[ i].pf_start_net_boneset