diff --git a/src/app.py b/src/app.py index 4cda43e..4a67be9 100644 --- a/src/app.py +++ b/src/app.py @@ -1,82 +1,79 @@ -import pygame +import pygame as pg import numpy as np from math import * -import src.transformation_matrices as tm +import src.constants as cn +import transformation as tm +from src.object_builder import ObjectBuilder +from src.object import Object +from src.camera import Camera class App: - clock: pygame.time.Clock - screen: pygame.Surface - scale: int - points: dict[str, np.matrix] - lines: list[str] - projection_matrix: np.matrix - angle_x: float + clock: pg.time.Clock + screen: pg.Surface + camera: Camera + objects = list[Object] def __init__(self): - self.clock = pygame.time.Clock() - self.screen = pygame.display.set_mode((1280, 720)) - self.scale = 100 - self.angle = 0.05 - self.points = { - "A": np.matrix([-1, -1, 1]), - "B": np.matrix([ 1, -1, 1]), - "C": np.matrix([ 1, 1, 1]), - "D": np.matrix([-1, 1, 1]), - "E": np.matrix([-1, -1, -1]), - "F": np.matrix([ 1, -1, -1]), - "G": np.matrix([ 1, 1, -1]), - "H": np.matrix([-1, 1, -1]), - } - self.lines = [ - "AB", - "AD", - "DC", - "BC", - "EF", - "EH", - "HG", - "FG", - "AE", - "BF", - "DH", - "CG" - ] - self.projection_matrix = np.matrix([ - [1, 0, 0], - [0, 1, 0] - ]) + self.clock = pg.time.Clock() + self.screen = pg.display.set_mode(cn.WINDOW_SIZE) + self.objects = [] + self.camera = Camera(-5, 6, -55) + self.create_objects() + + def create_objects(self): + obj_builder = ObjectBuilder() + va = obj_builder.add_vertex(-1, -1, 1) + vb = obj_builder.add_vertex( 1, -1, 1) + vc = obj_builder.add_vertex( 1, 1, 1) + vd = obj_builder.add_vertex(-1, 1, 1) + ve = obj_builder.add_vertex(-1, -1, -1) + vf = obj_builder.add_vertex( 1, -1, -1) + vg = obj_builder.add_vertex( 1, 1, -1) + vh = obj_builder.add_vertex(-1, 1, -1) + obj_builder.add_vertices_connection(va, vb) + obj_builder.add_vertices_connection(va, vd) + obj_builder.add_vertices_connection(vd, vc) + obj_builder.add_vertices_connection(vb, vc) + obj_builder.add_vertices_connection(ve, vf) + obj_builder.add_vertices_connection(ve, vh) + obj_builder.add_vertices_connection(vh, vg) + obj_builder.add_vertices_connection(vf, vg) + obj_builder.add_vertices_connection(va, ve) + obj_builder.add_vertices_connection(vb, vf) + obj_builder.add_vertices_connection(vd, vh) + obj_builder.add_vertices_connection(vc, vg) + self.objects.append(obj_builder.build()) def main(self): self.setup() while True: - self.clock.tick(60) - for event in pygame.event.get(): + self.clock.tick(cn.FPS) + for event in pg.event.get(): self.handle_event(event) self.update() - def handle_event(self, event: pygame.event.Event): + def handle_event(self, event: pg.event.Event): match event.type: - case pygame.QUIT: + case pg.QUIT: self.quit() - case pygame.KEYDOWN: + case pg.KEYDOWN: match event.key: - case pygame.K_ESCAPE: + case pg.K_ESCAPE: self.quit() - case pygame.K_s: - self.transform(tm.rotation_x(self.angle)) - case pygame.K_w: - self.transform(tm.rotation_x(-self.angle)) - case pygame.K_d: - self.transform(tm.rotation_y(self.angle)) - case pygame.K_a: - self.transform(tm.rotation_y(-self.angle)) - case pygame.K_q: - self.transform(tm.rotation_z(self.angle)) - case pygame.K_e: - self.transform(tm.rotation_z(-self.angle)) - + case pg.K_s: + self.camera.move_backward() + case pg.K_w: + self.camera.move_forward() + case pg.K_d: + self.camera.move_right() + case pg.K_a: + self.camera.move_left() + case pg.K_SPACE: + self.camera.move_up() + case pg.K_LSHIFT: + self.camera.move_down() def transform(self, transformation_matrix: np.matrix): for key in self.points.keys(): @@ -84,11 +81,20 @@ class App: self.points[key] = np.dot(transformation_matrix, point.reshape((3,1))) def setup(self): - pygame.display.set_caption("Virtual camera") + pg.display.set_caption("Virtual camera") def update(self): self.screen.fill((255,255,255)) + for obj in self.objects: + obj.draw() + pg.display.update() + def quit(self): + pg.quit() + exit() + + +""" projected_points = {} for point_key in self.points.keys(): @@ -98,18 +104,12 @@ class App: x = int(projected_2D[0][0] * self.scale) + (1280 / 2) y = int(projected_2D[1][0] * self.scale) + (720 / 2) - pygame.draw.circle(self.screen, (255, 0, 0), (x, y), 5) + pg.draw.circle(self.screen, (255, 0, 0), (x, y), 5) projected_points[point_key] = (x, y) for line in self.lines: point_a = projected_points[line[0]] point_b = projected_points[line[1]] - pygame.draw.line(self.screen, (0,0,0), point_a, point_b) - - - pygame.display.update() - - def quit(self): - pygame.quit() - exit() \ No newline at end of file + pg.draw.line(self.screen, (0,0,0), point_a, point_b) +""" \ No newline at end of file diff --git a/src/camera.py b/src/camera.py new file mode 100644 index 0000000..52a5e84 --- /dev/null +++ b/src/camera.py @@ -0,0 +1,30 @@ +import numpy as np +import transformation as tm + +class Camera: + moving_speed: float + rotation_speed: float + position: np.ndarray[float] + + def __init__(self, x: float, y: int, z: int): + self.moving_speed = 0.3 + self.rotation_speed = 0.015 + self.position = np.array([x, y, z, 1.0]) + + def move_forward(self): + self.position += tm.forward_array * self.moving_speed + + def move_backward(self): + self.position -= tm.forward_array * self.moving_speed + + def move_right(self): + self.position += tm.right_array * self.moving_speed + + def move_left(self): + self.position -= tm.right_array * self.moving_speed + + def move_up(self): + self.position += tm.up_array * self.moving_speed + + def move_down(self): + self.position -= tm.up_array * self.moving_speed \ No newline at end of file diff --git a/src/constants.py b/src/constants.py new file mode 100644 index 0000000..50a7584 --- /dev/null +++ b/src/constants.py @@ -0,0 +1,5 @@ +WINDOW_SIZE = (1280, 720) + +FPS = 60 +SCALE = 100 +ANGLE = 0.05 \ No newline at end of file diff --git a/src/object.py b/src/object.py new file mode 100644 index 0000000..09ac504 --- /dev/null +++ b/src/object.py @@ -0,0 +1,12 @@ +from vertex import Vertex + +class Object: + vertices: list[Vertex] + lines = list[(Vertex, Vertex)] + + def __init__(self, vertices: list[Vertex], lines: list[(Vertex, Vertex)]): + self.vertices = vertices + self.lines = lines + + def draw(): + pass \ No newline at end of file diff --git a/src/object_builder.py b/src/object_builder.py new file mode 100644 index 0000000..7778ace --- /dev/null +++ b/src/object_builder.py @@ -0,0 +1,20 @@ +from object import Object +from vertex import Vertex + +class ObjectBuilder: + vertices: list[Vertex] + lines: list[(Vertex, Vertex)] + + def __init__(self): + self.vertices = [] + + def add_vertex(self, x: int, y: int, z: int) -> Vertex: + v = Vertex(x, y, z) + self.vertices.append(v) + return v + + def add_vertices_connection(self, vertex1: Vertex, vertex2: Vertex): + self.lines.append((vertex1, vertex2)) + + def build(self) -> Object: + pass \ No newline at end of file diff --git a/src/transformation_matrices.py b/src/transformation.py similarity index 81% rename from src/transformation_matrices.py rename to src/transformation.py index ef7f7ad..448c84c 100644 --- a/src/transformation_matrices.py +++ b/src/transformation.py @@ -17,4 +17,8 @@ rotation_z = lambda angle: np.matrix([ [cos(angle), -sin(angle), 0], [sin(angle), cos(angle), 0], [0, 0, 1], -]) \ No newline at end of file +]) + +forward_array = np.array([0, 0, 1, 1]) +up_array = np.array([0, 1, 0, 1]) +right_array = np.array([1, 0, 0, 1]) \ No newline at end of file diff --git a/src/vertex.py b/src/vertex.py new file mode 100644 index 0000000..03eed4f --- /dev/null +++ b/src/vertex.py @@ -0,0 +1,14 @@ +import numpy as np + +class Vertex: + x: int + y: int + z: int + + def __init__(self, x: int, y: int, z: int): + self.x = x + self.y = y + self.z = z + + def to_matrix(self) -> np.matrix: + return np.matrix([self.x, self.y, self.z]) \ No newline at end of file diff --git a/camera.py b/virtual_camera.py similarity index 100% rename from camera.py rename to virtual_camera.py