<repo_name>Ghoris0127/cg<file_sep>/eindopdracht/interface.py
from OpenGL.GL import *
from OpenGL.GLUT import *
import ctypes

class Interface:
	def __init__(self, x, y, s_hor, s_ver, c, func):
		self.x = x
		self.y = y
		self.s_hor = s_hor
		self.s_ver = s_ver
		self.c = c
		self.func = func

	def check_pressed(self, button, x, y, window):
		if button == 0 and self.x - 0.5 * self.s_hor <= x <= self.x + 0.5 * self.s_hor and self.y - 0.5 * self.s_ver <= y <= self.y + 0.5 * self.s_ver:
			self.func(window)

	def draw(self):
		glBegin(GL_QUADS)
		glColor((1, 1, 1))
		glVertex((self.x - 0.5 * self.s_hor, self.y - 0.5 * self.s_ver))
		glVertex((self.x + 0.5 * self.s_hor, self.y - 0.5 * self.s_ver))
		glVertex((self.x + 0.5 * self.s_hor, self.y + 0.5 * self.s_ver))
		glVertex((self.x - 0.5 * self.s_hor, self.y + 0.5 * self.s_ver))
		glColor(self.c)
		glVertex((self.x - 0.5 * self.s_hor + 2, self.y - 0.5 * self.s_ver + 2))
		glVertex((self.x + 0.5 * self.s_hor - 2, self.y - 0.5 * self.s_ver + 2))
		glVertex((self.x + 0.5 * self.s_hor - 2, self.y + 0.5 * self.s_ver - 2))
		glVertex((self.x - 0.5 * self.s_hor + 2, self.y + 0.5 * self.s_ver - 2))
		glEnd()
<file_sep>/eindopdracht/lines.py
from window import Window
from shapes import Cube, Star, Curve
from interface import Interface

width = 1080
height = 720

def toggle_turning(window):
	for shape in window.shapes:
		if not isinstance(shape, Curve):
			shape.turning = not shape.turning

l = Window(width, height)
cube1 = Cube(0, 0, 0, 200, (1, 0, 0), True)
l.add_shape(cube1)
cube2 = Cube(0, -150, 0, 100, (0, 1, 0), True)
l.add_shape(cube2)
star = Star(350, 0, 0, 100, (1, 0, 1), True)
l.add_shape(star)
interface = Interface(50, 25, 100, 50, (0, 1, 1), toggle_turning)
l.add_interface(interface)
curve1 = Curve((100, 100), (100, 200), (200, 200), (0.5, 0, 0.5))
curve2 = Curve((100, 100), (100, 200), (0, 200), (0.5, 0, 0.5))
curve3 = Curve((100, 300), (100, 200), (0, 200), (0.5, 0, 0.5))
curve4 = Curve((100, 300), (100, 200), (200, 200), (0.5, 0, 0.5))
l.add_shape(curve1)
l.add_shape(curve2)
l.add_shape(curve3)
l.add_shape(curve4)
l.draw()

#data for testing the matrix multiplier function.
#matrix_one = [[4, 0, 3], [1, -1, 7], [-3, 3, 2]]
#matrix_two = [[-2, 3, 1], [2, -3, -5], [4, 0, 7]]
#print(mult_matrix_matrix(matrix_one, matrix_two))
<file_sep>/eindopdracht/window.py
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import math
import random
import time

