def get_projection_matrix(self): """Retrieves the projection matrix of this camera. This function sets up the proj_matrix attribute as well. Returns: Matrix4 - Projection matrix of this camera """ self.proj_matrix = Matrix4.zeros() if self.ortho: self.proj_matrix[0, 0] = self.res_x * 0.5 self.proj_matrix[1, 1] = self.res_y * 0.5 self.proj_matrix[3, 0] = 0 self.proj_matrix[3, 1] = 0 self.proj_matrix[3, 3] = 1 else: t = math.tan(self.fov * 0.5) a = self.res_y / self.res_x self.proj_matrix[0, 0] = 0.5 * self.res_x / t self.proj_matrix[1, 1] = 0.5 * self.res_y / (a * t) self.proj_matrix[2, 3] = 1 self.proj_matrix[2, 2] = self.far_plane / (self.far_plane - self.near_plane) self.proj_matrix[3, 2] = self.proj_matrix[2, 2] * self.near_plane return self.proj_matrix
def __init__(self, ortho, res_x, res_y): """ Arguments: ortho {bool} - True if this is an ortographic camera, false otherwise. res_x {int} - Horizontal resolution of the window. This will be the size of the window in ortographic view res_y {int} - Vertical resolution of the window. This will be the size of the window in ortographic view """ super().__init__(self) self.ortho = ortho """{bool} True if this is an ortographic camera, false otherwise""" self.res_x = res_x """{int} Horizontal resolution of the window. This will be the size of the window in ortographic view""" self.res_y = res_y """{int} Vertical resolution of the window. This will be the size of the window in ortographic view""" self.near_plane = 1 """{number} Distance from the camera to the near plane. Defaults to 1""" self.far_plane = 100 """{number} Distance from the camera to the far plane. Defaults to 100""" self.fov = math.radians(60) """{number} Field of view angle (in radians) of the camera (if in perspective mode)""" self.proj_matrix = Matrix4.identity() """{Matrix4} Projection matrix. This is only set after get_projection_matrix is called
def test_type(self): v1 = Vector4(3,4,5,1) v2 = Vector4(6,7,8,9) m = Matrix4([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]) self.assertTrue(isinstance(v1*10.0, Vector4)) self.assertTrue(isinstance(v1/10.0, Vector4)) self.assertTrue(isinstance(v1+v2, Vector4)) self.assertTrue(isinstance(v1-v2, Vector4)) self.assertTrue(isinstance(m(v2), Vector4)) self.assertTrue(isinstance(v1.dot(v2), float))
def get_camera_matrix(self): """Retrieves the view matrix of this camera. This is basically the same as a PRS matrix without scalling, and with the position and rotation negated. Returns: Matrix4 - View matrix of this camera """ trans = Matrix4.identity() trans[3, 0] = -self.position.x trans[3, 1] = -self.position.y trans[3, 2] = -self.position.z rotation_matrix = self.rotation.inverted().as_rotation_matrix() return trans * rotation_matrix
def draw_triangles(self, triangles, colour=(255, 255, 255), fill=True, shaded=True): """Draw triangle formed by v1, v2, v3""" # Initialise screen space transform matrix matrix = Matrix4.init_screen_space_transform( float(self.renderer.width) / 2.0, float(self.renderer.height) / 2.0) for tri in triangles: # Apply screen space transform to vertices min_y_vert = tri[0].transform(matrix).perspective_divide() mid_y_vert = tri[1].transform(matrix).perspective_divide() max_y_vert = tri[2].transform(matrix).perspective_divide() # Experimental shading normal = tri[0].triangle_normal(tri[1], tri[2]) # Backface culling # if (not self.draw_backfaces) and min_y_vert.triangle_area(max_y_vert, mid_y_vert) >= 0: # return # Calculate shading if shaded: shading = np.dot(normal, np.array([-0.57735, -0.57735, 0.57735])) if shading < 0: shading = 0 shading = np.array([shading, 0.2]).max() else: shading = 1 c = (colour[0] * shading, colour[1] * shading, colour[2] * shading) # Swap vertices to reorder if min_y_vert.y > max_y_vert.y: temp = max_y_vert max_y_vert = min_y_vert min_y_vert = temp if min_y_vert.y > mid_y_vert.y: temp = mid_y_vert mid_y_vert = min_y_vert min_y_vert = temp if mid_y_vert.y > max_y_vert.y: temp = max_y_vert max_y_vert = mid_y_vert mid_y_vert = temp # Use triangle area to determine handedness area = min_y_vert.triangle_area(max_y_vert, min_y_vert) handedness = area >= 0 # Write triangles to scan buffer and then draw triangles self.scan_triangle(min_y_vert, mid_y_vert, max_y_vert, handedness, c, fill)