import window import math import copy from matrix import Matrix4x4, Matrix3x3 from vectors import Vector4d, Vector3d, Vector2d from engine import Mesh from triangle import Triangle ui = window.Window(600, 600) near_plane = 0.1 far_plane = 1000.0 fov = 90.0 tris =[ Matrix3x3(Vector3d(0.0,0.0,0.0),Vector3d(0.0,1.0,0.0),Vector3d(1.0,1.0,0.0)), Matrix3x3(Vector3d(0.0,0.0,0.0),Vector3d(1.0,1.0,0.0),Vector3d(1.0,0.0,0.0)), Matrix3x3(Vector3d(1.0,0.0,0.0),Vector3d(1.0,1.0,0.0),Vector3d(1.0,1.0,1.0)), Matrix3x3(Vector3d(1.0,0.0,0.0),Vector3d(1.0,1.0,1.0),Vector3d(1.0,0.0,1.0)), Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(1.0,1.0,1.0),Vector3d(0.0,1.0,1.0)), Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,1.0,1.0),Vector3d(0.0,0.0,1.0)), Matrix3x3(Vector3d(0.0,0.0,1.0),Vector3d(0.0,1.0,1.0),Vector3d(0.0,1.0,0.0)), Matrix3x3(Vector3d(0.0,0.0,1.0),Vector3d(0.0,1.0,0.0),Vector3d(0.0,0.0,0.0)), Matrix3x3(Vector3d(0.0,1.0,0.0),Vector3d(0.0,1.0,1.0),Vector3d(1.0,1.0,1.0)), Matrix3x3(Vector3d(0.0,1.0,0.0),Vector3d(1.0,1.0,1.0),Vector3d(1.0,1.0,0.0)), Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,0.0,1.0),Vector3d(0.0,0.0,0.0)), Matrix3x3(Vector3d(1.0,0.0,1.0),Vector3d(0.0,0.0,0.0),Vector3d(1.0,0.0,0.0)) ] #tris = Mesh() def main(): #tris.load_obj_file('shuttle.obj') ui.thetax = 1 ui.window.bind('', left) ui.window.bind('', right) ui.window.bind('', mouse_start) ui.canvas.bind('', mouse_end) ui.canvas.old_coords = None ui.window.after(0, draw_scene) ui.show() def left(event): ui.theta -= .01 def right(event): ui.theta += .01 def mouse_start(event): ui.canvas.old_coords = event.x, event.y def mouse_end(event): x, y = ui.canvas.old_coords[0] - event.x, ui.canvas.old_coords[1] - event.y if x < 0: ui.theta += .01 else: ui.theta -= .01 print(ui.theta) if y < 0: ui.thetax += .01 else: ui.thetax -= .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 fov_rad = ui.theta / math.tan(fov * 0.5 / 180.0 * math.pi) row0 = Vector4d(aspect_ratio * fov_rad, 0, 0, 0) row1 = Vector4d(0, fov_rad, 0, 0) row2 = Vector4d(0, 0, far_plane / (far_plane - near_plane), 1.0) row3 = Vector4d(0, 0, -far_plane * near_plane / (far_plane - near_plane), 0) projection_matrix = Matrix4x4(row0, row1, row2, row3) row0 = Vector4d(math.cos(ui.theta), math.sin(ui.theta), 0, 0) row1 = Vector4d(-math.sin(ui.theta), math.cos(ui.theta), 0, 0) row2 = Vector4d(0, 0, 1, 0) row3 = Vector4d(0, 0, 0, 1) rotation_matrix_z = Matrix4x4(row0, row1, row2, row3) row0 = Vector4d(1, 0, 0, 0) row1 = Vector4d(0, math.cos(ui.thetax * 0.5), math.sin(ui.thetax * 0.5), 0) row2 = Vector4d(0, -math.sin(ui.thetax * 0.5), math.cos(ui.thetax * 0.5), 0) row3 = Vector4d(0, 0, 0, 1) rotation_matrix_x = Matrix4x4(row0, row1, row2, row3) triangles = [] for tri in tris: # Rotate on the z-axis row0 = rotation_matrix_z.multiply_3d(tri.row0) row1 = rotation_matrix_z.multiply_3d(tri.row1) row2 = rotation_matrix_z.multiply_3d(tri.row2) rotated_z = Matrix3x3(row0, row1, row2) # Rotate on the x-axis row0 = rotation_matrix_x.multiply_3d(rotated_z.row0) row1 = rotation_matrix_x.multiply_3d(rotated_z.row1) row2 = rotation_matrix_x.multiply_3d(rotated_z.row2) rotated_x = Matrix3x3(row0, row1, row2) # The offset into the screen translated = copy.copy(rotated_x) translated.row0.z += 3.0 translated.row1.z += 3.0 translated.row2.z += 3.0 # Use cross-product to get the surface normal (a Vector3d) x = translated.row1.x - translated.row0.x y = translated.row1.y - translated.row0.y z = translated.row1.z - translated.row0.z line1 = Vector3d(x, y, z) x = translated.row2.x - translated.row0.x y = translated.row2.y - translated.row0.y z = translated.row2.z - translated.row0.z line2 = Vector3d(x, y, z) normal = line1.cross_product(line2) # Now we normalize the normal w = math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z) normal.x /= w normal.y /= w normal.z /= w # Do we display this triangle? if normal.dot_product(translated.row0) < 0.0: # Lighting light = Vector3d(0, 0, -1) # Shining at the player. w = math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z) light.x /= w light.y /= w light.z /= w dot_product = normal.dot_product(light) r = abs(int(255 * dot_product)) # Scale into view row0 = projection_matrix.multiply_3d(translated.row0) row1 = projection_matrix.multiply_3d(translated.row1) row2 = projection_matrix.multiply_3d(translated.row2) projected = Matrix3x3(row0, row1, row2) projected.row0.x += 1 projected.row0.y += 1 projected.row1.x += 1 projected.row1.y += 1 projected.row2.x += 1 projected.row2.y += 1 projected.row0.x *= .5 * ui.width projected.row0.y *= .5 * ui.height projected.row1.x *= .5 * ui.width projected.row1.y *= .5 * ui.height projected.row2.x *= .5 * ui.width projected.row2.y *= .5 * ui.height t = Triangle(projected) t.color = r triangles.append(t) for projected in triangles: r = projected.color coords = [projected.coords.row0.x, projected.coords.row0.y, projected.coords.row1.x, projected.coords.row1.y, projected.coords.row2.x, projected.coords.row2.y] ui.canvas.create_polygon(coords, fill=from_rgb(r, r, r), outline="black") ui.canvas.update() #ui.canvas.after(100, draw_scene) def from_rgb(r, b, g): return "#%02x%02x%02x" %(r, g, b) main()