class Window:

	def __init__(self, sizeX, sizeY):
		self.sizeX = sizeX
		self.sizeY = sizeY
		self.shapes = []
		self.interfaces = []
		self.rotation = 45
		self.old_time = time.time()
		self.iso = Isometric(self)
		glutInit()
		glutInitDisplayMode(GLUT_RGB)
		glutInitWindowSize(sizeX, sizeY)
		glutCreateWindow("Eindopdracht".encode("ascii"))
		glOrtho(0, sizeX, sizeY, 0, -1, 1)
		glutDisplayFunc(self.display)
		glutMouseFunc(self.mouse_func)
		#added timer func that will update after 2 seconds
		glutTimerFunc(50, self.update, 1)
		glutKeyboardFunc(self.end)

	def add_shape(self, shape):
		self.shapes.append(shape)

	def add_interface(self, interface):
		self.interfaces.append(interface)

	def update(self, value):
		new_time = time.time()
		dt = new_time - self.old_time
		self.old_time = new_time

		for shape in self.shapes:
			shape.update(dt)

		glutTimerFunc(50, self.update, 1)

	def display(self):
		glClear(GL_COLOR_BUFFER_BIT)
		for shape in self.shapes:
			shape.draw(self.iso)
		for interface in self.interfaces:
			interface.draw()
		glFlush()
		glutPostRedisplay()

	def mouse_func(self, button, state, x, y):
		if state == 1:
			for interface in self.interfaces:
				interface.check_pressed(button, x, y, self)

	def end(self, key, x, y):
		exit()

	def draw(self):
		glutMainLoop()

#class to wrap the methods needed for isometric calculation
class Isometric():

	def __init__(self, window):
		self.window = window

	#method to multiply a matrix with a vector
	def mult_matrix_vector(self, matrix, vector):
		return_matrix = [0] * len(matrix)
		if len(matrix[0]) == len(vector):
			for i in range (0, len(matrix)):
				for j in range(0, len(vector)):
					return_matrix[i] += matrix[i][j] * vector[j]
		return return_matrix

	#method to multipy a matrix with a matrix
	def mult_matrix_matrix(self, matrix_one, matrix_two):
		return_matrix = []
		for i in range (0, len(matrix_one)):
			return_matrix.append([])
			for j in range (0, len(matrix_two[0])):
				return_matrix[i].append(0)

		if len(matrix_one[0]) == len(matrix_two):
			for h in range (0, len(matrix_one[0])):
				for i in range (0, len(matrix_one)):
					value = 0
					for j in range(0, len(matrix_one[0])):
						value += matrix_one[i][j] * matrix_two[j][h]
					return_matrix[i][h] = value
			return return_matrix

	''' in case of symmetry the rotational matrix that we need to implement is already used to create the view.
		with isometric you need to use 2 rotational matrixes. One for making the camera turn around the y axis and one around the x axis.
		we did the bonus excersize by multiplying our matrixes so that we only need to multiply the vector with one matrix.'''
	def isometricisize(self, coordinate_list, x, y, object_rotation):
		isometric_coordinates = []
		alpha = math.asin(math.tan(math.radians(30)))
		beta = math.radians(object_rotation + self.window.rotation)
		projection_matrix_one = ((math.cos(beta), 0, -1 * math.sin(beta)),
								 (0, 1, 0),
								 (math.sin(beta), 0, math.cos(beta)))
		projection_matrix_two = ((1, 0, 0),
								 (0, math.cos(alpha), math.sin(alpha)),
								 (0, -1 * math.sin(alpha), math.cos(alpha)))
		combined_matrix = self.mult_matrix_matrix(projection_matrix_two, projection_matrix_one)
		for coordinate in coordinate_list:
			matrix_calc = self.mult_matrix_vector(combined_matrix, coordinate)
			isometric_coordinates.append((matrix_calc[0] + 0.5 * self.window.sizeX + x, matrix_calc[1] + 0.5 * self.window.sizeY + y))
		return isometric_coordinates
<file_sep>/eindopdracht/shapes.py
from OpenGL.GL import *

class Curve:
	def __init__(self, p1, p2, p3, c):
		self.p1 = p1
		self.p2 = p2
		self.p3 = p3
		self.c = c

	def update(self, dt):
		pass

	def get_coordinates(self):
		return_list = []
		for t in range(0, 10, 1):
			t *= 0.1
			x_coor = (1 - t) ** 2 * self.p1[0] + 2 * (1 - t) * t * self.p2[0] + t ** 2 * self.p3[0]
			y_coor = (1 - t) ** 2 * self.p1[1] + 2 * (1 - t) * t * self.p2[1] + t ** 2 * self.p3[1]
			return_list.append((int(x_coor), int(y_coor)))
		return return_list

	def draw(self, perspective):
		glBegin(GL_LINE_STRIP)
		glColor(self.c)
		for coordinate in self.get_coordinates():
			glVertex(coordinate)
		glEnd()

