diff --git a/main.py b/main.py index 7d39f78..34e2c4a 100644 --- a/main.py +++ b/main.py @@ -61,7 +61,7 @@ def mouse_start(event): ui.canvas.old_coords = event.x, event.y def mouse_end(event): - x, y = event.x - ui.width / 2, event.y - ui.height / 2#ui.canvas.old_coords[0] - event.x, ui.canvas.old_coords[1] - event.y + x, y = event.x - ui.width / 2, event.y - ui.height / 2 if x < 0: ui.thetax -= .01 else: @@ -73,11 +73,9 @@ def mouse_end(event): ui.thetaz += .01 draw_scene() - #ui.theta += x / ui.width def draw_scene(): ui.canvas.delete("all") - #ui.theta += .01 # scaling factor aspect_ratio = ui.height / ui.width projection_matrix = Matrix4x4.get_projection_matrix(fov, aspect_ratio, near_plane, far_plane) @@ -86,79 +84,56 @@ def draw_scene(): rotation_matrix_x = Matrix4x4.get_x_rotation_matrix(ui.thetax) - #translation = Matrix4x4.get_translation_matrix(Vector3d(0, 0, 16)) + translation = Matrix4x4.get_translation_matrix(Vector3d(0, 0, 3)) - #world_matrix = Matrix4x4.get_identity_matrix() - #world_matrix = rotation_matrix_z.multiply_matrix(rotation_matrix_x) - #world_matrix = world_matrix.multiply_matrix(translation) + world_matrix = Matrix4x4.get_identity_matrix() + world_matrix = rotation_matrix_z.multiply_matrix(rotation_matrix_x) + world_matrix = world_matrix.multiply_matrix(translation) triangles = [] for tri in tris: - # Rotate on the z-axis - row1 = rotation_matrix_z.multiply_3d(tri.row1) - row2 = rotation_matrix_z.multiply_3d(tri.row2) - row3 = rotation_matrix_z.multiply_3d(tri.row3) + row1 = world_matrix.multiply_3d(tri[0]) + row2 = world_matrix.multiply_3d(tri[1]) + row3 = world_matrix.multiply_3d(tri[2]) - rotated_y = Matrix3x3(row1, row2, row3) - # Rotate on the x-axis - row1 = rotation_matrix_x.multiply_3d(rotated_y.row1) - row2 = rotation_matrix_x.multiply_3d(rotated_y.row2) - row3 = rotation_matrix_x.multiply_3d(rotated_y.row3) + transformed = Matrix3x3(row1, row2, row3) - rotated_x = Matrix3x3(row1, row2, row3) - # The offset into the screen - translated = copy.copy(rotated_x) - translated.row1.z += 3.0 - translated.row2.z += 3.0 - translated.row3.z += 3.0 - - # Use cross-product to get the surface normal (a Vector3d) - x = translated.row2.x - translated.row1.x - y = translated.row2.y - translated.row1.y - z = translated.row2.z - translated.row1.z - line1 = Vector3d(x, y, z) - - x = translated.row3.x - translated.row1.x - y = translated.row3.y - translated.row1.y - z = translated.row3.z - translated.row1.z - line2 = Vector3d(x, y, z) + line1 = transformed.row2.subtract_3d(transformed.row1) + line2 = transformed.row3.subtract_3d(transformed.row1) normal = line1.cross_product(line2) - # Now we normalize the normal - length = math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z) - normal.x /= length - normal.y /= length - normal.z /= length + normal = normal.get_normalized_form() # Do we display this triangle? - if normal.dot_product(translated.row1) < 0.0: + if normal.dot_product(transformed.row1) < 0.0: # Lighting light = Vector3d(0, 0, -1) # Shining at the player. - length = math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z) - light.x /= length - light.y /= length - light.z /= length + light = light.get_normalized_form() dot_product = normal.dot_product(light) r = abs(int(255 * dot_product)) # Scale into view - row1 = projection_matrix.multiply_3d(translated.row1) - row2 = projection_matrix.multiply_3d(translated.row2) - row3 = projection_matrix.multiply_3d(translated.row3) + row1 = projection_matrix.multiply_3d(transformed.row1) + row2 = projection_matrix.multiply_3d(transformed.row2) + row3 = projection_matrix.multiply_3d(transformed.row3) projected = Matrix3x3(row1, row2, row3) - projected.row1.x += 1 - projected.row1.y += 1 - projected.row2.x += 1 - projected.row2.y += 1 - projected.row3.x += 1 - projected.row3.y += 1 + projected.row1 = projected.row1.divide_3d(1) + projected.row2 = projected.row2.divide_3d(1) + projected.row3 = projected.row3.divide_3d(1) + + offset = Vector3d(1, 1, 0) + + projected.row1 = projected.row1.add_3d(offset) + projected.row2 = projected.row2.add_3d(offset) + projected.row3 = projected.row3.add_3d(offset) + projected.row1.x *= .5 * ui.width projected.row1.y *= .5 * ui.height projected.row2.x *= .5 * ui.width diff --git a/matrix.py b/matrix.py index a4f598a..cac15dd 100644 --- a/matrix.py +++ b/matrix.py @@ -10,13 +10,25 @@ class Matrix3x3: def row1(self): return self.rows[0] + @row1.setter + def row1(self, value): + self.rows[0] = value + @property def row2(self): return self.rows[1] + @row2.setter + def row2(self, value): + self.rows[1] = value + @property def row3(self): return self.rows[2] + + @row3.setter + def row3(self, value): + self.rows[2] = value def __getitem__(self, key): return self.rows[key] @@ -42,6 +54,10 @@ class Matrix4x4(Matrix3x3): def row4(self): return self.rows[3] + @row4.setter + def row4(self, value): + self.rows[3] = value + def multiply_3d(self, vector3d): x = vector3d.x * self.row1.x + vector3d.y * self.row2.x + vector3d.z * self.row3.x + self.row4.x y = vector3d.x * self.row1.y + vector3d.y * self.row2.y + vector3d.z * self.row3.y + self.row4.y diff --git a/vectors.py b/vectors.py index 4be9734..5b34fbc 100644 --- a/vectors.py +++ b/vectors.py @@ -1,3 +1,5 @@ +import math + class Vector2d: def __init__(self, x, y): self.points = [x, y] @@ -23,6 +25,9 @@ class Vector2d: def __setitem__(self, key, value): self.points[key] = value + + #def get_normalized_form(self): + # return Vector3d(self.x / 2, self.y / 2, self.z / 2) class Vector3d(Vector2d): def __init__(self, x, y, z): @@ -42,6 +47,22 @@ class Vector3d(Vector2d): # Returns a scalar that defines how similar two # vectors are to one another. return self.x * vector3d.x + self.y * vector3d.y + self.z * vector3d.z + + def vector_3d_length(self): + return math.sqrt(self.dot_product(self)) + + def subtract_3d(self, vector3d): + return Vector3d(self.x - vector3d.x, self.y - vector3d.y, self.z - vector3d.z) + + def add_3d(self, vector3d): + return Vector3d(self.x + vector3d.x, self.y + vector3d.y, self.z + vector3d.z) + + def divide_3d(self, value): + return Vector3d(self.x / value, self.y / value, self.z / value) + + def get_normalized_form(self): + length = self.vector_3d_length() + return Vector3d(self.x / length, self.y / length, self.z / length) @property def z(self): @@ -62,3 +83,6 @@ class Vector4d(Vector3d): @w.setter def w(self, value): self.points[3] = value + + #def get_normalized_form(self): + # return Vector3d(self.x / 4, self.y / 4, self.z / 4)