basilisk-engine 0.1.17__py3-none-any.whl → 0.1.19__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (87) hide show
  1. basilisk/__init__.py +15 -15
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +224 -224
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +2 -2
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +179 -179
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +206 -206
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +72 -72
  25. basilisk/generic/input_validation.py +66 -66
  26. basilisk/generic/math.py +6 -6
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/mouse.py +61 -61
  34. basilisk/input/path.py +14 -14
  35. basilisk/mesh/cube.py +33 -33
  36. basilisk/mesh/mesh.py +230 -230
  37. basilisk/mesh/mesh_from_data.py +130 -130
  38. basilisk/mesh/model.py +271 -271
  39. basilisk/mesh/narrow_aabb.py +89 -89
  40. basilisk/mesh/narrow_bvh.py +91 -91
  41. basilisk/mesh/narrow_primative.py +23 -23
  42. basilisk/nodes/helper.py +28 -28
  43. basilisk/nodes/node.py +684 -684
  44. basilisk/nodes/node_handler.py +96 -95
  45. basilisk/particles/particle_handler.py +64 -64
  46. basilisk/particles/particle_renderer.py +92 -92
  47. basilisk/physics/impulse.py +112 -112
  48. basilisk/physics/physics_body.py +43 -43
  49. basilisk/physics/physics_engine.py +35 -35
  50. basilisk/render/batch.py +105 -105
  51. basilisk/render/camera.py +221 -211
  52. basilisk/render/chunk.py +106 -106
  53. basilisk/render/chunk_handler.py +165 -165
  54. basilisk/render/frame.py +101 -101
  55. basilisk/render/framebuffer.py +130 -130
  56. basilisk/render/image.py +87 -87
  57. basilisk/render/image_handler.py +122 -122
  58. basilisk/render/light.py +96 -96
  59. basilisk/render/light_handler.py +58 -58
  60. basilisk/render/material.py +219 -219
  61. basilisk/render/material_handler.py +135 -135
  62. basilisk/render/post_process.py +132 -132
  63. basilisk/render/shader.py +110 -110
  64. basilisk/render/shader_handler.py +80 -80
  65. basilisk/render/sky.py +120 -120
  66. basilisk/scene.py +276 -276
  67. basilisk/shaders/batch.frag +276 -276
  68. basilisk/shaders/batch.vert +115 -115
  69. basilisk/shaders/crt.frag +31 -31
  70. basilisk/shaders/draw.frag +21 -21
  71. basilisk/shaders/draw.vert +21 -21
  72. basilisk/shaders/filter.frag +22 -22
  73. basilisk/shaders/frame.frag +12 -12
  74. basilisk/shaders/frame.vert +13 -13
  75. basilisk/shaders/geometry.frag +8 -8
  76. basilisk/shaders/geometry.vert +41 -41
  77. basilisk/shaders/normal.frag +59 -59
  78. basilisk/shaders/normal.vert +96 -96
  79. basilisk/shaders/particle.frag +71 -71
  80. basilisk/shaders/particle.vert +84 -84
  81. basilisk/shaders/sky.frag +9 -9
  82. basilisk/shaders/sky.vert +13 -13
  83. {basilisk_engine-0.1.17.dist-info → basilisk_engine-0.1.19.dist-info}/METADATA +45 -38
  84. basilisk_engine-0.1.19.dist-info/RECORD +103 -0
  85. {basilisk_engine-0.1.17.dist-info → basilisk_engine-0.1.19.dist-info}/WHEEL +1 -1
  86. basilisk_engine-0.1.17.dist-info/RECORD +0 -103
  87. {basilisk_engine-0.1.17.dist-info → basilisk_engine-0.1.19.dist-info}/top_level.txt +0 -0
