예제 #1
0
 def get_influences(self, bone_map, all_influences):
     """
     :param bone_map: map of bone names to bones
     :returns influence collection
     """
     # construct my own bone map
     # my_bone_map = [bone_map[name] for name in self.bones]
     weights = self.weights
     my_bone_map, matrices = self.__order_bones(bone_map)
     if len(self.bones) == 1 and np.allclose(weights, 1.0):     # No influence needed
         influence = Influence()
         influence[my_bone_map[0].name] = Weight(my_bone_map[0], 1.0)
         influence = all_influences.create_or_find(influence)
         self.geometry.apply_matrix(matrices[0])
         return InfluenceCollection({0: influence})
     influences = {}
     indices = self.vertex_weight_indices
     vertex_weight_counts = self.vertex_weight_counts
     j = 0
     # Now construct influences
     vertices = self.geometry.vertices
     for vertex_index in range(len(vertex_weight_counts)):
         weight_count = vertex_weight_counts[vertex_index]
         influence = Influence()
         for i in range(weight_count):
             bone = my_bone_map[indices[j, 0]]
             influence[bone.name] = Weight(bone, weights[indices[j, 1]])
             j += 1
         influences[vertex_index] = all_influences.create_or_find(influence)
         # apply_matrix(matrices[] vertices[vertex_index]
     return InfluenceCollection(influences)
예제 #2
0
 def get_influences(self, bone_map, all_influences):
     """
     :param bone_map: map of bone names to bones
     :returns influence collection
     """
     # construct my own bone map
     # my_bone_map = [bone_map[name] for name in self.bones]
     weights = self.weights
     try:
         my_bone_map, matrices = self.__order_bones(bone_map)
         if len(self.bones) == 1 and np.allclose(
                 weights, 1.0):  # No influence needed
             influence = Influence()
             influence[my_bone_map[0].name] = Weight(my_bone_map[0], 1.0)
             influence = all_influences.create_or_find(influence)
             # if type(self.geometry) == list:
             #     for x in self.geometry:
             #         x.apply_matrix(matrices[0])
             # else:
             #     self.geometry.apply_matrix(matrices[0])
             return InfluenceCollection({0: influence})
         else:
             influences = {}
             indices = self.vertex_weight_indices
             vertex_weight_counts = self.vertex_weight_counts
             j = 0
             # Now construct influences
             # vertices = self.geometry.vertices
             for vertex_index in range(len(vertex_weight_counts)):
                 weight_count = vertex_weight_counts[vertex_index]
                 influence = Influence()
                 for i in range(weight_count):
                     bone = my_bone_map[indices[j, 0]]
                     influence[bone.name] = Weight(bone,
                                                   weights[indices[j, 1]])
                     j += 1
                 influences[vertex_index] = all_influences.create_or_find(
                     influence)
                 # apply_matrix(matrices[] vertices[vertex_index]
             return InfluenceCollection(influences)
     except KeyError:  # Bone wasn't found, use default influence
         influence = Influence()
         x = None
         for x in bone_map:
             break
         influence[x] = Weight(bone_map[x], 1.0)
         return InfluenceCollection(
             {0: all_influences.create_or_find(influence)})
