Exemplo n.º 1
0
    def load_file(self, file_path):

        mesh_data = {}
        abs_file_path = os.path.abspath(file_path)

        with open(abs_file_path, "rb") as file:
            magic = file.read(16)

            if magic.decode("utf-8") != "INTERQUAKEMODEL\0":
                mesh_data["error"] = "Doesnt match magic"
                return mesh_data

            header = {}
            #reads the header informations
            header["version"] = int.from_bytes(file.read(4), "little")
            header["filesize"] = int.from_bytes(file.read(4), "little")
            header["flags"] = int.from_bytes(file.read(4), "little")
            header["num_text"] = int.from_bytes(file.read(4), "little")
            header["ofs_text"] = int.from_bytes(file.read(4), "little")
            header["num_meshes"] = int.from_bytes(file.read(4), "little")
            header["ofs_meshes"] = int.from_bytes(file.read(4), "little")
            header["num_vertexarr"] = int.from_bytes(file.read(4), "little")
            header["num_vertexes"] = int.from_bytes(file.read(4), "little")
            header["ofs_vertexarr"] = int.from_bytes(file.read(4), "little")
            header["num_triangle"] = int.from_bytes(file.read(4), "little")
            header["ofs_triangle"] = int.from_bytes(file.read(4), "little")
            header["ofs_adjacency"] = int.from_bytes(file.read(4), "little")
            header["num_joints"] = int.from_bytes(file.read(4), "little")
            header["ofs_joints"] = int.from_bytes(file.read(4), "little")
            header["num_poses"] = int.from_bytes(file.read(4), "little")
            header["ofs_poses"] = int.from_bytes(file.read(4), "little")
            header["num_anims"] = int.from_bytes(file.read(4), "little")
            header["ofs_anims"] = int.from_bytes(file.read(4), "little")
            header["num_frames"] = int.from_bytes(file.read(4), "little")
            header["num_framechannels"] = int.from_bytes(
                file.read(4), "little")
            header["ofs_frames"] = int.from_bytes(file.read(4), "little")
            header["ofs_bounds"] = int.from_bytes(file.read(4), "little")
            header["num_comment"] = int.from_bytes(file.read(4), "little")
            header["ofs_comment"] = int.from_bytes(file.read(4), "little")
            header["num_extension"] = int.from_bytes(file.read(4), "little")
            header["ofs_extension"] = int.from_bytes(file.read(4), "little")

            if header["version"] != 2:
                mesh_data[
                    "error"] = "Model is outdated, only Version 2 is supported"
                return mesh_data

            indices = []
            vertex_arrays = []
            meshes = []

            #read the text parts
            file.seek(header["ofs_text"])
            text_blob = file.read(header["num_text"]).decode("utf-8")

            #reads the mesh vertex informations
            file.seek(header["ofs_vertexarr"])

            for i in range(header["num_vertexarr"]):
                vertex_data = {}

                vertex_data["type"] = int.from_bytes(file.read(4), "little")
                vertex_data["flags"] = int.from_bytes(file.read(4), "little")
                vertex_data["format"] = int.from_bytes(file.read(4), "little")
                vertex_data["size"] = int.from_bytes(file.read(4), "little")
                vertex_data["offset"] = int.from_bytes(file.read(4), "little")
                vertex_data["num_entries"] = header[
                    "num_vertexes"] * vertex_data["size"]
                vertex_data["str_type"] = VERTEX_ORDER[i]

                vertex_arrays.append(vertex_data)

            center_of_mass_values = []
            center_of_mass_vector = vector3.Vector3()

            for i in range(len(vertex_arrays)):
                data = []

                file.seek(vertex_arrays[i]["offset"])

                for _ in range(vertex_arrays[i]["num_entries"]):

                    gl_type = VERTEX_FORMAT[vertex_arrays[i]["format"]][0]
                    value = 0

                    if gl_type == GL_FLOAT:
                        (value, ) = struct.unpack("f", file.read(4))
                    elif gl_type == GL_BYTE:
                        value = int.from_bytes(file.read(1),
                                               byteorder="little",
                                               signed=True)
                    elif gl_type == GL_UNSIGNED_BYTE:
                        value = int.from_bytes(file.read(1), "little")
                    elif gl_type == GL_INT:
                        value = int.from_bytes(file.read(4),
                                               "little",
                                               signed=True)
                    elif gl_type == GL_UINT:
                        value = int.from_bytes(file.read(4), "little")
                    else:
                        print("IQM-Loader: Not implemented datatype - ",
                              gl_type)

                    if i == 0:
                        center_of_mass_values.append(value)

                        if len(center_of_mass_values) == 3:
                            center_of_mass_vector = center_of_mass_vector + vector3.Vector3(
                                center_of_mass_values[0],
                                center_of_mass_values[1],
                                center_of_mass_values[2])
                            center_of_mass_values = []

                    data.append(value)

                vertex_arrays[i]["data"] = data

            #calculate the center of mass as a centroid
            center_of_mass_vector = center_of_mass_vector / (
                vertex_arrays[0]["num_entries"] / 3)
            mesh_data["center_of_mass"] = center_of_mass_vector

            #reads the ibo-data
            file.seek(header["ofs_triangle"])

            for i in range(header["num_triangle"]):
                indices.append(int.from_bytes(file.read(4), "little"))
                indices.append(int.from_bytes(file.read(4), "little"))
                indices.append(int.from_bytes(file.read(4), "little"))

            #reads the mesh information to later load them
            file.seek(header["ofs_meshes"])
            base_path = os.path.dirname(file_path)
            tex_pool = self.scene_manager.get_texture_pool()

            for i in range(header["num_meshes"]):
                mesh_informations = {}

                mesh_informations["name"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["material"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["first_vertex"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["num_vertices"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["first_triangle"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["num_triangle"] = int.from_bytes(
                    file.read(4), "little")
                mesh_informations["str_name"] = self.resolve_name(
                    text_blob, mesh_informations["name"])
                mesh_informations["str_material"] = self.resolve_name(
                    text_blob, mesh_informations["material"])

                tex_pool.load_texture(mesh_informations["str_material"],
                                      base_path,
                                      mesh_informations["str_material"]
                                      )  #load the material texture
                material = Material()
                material.assign_material("diffuse_texture",
                                         mesh_informations["str_material"])

                mesh_informations["material_obj"] = material
                meshes.append(mesh_informations)

            anim_data = self.load_animation(header, file, text_blob)

            if anim_data != None:
                mesh_data["animation_data"] = anim_data

            #reads the stored bbox (should be atleast one)
            mesh_data["bboxes"] = []

            file.seek(header["ofs_bounds"])

            if header["num_frames"] == 0:
                mesh_data["bboxes"].append(AABB())
            else:
                for i in range(header["num_frames"]):
                    (min_x, ) = struct.unpack("f", file.read(4))
                    (min_y, ) = struct.unpack("f", file.read(4))
                    (min_z, ) = struct.unpack("f", file.read(4))

                    (max_x, ) = struct.unpack("f", file.read(4))
                    (max_y, ) = struct.unpack("f", file.read(4))
                    (max_z, ) = struct.unpack("f", file.read(4))

                    (xyradius, ) = struct.unpack("f", file.read(4))
                    (radius, ) = struct.unpack("f", file.read(4))

                    aabb = AABB(vector3.Vector3(min_x, min_y, min_z),
                                vector3.Vector3(max_x, max_y, max_z), True)

                    mesh_data["bboxes"].append(aabb)

        mesh_data["buffers"] = []
        mesh_data["indices"] = indices
        mesh_data["mesh_informations"] = meshes

        for i in range(len(vertex_arrays)):
            buffer = {}
            buffer["size"] = vertex_arrays[i]["size"]
            buffer["data"] = vertex_arrays[i]["data"]
            buffer["data_type"] = VERTEX_FORMAT[vertex_arrays[i]["format"]]

            buffer["normalized"] = GL_FALSE

            if i == 5:
                buffer["normalized"] = GL_TRUE

            mesh_data["buffers"].append(buffer)

        return mesh_data