basilisk/render/shader.py CHANGED
@@ -1,111 +1,111 @@
1
- import moderngl as mgl
2
- import random
3
-
4
- attribute_mappings = {
5
- 'in_position' : [0, 1, 2],
6
- 'in_uv' : [3, 4],
7
- 'in_normal' : [5, 6, 7],
8
- 'in_tangent' : [8, 9, 10],
9
- 'in_bitangent' : [11, 12, 13],
10
- 'obj_position' : [14, 15, 16],
11
- 'obj_rotation' : [17, 18, 19, 20],
12
- 'obj_scale' : [21, 22, 23],
13
- 'obj_material' : [24],
14
- }
15
-
16
-
17
- class Shader:
18
- program: mgl.Program=None
19
- """Shader program for the vertex and fragment shader"""
20
- vertex_shader: str
21
- """String representation of the vertex shader"""
22
- fragment_shader: str
23
- """String representation of the vertex shader"""
24
- uniforms: list[str]=[]
25
- """List containg the names of all uniforms in the shader"""
26
- attribute_indices: list[int]
27
- """List of indices that map all possible shader attributes to the ones used byu the shader"""
28
- fmt: str
29
- """String representation of the format for building vaos"""
30
- attributes: list[str]
31
- """List representation of the attributes for building vaos"""
32
-
33
- def __init__(self, engine, vert: str=None, frag: str=None) -> None:
34
- """
35
- Basilisk shader object. Contains shader program and shader attrbibute/uniform information
36
- Args:
37
- vert: str=None
38
- Path to the vertex shader. Defaults to internal if none is given
39
- frag: str=None
40
- Path to the fragment shader. Defaults to internal if none is given
41
- """
42
-
43
- self.engine = engine
44
- self.ctx = engine.ctx
45
-
46
- # Default class attributes values
47
- self.uniforms = []
48
- self.attribute_indices = []
49
- self.fmt = ''
50
- self.attributes = []
51
-
52
- # Default vertex and fragment shaders
53
- if vert == None: vert = self.engine.root + '/shaders/batch.vert'
54
- if frag == None: frag = self.engine.root + '/shaders/batch.frag'
55
-
56
- # Read the shaders
57
- with open(vert) as file:
58
- self.vertex_shader = file.read()
59
- with open(frag) as file:
60
- self.fragment_shader = file.read()
61
-
62
- # Hash value for references
63
- if vert == None and frag == None:
64
- self.hash = hash((self.vertex_shader, self.fragment_shader, 'default'))
65
- else:
66
- self.hash = hash((self.vertex_shader, self.fragment_shader))
67
-
68
- # Create a string of all lines in both shaders
69
- lines = f'{self.vertex_shader}\n{self.fragment_shader}'.split('\n')
70
-
71
- # Parse through shader to find uniforms and attributes
72
- for line in lines:
73
- tokens = line.strip().split(' ')
74
-
75
- # Add uniforms
76
- if tokens[0] == 'uniform' and len(tokens) > 2:
77
- self.uniforms.append(tokens[-1][:-1])
78
-
79
- # Add attributes
80
- if tokens[0] == 'layout' and len(tokens) > 2 and 'in' in line:
81
- self.attributes.append(tokens[-1][:-1])
82
-
83
- if tokens[-1][:-1] not in attribute_mappings: continue
84
- indices = attribute_mappings[tokens[-1][:-1]]
85
- self.attribute_indices.extend(indices)
86
- self.fmt += f'{len(indices)}f '
87
-
88
- # Create a program with shaders
89
- self.program = self.ctx.program(vertex_shader=self.vertex_shader, fragment_shader=self.fragment_shader)
90
-
91
- def set_main(self):
92
- """
93
- Selects a shader for use
94
- """
95
-
96
- self.engine.scene.shader_handler.add(self)
97
- # self.engine.scene.node_handler.chunk_handler.update_all()
98
- self.engine.scene.node_handler.chunk_handler.swap_default(self)
99
-
100
- def write(self, name: str, value) -> None:
101
- """
102
- Writes a uniform to the shader program
103
- """
104
-
105
- self.program[name].write(value)
106
-
107
- def __del__(self) -> int:
108
- if self.program: self.program.release()
109
-
110
- def __hash__(self) -> int:
1
+ import moderngl as mgl
2
+ import random
3
+
4
+ attribute_mappings = {
5
+ 'in_position' : [0, 1, 2],
6
+ 'in_uv' : [3, 4],
7
+ 'in_normal' : [5, 6, 7],
8
+ 'in_tangent' : [8, 9, 10],
9
+ 'in_bitangent' : [11, 12, 13],
10
+ 'obj_position' : [14, 15, 16],
11
+ 'obj_rotation' : [17, 18, 19, 20],
12
+ 'obj_scale' : [21, 22, 23],
13
+ 'obj_material' : [24],
14
+ }
15
+
16
+
17
+ class Shader:
18
+ program: mgl.Program=None
19
+ """Shader program for the vertex and fragment shader"""
20
+ vertex_shader: str
21
+ """String representation of the vertex shader"""
22
+ fragment_shader: str
23
+ """String representation of the vertex shader"""
24
+ uniforms: list[str]=[]
25
+ """List containg the names of all uniforms in the shader"""
26
+ attribute_indices: list[int]
27
+ """List of indices that map all possible shader attributes to the ones used byu the shader"""
28
+ fmt: str
29
+ """String representation of the format for building vaos"""
30
+ attributes: list[str]
31
+ """List representation of the attributes for building vaos"""
32
+
33
+ def __init__(self, engine, vert: str=None, frag: str=None) -> None:
34
+ """
35
+ Basilisk shader object. Contains shader program and shader attrbibute/uniform information
36
+ Args:
37
+ vert: str=None
38
+ Path to the vertex shader. Defaults to internal if none is given
39
+ frag: str=None
40
+ Path to the fragment shader. Defaults to internal if none is given
41
+ """
42
+
43
+ self.engine = engine
44
+ self.ctx = engine.ctx
45
+
46
+ # Default class attributes values
47
+ self.uniforms = []
48
+ self.attribute_indices = []
49
+ self.fmt = ''
50
+ self.attributes = []
51
+
52
+ # Default vertex and fragment shaders
53
+ if vert == None: vert = self.engine.root + '/shaders/batch.vert'
54
+ if frag == None: frag = self.engine.root + '/shaders/batch.frag'
55
+
56
+ # Read the shaders
57
+ with open(vert) as file:
58
+ self.vertex_shader = file.read()
59
+ with open(frag) as file:
60
+ self.fragment_shader = file.read()
61
+
62
+ # Hash value for references
63
+ if vert == None and frag == None:
64
+ self.hash = hash((self.vertex_shader, self.fragment_shader, 'default'))
65
+ else:
66
+ self.hash = hash((self.vertex_shader, self.fragment_shader))
67
+
68
+ # Create a string of all lines in both shaders
69
+ lines = f'{self.vertex_shader}\n{self.fragment_shader}'.split('\n')
70
+
71
+ # Parse through shader to find uniforms and attributes
72
+ for line in lines:
73
+ tokens = line.strip().split(' ')
74
+
75
+ # Add uniforms
76
+ if tokens[0] == 'uniform' and len(tokens) > 2:
77
+ self.uniforms.append(tokens[-1][:-1])
78
+
79
+ # Add attributes
80
+ if tokens[0] == 'layout' and len(tokens) > 2 and 'in' in line:
81
+ self.attributes.append(tokens[-1][:-1])
82
+
83
+ if tokens[-1][:-1] not in attribute_mappings: continue
84
+ indices = attribute_mappings[tokens[-1][:-1]]
85
+ self.attribute_indices.extend(indices)
86
+ self.fmt += f'{len(indices)}f '
87
+
88
+ # Create a program with shaders
89
+ self.program = self.ctx.program(vertex_shader=self.vertex_shader, fragment_shader=self.fragment_shader)
90
+
91
+ def set_main(self):
92
+ """
93
+ Selects a shader for use
94
+ """
95
+
96
+ self.engine.scene.shader_handler.add(self)
97
+ # self.engine.scene.node_handler.chunk_handler.update_all()
98
+ self.engine.scene.node_handler.chunk_handler.swap_default(self)
99
+
100
+ def write(self, name: str, value) -> None:
101
+ """
102
+ Writes a uniform to the shader program
103
+ """
104
+
105
+ self.program[name].write(value)
106
+
107
+ def __del__(self) -> int:
108
+ if self.program: self.program.release()
109
+
110
+ def __hash__(self) -> int:
111
111
  return self.hash
