├── .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 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
--------------------------------------------------------------------------------