def custom_test_update(self, dt): if self.grab == True: self.entities[0].get_transform().set_local_position( self.camera.get_local_position() + vector3.Vector3(0.0, -2.0, 0.0)) self.entities[0].get_component( "RigidBody").linear_velocity = vector3.Vector3() self.entities[0].get_component( "RigidBody").angular_velocity = vector3.Vector3() self.time = self.time + dt
def __init__(self, w, h, d): super().__init__() h_w = w * 0.5 h_h = h * 0.5 h_d = d * 0.5 self.collision_base_points.append(vector3.Vector3(-h_w, -h_h, -h_d)) #000 self.collision_base_points.append(vector3.Vector3(-h_w, -h_h, h_d)) #001 self.collision_base_points.append(vector3.Vector3(-h_w, h_h, -h_d)) #010 self.collision_base_points.append(vector3.Vector3(-h_w, h_h, h_d)) #011 self.collision_base_points.append(vector3.Vector3(h_w, -h_h, -h_d)) #100 self.collision_base_points.append(vector3.Vector3(h_w, -h_h, h_d)) #101 self.collision_base_points.append(vector3.Vector3(h_w, h_h, -h_d)) #110 self.collision_base_points.append(vector3.Vector3(h_w, h_h, h_d)) #111 self.transformed_collision_points = self.collision_base_points
def __init__(self, entity=None): self.attached_entity = entity self.position = vector3.Vector3() self.rotation = quaternion.Quaternion() self.scale = vector3.Vector3() self.result_matrix = matrix4.Matrix4() self.rotation_matrix = matrix4.Matrix4() self.position_matrix = matrix4.Matrix4() self.scale_matrix = matrix4.Matrix4() self.need_update = False self.childs = [] self.parent = None
def __init__(self, scene_mgr): self.scene_mgr = scene_mgr self.physics_entities = [] self.gravity = vector3.Vector3(0.0, -9.81, 0.0) self.debug_contact = 0.0
def from_matrix(matrix): trace = matrix.m[0][0] + matrix.m[1][1] + matrix.m[2][2] if trace > 0.0: s = 0.5 / math.sqrt(trace + 1.0) m_w = 0.25 / s m_x = (matrix.m[1][2] - matrix.m[2][1]) * s m_y = (matrix.m[2][0] - matrix.m[0][2]) * s m_z = (matrix.m[0][1] - matrix.m[1][0]) * s else: if matrix.m[0][0] > matrix.m[1][1] and matrix.m[0][0] > matrix.m[ 2][2]: s = math.sqrt(1.0 + matrix.m[0][0] - matrix.m[1][1] - matrix.m[2][2]) * 2.0 m_w = (matrix.m[1][2] - matrix.m[2][1]) / s m_x = 0.25 * s m_y = (matrix.m[1][0] + matrix.m[0][1]) / s m_z = (matrix.m[2][0] + matrix.m[0][2]) / s elif matrix.m[1][1] > matrix.m[2][2]: s = math.sqrt(1.0 + matrix.m[1][1] - matrix.m[0][0] - matrix.m[2][2]) * 2.0 m_w = (matrix.m[2][0] - matrix.m[0][2]) / s m_x = (matrix.m[1][0] + matrix.m[0][1]) / s m_y = 0.25 * s m_z = (matrix.m[2][1] + matrix.m[1][2]) / s else: s = math.sqrt(1.0 + matrix.m[2][2] - matrix.m[0][0] - matrix.m[1][1]) * 2.0 m_w = (matrix.m[0][1] - matrix.m[1][0]) / s m_x = (matrix.m[2][0] + matrix.m[0][2]) / s m_y = (matrix.m[2][1] + matrix.m[1][2]) / s m_z = 0.25 * s return Quaternion(vector3.Vector3(m_x, m_y, m_z), m_w)
def update_positions(self, dt): if self.awake == False: return transform = self.attached_entity.transform #integrate rotation spin = quaternion.Quaternion(self.angular_velocity, 0.0).mul_value(0.5) * transform.rotation new_rot = transform.rotation + spin.mul_value(dt) self.update_position_from_global_centroid() transform.set_local_rotation(new_rot.get_normalized()) #reset force and torque so that an push doesnt happened forever self.force_accumulator = vector3.Vector3() self.torque_accumulator = vector3.Vector3()
def __init__(self, min=vector3.Vector3(), max=vector3.Vector3(), calc_knots=False): self.min = min self.max = max self.projected = {} self.projected["min"] = min self.projected["max"] = max self.projected["base_knots"] = [] self.projected["transformed_knots"] = [] if calc_knots: self.calculate_knots("base_knots", min, max) self.projected["transformed_knots"] = self.projected[ "base_knots"] #at the beginning they should be the same
def mul_vec3(self, vector): result = vector3.Vector3() result.x = self.m[0][0] * vector.x + self.m[1][0] * vector.y + self.m[2][0] * vector.z result.y = self.m[0][1] * vector.x + self.m[1][1] * vector.y + self.m[2][1] * vector.z result.z = self.m[0][2] * vector.x + self.m[1][2] * vector.y + self.m[2][2] * vector.z return result
def mul_vector3(self, vec): n_w = -self.axis.x * vec.x - self.axis.y * vec.y - self.axis.z * vec.z n_x = self.w * vec.x + self.axis.y * vec.z - self.axis.z * vec.y n_y = self.w * vec.y + self.axis.z * vec.x - self.axis.x * vec.z n_z = self.w * vec.z + self.axis.x * vec.y - self.axis.y * vec.x return Quaternion(vector3.Vector3(n_x, n_y, n_z), n_w)
def __mul__(self, other): a = self b = other n_w = a.w * b.w - a.axis.x * b.axis.x - a.axis.y * b.axis.y - a.axis.z * b.axis.z n_x = a.w * b.axis.x + a.axis.x * b.w + a.axis.y * b.axis.z - a.axis.z * b.axis.y n_y = a.w * b.axis.y - a.axis.x * b.axis.z + a.axis.y * b.w + a.axis.z * b.axis.x n_z = a.w * b.axis.z + a.axis.x * b.axis.y - a.axis.y * b.axis.x + a.axis.z * b.w return Quaternion(vector3.Vector3(n_x, n_y, n_z), n_w)
def get_centroid(self): centroid = vector3.Vector3() for i in range(len(self.collision_base_points)): centroid = centroid + self.collision_base_points[i] centroid = centroid * len(self.collision_base_points) return centroid
def get_normalized(self): length = self.get_len() if (length == 0): length = 1.0 norm_axis = vector3.Vector3(self.axis.x / length, self.axis.y / length, self.axis.z / length) norm_w = self.w / length return Quaternion(norm_axis, norm_w)
def create_box_shape(w, h, d): points = [] vertices = [] ibo = [0, 1, 3, 2, 0, 4, 5, 1, 0, 4, 6, 7, 5, 7, 3, 2, 6] h_w = w * 0.5 h_h = h * 0.5 h_d = d * 0.5 points.append(vector3.Vector3(-h_w, -h_h, -h_d)) #000 points.append(vector3.Vector3(-h_w, -h_h, h_d)) #001 points.append(vector3.Vector3(-h_w, h_h, -h_d)) #010 points.append(vector3.Vector3(-h_w, h_h, h_d)) #011 points.append(vector3.Vector3(h_w, -h_h, -h_d)) #100 points.append(vector3.Vector3(h_w, -h_h, h_d)) #101 points.append(vector3.Vector3(h_w, h_h, -h_d)) #110 points.append(vector3.Vector3(h_w, h_h, h_d)) #111 for i in range(8): vertices.append(points[i].x) vertices.append(points[i].y) vertices.append(points[i].z) data = {} data["vbo"] = {} data["vbo"]["type"] = GL_ARRAY_BUFFER data["vbo"]["size"] = ctypes.sizeof(GLfloat * len(vertices)) data["vbo"]["data"] = (GLfloat * len(vertices))(*vertices) data["vbo"]["attributes"] = [{}] data["vbo"]["attributes"][0]["size"] = 3 data["vbo"]["attributes"][0]["type"] = GL_FLOAT data["vbo"]["attributes"][0]["stride"] = 0 data["vbo"]["attributes"][0]["offset"] = 0 data["vbo"]["attributes"][0]["normalized"] = GL_FALSE data["ibo"] = {} data["ibo"]["type"] = GL_ELEMENT_ARRAY_BUFFER data["ibo"]["size"] = ctypes.sizeof(GLuint * len(ibo)) data["ibo"]["data"] = (GLuint * len(ibo))(*ibo) mesh = Mesh("dbg_aabb") mesh.get_buffer().clear_buffer() mesh.get_buffer().prepare_buffer(GL_LINE_STRIP, len(ibo), GL_UNSIGNED_INT, data) mesh.get_buffer().create_buffer() return mesh
def calculate_aabb_unprojected(self, transform): matrix = transform.get_transformation_matrix() u_min = vector3.Vector3(math.inf, math.inf, math.inf) u_max = vector3.Vector3(-math.inf, -math.inf, -math.inf) for i in range(len(self.projected["base_knots"])): t_vec = matrix.mul_vec3(self.projected["base_knots"][i]) u_min.x = min(t_vec.x, u_min.x) u_min.y = min(t_vec.y, u_min.y) u_min.z = min(t_vec.z, u_min.z) u_max.x = max(t_vec.x, u_max.x) u_max.y = max(t_vec.y, u_max.y) u_max.z = max(t_vec.z, u_max.z) self.projected["min"] = u_min self.projected["max"] = u_max self.calculate_knots("transformed_knots", u_min, u_max)
def __init__(self, col_shape): super().__init__(col_shape) self.mass = 1.0 self.inv_mass = 1.0 / self.mass self.damping = 1.0 self.friction = 0.05 self.col_shape.calculate_inertia_tensor(self.mass) self.world_rotational_inertia = self.col_shape.get_inertia_tensor() self.inv_world_rotational_inertia = self.col_shape.get_inverse_inertia_tensor( ) self.local_centroid = self.col_shape.get_centroid() self.world_centroid = self.local_centroid self.linear_velocity = vector3.Vector3() self.angular_velocity = vector3.Vector3() self.force_accumulator = vector3.Vector3() self.torque_accumulator = vector3.Vector3()
def calculate_knots(self, index, min, max): self.projected[index] = [] self.projected[index].append(vector3.Vector3(min.x, min.y, min.z)) #000 self.projected[index].append(vector3.Vector3(min.x, min.y, max.z)) #001 self.projected[index].append(vector3.Vector3(min.x, max.y, min.z)) #010 self.projected[index].append(vector3.Vector3(min.x, max.y, max.z)) #011 self.projected[index].append(vector3.Vector3(max.x, min.y, min.z)) #100 self.projected[index].append(vector3.Vector3(max.x, min.y, max.z)) #101 self.projected[index].append(vector3.Vector3(max.x, max.y, min.z)) #110 self.projected[index].append(vector3.Vector3(max.x, max.y, max.z)) #111
def extract_frustum_planes(self, matrix): self.planes = [] m = matrix.m #left plane a = m[0][3] + m[0][0] b = m[1][3] + m[1][0] c = m[2][3] + m[2][0] d = m[3][3] + m[3][0] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d)) #right plane a = m[0][3] - m[0][0] b = m[1][3] - m[1][0] c = m[2][3] - m[2][0] d = m[3][3] - m[3][0] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d)) #top plane a = m[0][3] + m[0][1] b = m[1][3] + m[1][1] c = m[2][3] + m[2][1] d = m[3][3] + m[3][1] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d)) #bottom plane a = m[0][3] - m[0][1] b = m[1][3] - m[1][1] c = m[2][3] - m[2][1] d = m[3][3] - m[3][1] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d)) #near plane a = m[0][3] + m[0][2] b = m[1][3] + m[1][2] c = m[2][3] + m[2][2] d = m[3][3] + m[3][2] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d)) #bottom plane a = m[0][3] - m[0][2] b = m[1][3] - m[1][2] c = m[2][3] - m[2][2] d = m[3][3] - m[3][2] self.planes.append(plane.Plane(vector3.Vector3(a, b, c), d))
def get_mouse_direction(self): mx, my = self.key_mapper.get_mouse_position() width, height = self.engine.get_size() nx = mx / width ny = my / height nx = nx * 2.0 - 1.0 ny = ny * 2.0 - 1.0 ray_clip = vector3.Vector3(nx, ny, -1.0) ray_eye = self.inv_perspective_matrix.mul_vec3(ray_clip, 1.0) ray_eye.z = -1.0 ray_world = self.inverse_matrix.mul_vec3(ray_eye, 0.0) return ray_world
def set_look_matrix(self, direction, up_vector = vector3.Vector3(0.0,1.0,0.0)): z_axis = direction z_axis.normalize() x_axis = up_vector.cross( z_axis ) x_axis.normalize() y_axis = z_axis.cross(x_axis) self.m[0][0] = x_axis.x self.m[1][0] = x_axis.y self.m[2][0] = x_axis.z self.m[0][1] = y_axis.x self.m[1][1] = y_axis.y self.m[2][1] = y_axis.z self.m[0][2] = z_axis.x self.m[1][2] = z_axis.y self.m[2][2] = z_axis.z
def __init__(self, axis=vector3.Vector3(), w=1.0): self.axis = axis self.w = w
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
def load_animation(self, header, file, text_blob): if header["num_anims"] == 0: return None animation_data = {} animation_data["frame_positions"] = [] joints = [] poses = [] animations = [] frames = [] #load all joints if we have any if header["ofs_joints"] != 0: file.seek(header["ofs_joints"]) for i in range(header["num_joints"]): joint = {} joint["name"] = self.resolve_name( text_blob, int.from_bytes(file.read(4), "little")) joint["parent"] = int.from_bytes(file.read(4), byteorder="little", signed=True) (tx, ) = struct.unpack("f", file.read(4)) (ty, ) = struct.unpack("f", file.read(4)) (tz, ) = struct.unpack("f", file.read(4)) (rx, ) = struct.unpack("f", file.read(4)) (ry, ) = struct.unpack("f", file.read(4)) (rz, ) = struct.unpack("f", file.read(4)) (rw, ) = struct.unpack("f", file.read(4)) (sx, ) = struct.unpack("f", file.read(4)) (sy, ) = struct.unpack("f", file.read(4)) (sz, ) = struct.unpack("f", file.read(4)) joint["translate"] = vector3.Vector3(tx, ty, tz) joint["rotate"] = quaternion.Quaternion( vector3.Vector3(rx, ry, rz), rw).get_normalized() joint["scale"] = vector3.Vector3(sx, sy, sz) joints.append(joint) animation_data["joints"] = joints #load all animations if we have any if header["ofs_anims"] != 0: file.seek(header["ofs_anims"]) for i in range(header["num_anims"]): animation = {} animation["name"] = self.resolve_name( text_blob, int.from_bytes(file.read(4), "little")) animation["first_frame"] = int.from_bytes( file.read(4), "little") animation["num_frames"] = int.from_bytes( file.read(4), "little") (framerate, ) = struct.unpack("f", file.read(4)) animation["framerate"] = framerate animation["flags"] = int.from_bytes(file.read(4), "little") animations.append(animation) animation_data["animations"] = animations #load all frame_data and translate them if we have any if header["ofs_poses"] != 0: file.seek(header["ofs_frames"]) for i in range(header["num_frames"] * header["num_framechannels"]): value = int.from_bytes(file.read(2), "little") frames.append(value) file.seek(header["ofs_poses"]) #load all poses, but in raw, since we need to modify/stretch them to match them witch all animation we will have for i in range(header["num_poses"]): pose = {} pose["parent"] = int.from_bytes(file.read(4), byteorder="little", signed=True) pose["channel_mask"] = int.from_bytes(file.read(4), "little") channel_offset = [] channel_scale = [] for i in range(10): (val, ) = struct.unpack("f", file.read(4)) channel_offset.append(val) for i in range(10): (val, ) = struct.unpack("f", file.read(4)) channel_scale.append(val) pose[ "channel_offset"] = channel_offset #translation, rotation, scale pose["channel_scale"] = channel_scale poses.append(pose) animation_data["poses"] = poses frame_index = 0 #remap all our animation data for i in range(header["num_frames"]): animation_data["frame_positions"].append([]) for j in range(header["num_poses"]): channel_mask = poses[j]["channel_mask"] channel_offset = poses[j]["channel_offset"] channel_scale = poses[j]["channel_scale"] translate = vector3.Vector3() scale = vector3.Vector3() translate.x, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 0) translate.y, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 1) translate.z, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 2) rx, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 3) ry, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 4) rz, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 5) rw, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 6) scale.x, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 7) scale.y, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 8) scale.z, frame_index = self.extract_frame_data( channel_offset, channel_mask, channel_scale, frames, frame_index, 9) rotation = quaternion.Quaternion( vector3.Vector3(rx, ry, rz), rw ) #we need to assign it here with the constructor, otherwise everything explodes for some reason ... animation_data["frame_positions"][i].append({ "pose": poses[j], "translate": translate, "rotate": rotation, "scale": scale }) return animation_data
def get_z_vector(self): return vector3.Vector3(self.m[0][2], self.m[1][2], self.m[2][2])
def get_y_vector(self): return vector3.Vector3(self.m[0][1], self.m[1][1], self.m[2][1])
def get_x_vector(self): return vector3.Vector3(self.m[0][0], self.m[1][0], self.m[2][0])
def look_at(direction, up_vector=vector3.Vector3(0.0, 1.0, 0.0)): matrix = matrix4.Matrix4() matrix.set_Look_matrix(direction, up_vector) return Quaternion.from_matrix(matrix)
def look_at(self, direction, up_vector=vector3.Vector3(0.0, 1.0, 0.0)): self.rotation_matrix.set_look_matrix(direction, up_vector) self.rotation = quaternion.Quaternion.from_matrix(self.rotation_matrix) self.rotation_matrix = self.rotation.to_matrix() self.need_update = True
def get_penetration_data(simplex_points, polygon_a, mat_a, polygon_b, mat_b): a = simplex_points[0] b = simplex_points[1] c = simplex_points[2] d = simplex_points[3] faces = [] for i in range(EPA_MAX_NUM_FACES): pack = [a, b, c, vector3.Vector3()] faces.append(pack) faces[0] = [ a, b, c, (b[VECTOR] - a[VECTOR]).cross(c[VECTOR] - a[VECTOR]).get_normalized() ] #abc faces[1] = [ a, c, d, (c[VECTOR] - a[VECTOR]).cross(d[VECTOR] - a[VECTOR]).get_normalized() ] #acd faces[2] = [ a, d, b, (d[VECTOR] - a[VECTOR]).cross(b[VECTOR] - a[VECTOR]).get_normalized() ] #adb faces[3] = [ b, d, c, (d[VECTOR] - b[VECTOR]).cross(c[VECTOR] - b[VECTOR]).get_normalized() ] #bdc num_faces = 4 closest_face = 0 for iteration in range(EPA_MAX_NUM_ITERATIONS): min_dist = faces[0][0][VECTOR].dot(faces[0][3]) closest_face = 0 for i in range(1, num_faces): dist = faces[i][0][VECTOR].dot(faces[i][3]) if dist < min_dist: min_dist = dist closest_face = i search_dir = faces[closest_face][3] p = gjk.GJK.support_function(polygon_a, polygon_b, search_dir) if p[VECTOR].dot(search_dir) - min_dist < EPA_TOLERANCE: break loose_edges = [] for i in range(EPA_MAX_NUM_LOOSE_EDGES): loose_edges.append([0, 0]) num_loose_edges = 0 i = 0 while i < num_faces: if faces[i][3].dot(p[VECTOR] - faces[i][0][VECTOR]) > 0: for j in range(3): current_edge = [faces[i][j], faces[i][(j + 1) % 3]] found_edge = False k = 0 while k < num_loose_edges: if loose_edges[k][1] == current_edge[ 0] and loose_edges[k][0] == current_edge[1]: loose_edges[k][0] = loose_edges[num_loose_edges - 1][0] loose_edges[k][1] = loose_edges[num_loose_edges - 1][1] num_loose_edges = num_loose_edges - 1 found_edge = True k = num_loose_edges k = k + 1 if not found_edge: if num_loose_edges >= EPA_MAX_NUM_LOOSE_EDGES: break loose_edges[num_loose_edges][0] = current_edge[0] loose_edges[num_loose_edges][1] = current_edge[1] num_loose_edges = num_loose_edges + 1 faces[i][0] = faces[num_faces - 1][0] faces[i][1] = faces[num_faces - 1][1] faces[i][2] = faces[num_faces - 1][2] faces[i][3] = faces[num_faces - 1][3] num_faces = num_faces - 1 i = i - 1 i = i + 1 for i in range(num_loose_edges): if num_faces >= EPA_MAX_NUM_FACES: break faces[num_faces][0] = loose_edges[i][0] faces[num_faces][1] = loose_edges[i][1] faces[num_faces][2] = p faces[num_faces][3] = (loose_edges[i][0][VECTOR] - loose_edges[i][1][VECTOR] ).cross(loose_edges[i][0][VECTOR] - p[VECTOR]).get_normalized() if faces[num_faces][0][VECTOR].dot( faces[num_faces][3]) + EPA_TOLERANCE < 0: tmp = faces[num_faces][0] faces[num_faces][0] = faces[num_faces][1] faces[num_faces][1] = tmp faces[num_faces][3] = faces[num_faces][3].negate() num_faces = num_faces + 1 if iteration >= EPA_MAX_NUM_ITERATIONS: print("warning, epa couldnt find the closes triangle point") min_normal = search_dir min_distance = min_normal.dot(p[VECTOR]) + 0.0001 #this method here will only give one collision point contact_points = [] local_contact_points = [] point_on_closest_triangle = min_normal * min_distance closest_triangle_a = faces[closest_face][0][VECTOR] closest_triangle_b = faces[closest_face][1][VECTOR] closest_triangle_c = faces[closest_face][2][VECTOR] v, w, u = EPA.barycentric(point_on_closest_triangle, min_normal, closest_triangle_a, closest_triangle_b, closest_triangle_c) polygon_triangle_a_0 = polygon_a[faces[closest_face][0][1]] polygon_triangle_a_1 = polygon_a[faces[closest_face][1][1]] polygon_triangle_a_2 = polygon_a[faces[closest_face][2][1]] contact_point = polygon_triangle_a_0 * v + polygon_triangle_a_1 * w + polygon_triangle_a_2 * u #note that our contact point should be inside of the mesh not on top of them contact_points.append(contact_point - min_normal * min_distance) local_contact_points.append( mat_a.get_inverse().mul_vec3(contact_point)) local_contact_points.append( mat_b.get_inverse().mul_vec3(contact_point)) #based on http://allenchou.net/2013/12/game-physics-contact-generation-epa/ if min_normal.x >= 0.57735: t = vector3.Vector3(min_normal.y, -min_normal.x, 0.0) else: t = vector3.Vector3(0.0, min_normal.z, -min_normal.y) t1 = t.get_normalized() t2 = min_normal.cross(t1) data = {} data["seperation_point"] = min_normal * min_distance data["contact_points"] = contact_points data["local_contact_points"] = local_contact_points data["tangents"] = [t1, t2] data["min_normal"] = min_normal data["min_distance"] = min_distance return data
def create_test_scene(self): self.loader = mesh_loader.MeshLoader(self) self.mesh_pool = [] self.mesh_pool.append( self.loader.get_meshs("data/models/objs/cube.obj")) self.mesh_pool.append( self.loader.get_meshs("data/models/objs/ground_box.obj")) #self.mesh_pool.append(self.loader.get_meshs("data/models/iqms/mrfixit/mrfixit.iqm")) ent = Entity(self) ent.add_component(mesh_renderer.MeshRenderer(self.mesh_pool[0])) ent.add_component(mesh_debug_renderer.MeshDebugRenderer()) b_size = self.mesh_pool[0][0].get_aabb().get_size() ent.add_component( rigid_body.RigidBody( box_collision_shape.BoxCollisionShape(b_size.x, b_size.y, b_size.z))) self.entities.append(ent) ent2 = Entity(self) ent2.add_component(mesh_renderer.MeshRenderer(self.mesh_pool[0])) ent2.add_component(mesh_debug_renderer.MeshDebugRenderer()) b_size = self.mesh_pool[0][0].get_aabb().get_size() ent2.add_component( static_body.StaticBody( box_collision_shape.BoxCollisionShape(b_size.x, b_size.y, b_size.z))) self.entities.append(ent2) ent3 = Entity(self) ent3.add_component(mesh_renderer.MeshRenderer(self.mesh_pool[1])) ent3.add_component(mesh_debug_renderer.MeshDebugRenderer()) b_size = self.mesh_pool[1][0].get_aabb().get_size() ent3.add_component( static_body.StaticBody( box_collision_shape.BoxCollisionShape(b_size.x, -b_size.y, b_size.z))) self.entities.append(ent3) ent4 = Entity(self) ent4.add_component( primitive_render.PrimitiveRender( DebugShapes.create_box_shape(b_size.x * 0.5, b_size.y, b_size.z))) self.entities.append(ent4) #for testing we say the mesh is at the origin for now quat = quaternion.Quaternion(vector3.Vector3(0.0, 0.0, -1.0), 3.141 * 0.5).get_axis_quaternion() quat = quat * quaternion.Quaternion(vector3.Vector3(0.0, -1.0, 0.0), 3.141 * 0.5).get_axis_quaternion() self.t1_position = vector3.Vector3(0.0, 5.0, -10.0) self.entities[0].get_transform().set_local_rotation( quaternion.Quaternion.from_axis(vector3.Vector3(), 1.0)) self.entities[0].get_transform().set_local_position(self.t1_position) self.entities[1].get_transform().set_local_rotation( quat.get_normalized()) self.entities[1].get_transform().set_local_position( vector3.Vector3(5.0, -5.0, -10.0)) self.entities[0].get_component("MeshRenderer").play_animation( "idle", 1.0) self.entities[1].get_component("MeshRenderer").play_animation( "idle", 1.0) self.entities[2].get_transform().set_local_position( vector3.Vector3(0.0, -8, 0.0)) self.entities[2].get_component( "MeshRenderer").get_materials()[0].assign_material( "mesh_color", [0.5, 0.5, 0.5, 1.0]) self.entities[3].get_transform().set_local_position( vector3.Vector3(0.0, -8, 0.0))
def read_file(self, file_path): tex_pool = self.scene_manager.get_texture_pool() meshes = [] mesh_data = {} global_data = {} line_count = 0 calc_face_offset = 0 global_data["raw_vertices"] = [] global_data["raw_tex_coords"] = [] global_data["raw_normals"] = [] for line in open(file_path, "r"): if line.startswith("#"): continue values = line.split() if not values: continue if values[0] == "o": if "name" in mesh_data: meshes.append(mesh_data) mesh_data = {} mesh_data["center_of_mass"] = vector3.Vector3() mesh_data["name"] = values[1] mesh_data["type"] = GL_TRIANGLES mesh_data["vertices"] = [] mesh_data["indices"] = [] mesh_data["diffuse_texture"] = "" mesh_data["aabb"] = AABB(vector3.Vector3(math.inf, math.inf, math.inf), vector3.Vector3(-math.inf, -math.inf, -math.inf)) if values[0] == "v": x = float(values[1]) y = float(values[2]) z = float(values[3]) global_data["raw_vertices"].append(x) global_data["raw_vertices"].append(y) global_data["raw_vertices"].append(z) mesh_data["center_of_mass"].x += x mesh_data["center_of_mass"].y += y mesh_data["center_of_mass"].z += z mesh_data["aabb"].min.x = min(mesh_data["aabb"].min.x, x) mesh_data["aabb"].min.y = min(mesh_data["aabb"].min.y, y) mesh_data["aabb"].min.z = min(mesh_data["aabb"].min.z, z) mesh_data["aabb"].max.x = max(mesh_data["aabb"].max.x, x) mesh_data["aabb"].max.y = max(mesh_data["aabb"].max.y, y) mesh_data["aabb"].max.z = max(mesh_data["aabb"].max.z, z) if values[0] == "vt": global_data["raw_tex_coords"].append(float(values[1]) ) global_data["raw_tex_coords"].append(float(values[2]) ) if values[0] == "vn": global_data["raw_normals"].append(float(values[1]) ) global_data["raw_normals"].append(float(values[2]) ) global_data["raw_normals"].append(float(values[3]) ) if values[0] == "f": mesh_data["type"] = FACE_MAPPING[len(values)-1] for v in values[1:]: vals = v.split("/") v_indx = (int(vals[0]) - 1) * 3 tx_indx = (int(vals[1]) - 1) * 2 n_indx = (int(vals[2]) - 1) * 3 mesh_data["vertices"].append(global_data["raw_vertices"][v_indx] ) mesh_data["vertices"].append(global_data["raw_vertices"][v_indx+1] ) mesh_data["vertices"].append(global_data["raw_vertices"][v_indx+2] ) mesh_data["vertices"].append(global_data["raw_tex_coords"][tx_indx] ) mesh_data["vertices"].append(global_data["raw_tex_coords"][tx_indx+1] ) mesh_data["vertices"].append(global_data["raw_normals"][n_indx] ) mesh_data["vertices"].append(global_data["raw_normals"][n_indx+1] ) mesh_data["vertices"].append(global_data["raw_normals"][n_indx+2] ) mesh_data["indices"].append( len(mesh_data["indices"]) ) line_count = line_count + 1 meshes.append(mesh_data) base_path = os.path.dirname(file_path) base_name = os.path.basename(os.path.splitext(file_path)[0]) materials = [] for i in range(len(meshes)): meshes[i]["center_of_mass"] = meshes[i]["center_of_mass"] / (len(meshes[i]["vertices"]) / 3) materials.append(Material()) if os.path.isfile(base_path + "/" + base_name + ".mtl"): for line in open(base_path + "/" + base_name + ".mtl", "r"): if line.startswith("#"): continue values = line.split() if not values: continue if values[0] == "map_Kd": tex_pool.load_texture(values[1], base_path, base_path + "/" + values[1])#load the material texture for i in range(len(meshes)): materials[i].assign_material("diffuse_texture", values[1]) for i in range(len(meshes)): meshes[i]["material"] = materials[i] return meshes