@@ -1,81 +1,81 @@
1
- import moderngl as mgl
2
- import glm
3
- from .shader import Shader
4
-
5
-
6
- class ShaderHandler:
7
- engine: ...
8
- """Back reference to the parent engine"""
9
- scene: ...
10
- """Back reference to the parent scene"""
11
- ctx: mgl.Context
12
- """Back reference to the parent context"""
13
- shaders: set
14
- """Dictionary containing all the shaders"""
15
- uniform_values: dict = {}
16
- """Dictionary containing uniform values"""
17
-
18
- def __init__(self, scene) -> None:
19
- """
20
- Handles all the shader programs in a basilisk scene
21
- """
22
-
23
- # Back references
24
- self.scene = scene
25
- self.engine = scene.engine
26
- self.ctx = scene.engine.ctx
27
-
28
- # Initalize dictionaries
29
- self.shaders = set()
30
- self.add(self.engine.shader)
31
-
32
- def add(self, shader: Shader) -> None:
33
- """
34
- Creates a shader program from a file name.
35
- Parses through shaders to identify uniforms and save for writting
36
- """
37
-
38
-
39
- if not shader: return None
40
- if shader in self.shaders: return shader
41
-
42
- self.shaders.add(shader)
43
-
44
- if self.scene.material_handler:
45
- self.scene.light_handler.write()
46
- self.scene.material_handler.write()
47
- self.scene.material_handler.image_handler.write()
48
-
49
- return shader
50
-
51
- def get_uniforms_values(self) -> None:
52
- """
53
- Gets uniforms from various parts of the scene.
54
- These values are stored and used in write_all_uniforms and update_uniforms.
55
- This is called by write_all_uniforms and update_uniforms, so there is no need to call this manually.
56
- """
57
-
58
- self.uniform_values = {
59
- 'projectionMatrix' : self.scene.camera.m_proj,
60
- 'viewMatrix' : self.scene.camera.m_view,
61
- 'cameraPosition' : self.scene.camera.position,
62
- 'viewportDimensions' : glm.vec2(self.engine.win_size),
63
- }
64
-
65
- def write(self) -> None:
66
- """
67
- Writes all of the uniforms in every shader program.
68
- """
69
-
70
- self.get_uniforms_values()
71
- for uniform in self.uniform_values:
72
- for shader in self.shaders:
73
- if not uniform in shader.uniforms: continue # Does not write uniforms not in the shader
74
- shader.write(uniform, self.uniform_values[uniform])
75
-
76
- def release(self) -> None:
77
- """
78
- Releases all shader programs in handler
79
- """
80
-
1
+ import moderngl as mgl
2
+ import glm
3
+ from .shader import Shader
4
+
5
+
6
+ class ShaderHandler:
7
+ engine: ...
8
+ """Back reference to the parent engine"""
9
+ scene: ...
10
+ """Back reference to the parent scene"""
11
+ ctx: mgl.Context
12
+ """Back reference to the parent context"""
13
+ shaders: set
14
+ """Dictionary containing all the shaders"""
15
+ uniform_values: dict = {}
16
+ """Dictionary containing uniform values"""
17
+
18
+ def __init__(self, scene) -> None:
19
+ """
20
+ Handles all the shader programs in a basilisk scene
21
+ """
22
+
23
+ # Back references
24
+ self.scene = scene
25
+ self.engine = scene.engine
26
+ self.ctx = scene.engine.ctx
27
+
28
+ # Initalize dictionaries
29
+ self.shaders = set()
30
+ self.add(self.engine.shader)
31
+
32
+ def add(self, shader: Shader) -> None:
33
+ """
34
+ Creates a shader program from a file name.
35
+ Parses through shaders to identify uniforms and save for writting
36
+ """
37
+
38
+
39
+ if not shader: return None
40
+ if shader in self.shaders: return shader
41
+
42
+ self.shaders.add(shader)
43
+
44
+ if self.scene.material_handler:
45
+ self.scene.light_handler.write()
46
+ self.scene.material_handler.write()
47
+ self.scene.material_handler.image_handler.write()
48
+
49
+ return shader
50
+
51
+ def get_uniforms_values(self) -> None:
52
+ """
53
+ Gets uniforms from various parts of the scene.
54
+ These values are stored and used in write_all_uniforms and update_uniforms.
55
+ This is called by write_all_uniforms and update_uniforms, so there is no need to call this manually.
56
+ """
57
+
58
+ self.uniform_values = {
59
+ 'projectionMatrix' : self.scene.camera.m_proj,
60
+ 'viewMatrix' : self.scene.camera.m_view,
61
+ 'cameraPosition' : self.scene.camera.position,
62
+ 'viewportDimensions' : glm.vec2(self.engine.win_size),
63
+ }
64
+
65
+ def write(self) -> None:
66
+ """
67
+ Writes all of the uniforms in every shader program.
68
+ """
69
+
70
+ self.get_uniforms_values()
71
+ for uniform in self.uniform_values:
72
+ for shader in self.shaders:
73
+ if not uniform in shader.uniforms: continue # Does not write uniforms not in the shader
74
+ shader.write(uniform, self.uniform_values[uniform])
75
+
76
+ def release(self) -> None:
77
+ """
78
+ Releases all shader programs in handler
79
+ """
80
+
81
81
  [shader.__del__() for shader in self.shaders]