예제 #3
0
def decode_polygon(polygon, influences=None):
    """ Decodes an mdl0 polygon
            :returns geometry
        """
    # build the decoder_string decoder
    if influences is None:
        influences = polygon.parent.get_influences()
    pos_matrix_index = polygon.get_weight_index()
    vertex_index = polygon.get_vertex_index()
    vertices = polygon.get_vertex_group()
    normals = polygon.get_normal_group()
    normal_index = polygon.get_normal_index()
    colors = polygon.get_color_group()
    color_index = polygon.get_color0_index()
    texcoords = []
    texcoord_index = polygon.get_uv_index(0)
    for i in range(polygon.count_uvs()):
        texcoords.append(polygon.get_uv_group(i))

    face_point_indices, weights = decode_indices(polygon, polygon.encode_str)
    face_point_indices = np.array(face_point_indices, dtype=np.uint)
    face_point_indices[:, [0, 1]] = face_point_indices[:, [1, 0]]
    g_verts = PointCollection(vertices.get_decoded(),
                              face_point_indices[:, :, vertex_index])
    linked_bone = polygon.get_linked_bone()
    if pos_matrix_index >= 0:  # apply influences to vertices
        influence_collection = decode_pos_mtx_indices(
            influences, weights, g_verts,
            face_point_indices[:, :, pos_matrix_index] // 3)
    else:
        influence = influences[linked_bone.weight_id]
        g_verts.apply_affine_matrix(np.array(
            linked_bone.get_transform_matrix()),
                                    apply=True)
        influence_collection = InfluenceCollection({0: influence})
    from abmatt.converters.geometry import Geometry
    geometry = Geometry(polygon.name,
                        polygon.get_material().name,
                        g_verts,
                        triangles=None,
                        influences=influence_collection,
                        linked_bone=linked_bone)
    # create the point collections
    if normals:
        geometry.normals = PointCollection(
            normals.get_decoded(), face_point_indices[:, :, normal_index])
    if colors:
        geometry.colors = ColorCollection(
            colors.get_decoded(), face_point_indices[:, :, color_index])
    for tex in texcoords:
        pc = PointCollection(tex.get_decoded(),
                             face_point_indices[:, :, texcoord_index],
                             tex.minimum, tex.maximum)
        geometry.texcoords.append(pc)
        texcoord_index += 1
    return geometry
예제 #4
0
def decode_pos_mtx_indices(all_influences, weight_groups, vertices,
                           pos_mtx_indices):
    """ Finds and applies the weight matrix to the corresponding vertices
    :param all_influences: map of influence ids to influences
    :param weight_groups: map of each beginning group face_point index to list of weights
    :param vertices: PointCollection
    :param pos_mtx_indices: np array of face_point indices corresponding to those in vertices
    :return: InfluenceCollection
    """
    influences = {}  # map vertex indices to influences used by this geometry
    vert_indices = vertices.face_indices
    points = vertices.points
    # Order the indices of each group so we can slice up the indices
    slicer = sorted(weight_groups.keys())
    slicer.append(len(vert_indices))  # add the max onto the end for slicing

    remapper = {}
    new_points = []
    new_face_indices = deepcopy(vert_indices)
    # Each weighting slice group
    for i in range(len(slicer) - 1):
        start = slicer[i]
        end = slicer[i + 1]
        weights = np.array(weight_groups[start])
        vertex_slice = vert_indices[start:end]
        pos_mtx_slice = pos_mtx_indices[start:end]

        # map each vertex to an influence
        for i in range(len(vertex_slice)):
            for j in range(3):
                vert_id = vertex_slice[i, j]
                inf = all_influences[weights[pos_mtx_slice[i, j]]]
                weight_id = inf.influence_id
                remappings = remapper.get(vert_id)
                add_it = bool(remappings is None)
                if not remappings:
                    remapper[vert_id] = remappings = []
                if not add_it:
                    add_it = True
                    for index, influence in remappings:
                        if influence.influence_id == weight_id:
                            add_it = False
                            new_face_indices[start + i, j] = index
                            break
                if add_it:
                    remappings.append((len(new_points), inf))
                    influences[len(new_points)] = inf
                    new_face_indices[start + i, j] = len(new_points)
                    new_points.append(
                        inf.apply_to(points[vert_id], decode=True))
    vertices.points = np.array(new_points)
    vertices.face_indices = new_face_indices
    assert len(influences) == len(new_points)
    return InfluenceCollection(influences)
예제 #5
0
def decode_pos_mtx_indices(all_influences, weight_groups, vertices,
                           pos_mtx_indices):
    """ Finds and applies the weight matrix to the corresponding vertices
    :param all_influences: map of influence ids to influences
    :param weight_groups: map of each beginning group face_point index to list of weights
    :param vertices: PointCollection
    :param pos_mtx_indices: np array of face_point indices corresponding to those in vertices
    :return: InfluenceCollection
    """
    influences = {}  # map vertex indices to influences used by this geometry
    vert_indices = vertices.face_indices
    points = vertices.points
    # Order the indices of each group so we can slice up the indices
    slicer = sorted(weight_groups.keys())
    slicer.append(len(vert_indices))  # add the max onto the end for slicing

    # Each weighting slice group
    for i in range(len(slicer) - 1):
        start = slicer[i]
        end = slicer[i + 1]
        weights = np.array(weight_groups[start])
        vertex_slice = vert_indices[start:end].flatten()
        pos_mtx_slice = pos_mtx_indices[start:end].flatten()
        # get the ordered indices corresponding to vertices
        vertex_indices, indices = np.unique(vertex_slice, return_index=True)
        weight_indices = weights[pos_mtx_slice[
            indices]]  # get the matrix corresponding to vert index, resolve to weight_id

        # map each vertex id to an influence and apply it
        for i in range(len(vertex_indices)):
            vertex_index = vertex_indices[i]
            if vertex_index not in influences:
                influences[vertex_index] = influence = all_influences[
                    weight_indices[i]]
                points[vertex_index] = influence.apply_to(points[vertex_index],
                                                          decode=True)
            elif influences[vertex_index].influence_id != weight_indices[i]:
                AutoFix.get().warn(
                    f'vertex {vertex_index} has multiple different influences!'
                )
                influences[vertex_index] = all_influences[weight_indices[i]]

    assert len(influences) == len(points)
    return InfluenceCollection(influences)
예제 #6
0
def decode_mdl0_influences(mdl0):
    influences = {}
    bones = mdl0.bones
    bonetable = mdl0.bone_table
    # Get bonetable influences
    for i in range(len(bonetable)):
        index = bonetable[i]
        if index >= 0:
            bone = bones[index]
            influences[i] = Influence(
                bone_weights={bone.name: Weight(bone, 1)}, influence_id=i)

    # Get mixed influences
    nodemix = mdl0.NodeMix
    if nodemix is not None:
        for inf in nodemix.mixed_weights:
            weight_id = inf.weight_id
            influences[weight_id] = influence = Influence(
                influence_id=weight_id)
            for x in inf:
                bone = bones[bonetable[x[0]]]
                influence[bone.name] = Weight(bone, x[1])
    return InfluenceCollection(influences)
예제 #7
0
def decode_polygon(polygon, influences):
    """ Decodes an mdl0 polygon
            :returns geometry
        """
    # build the decoder_string decoder
    pos_matrix_index = polygon.get_weight_index()
    tex_matrix_index = polygon.get_uv_matrix_index(0)
    vertex_index = polygon.get_vertex_index()
    vertices = polygon.get_vertex_group()
    normals = polygon.get_normal_group()
    normal_index = polygon.get_normal_index()
    colors = polygon.get_color_group()
    color_index = polygon.get_color0_index()
    texcoords = []
    texcoord_index = polygon.get_uv_index(0)
    for i in range(polygon.count_uvs()):
        texcoords.append(polygon.get_uv_group(i))

    face_point_indices, weights = decode_indices(polygon, polygon.encode_str)
    face_point_indices = np.array(face_point_indices, dtype=np.uint)
    face_point_indices[:, [0, 1]] = face_point_indices[:, [1, 0]]
    # decoded_verts =
    g_verts = PointCollection(decode_geometry_group(vertices),
                              face_point_indices[:, :, vertex_index])
    linked_bone = polygon.get_bone()
    if pos_matrix_index >= 0:  # apply influences to vertices
        influence_collection = decode_pos_mtx_indices(
            influences, weights, g_verts,
            face_point_indices[:, :, pos_matrix_index] // 3)
    else:
        influence = influences[linked_bone.weight_id]
        rotation_matrix = get_rotation_matrix(
            np.array(linked_bone.get_inv_transform_matrix(), dtype=float))
        decoded_verts = influence.apply_to_all(g_verts.points, decode=True)
        if not np.allclose(rotation_matrix, np.identity(3)):
            for i in range(len(decoded_verts)):
                decoded_verts[i] = np.dot(rotation_matrix, decoded_verts[i])
        influence_collection = InfluenceCollection({0: influence})
    if tex_matrix_index > 0:
        for x in polygon.has_tex_matrix:
            if x:
                indices = face_point_indices[:, :, tex_matrix_index]
                tex_matrix_index += 1

    geometry = Geometry(polygon.name,
                        polygon.get_material().name,
                        g_verts,
                        triangles=face_point_indices[:, :, vertex_index:],
                        influences=influence_collection,
                        linked_bone=linked_bone)
    # create the point collections
    if normals:
        geometry.normals = PointCollection(
            decode_geometry_group(normals), face_point_indices[:, :,
                                                               normal_index])
    if colors:
        geometry.colors = ColorCollection(
            ColorCollection.decode_data(colors),
            face_point_indices[:, :, color_index])
    for tex in texcoords:
        x = decode_geometry_group(tex)
        pc = PointCollection(x, face_point_indices[:, :, texcoord_index],
                             tex.minimum, tex.maximum)
        pc.flip_points()
        geometry.texcoords.append(pc)
        texcoord_index += 1
    return geometry