import pygame as pg
from math import *
from settings import *
import sys, json
pg.init()
flags = pg.FULLSCREEN | pg.DOUBLEBUF
screen = pg.display.set_mode([0, 0], flags, vsync = True)
del flags
clock = pg.time.Clock()
working_dir = "/".join(__file__.split('/')[0:-1])+'/'
if working_dir == '/': working_dir = "/".join(__file__.split('\\')[0:-1])+'/'
sys.path.append(working_dir)
objects = []
SIZE = {}
SIZE["screen"] = screen.get_size()
SIZE["half_screen"] = [SIZE["screen"][0] // 2, SIZE["screen"][1] // 2]
class Camera:
def __init__(self, pos, rotation):
self.x, self.y, self.z = pos
self.rot = rotation
def movement(self, key):
if key[pg.K_a]: self.x += 10
if key[pg.K_d]: self.x -= 10
if key[pg.K_w]: self.z -= 10
if key[pg.K_s]: self.z += 10
if key[pg.K_q]: self.y -= 10
if key[pg.K_e]: self.y += 10
camera = Camera([0, 0, 0], [0, 0, 0])
class Object:
def __init__(self, pos = [0, 0, 0], rotation = [0, 0, 0], points = [], sides = [], outlines = [], outline_color = (0, 0, 0), show_outlines = True):
self.real_pos = pos
self.pos = pos
self.rot = rotation
self.points = points
self.sides = sides
self.show_outlines = show_outlines
self.outlines = outlines
self.outline_color = outline_color
def render_point(self, pos, fov = OBJECTS_FOV):
global SIZE
x, y, z = pos
x, y = x * cos(radians(self.rot[0])) - y * sin(radians(self.rot[0])), y * cos(radians(self.rot[0])) + x * sin(radians(self.rot[0]))
y, z = y * cos(radians(self.rot[1])) - z * sin(radians(self.rot[1])), z * cos(radians(self.rot[1])) + y * sin(radians(self.rot[1]))
x, z = x * cos(radians(self.rot[2])) - z * sin(radians(self.rot[2])), z * cos(radians(self.rot[2])) + x * sin(radians(self.rot[2]))
x += self.pos[0] - SIZE["half_screen"][0]
y += self.pos[1] - SIZE["half_screen"][1]
z += self.pos[2]
x, y = x * fov / z, y * fov / z
x += SIZE["half_screen"][0]
y += SIZE["half_screen"][1]
return (int(x), int(y))
def sort(self, obj):
global SIZE
sx = sy = sz = 0
for a in obj[0]:
x, y, z = self.points[a]
x, y = x * cos(radians(self.rot[0])) - y * sin(radians(self.rot[0])), y * cos(radians(self.rot[0])) + x * sin(radians(self.rot[0]))
y, z = y * cos(radians(self.rot[1])) - z * sin(radians(self.rot[1])), z * cos(radians(self.rot[1])) + y * sin(radians(self.rot[1]))
x, z = x * cos(radians(self.rot[2])) - z * sin(radians(self.rot[2])), z * cos(radians(self.rot[2])) + x * sin(radians(self.rot[2]))
x += self.pos[0]
y += self.pos[1]
z += self.pos[2]
sx += x; sy += y; sz += z
sx /= len(obj[0]); sy /= len(obj[0]); sz /= len(obj[0])
dis = sqrt(((SIZE["half_screen"][0] - sx) ** 2) + ((SIZE["half_screen"][1] - sy) ** 2) + ((0 - sz) ** 2))
return dis
def draw(self, screen):
list1 = self.sides
list1.sort(key = self.sort, reverse = True)
for ab in list1:
p = []
for a in ab[0]:
p.append(self.render_point(self.points[a]))
pg.draw.polygon(screen, ab[1], p)
if self.show_outlines:
for b in self.outlines:
pg.draw.line(screen, self.outline_color, self.render_point(self.points[b[0]]), self.render_point(self.points[b[1]]))
def load_obj(path):
with open(path, "r") as args:
kwargs = json.load(args)
objects.append(Object(**kwargs))
load_obj(working_dir+'cube.json')
load_obj(working_dir+'triangle.json')
while True:
screen.fill((100, 100, 100))
for event in pg.event.get():
if event.type == pg.QUIT: pg.quit()
key = pg.key.get_pressed()
for obj in objects:
obj.pos = obj.real_pos[0] + camera.x, obj.real_pos[1] + camera.y, obj.real_pos[2] + camera.z
obj.draw(screen)
if key[pg.K_f]: obj.rot[0] += 3
if key[pg.K_h]: obj.rot[0] -= 3
if key[pg.K_g]: obj.rot[1] += 3
if key[pg.K_t]: obj.rot[1] -= 3
if key[pg.K_r]: obj.rot[2] += 3
if key[pg.K_y]: obj.rot[2] -= 3
camera.movement(key)
if FPS_COUNTER:
fps = font.render(str(round(clock.get_fps(), 1)), True, (255, 255, 255))
screen.blit(fps, (5, 5))
pg.display.flip()
clock.tick(FPS)