basilisk/render/sky.py CHANGED
@@ -1,121 +1,121 @@
1
- import numpy as np
2
- from PIL import Image as PIL_Image
3
- from .shader import Shader
4
-
5
- class Sky:
6
- texture_cube=None
7
- vbo = None
8
- vao = None
9
- def __init__(self, engine, sky_texture: str | list=None):
10
- """
11
- Handler for all skybox rendering
12
- """
13
-
14
- self.scene = engine.scene
15
- self.ctx = engine.ctx
16
-
17
- if not sky_texture: sky_texture = engine.root + '/bsk_assets/skybox.png'
18
-
19
- self.set_renderer()
20
- self.set_texture(sky_texture)
21
-
22
- def render(self):
23
- """
24
- Render the skybox to current render destination
25
- """
26
- self.vao.render()
27
-
28
- def write(self):
29
- # Write the texture cube to the sky shader
30
- self.shader.program['skyboxTexture'] = 8
31
- self.texture_cube.use(location = 8)
32
-
33
- shader = self.scene.engine.shader
34
- if 'skyboxTexture' not in shader.uniforms: return
35
- shader.program['skyboxTexture'] = 8
36
- self.texture_cube.use(location = 8)
37
-
38
-
39
- def set_texture(self, skybox_images: list):
40
- """
41
- Sets the skybox texture. Can either be set with 6 images for each skybox side or a single skybox image.
42
- List items should be string paths.
43
- The six images should be should be in the following order: right, left, top, bottom, front, back
44
- """
45
-
46
- # Release any existing memory
47
- if self.texture_cube: self.texture_cube.release()
48
-
49
- # Function-Scoped data
50
- images = None
51
-
52
- # Given a sinlge image for the skybox
53
- if isinstance(skybox_images, str) or ((isinstance(skybox_images, list) or isinstance(skybox_images, tuple)) and len(skybox_images) == 1):
54
- path = skybox_images if isinstance(skybox_images, str) else skybox_images[0]
55
-
56
- # Verify the path type
57
- if not isinstance(path, str): raise ValueError(f"Skybox: Invalid image path type {type(path)}")
58
-
59
- image = PIL_Image.open(path).convert('RGB')
60
- width, height = image.size[0] // 4, image.size[1] // 3
61
-
62
- images = [image.crop((x * width, y * height, (x + 1) * width, (y + 1) * height)) for x, y in [(2, 1), (0, 1), (1, 0), (1, 2), (1, 1), (3, 1)]]
63
-
64
- # Given a list of images for the skybox
65
- elif isinstance(skybox_images, list) or isinstance(skybox_images, tuple):
66
- # Verify the correct number of images was given
67
- if len(skybox_images) != 6: raise ValueError("Skybox: Invalid number of images for skybox. Expected 1 or 6")
68
- # Verify the all image path types
69
- if not all([isinstance(path, str) for path in skybox_images]): raise ValueError(f"Skybox: Invalid image path type {type(path)}")
70
-
71
- images = [PIL_Image.open(path).convert('RGB') for path in skybox_images]
72
-
73
- else:
74
- raise ValueError(f"Skybox: Invalid skybox type {type(skybox_images)}. Expected list of string paths or a single image")
75
-
76
- # Create a texture map from the images
77
- size = min(images[0].size)
78
- size = (size, size)
79
- images = [img.resize(size) for img in images]
80
- images = [img.tobytes() for img in images]
81
- self.texture_cube = self.ctx.texture_cube(size=size, components=3, data=None)
82
- for i, data in enumerate(images):
83
- self.texture_cube.write(face=i, data=data)
84
-
85
- def set_renderer(self):
86
- """
87
-
88
- """
89
-
90
- # Release any existing memory
91
- if self.vbo: self.vbo.release()
92
- if self.vao: self.vao.release()
93
-
94
- # Get the cube vertex data
95
- vertices = [(-1, -1, 1), ( 1, -1, 1), (1, 1, 1), (-1, 1, 1),
96
- (-1, 1, -1), (-1, -1, -1), (1, -1, -1), ( 1, 1, -1)]
97
-
98
- indices = [(0, 2, 3), (0, 1, 2),
99
- (1, 7, 2), (1, 6, 7),
100
- (6, 5, 4), (4, 7, 6),
101
- (3, 4, 5), (3, 5, 0),
102
- (3, 7, 4), (3, 2, 7),
103
- (0, 6, 1), (0, 5, 6)]
104
-
105
- vertex_data = np.array([vertices[ind] for trigangle in indices for ind in trigangle], dtype='f4')
106
- vertex_data = np.flip(vertex_data, 1).copy(order='C')
107
-
108
- # Create a renderable vao
109
- self.vbo = self.ctx.buffer(vertex_data)
110
- root = self.scene.engine.root
111
- self.shader = self.scene.shader_handler.add(Shader(self.scene.engine, root + '/shaders/sky.vert', root + '/shaders/sky.frag'))
112
- self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f', 'in_position')], skip_errors=True)
113
-
114
- def __del__(self):
115
- """
116
- Releases all data used by the skybox
117
- """
118
-
119
- if self.texture_cube: self.texture_cube.release()
120
- if self.vbo: self.vbo.release()
1
+ import numpy as np
2
+ from PIL import Image as PIL_Image
3
+ from .shader import Shader
4
+
5
+ class Sky:
6
+ texture_cube=None
7
+ vbo = None
8
+ vao = None
9
+ def __init__(self, engine, sky_texture: str | list=None):
10
+ """
11
+ Handler for all skybox rendering
12
+ """
13
+
14
+ self.scene = engine.scene
15
+ self.ctx = engine.ctx
16
+
17
+ if not sky_texture: sky_texture = engine.root + '/bsk_assets/skybox.png'
18
+
19
+ self.set_renderer()
20
+ self.set_texture(sky_texture)
21
+
22
+ def render(self):
23
+ """
24
+ Render the skybox to current render destination
25
+ """
26
+ self.vao.render()
27
+
28
+ def write(self):
29
+ # Write the texture cube to the sky shader
30
+ self.shader.program['skyboxTexture'] = 8
31
+ self.texture_cube.use(location = 8)
32
+
33
+ shader = self.scene.engine.shader
34
+ if 'skyboxTexture' not in shader.uniforms: return
35
+ shader.program['skyboxTexture'] = 8
36
+ self.texture_cube.use(location = 8)
37
+
38
+
39
+ def set_texture(self, skybox_images: list):
40
+ """
41
+ Sets the skybox texture. Can either be set with 6 images for each skybox side or a single skybox image.
42
+ List items should be string paths.
43
+ The six images should be should be in the following order: right, left, top, bottom, front, back
44
+ """
45
+
46
+ # Release any existing memory
47
+ if self.texture_cube: self.texture_cube.release()
48
+
49
+ # Function-Scoped data
50
+ images = None
51
+
52
+ # Given a sinlge image for the skybox
53
+ if isinstance(skybox_images, str) or ((isinstance(skybox_images, list) or isinstance(skybox_images, tuple)) and len(skybox_images) == 1):
54
+ path = skybox_images if isinstance(skybox_images, str) else skybox_images[0]
55
+
56
+ # Verify the path type
57
+ if not isinstance(path, str): raise ValueError(f"Skybox: Invalid image path type {type(path)}")
58
+
59
+ image = PIL_Image.open(path).convert('RGB')
60
+ width, height = image.size[0] // 4, image.size[1] // 3
61
+
62
+ images = [image.crop((x * width, y * height, (x + 1) * width, (y + 1) * height)) for x, y in [(2, 1), (0, 1), (1, 0), (1, 2), (1, 1), (3, 1)]]
63
+
64
+ # Given a list of images for the skybox
65
+ elif isinstance(skybox_images, list) or isinstance(skybox_images, tuple):
66
+ # Verify the correct number of images was given
67
+ if len(skybox_images) != 6: raise ValueError("Skybox: Invalid number of images for skybox. Expected 1 or 6")
68
+ # Verify the all image path types
69
+ if not all([isinstance(path, str) for path in skybox_images]): raise ValueError(f"Skybox: Invalid image path type {type(path)}")
70
+
71
+ images = [PIL_Image.open(path).convert('RGB') for path in skybox_images]
72
+
73
+ else:
74
+ raise ValueError(f"Skybox: Invalid skybox type {type(skybox_images)}. Expected list of string paths or a single image")
75
+
76
+ # Create a texture map from the images
77
+ size = min(images[0].size)
78
+ size = (size, size)
79
+ images = [img.resize(size) for img in images]
80
+ images = [img.tobytes() for img in images]
81
+ self.texture_cube = self.ctx.texture_cube(size=size, components=3, data=None)
82
+ for i, data in enumerate(images):
83
+ self.texture_cube.write(face=i, data=data)
84
+
85
+ def set_renderer(self):
86
+ """
87
+
88
+ """
89
+
90
+ # Release any existing memory
91
+ if self.vbo: self.vbo.release()
92
+ if self.vao: self.vao.release()
93
+
94
+ # Get the cube vertex data
95
+ vertices = [(-1, -1, 1), ( 1, -1, 1), (1, 1, 1), (-1, 1, 1),
96
+ (-1, 1, -1), (-1, -1, -1), (1, -1, -1), ( 1, 1, -1)]
97
+
98
+ indices = [(0, 2, 3), (0, 1, 2),
99
+ (1, 7, 2), (1, 6, 7),
100
+ (6, 5, 4), (4, 7, 6),
101
+ (3, 4, 5), (3, 5, 0),
102
+ (3, 7, 4), (3, 2, 7),
103
+ (0, 6, 1), (0, 5, 6)]
104
+
105
+ vertex_data = np.array([vertices[ind] for trigangle in indices for ind in trigangle], dtype='f4')
106
+ vertex_data = np.flip(vertex_data, 1).copy(order='C')
107
+
108
+ # Create a renderable vao
109
+ self.vbo = self.ctx.buffer(vertex_data)
110
+ root = self.scene.engine.root
111
+ self.shader = self.scene.shader_handler.add(Shader(self.scene.engine, root + '/shaders/sky.vert', root + '/shaders/sky.frag'))
112
+ self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f', 'in_position')], skip_errors=True)
113
+
114
+ def __del__(self):
115
+ """
116
+ Releases all data used by the skybox
117
+ """
118
+
119
+ if self.texture_cube: self.texture_cube.release()
120
+ if self.vbo: self.vbo.release()
121
121
  if self.vao: self.vao.release()