├── .idea ├── .gitignore ├── Graphics-Space_Invaders.iml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── README.md ├── graphics ├── ThreeDObject.py ├── __init__.py ├── __pycache__ │ ├── ThreeDObject.cpython-39.pyc │ ├── __init__.cpython-39.pyc │ ├── attribute_provider.cpython-39.pyc │ ├── camera_file.cpython-39.pyc │ ├── home.cpython-39.pyc │ ├── keyboard.cpython-39.pyc │ ├── matrix_file.cpython-39.pyc │ ├── mesh_file.cpython-39.pyc │ ├── openGlUtilClass.cpython-39.pyc │ ├── rendering.cpython-39.pyc │ ├── scene_file.cpython-39.pyc │ ├── texture_file.cpython-39.pyc │ └── unifor_file.cpython-39.pyc ├── attribute_provider.py ├── camera_file.py ├── gourp_file.py ├── home.py ├── keyboard.py ├── matrix_file.py ├── mesh_file.py ├── openGlUtilClass.py ├── rendering.py ├── scene_file.py ├── texture_file.py └── unifor_file.py ├── images ├── grass.jpg ├── music.mp3 ├── sky.webp ├── space1.jpg ├── space2.jpg ├── space3.jpg ├── space4.jpg ├── space5.png ├── space6.png ├── space7.png ├── space8.png ├── space9.png ├── water.jpeg └── water2.jpeg ├── main.py └── utility ├── __init__.py ├── __pycache__ ├── __init__.cpython-39.pyc ├── box_geo.cpython-39.pyc ├── bsc_mat.cpython-39.pyc ├── ellips_geo.cpython-39.pyc ├── geometry_file.cpython-39.pyc ├── mat.cpython-39.pyc ├── movtRig.cpython-39.pyc ├── para_geo.cpython-39.pyc ├── rect_geo.cpython-39.pyc ├── sphere_geo.cpython-39.pyc ├── surfce_mat.cpython-39.pyc └── textu_mat.cpython-39.pyc ├── box_geo.py ├── bsc_mat.py ├── ellips_geo.py ├── geometry_file.py ├── mat.py ├── movtRig.py ├── para_geo.py ├── rect_geo.py ├── sphere_geo.py ├── surfce_mat.py └── textu_mat.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/Graphics-Space_Invaders.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Space-Invaders_GRAPHICS 2 | 3 | Space Invader is a graphics-based application that brings an interactive 3D space experience to users. This project utilizes the OpenGL library to render and animate graphics within a 3D environment. The primary goal of the project is to create an immersive space-themed experience where users can witness moving graphics and explore a simulated space setting. 4 | 5 | ## Features 6 | 7 | - Utilizes OpenGL library for rendering graphics. 8 | - Implements 3D graphics in a space-themed environment. 9 | - Dynamic movement of graphics within the 3D space. 10 | - Uses data structures and algorithms for efficient rendering and animation. 11 | 12 | ## Getting Started 13 | 14 | ### Prerequisites 15 | 16 | - Python installed on your system. 17 | - Ensure OpenGL library is installed. You can install it using pip: 18 | ``` 19 | pip install PyOpenGL 20 | ``` 21 | 22 | ### Running the Application 23 | 24 | 1. Clone the repository to your local machine. 25 | 2. Navigate to the project directory. 26 | 3. Run the application using `main.py`: 27 | ``` 28 | python main.py 29 | ``` 30 | 31 | ## Usage 32 | 33 | Upon running `main.py`, the application will launch the space-themed graphics environment. Users can interact with the environment to experience the moving graphics within the 3D space. 34 | -------------------------------------------------------------------------------- /graphics/ThreeDObject.py: -------------------------------------------------------------------------------- 1 | from graphics.matrix_file import MatrixFile 2 | 3 | 4 | # in scene graph tree we represent anode using 3D objects 5 | class Three_D_Object(object): 6 | def __init__(self): 7 | 8 | # this is a matrix used to store transform data 9 | self.transform = MatrixFile.make_identity() 10 | # it references the prent objects 11 | self.parent = None 12 | # this references child objects 13 | self.children = [] 14 | 15 | # this function used to add a child for the node 16 | def add(self, child): 17 | self.children.append(child) 18 | child.parent = self 19 | 20 | # this function used to remove a child from the node 21 | def remove(self, child): 22 | self.children.remove(child) 23 | child.parent = None 24 | 25 | # used to calculate the transformation of 3D object relative to root scene 26 | def getWorldMatrix(self): 27 | if self.parent is None: 28 | return self.transform 29 | else: 30 | return self.parent.getWorldMatrix() @ self.transform 31 | 32 | def getDescendantList(self): 33 | descendants = [] 34 | nodesToProcess = [self] 35 | while len(nodesToProcess) > 0: 36 | # remove the node at index 0 37 | node = nodesToProcess.pop(0) 38 | # add this node to descendants of children 39 | descendants.append(node) 40 | # add children with nodes to process 41 | nodesToProcess = node.children + nodesToProcess 42 | return descendants 43 | 44 | def applyMatrix(self, matrix, localCoord=True): 45 | if localCoord: 46 | self.transform = self.transform @ matrix 47 | else: 48 | self.transform = matrix @ self.transform 49 | 50 | def translate(self, x, y, z, localCoord=True): 51 | m = MatrixFile.make_translation(x, y, z) 52 | self.applyMatrix(m, localCoord) 53 | 54 | def rotateX(self, angle, localCoord=True): 55 | m = MatrixFile.make_rotation_X(angle) 56 | self.applyMatrix(m, localCoord) 57 | 58 | def rotateY(self, angle, localCoord=True): 59 | m = MatrixFile.make_rotation_Y(angle) 60 | self.applyMatrix(m, localCoord) 61 | 62 | def rotateZ(self, angle, localCoord=True): 63 | m = MatrixFile.make_rotation_Z(angle) 64 | self.applyMatrix(m, localCoord) 65 | 66 | def scale(self, s, localCoord=True): 67 | m = MatrixFile.make_scale(s) 68 | self.applyMatrix(m, localCoord) 69 | 70 | def getPosition(self): 71 | return [self.transform.item((0, 3)), 72 | self.transform.item((1, 3)), 73 | self.transform.item((2, 3))] 74 | 75 | def getWorldPosition(self): 76 | worldTransform = self.getWorldMatrix() 77 | return [worldTransform.item((0, 3)), 78 | worldTransform.item((1, 3)), 79 | worldTransform.item((2, 3))] 80 | 81 | def setPosition(self, position): 82 | self.transform.itemset((0, 3), position[0]) 83 | self.transform.itemset((1, 3), position[1]) 84 | self.transform.itemset((2, 3), position[2]) 85 | -------------------------------------------------------------------------------- /graphics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__init__.py -------------------------------------------------------------------------------- /graphics/__pycache__/ThreeDObject.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/ThreeDObject.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/__init__.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/__init__.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/attribute_provider.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/attribute_provider.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/camera_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/camera_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/home.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/home.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/keyboard.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/keyboard.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/matrix_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/matrix_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/mesh_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/mesh_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/openGlUtilClass.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/openGlUtilClass.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/rendering.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/rendering.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/scene_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/scene_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/texture_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/texture_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/__pycache__/unifor_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/graphics/__pycache__/unifor_file.cpython-39.pyc -------------------------------------------------------------------------------- /graphics/attribute_provider.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GL import * 2 | import numpy 3 | 4 | 5 | # vertex shader uses the data stored in vertex buffer 6 | class AttributeProvider: 7 | def __init__(self, data_type_of_vertex, value): 8 | # store the type of data 9 | self.data_type_of_vertex = data_type_of_vertex 10 | # store the value 11 | self.data = value 12 | # this reference the buffer from the gpu for computation 13 | self.buffer_reference = glGenBuffers(1) 14 | self.up_load_data() 15 | 16 | def up_load_data(self): 17 | # change number format into numpy 18 | data = numpy.array(self.data).astype(numpy.float32) 19 | # here we select which buffer to use 20 | glBindBuffer(GL_ARRAY_BUFFER, self.buffer_reference) 21 | # this function put the data in the selected buffer 22 | glBufferData(GL_ARRAY_BUFFER, data.ravel(), GL_STATIC_DRAW) 23 | 24 | # this function associate the variable in the program with the buffer 25 | # we created above 26 | 27 | def associate_variable(self, program_reference, variableName): 28 | # using this function we get program and we assign its location to this variable 29 | variable_ref = glGetAttribLocation(program_reference, variableName) 30 | if variable_ref == -1: 31 | return 32 | # here we select the buffer used in this program 33 | glBindBuffer(GL_ARRAY_BUFFER, self.buffer_reference) 34 | if self.data_type_of_vertex == "int": 35 | glVertexAttribPointer(variable_ref, 1, GL_INT, False, 0, None) 36 | elif self.data_type_of_vertex == "float": 37 | glVertexAttribPointer(variable_ref, 1, GL_FLOAT, False, 0, None) 38 | elif self.data_type_of_vertex == "vec2": 39 | glVertexAttribPointer(variable_ref, 2, GL_FLOAT, False, 0, None) 40 | elif self.data_type_of_vertex == "vec3": 41 | glVertexAttribPointer(variable_ref, 3, GL_FLOAT, False, 0, None) 42 | elif self.data_type_of_vertex == "vec4": 43 | glVertexAttribPointer(variable_ref, 4, GL_FLOAT, False, 0, None) 44 | 45 | else: 46 | raise Exception("Attribute " + variableName + " has unknown type " + self.data_type_of_vertex) 47 | # indicate that data will be streamed to this variable 48 | glEnableVertexAttribArray(variable_ref) 49 | -------------------------------------------------------------------------------- /graphics/camera_file.py: -------------------------------------------------------------------------------- 1 | from graphics.ThreeDObject import Three_D_Object 2 | from graphics.matrix_file import MatrixFile 3 | from numpy.linalg import inv 4 | 5 | 6 | # This class used to represent virtual camera used to view the scene 7 | class CameraView(Three_D_Object): 8 | def __init__(self, angle_of_view=60, aspectRatio=1, near=0.1, far=1000): 9 | super().__init__() 10 | # the camera itself is not rendered like other node but it's transformation affects the 11 | # current placement of the objects in the scene 12 | self.projection_matrix = MatrixFile.make_perspective(angle_of_view, aspectRatio, near, far) 13 | self.view_matrix = MatrixFile.make_identity() 14 | 15 | def updateViewMatrix(self): 16 | self.view_matrix = inv(self.getWorldMatrix()) 17 | 18 | 19 | -------------------------------------------------------------------------------- /graphics/gourp_file.py: -------------------------------------------------------------------------------- 1 | from graphics.ThreeDObject import Three_D_Object 2 | 3 | 4 | # Used to represent an iterior node to which other nodes are attached and enable 5 | # easily transform them as a single unit. 6 | class GroupObjectObject(Three_D_Object): 7 | def __init__(self): 8 | super().__init__() 9 | -------------------------------------------------------------------------------- /graphics/home.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from graphics.keyboard import KeyBoard 3 | 4 | 5 | 6 | 7 | 8 | class missile: 9 | def __init__(self, x, y): 10 | self.x = x 11 | self.y = y 12 | 13 | # playerImg = pygame.image.load('images/photo1.jpeg') 14 | class enemy: 15 | def __init__(self, x, y): 16 | self.x = x 17 | self.y = y 18 | 19 | # enemyImg = pygame.image.load('images/photo2.jpeg') 20 | class bullet: 21 | def __init__(self, x, y): 22 | self.x = x 23 | self.y = y 24 | 25 | class Home(object): 26 | def __init__(self, sizeOfScreen=None): 27 | if sizeOfScreen is None: 28 | sizeOfScreen = [800, 700] 29 | # pygame.init() initialize all pygame modules 30 | pygame.init() 31 | # used for rendering purpose 32 | display_flags = pygame.DOUBLEBUF | pygame.OPENGL 33 | # initialization of buffer 34 | pygame.display.gl_set_attribute( 35 | pygame.GL_MULTISAMPLEBUFFERS, 1) 36 | # for compatablity purpose 37 | pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, 4) 38 | pygame.display.gl_set_attribute( 39 | pygame.GL_CONTEXT_PROFILE_MASK, 40 | pygame.GL_CONTEXT_PROFILE_CORE) 41 | # window for display 42 | self.window = pygame.display.set_mode(sizeOfScreen, display_flags) 43 | pygame.display.set_caption("Space Invader") 44 | # check the loop is running 45 | self.running_state = True 46 | # used to control time 47 | self.clock = pygame.time.Clock() 48 | self.keyboard = KeyBoard() 49 | # time passed from the start 50 | self.time_pass = 0 51 | 52 | def init(self): 53 | pass 54 | 55 | def draw(self): 56 | pass 57 | 58 | def run(self): 59 | self.init() 60 | # this is running loop 61 | while self.running_state: 62 | self.keyboard.update() 63 | if self.keyboard.quit: 64 | self.running_state = False 65 | self.delta_time = self.clock.get_time() / 1000 66 | self.time_pass += self.delta_time 67 | self.draw() 68 | pygame.display.flip() 69 | self.clock.tick(60) 70 | 71 | pygame.quit() 72 | -------------------------------------------------------------------------------- /graphics/keyboard.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | 4 | class KeyBoard(object): 5 | def __init__(self): 6 | # the following list hold the key states 7 | self.keyboard_down_list = [] 8 | self.keyboard_pressed_list = [] 9 | self.keyboard_up_ist = [] 10 | self.quit = False 11 | 12 | def update(self): 13 | self.keyboard_down_list = [] 14 | self.keyboard_up_ist = [] 15 | for event in pygame.event.get(): 16 | if event.type == pygame.QUIT: 17 | self.quit = True 18 | # here we check for key is down or up 19 | # we get the name of the key 20 | if event.type == pygame.KEYDOWN: 21 | keyName = pygame.key.name(event.key) 22 | self.keyboard_down_list.append(keyName) 23 | self.keyboard_pressed_list.append(keyName) 24 | if event.type == pygame.KEYUP: 25 | keyName = pygame.key.name(event.key) 26 | self.keyboard_pressed_list.remove(keyName) 27 | self.keyboard_up_ist.append(keyName) 28 | 29 | def is_key_down(self, key_code): 30 | return key_code in self.keyboard_down_list 31 | 32 | def is_key_pressed(self, key_code): 33 | return key_code in self.keyboard_pressed_list 34 | 35 | def is_Key_up(self, key_code): 36 | return key_code in self.keyboard_up_ist 37 | -------------------------------------------------------------------------------- /graphics/matrix_file.py: -------------------------------------------------------------------------------- 1 | import numpy 2 | from math import sin, cos, tan, pi 3 | 4 | 5 | # matrix is two dimensional array of numbers used to perform transformation easily 6 | class MatrixFile(object): 7 | 8 | # Identity matrix is a matrix which results the matrix after multiplication 9 | @staticmethod 10 | def make_identity(): 11 | return MatrixFile.unique("hello") 12 | 13 | # used to make identity matrix 14 | @staticmethod 15 | def unique(data_type): 16 | return numpy.array([[1, 0, 0, 0], 17 | [0, 1, 0, 0], 18 | [0, 0, 1, 0], 19 | [0, 0, 0, 1]]).astype(float) 20 | 21 | # translation is linear movement in different direction 22 | # the following two functions are used to apply translation 23 | @staticmethod 24 | def make_translation(x, y, z): 25 | return MatrixFile.translateMatrix(x, y, z) 26 | 27 | @staticmethod 28 | def translateMatrix(x, y, z): 29 | return numpy.array([[1, 0, 0, x], 30 | [0, 1, 0, y], 31 | [0, 0, 1, z], 32 | [0, 0, 0, 1]]).astype(float) 33 | 34 | # rotation is one of the linear transforamtion in order to along a specified axis 35 | # we need to apply different formulas for X, Y, Z 36 | @staticmethod 37 | def make_rotation_X(angle): 38 | return MatrixFile.x_rotate(angle) 39 | 40 | # ROTATION along x-axis 41 | @staticmethod 42 | def x_rotate(data_type): 43 | c = cos(data_type) 44 | s = sin(data_type) 45 | return numpy.array([[1, 0, 0, 0], 46 | [0, c, -s, 0], 47 | [0, s, c, 0], 48 | [0, 0, 0, 1]]).astype(float) 49 | 50 | # rotation along y-axis 51 | @staticmethod 52 | def make_rotation_Y(angle): 53 | return MatrixFile.y_rotate(angle) 54 | 55 | @staticmethod 56 | def y_rotate(angle): 57 | c = cos(angle) 58 | s = sin(angle) 59 | return numpy.array([[c, 0, s, 0], 60 | [0, 1, 0, 0], 61 | [-s, 0, c, 0], 62 | [0, 0, 0, 1]]).astype(float) 63 | 64 | # rotation along z-axis 65 | @staticmethod 66 | def make_rotation_Z(angle): 67 | return MatrixFile.z_rotate(angle) 68 | 69 | @staticmethod 70 | def z_rotate(angle): 71 | c = cos(angle) 72 | s = sin(angle) 73 | return numpy.array([[c, -s, 0, 0], 74 | [s, c, 0, 0], 75 | [0, 0, 1, 0], 76 | [0, 0, 0, 1]]).astype(float) 77 | 78 | @staticmethod 79 | def make_scale(s): 80 | return MatrixFile.scaler(s) 81 | 82 | @staticmethod 83 | def scaler(s): 84 | return numpy.array([[s, 0, 0, 0], 85 | [0, s, 0, 0], 86 | [0, 0, s, 0], 87 | [0, 0, 0, 1]]).astype(float) 88 | 89 | # to make perspective view we need angle of view aspect ratio near and far distance 90 | @staticmethod 91 | def make_perspective(angle_of_view_of_scene=60, 92 | aspect_ration_of_scene=1, near=0.1, far=1000): 93 | a = angle_of_view_of_scene * pi / 180.0 94 | d = 1.0 / tan(a / 2) 95 | r = aspect_ration_of_scene 96 | b = (far + near) / (near - far) 97 | c = 2 * far * near / (near - far) 98 | return numpy.array([[d / r, 0, 0, 0], 99 | [0, d, 0, 0], 100 | [0, 0, b, c], 101 | [0, 0, -1, 0]]).astype(float) 102 | -------------------------------------------------------------------------------- /graphics/mesh_file.py: -------------------------------------------------------------------------------- 1 | from graphics.ThreeDObject import Three_D_Object 2 | from OpenGL.GL import * 3 | 4 | 5 | # this class represent visible object in the scene 6 | # it uses different data to specifiy an object for v-related data it use 7 | # geometric data and appearance material data 8 | class MeshObjectObject(Three_D_Object): 9 | def __init__(self, geometry, material): 10 | super().__init__() 11 | self.geometrical_shape = geometry 12 | self.material_object = material 13 | self.visible = True 14 | self.vaoRef = glGenVertexArrays(1) 15 | glBindVertexArray(self.vaoRef) 16 | for variable_name, attribute_object in geometry.attributes.items(): 17 | attribute_object.associate_variable(material.program_ref, variable_name) 18 | glBindVertexArray(0) 19 | -------------------------------------------------------------------------------- /graphics/openGlUtilClass.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GL import * 2 | 3 | 4 | # we use this class for the purpose of compiling and linking 5 | # the vertex and fragment shader to create gpu program 6 | class OpenGLUtilClass(object): 7 | @staticmethod 8 | def initialize_shader(shader_code, type_of_shader): 9 | 10 | # this the code we put in shader 11 | shader_code = '#version 330 \n ' + shader_code 12 | # the first step is creating shader 13 | shader_reference = glCreateShader(type_of_shader) 14 | # then we add shader code 15 | glShaderSource(shader_reference, shader_code) 16 | # finally we compile shader code 17 | glCompileShader(shader_reference) 18 | # we check status 19 | compile_success = glGetShaderiv(shader_reference, GL_COMPILE_STATUS) 20 | if not compile_success: 21 | error_message = glGetShaderInfoLog(shader_reference) 22 | glDeleteShader(shader_reference) 23 | error_message = '\n' + error_message.decode('utf-8') 24 | raise Exception(error_message) 25 | return shader_reference 26 | 27 | # here create instance of object and link compiled shaders 28 | 29 | @staticmethod 30 | def initialize_program(vertex_shader_codes, fragment_shaders_codes): 31 | vertex_shader_ref = OpenGLUtilClass.initialize_shader( 32 | vertex_shader_codes, GL_VERTEX_SHADER) 33 | fragment_shader_ref = OpenGLUtilClass.initialize_shader( 34 | fragment_shaders_codes, GL_FRAGMENT_SHADER) 35 | # creating reference for the program 36 | programRef = glCreateProgram() 37 | glAttachShader(programRef, vertex_shader_ref) 38 | glAttachShader(programRef, fragment_shader_ref) 39 | glLinkProgram(programRef) 40 | link_success = glGetProgramiv(programRef, 41 | GL_LINK_STATUS) 42 | if not link_success: 43 | error_message = glGetProgramInfoLog(programRef) 44 | glDeleteProgram(programRef) 45 | error_message = '\n' + error_message.decode('utf-8') 46 | raise Exception(error_message) 47 | return programRef 48 | 49 | @staticmethod 50 | def print_system_info(): 51 | print(" Vendor: " + glGetString(GL_VENDOR). 52 | decode('utf-8')) 53 | print("Renderer: " + glGetString(GL_RENDERER). 54 | decode('utf-8')) 55 | print("OpenGL version supported: " + 56 | glGetString(GL_VERSION).decode('utf-8')) 57 | print(" GLSL version supported: " + 58 | glGetString(GL_SHADING_LANGUAGE_VERSION). 59 | decode('utf-8')) 60 | -------------------------------------------------------------------------------- /graphics/rendering.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GL import * 2 | from graphics.mesh_file import MeshObjectObject 3 | 4 | 5 | class ObjectRenderer(object): 6 | def __init__(self, clear_color=None): 7 | if clear_color is None: 8 | clear_color = [0, 0, 0] 9 | glEnable(GL_DEPTH_TEST) 10 | glEnable(GL_MULTISAMPLE) 11 | glClearColor(clear_color[0], clear_color[1], clear_color[2], 1) 12 | glEnable(GL_BLEND) 13 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 14 | self.attributes = {} 15 | 16 | def render_object(self, scene, camera): 17 | glClear(GL_COLOR_BUFFER_BIT | 18 | GL_DEPTH_BUFFER_BIT) 19 | camera.updateViewMatrix() 20 | descendant_list = scene.getDescendantList() 21 | mesh_filter = lambda x: isinstance(x, MeshObjectObject) 22 | mesh_list = list(filter(mesh_filter, 23 | descendant_list)) 24 | for mesh in mesh_list: 25 | if not mesh.visible: 26 | continue 27 | glUseProgram(mesh.material_object.program_ref) 28 | # bind VAO 29 | glBindVertexArray(mesh.vaoRef) 30 | mesh.material_object.uniforms["modelMatrix"].data = mesh.getWorldMatrix() 31 | mesh.material_object.uniforms["viewMatrix"].data = camera.view_matrix 32 | mesh.material_object.uniforms["projectionMatrix"].data = camera.projection_matrix 33 | 34 | for variable_name, uniform_object in mesh.material_object.uniforms.items(): 35 | uniform_object.up_load_data() 36 | mesh.material_object.update_render_settings() 37 | glDrawArrays(mesh.material_object. 38 | settings["drawStyle"], 0, 39 | mesh.geometrical_shape.vertex_count) 40 | 41 | def check_errors(self): 42 | status = '' 43 | while self.attributes: 44 | if self.attributes.keys() != self.attributes.values(): 45 | print("attribute error") 46 | status = "error" 47 | else: 48 | print("successfully created") 49 | status = "success" 50 | return status 51 | 52 | def get_status_of_object(self): 53 | # this function used to tell the status of object 54 | status = self.check_errors() 55 | 56 | if status == "success": 57 | return "success status" 58 | else: 59 | return "failure status" 60 | 61 | def current_state_of_object(self): 62 | 63 | attribute = self.attributes.keys() 64 | values = self.attributes.values() 65 | len_attributes = self.attributes.items() 66 | 67 | current_state = {"attributes": attribute, "values": values, "attr_len": len_attributes} 68 | return current_state 69 | -------------------------------------------------------------------------------- /graphics/scene_file.py: -------------------------------------------------------------------------------- 1 | from graphics.ThreeDObject import Three_D_Object 2 | 3 | # this class used to represent a node that do not correspond to visible objects in 4 | # the scene. It represents the root of the tree. 5 | class SceneOfObjectObject(Three_D_Object): 6 | def __init__(self): 7 | super().__init__() 8 | -------------------------------------------------------------------------------- /graphics/texture_file.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from OpenGL.GL import * 3 | 4 | 5 | class TextureFile(object): 6 | def __init__(self, fileName=None, properties=None): 7 | if properties is None: 8 | properties = {} 9 | self.surface = None 10 | self.textureRef = glGenTextures(1) 11 | self.properties = { 12 | "magFilter": GL_LINEAR, 13 | "minFilter": GL_LINEAR_MIPMAP_LINEAR, 14 | "wrap": GL_REPEAT 15 | } 16 | self.attributes = {} 17 | self.set_properties(properties) 18 | if fileName is not None: 19 | self.load_image(fileName) 20 | self.upload_data() 21 | 22 | def load_image(self, fileName): 23 | self.surface = pygame.image.load(fileName) 24 | 25 | def set_properties(self, props): 26 | for _name, data in props.items(): 27 | if _name in self.properties.keys(): 28 | self.properties[_name] = data 29 | 30 | else: # unknown property type 31 | raise Exception("Texture has no property with name: " + _name) 32 | 33 | def upload_data(self): 34 | width = self.surface.get_width() 35 | height = self.surface.get_height() 36 | pixel_data = pygame.image.tostring(self. 37 | surface, "RGBA", 1) 38 | glBindTexture(GL_TEXTURE_2D, self.textureRef) 39 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 40 | width, height, 0, GL_RGBA, 41 | GL_UNSIGNED_BYTE, pixel_data) 42 | glGenerateMipmap(GL_TEXTURE_2D) 43 | glTexParameteri(GL_TEXTURE_2D, 44 | GL_TEXTURE_MAG_FILTER, 45 | self.properties["magFilter"]) 46 | glTexParameteri(GL_TEXTURE_2D, 47 | GL_TEXTURE_MIN_FILTER, 48 | self.properties["minFilter"]) 49 | glTexParameteri(GL_TEXTURE_2D, 50 | GL_TEXTURE_WRAP_S, 51 | self.properties["wrap"]) 52 | glTexParameteri(GL_TEXTURE_2D, 53 | GL_TEXTURE_WRAP_T, 54 | self.properties["wrap"]) 55 | glTexParameterfv(GL_TEXTURE_2D, 56 | GL_TEXTURE_BORDER_COLOR, [1, 1, 1, 1]) 57 | 58 | def check_errors(self): 59 | status = '' 60 | while self.attributes: 61 | if self.attributes.keys() != self.attributes.values(): 62 | print("attribute error") 63 | status = "error" 64 | else: 65 | print("successfully created") 66 | status = "success" 67 | return status 68 | 69 | def get_status_of_object(self): 70 | # this function used to tell the status of object 71 | status = self.check_errors() 72 | 73 | if status == "success": 74 | return "success status" 75 | else: 76 | return "failure status" 77 | 78 | def current_state_of_object(self): 79 | 80 | attribute = self.attributes.keys() 81 | values = self.attributes.values() 82 | len_attributes = self.attributes.items() 83 | 84 | current_state = {"attributes": attribute, "values": values, "attr_len": len_attributes} 85 | return current_state 86 | -------------------------------------------------------------------------------- /graphics/unifor_file.py: -------------------------------------------------------------------------------- 1 | from OpenGL.GL import * 2 | 3 | 4 | # this class used to send data directly from cpu to gpu. 5 | class UniformProvider(object): 6 | def __init__(self, type_of_data, data): 7 | self.type_of_data = type_of_data 8 | self.data = data 9 | # this variable reference the location variable in program 10 | self.variable_reference = None 11 | 12 | # this function get the required variable 13 | def locate_variable(self, programRef, variableName): 14 | self.variable_reference = glGetUniformLocation(programRef, variableName) 15 | 16 | def up_load_data(self): 17 | 18 | # if the program does not reference the variable, then exit 19 | if self.variable_reference == -1: 20 | return 21 | if self.type_of_data == "int": 22 | glUniform1i(self.variable_reference, self.data) 23 | elif self.type_of_data == "bool": 24 | glUniform1i(self.variable_reference, self.data) 25 | elif self.type_of_data == "float": 26 | glUniform1f(self.variable_reference, self.data) 27 | elif self.type_of_data == "vec2": 28 | glUniform2f(self.variable_reference, self.data[0], self.data[1]) 29 | elif self.type_of_data == "vec3": 30 | glUniform3f(self.variable_reference, self.data[0], self.data[1], self.data[2]) 31 | elif self.type_of_data == "vec4": 32 | glUniform4f(self.variable_reference, self.data[0], self.data[1], self.data[2], self.data[3]) 33 | elif self.type_of_data == "mat4": 34 | glUniformMatrix4fv(self.variable_reference, 1, GL_TRUE, self.data) 35 | elif self.type_of_data == "sampler2D": 36 | textureObjectRef, textureUnitRef = self.data 37 | # activate texture unit 38 | glActiveTexture(GL_TEXTURE0 + textureUnitRef) 39 | glBindTexture(GL_TEXTURE_2D, textureObjectRef) 40 | glUniform1i(self.variable_reference, textureUnitRef) 41 | -------------------------------------------------------------------------------- /images/grass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/grass.jpg -------------------------------------------------------------------------------- /images/music.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/music.mp3 -------------------------------------------------------------------------------- /images/sky.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/sky.webp -------------------------------------------------------------------------------- /images/space1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space1.jpg -------------------------------------------------------------------------------- /images/space2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space2.jpg -------------------------------------------------------------------------------- /images/space3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space3.jpg -------------------------------------------------------------------------------- /images/space4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space4.jpg -------------------------------------------------------------------------------- /images/space5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space5.png -------------------------------------------------------------------------------- /images/space6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space6.png -------------------------------------------------------------------------------- /images/space7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space7.png -------------------------------------------------------------------------------- /images/space8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space8.png -------------------------------------------------------------------------------- /images/space9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/space9.png -------------------------------------------------------------------------------- /images/water.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/water.jpeg -------------------------------------------------------------------------------- /images/water2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/images/water2.jpeg -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from pygame import mixer 2 | 3 | from graphics.home import Home 4 | from graphics.rendering import ObjectRenderer 5 | from graphics.scene_file import SceneOfObjectObject 6 | from graphics.camera_file import CameraView 7 | from graphics.mesh_file import MeshObjectObject 8 | from graphics.texture_file import TextureFile 9 | from utility.textu_mat import TextureMaterialOfObject 10 | from utility.rect_geo import RectangleGeometryOfObject 11 | from utility.sphere_geo import SphereGeometryOfObject 12 | from utility.movtRig import MovementRigObject 13 | 14 | 15 | # render a basic scene 16 | class Test(Home): 17 | def __init__(self, sizeOfScreen=None): 18 | super().__init__(sizeOfScreen) 19 | self.current = 0 20 | self.picture_list = [ 21 | ["images/space1.jpg", "images/space2.jpg"], 22 | ["images/sky.webp", "images/grass.jpg"], 23 | ["images/space6.png", "images/space7.png"], 24 | ["images/space5.png", "images/space4.jpg"], 25 | ["images/space8.png", "images/water2.jpeg"], 26 | ] 27 | self.rig = MovementRigObject() 28 | self.camera = CameraView(aspectRatio=800 / 600) 29 | self.scene = SceneOfObjectObject() 30 | self.renderer = ObjectRenderer() 31 | 32 | mixer.init() 33 | mixer.music.load('images/music.mp3') 34 | mixer.music.play() 35 | 36 | def init(self): 37 | print("Initializing program...") 38 | 39 | self.camera.setPosition([0, 0, 4]) 40 | self.rig.add(self.camera) 41 | self.scene.add(self.rig) 42 | self.rig.setPosition([0, 1, 4]) 43 | self.picture_changer() 44 | 45 | def picture_changer(self, idx=0): 46 | skyGeometry = SphereGeometryOfObject(radius=50) 47 | skyMaterial = TextureMaterialOfObject(TextureFile(self.picture_list[idx][0])) 48 | sky = MeshObjectObject(skyGeometry, skyMaterial) 49 | self.scene.add(sky) 50 | grassGeometry = RectangleGeometryOfObject(width=100, height=100) 51 | grassMaterial = TextureMaterialOfObject(TextureFile(self.picture_list[idx][1]), 52 | {"repeatUV": [50, 50]}) 53 | grass = MeshObjectObject(grassGeometry, grassMaterial) 54 | grass.rotateX(-3.14 / 2) 55 | self.scene.add(grass) 56 | 57 | def draw(self): 58 | self.rig.update(self.keyboard, self.delta_time) 59 | self.renderer.render_object(self.scene, self.camera) 60 | if self.keyboard.is_key_pressed("j") and self.current != 0: 61 | self.current = 0 62 | self.scene = SceneOfObjectObject() 63 | self.scene.add(self.rig) 64 | self.picture_changer(self.current) 65 | if self.keyboard.is_key_pressed("u") and self.current != 1: 66 | self.current = 1 67 | self.scene = SceneOfObjectObject() 68 | self.scene.add(self.rig) 69 | self.picture_changer(self.current) 70 | if self.keyboard.is_key_pressed("i") and self.current != 2: 71 | self.current = 2 72 | self.scene = SceneOfObjectObject() 73 | self.scene.add(self.rig) 74 | self.picture_changer(self.current) 75 | if self.keyboard.is_key_pressed("k") and self.current != 3: 76 | self.current = 3 77 | self.scene = SceneOfObjectObject() 78 | self.scene.add(self.rig) 79 | self.picture_changer(self.current) 80 | if self.keyboard.is_key_pressed("l") and self.current != 4: 81 | self.current = 4 82 | self.scene = SceneOfObjectObject() 83 | self.scene.add(self.rig) 84 | self.picture_changer(self.current) 85 | 86 | 87 | Test().run() 88 | -------------------------------------------------------------------------------- /utility/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__init__.py -------------------------------------------------------------------------------- /utility/__pycache__/__init__.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/__init__.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/box_geo.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/box_geo.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/bsc_mat.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/bsc_mat.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/ellips_geo.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/ellips_geo.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/geometry_file.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/geometry_file.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/mat.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/mat.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/movtRig.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/movtRig.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/para_geo.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/para_geo.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/rect_geo.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/rect_geo.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/sphere_geo.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/sphere_geo.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/surfce_mat.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/surfce_mat.cpython-39.pyc -------------------------------------------------------------------------------- /utility/__pycache__/textu_mat.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Endalebob/Space-Invaders/4b56b55ed012dee55cf6d77a167e08c27c09c8c1/utility/__pycache__/textu_mat.cpython-39.pyc -------------------------------------------------------------------------------- /utility/box_geo.py: -------------------------------------------------------------------------------- 1 | from utility.geometry_file import GeometryOfObject 2 | 3 | 4 | # by extending geometry of object class this class create box 5 | # shaped objects 6 | class BoxGeometryOfObjectOfObject(GeometryOfObject): 7 | def __init__(self, width=1, height=1, depth=1): 8 | super().__init__() 9 | P0 = [-width / 2, -height / 2, -depth / 2] 10 | P1 = [width / 2, -height / 2, -depth / 2] 11 | P2 = [-width / 2, height / 2, -depth / 2] 12 | P3 = [width / 2, height / 2, -depth / 2] 13 | P4 = [-width / 2, -height / 2, depth / 2] 14 | P5 = [width / 2, -height / 2, depth / 2] 15 | P6 = [-width / 2, height / 2, depth / 2] 16 | P7 = [width / 2, height / 2, depth / 2] 17 | # different face colors 18 | C1, C2 = [1, 0.5, 0.5], [0.5, 0, 0] 19 | C3, C4 = [0.5, 1, 0.5], [0, 0.5, 0] 20 | C5, C6 = [0.5, 0.5, 1], [0, 0, 0.5] 21 | # position of the cube 22 | position_data = [P5, P1, P3, P5, P3, P7, P0, P4, P6, P0, 23 | P6, P2, P6, P7, P3, P6, P3, P2, 24 | P0, P1, P5, P0, P5, P4, P4, P5, P7, 25 | P4, P7, P6, P1, P0, P2, P1, P2, P3] 26 | color_data = [C1] * 6 + [C2] * 6 + [C3] * 6 + [C4] * 6 + [C5] * 6 + [C6] * 6 27 | 28 | self.add_attribute("vec3", "vertexPosition", position_data) 29 | self.add_attribute("vec3", "vertexColor", color_data) 30 | self.count_vertices() 31 | # texture coordinates 32 | T0, T1, T2, T3 = [0, 0], [1, 0], [0, 1], [1, 1] 33 | uvData = [T0, T1, T3, T0, T3, T2] * 6 34 | self.add_attribute("vec2", "vertexUV", uvData) 35 | 36 | def check_error(self): 37 | status = '' 38 | while self.add_attribute: 39 | if self.attributes.keys() == self.attributes.values(): 40 | print("attribute error") 41 | status = "error" 42 | else: 43 | print("successfully created") 44 | status = "success" 45 | return status 46 | 47 | def get_status(self): 48 | # this function used to tell the status of object 49 | status = self.check_error() 50 | if status == "success": 51 | return "success status" 52 | else: 53 | return "failure status" 54 | 55 | def current_state(self): 56 | attribute = self.attributes.keys() 57 | values = self.attributes.values() 58 | len_attributes = self.count_vertices() 59 | current_state = {} 60 | current_state["attributes"] = attribute 61 | current_state["values"] = values 62 | current_state["attr_len"] = len_attributes 63 | return current_state 64 | 65 | -------------------------------------------------------------------------------- /utility/bsc_mat.py: -------------------------------------------------------------------------------- 1 | from utility.mat import MaterialOfObject 2 | from graphics.unifor_file import UniformProvider 3 | 4 | 5 | class BasicMaterialOfObjectObject(MaterialOfObject): 6 | def __init__(self): 7 | # this shader are used to render the vertexes 8 | vertex_shader_code = """ 9 | uniform mat4 projectionMatrix; 10 | uniform mat4 viewMatrix; 11 | uniform mat4 modelMatrix; 12 | in vec3 vertexPosition; 13 | in vec3 vertexColor; 14 | out vec3 color; 15 | void main() 16 | { 17 | gl_Position = projectionMatrix * 18 | viewMatrix * modelMatrix 19 | * vec4(vertexPosition, 1.0); 20 | color = vertexColor; 21 | } 22 | """ 23 | 24 | # this variable used to add color 25 | fragment_shader_code = """ 26 | uniform vec3 baseColor; 27 | uniform bool useVertexColors; 28 | in vec3 color; 29 | out vec4 fragColor; 30 | void main() 31 | { 32 | vec4 tempColor = vec4(baseColor, 1.0); 33 | if ( useVertexColors ) 34 | tempColor *= vec4(color, 1.0); 35 | fragColor = tempColor; 36 | } 37 | """ 38 | 39 | super().__init__(vertex_shader_code, fragment_shader_code) 40 | self.add_uniform("vec3", "baseColor", [1.0, 1.0, 1.0]) 41 | self.add_uniform("bool", "useVertexColors", False) 42 | self.locate_uniforms() 43 | -------------------------------------------------------------------------------- /utility/ellips_geo.py: -------------------------------------------------------------------------------- 1 | from utility.para_geo import ParametricGeometryOfObject 2 | from math import sin, cos, pi 3 | 4 | 5 | class EllipsoidGeometryOfObject(ParametricGeometryOfObject): 6 | def __init__(self, width=1, height=1, depth=1, 7 | radius_segments=32, height_segments=16): 8 | def S(u, v): 9 | return [width / 2 * sin(u) * cos(v), 10 | height / 2 * sin(v), 11 | depth / 2 * cos(u) * cos(v)] 12 | 13 | super().__init__(0, 2 * pi, radius_segments, 14 | -pi / 2, pi / 2, height_segments, S) 15 | 16 | def check_error(self): 17 | status = '' 18 | while self.add_attribute: 19 | if self.attributes.keys() != self.attributes.values(): 20 | print("attribute error") 21 | status = "error" 22 | else: 23 | print("successfully created") 24 | status = "success" 25 | return status 26 | 27 | def get_status(self): 28 | # this function used to tell the status of object 29 | status = self.check_error() 30 | 31 | if status == "success": 32 | return "success status" 33 | else: 34 | return "failure status" 35 | 36 | def current_state(self): 37 | 38 | attribute = self.attributes.keys() 39 | values = self.attributes.values() 40 | len_attributes = self.count_vertices() 41 | 42 | current_state = {} 43 | current_state["attributes"] = attribute 44 | current_state["values"] = values 45 | current_state["attr_len"] = len_attributes 46 | return current_state 47 | -------------------------------------------------------------------------------- /utility/geometry_file.py: -------------------------------------------------------------------------------- 1 | from graphics.attribute_provider import AttributeProvider 2 | 3 | 4 | # Geometry objects will store attribute data and the total number of 5 | # vertices. 6 | # this class used to store attribute data and number of vertices 7 | class GeometryOfObject(object): 8 | def __init__(self): 9 | 10 | # this dictionary used to store attributes 11 | self.attributes = {} 12 | # used to count vertex 13 | self.vertex_count = None 14 | 15 | def add_attribute(self, dataType, variableName, data): 16 | self.attributes[variableName] = AttributeProvider(dataType, data) 17 | 18 | def count_vertices(self): 19 | attrib = list(self.attributes.values())[0] 20 | self.vertex_count = len(attrib.data) 21 | -------------------------------------------------------------------------------- /utility/mat.py: -------------------------------------------------------------------------------- 1 | from graphics.openGlUtilClass import OpenGLUtilClass 2 | from graphics.unifor_file import UniformProvider 3 | from OpenGL.GL import * 4 | 5 | 6 | # store data related to rendering 7 | # shader program references, uniform data, opengl render settings 8 | class MaterialOfObject(object): 9 | def __init__(self, vertexShaderCode, fragmentShaderCode): 10 | self.program_ref = OpenGLUtilClass.initialize_program(vertexShaderCode, fragmentShaderCode) 11 | # this dictionary used to store uniform data 12 | self.uniforms = {"modelMatrix": UniformProvider("mat4", None), "viewMatrix": UniformProvider("mat4", None), 13 | "projectionMatrix": UniformProvider("mat4", None)} 14 | # this dictionary used to rendering 15 | self.settings = {"drawStyle": GL_TRIANGLES} 16 | self.attributes = {} 17 | 18 | def add_uniform(self, dataType, variableName, data): 19 | self.uniforms[variableName] = UniformProvider(dataType, data) 20 | 21 | def locate_uniforms(self): 22 | for variableName, uniformObject in self.uniforms.items(): 23 | uniformObject.locate_variable(self.program_ref, variableName) 24 | 25 | # this function implemented in other class 26 | def update_render_settings(self): 27 | pass 28 | 29 | # used to update uniforms 30 | def set_properties(self, properties): 31 | for name, data in properties.items(): 32 | 33 | # change or update uniform variables 34 | if name in self.uniforms.keys(): 35 | self.uniforms[name].data = data 36 | # update render settings 37 | elif name in self.settings.keys(): 38 | self.settings[name] = data 39 | # unknown property type 40 | else: 41 | raise Exception("Material has no property named: " + name) 42 | 43 | def check_errors(self): 44 | status = '' 45 | while self.attributes: 46 | if self.attributes.keys() != self.attributes.values(): 47 | print("attribute error") 48 | status = "error" 49 | else: 50 | print("successfully created") 51 | status = "success" 52 | return status 53 | 54 | def get_status_of_object(self): 55 | # this function used to tell the status of object 56 | status = self.check_errors() 57 | 58 | if status == "success": 59 | return "success status" 60 | else: 61 | return "failure status" 62 | 63 | def current_state_of_object(self): 64 | 65 | attribute = self.attributes.keys() 66 | values = self.attributes.values() 67 | len_attributes = self.attributes.items() 68 | 69 | current_state = {} 70 | current_state["attributes"] = attribute 71 | current_state["values"] = values 72 | current_state["attr_len"] = len_attributes 73 | return current_state 74 | 75 | -------------------------------------------------------------------------------- /utility/movtRig.py: -------------------------------------------------------------------------------- 1 | from graphics.ThreeDObject import Three_D_Object 2 | 3 | 4 | class MovementRigObject(Three_D_Object): 5 | def __init__(self, units_per_second=1, degrees_per_second=60): 6 | super().__init__() 7 | self.look_attachment = Three_D_Object() 8 | self.children = [self.look_attachment] 9 | self.look_attachment.parent = self 10 | self.units_per_seconds = units_per_second 11 | self.degrees_per_seconds = degrees_per_second 12 | # this is mapping of keys to move the scene in space 13 | # to move in forward directions 14 | self.KEY_MOVE_FORWARDS = "w" 15 | # to move in backward directions 16 | self.KEY_MOVE_BACKWARDS = "s" 17 | # to move in left directions 18 | self.KEY_MOVE_LEFT = "a" 19 | # to move in right directions 20 | self.KEY_MOVE_RIGHT = "d" 21 | # to move in up directions 22 | self.KEY_MOVE_UP = "r" 23 | # to move in down directions 24 | self.KEY_MOVE_DOWN = "f" 25 | # to turn in left directions 26 | self.KEY_TURN_LEFT = "q" 27 | # to turn in right directions 28 | self.KEY_TURN_RIGHT = "e" 29 | # to move in up directions 30 | self.KEY_LOOK_UP = "t" 31 | # to move in down directions 32 | self.KEY_LOOK_DOWN = "g" 33 | 34 | # this function update the position of key pressed 35 | def update(self, input_objects, delta_times): 36 | # when the key pressed by how much amount the scene must move 37 | moveAmount = self.units_per_seconds * delta_times 38 | # when the key pressed by how much amount the scene must rotate 39 | rotateAmount = self.degrees_per_seconds * (3.1415926 / 180) * delta_times 40 | if input_objects.is_key_pressed(self.KEY_MOVE_FORWARDS): 41 | self.translate(0, 0, -moveAmount) 42 | if input_objects.is_key_pressed(self.KEY_MOVE_BACKWARDS): 43 | self.translate(0, 0, moveAmount) 44 | if input_objects.is_key_pressed(self.KEY_MOVE_LEFT): 45 | self.translate(-moveAmount, 0, 0) 46 | if input_objects.is_key_pressed(self.KEY_MOVE_RIGHT): 47 | self.translate(moveAmount, 0, 0) 48 | if input_objects.is_key_pressed(self.KEY_MOVE_UP): 49 | self.translate(0, moveAmount, 0) 50 | if input_objects.is_key_pressed(self.KEY_MOVE_DOWN): 51 | self.translate(0, -moveAmount, 0) 52 | if input_objects.is_key_pressed(self.KEY_TURN_RIGHT): 53 | self.rotateY(-rotateAmount) 54 | if input_objects.is_key_pressed(self.KEY_TURN_LEFT): 55 | self.rotateY(rotateAmount) 56 | if input_objects.is_key_pressed(self.KEY_LOOK_UP): 57 | self.look_attachment.rotateX(rotateAmount) 58 | if input_objects.is_key_pressed(self.KEY_LOOK_DOWN): 59 | self.look_attachment.rotateX(-rotateAmount) 60 | 61 | # used to add the child in the node 62 | def add(self, child): 63 | self.look_attachment.add(child) 64 | 65 | # used to remove the child from the node 66 | def remove(self, child): 67 | self.look_attachment.remove(child) 68 | -------------------------------------------------------------------------------- /utility/para_geo.py: -------------------------------------------------------------------------------- 1 | from utility.geometry_file import GeometryOfObject 2 | 3 | 4 | class ParametricGeometryOfObject(GeometryOfObject): 5 | def __init__(self, uStart, uEnd, uResolution, 6 | vStart, vEnd, vResolution, surfaceFunction): 7 | super(ParametricGeometryOfObject, self).__init__() 8 | deltaU = (uEnd - uStart) / uResolution 9 | deltaV = (vEnd - vStart) / vResolution 10 | positions = [] 11 | for uIndex in range(uResolution + 1): 12 | vArray = [] 13 | for vIndex in range(vResolution + 1): 14 | u = uStart + uIndex * deltaU 15 | v = vStart + vIndex * deltaV 16 | vArray.append(surfaceFunction(u, v)) 17 | positions.append(vArray) 18 | uvs = [] 19 | uvData = [] 20 | for uIndex in range(uResolution + 1): 21 | vArray = [] 22 | for vIndex in range(vResolution + 1): 23 | u = uIndex / uResolution 24 | v = vIndex / vResolution 25 | vArray.append([u, v]) 26 | uvs.append(vArray) 27 | # store vertex data 28 | positionData = [] 29 | colorData = [] 30 | # default vertex colors 31 | C1, C2, C3 = [1, 0, 0], [0, 1, 0], [0, 0, 1] 32 | C4, C5, C6 = [0, 1, 1], [1, 0, 1], [1, 1, 0] 33 | # group vertex data into triangles 34 | # note: .copy() is necessary to avoid storing references 35 | for xIndex in range(uResolution): 36 | for yIndex in range(vResolution): 37 | # position data 38 | pA = positions[xIndex + 0][yIndex + 0] 39 | pB = positions[xIndex + 1][yIndex + 0] 40 | pD = positions[xIndex + 0][yIndex + 1] 41 | pC = positions[xIndex + 1][yIndex + 1] 42 | positionData += [pA.copy(), pB.copy(), 43 | pC.copy(), pA.copy(), pC.copy(), 44 | pD.copy()] 45 | # color data 46 | colorData += [C1, C2, C3, C4, C5, C6] 47 | # uv coordinates 48 | uvA = uvs[xIndex + 0][yIndex + 0] 49 | uvB = uvs[xIndex + 1][yIndex + 0] 50 | uvD = uvs[xIndex + 0][yIndex + 1] 51 | uvC = uvs[xIndex + 1][yIndex + 1] 52 | uvData += [uvA, uvB, uvC, uvA, uvC, uvD] 53 | self.add_attribute("vec3", "vertexPosition", 54 | positionData) 55 | self.add_attribute("vec3", "vertexColor", 56 | colorData) 57 | self.add_attribute("vec2", "vertexUV", uvData) 58 | self.count_vertices() 59 | 60 | def check_errors(self): 61 | status = '' 62 | while self.add_attribute: 63 | if self.attributes.keys() != self.attributes.values(): 64 | print("attribute error") 65 | status = "error" 66 | else: 67 | print("successfully created") 68 | status = "success" 69 | return status 70 | 71 | def get_status_of_object(self): 72 | # this function used to tell the status of object 73 | status = self.check_errors() 74 | 75 | if status == "success": 76 | return "success status" 77 | else: 78 | return "failure status" 79 | 80 | def current_state_of_object(self): 81 | 82 | attribute = self.attributes.keys() 83 | values = self.attributes.values() 84 | len_attributes = self.count_vertices() 85 | 86 | current_state = {} 87 | current_state["attributes"] = attribute 88 | current_state["values"] = values 89 | current_state["attr_len"] = len_attributes 90 | return current_state 91 | -------------------------------------------------------------------------------- /utility/rect_geo.py: -------------------------------------------------------------------------------- 1 | from utility.geometry_file import GeometryOfObject 2 | 3 | 4 | # by extending geometry of object class this class create rectangular 5 | # shaped objects 6 | class RectangleGeometryOfObject(GeometryOfObject): 7 | def __init__(self, width=1, height=1): 8 | super().__init__() 9 | P0 = [-width / 2, -height / 2, 0] 10 | P1 = [width / 2, -height / 2, 0] 11 | P2 = [-width / 2, height / 2, 0] 12 | P3 = [width / 2, height / 2, 0] 13 | # these are colors corresponding to the vertices 14 | C0, C1, C2, C3 = [1, 1, 1], [1, 0, 0], [0, 1, 0], [0, 0, 1] 15 | position_Data = [P0, P1, P3, P0, P3, P2] 16 | color_Data = [C0, C1, C3, C0, C3, C2] 17 | self.add_attribute("vec3", "vertexPosition", 18 | position_Data) 19 | self.add_attribute("vec3", "vertexColor", 20 | color_Data) 21 | # used to get the length of vertices 22 | self.count_vertices() 23 | # texture coordinates 24 | T0, T1, T2, T3 = [0, 0], [1, 0], [0, 1], [1, 1] 25 | uvData = [T0, T1, T3, T0, T3, T2] 26 | self.add_attribute("vec2", "vertexUV", uvData) 27 | 28 | def check_error(self): 29 | status = '' 30 | while self.add_attribute: 31 | if self.attributes.keys() == self.attributes.values(): 32 | print("attribute error") 33 | status = "error" 34 | else: 35 | print("successfully created") 36 | status = "success" 37 | return status 38 | 39 | def get_status(self): 40 | # this function used to tell the status of object 41 | status = self.check_error() 42 | if status == "success": 43 | return "success status" 44 | else: 45 | return "failure status" 46 | -------------------------------------------------------------------------------- /utility/sphere_geo.py: -------------------------------------------------------------------------------- 1 | from utility.ellips_geo import EllipsoidGeometryOfObject 2 | from math import sin, cos, pi 3 | 4 | 5 | class SphereGeometryOfObject(EllipsoidGeometryOfObject): 6 | def __init__(self, radius=1, 7 | radius_segments=32, height_segments=16): 8 | super().__init__(2 * radius, 2 * radius, 2 * radius, 9 | radius_segments, 10 | height_segments) 11 | 12 | def check_error(self): 13 | status = '' 14 | while self.add_attribute: 15 | if self.attributes.keys() != self.attributes.values(): 16 | print("attribute error") 17 | status = "error" 18 | else: 19 | print("successfully created") 20 | status = "success" 21 | return status 22 | 23 | def get_status_of_objects(self): 24 | # this function used to tell the status of object 25 | status = self.check_errors() 26 | 27 | if status == "success": 28 | return "success status" 29 | else: 30 | return "failure status" 31 | 32 | def current_state_of_objects(self): 33 | 34 | attribute = self.attributes.keys() 35 | values = self.attributes.values() 36 | len_attributes = self.count_vertices() 37 | 38 | current_state = {} 39 | current_state["attributes"] = attribute 40 | current_state["values"] = values 41 | current_state["attr_len"] = len_attributes 42 | return current_state 43 | 44 | -------------------------------------------------------------------------------- /utility/surfce_mat.py: -------------------------------------------------------------------------------- 1 | from utility.bsc_mat import BasicMaterialOfObjectObject 2 | from OpenGL.GL import * 3 | 4 | 5 | class SurfaceMaterialOfObject(BasicMaterialOfObjectObject): 6 | def __init__(self, properties=None): 7 | super().__init__() 8 | if properties is None: 9 | properties = {} 10 | self.settings["drawStyle"] = GL_TRIANGLES 11 | self.settings["doubleSide"] = False 12 | self.settings["wireframe"] = False 13 | self.settings["lineWidth"] = 1 14 | self.set_properties(properties) 15 | 16 | def update_render_settings(self): 17 | if self.settings["doubleSide"]: 18 | glDisable(GL_CULL_FACE) 19 | 20 | else: 21 | glEnable(GL_CULL_FACE) 22 | if self.settings["wireframe"]: 23 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) 24 | else: 25 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) 26 | glLineWidth(self.settings["lineWidth"]) 27 | 28 | def check_error(self): 29 | status = '' 30 | while self.attributes: 31 | if self.attributes.keys() != self.attributes.values(): 32 | print("attribute error") 33 | status = "error" 34 | else: 35 | print("successfully created") 36 | status = "success" 37 | return status 38 | 39 | def get_status(self): 40 | # this function used to tell the status of object 41 | status = self.check_error() 42 | 43 | if status == "success": 44 | return "success status" 45 | else: 46 | return "failure status" 47 | 48 | def current_state(self): 49 | 50 | attribute = self.attributes.keys() 51 | values = self.attributes.values() 52 | len_attributes = self.attributes.items() 53 | 54 | current_state = {} 55 | current_state["attributes"] = attribute 56 | current_state["values"] = values 57 | current_state["attr_len"] = len_attributes 58 | return current_state 59 | 60 | -------------------------------------------------------------------------------- /utility/textu_mat.py: -------------------------------------------------------------------------------- 1 | from utility.mat import MaterialOfObject 2 | from OpenGL.GL import * 3 | 4 | 5 | class TextureMaterialOfObject(MaterialOfObject): 6 | def __init__(self, texture, properties=None): 7 | if properties is None: 8 | properties = {} 9 | vertex_shader_code = """ 10 | uniform mat4 projectionMatrix; 11 | uniform mat4 viewMatrix; 12 | uniform mat4 modelMatrix; 13 | in vec3 vertexPosition; 14 | in vec2 vertexUV; 15 | uniform vec2 repeatUV; 16 | uniform vec2 offsetUV; 17 | out vec2 UV; 18 | void main() 19 | { 20 | gl_Position = projectionMatrix * 21 | viewMatrix * 22 | modelMatrix * vec4(vertexPosition, 23 | 1.0); 24 | UV = vertexUV * repeatUV + offsetUV; 25 | } 26 | """ 27 | fragment_shader_code = """ 28 | uniform vec3 baseColor; 29 | uniform sampler2D texture; 30 | in vec2 UV; 31 | out vec4 fragColor; 32 | void main() 33 | { 34 | vec4 color = vec4(baseColor, 1.0) * 35 | texture2D(texture, UV); 36 | if (color.a < 0.10) 37 | discard; 38 | fragColor = color; 39 | } 40 | """ 41 | super().__init__(vertex_shader_code, 42 | fragment_shader_code) 43 | self.add_uniform("vec3", "baseColor", [1.0, 44 | 1.0, 1.0]) 45 | self.add_uniform("sampler2D", "texture", 46 | [texture.textureRef, 1]) 47 | self.add_uniform("vec2", "repeatUV", [1.0, 48 | 1.0]) 49 | self.add_uniform("vec2", "offsetUV", [0.0, 50 | 0.0]) 51 | self.locate_uniforms() 52 | # render both sides? 53 | self.settings["doubleSide"] = True 54 | # render triangles as wireframe? 55 | self.settings["wireframe"] = False 56 | # line thickness for wireframe rendering 57 | self.settings["lineWidth"] = 1 58 | self.set_properties(properties) 59 | 60 | def update_render_settings(self): 61 | if self.settings["doubleSide"]: 62 | glDisable(GL_CULL_FACE) 63 | else: 64 | glEnable(GL_CULL_FACE) 65 | if self.settings["wireframe"]: 66 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) 67 | else: 68 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) 69 | glLineWidth(self.settings["lineWidth"]) 70 | 71 | def check_error(self): 72 | status = '' 73 | while self.attributes: 74 | if self.attributes.keys() != self.attributes.values(): 75 | print("attribute error") 76 | status = "error" 77 | else: 78 | print("successfully created") 79 | status = "success" 80 | return status 81 | 82 | def get_status(self): 83 | # this function used to tell the status of object 84 | status = self.check_error() 85 | 86 | if status == "success": 87 | return "success status" 88 | else: 89 | return "failure status" 90 | 91 | def current_state(self): 92 | 93 | attribute = self.attributes.keys() 94 | values = self.attributes.values() 95 | len_attributes = self.attributes.items() 96 | 97 | current_state = {} 98 | current_state["attributes"] = attribute 99 | current_state["values"] = values 100 | current_state["attr_len"] = len_attributes 101 | return current_state 102 | 103 | --------------------------------------------------------------------------------