class Star:
	vertices = [[0, -1, 0],
				[-0.95, -0.31, 0],
				[-0.59, 0.81, 0],
				[0.59, 0.81, 0],
				[0.95, -0.31, 0]]

	edges = ((0, 2),
			 (2, 4),
			 (4, 1),
			 (1, 3),
			 (3, 0))

	def __init__(self, x, y, z, s, c, turning):
		self.x = x # x coordinate
		self.y = y # y coordinate
		self.z = z # z coordinate
		self.s = s # s (scale)
		self.c = c # c color (f, f, f)
		self.r = 0
		self.turning = turning

	# Converts vertices to coordinates in the world
	def return_vertex_coordinates(self):
		return_coordinates = []
		for vertex in self.vertices:
			new_x = vertex[0] * 0.5 * self.s
			new_y = vertex[1] * 0.5 * self.s
			new_z = vertex[2] * 0.5 * self.s
			return_coordinates.append((new_x, new_y, new_z))
		return return_coordinates

	#returns the list with edgess
	def return_edges(self):
		return self.edges

	def update(self, dt):
		if self.turning:
			self.r -= 100 * dt

	def draw(self, perspective):
		#makes the isometric representation for an array of coordinates taking the current rotation into account
		isometric_coordinates = perspective.isometricisize(self.return_vertex_coordinates(), self.x, self.y, self.r)
		#draws lines between the calculated coordinates
		glBegin(GL_LINES)
		glColor(self.c)
		for edge in self.edges:
			glVertex(isometric_coordinates[edge[0]])
			glVertex(isometric_coordinates[edge[1]])
		#increases rotation for one
		glEnd()

class Cube:
	# vertices related from the middle of the cube
	vertices = ((1, -1, -1),
				(1, 1, -1),
				(-1, 1, -1),
				(-1, -1, -1),
				(1, -1, 1),
				(1, 1, 1),
				(-1, -1, 1),
				(-1, 1, 1))

	# edges to show which vertex connects to which other vertex
	edges = ((0,1),
			 (0,3),
			 (0,4),
			 (2,1),
			 (2,3),
			 (2,7),
			 (6,3),
			 (6,4),
			 (6,7),
			 (5,1),
			 (5,4),
			 (5,7))

	surfaces = ((0,1,2,3),
				(3,2,7,6),
				(6,7,5,4),
				(4,5,1,0),
				(1,5,7,2),
				(4,0,3,6))

	def __init__(self, x, y, z, s, c, turning):
		self.x = x # x coordinate
		self.y = y # y coordinate
		self.z = z # z coordinate
		self.s = s # s (scale)
		self.c = c # c color (f, f, f)
		self.r = 45
		self.turning = turning

	# Converts vertices to coordinates in the world
	def return_vertex_coordinates(self):
		return_coordinates = []
		for vertex in self.vertices:
			new_x = vertex[0] * 0.5 * self.s
			new_y = vertex[1] * 0.5 * self.s
			new_z = vertex[2] * 0.5 * self.s
			return_coordinates.append((new_x, new_y, new_z))
		return return_coordinates

	#returns the list with edgess
	def return_edges(self):
		return self.edges

	def update(self, dt):
		if self.turning:
			self.r += 100 * dt

	def draw(self, perspective):
		#makes the isometric representation for an array of coordinates taking the current rotation into account
		isometric_coordinates = perspective.isometricisize(self.return_vertex_coordinates(), self.x, self.y, self.r)
		#draws lines between the calculated coordinates
		glBegin(GL_QUADS)
		glColor(self.c)
		for surface in self.surfaces:
			for vertex in surface:
				glVertex(isometric_coordinates[vertex])
		glEnd()

		glBegin(GL_LINES)
		glColor((1, 1, 1))
		for edge in self.edges:
			glVertex(isometric_coordinates[edge[0]])
			glVertex(isometric_coordinates[edge[1]])
		#increases rotation for one
		glEnd()
