basilisk-engine 0.1.38__py3-none-any.whl → 0.1.40__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.
- basilisk/__init__.py +26 -26
- basilisk/audio/sound.py +27 -27
- basilisk/bsk_assets/cube.obj +48 -48
- basilisk/collisions/broad/broad_aabb.py +102 -102
- basilisk/collisions/broad/broad_bvh.py +137 -137
- basilisk/collisions/collider.py +95 -95
- basilisk/collisions/collider_handler.py +226 -226
- basilisk/collisions/narrow/contact_manifold.py +95 -95
- basilisk/collisions/narrow/dataclasses.py +34 -34
- basilisk/collisions/narrow/deprecated.py +46 -46
- basilisk/collisions/narrow/epa.py +91 -91
- basilisk/collisions/narrow/gjk.py +66 -66
- basilisk/collisions/narrow/graham_scan.py +24 -24
- basilisk/collisions/narrow/helper.py +29 -29
- basilisk/collisions/narrow/line_intersections.py +106 -106
- basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
- basilisk/config.py +53 -53
- basilisk/draw/draw.py +100 -100
- basilisk/draw/draw_handler.py +178 -178
- basilisk/draw/font_renderer.py +28 -28
- basilisk/engine.py +165 -165
- basilisk/generic/abstract_bvh.py +15 -15
- basilisk/generic/abstract_custom.py +133 -133
- basilisk/generic/collisions.py +70 -70
- basilisk/generic/input_validation.py +82 -82
- basilisk/generic/math.py +18 -7
- basilisk/generic/matrices.py +35 -35
- basilisk/generic/meshes.py +72 -72
- basilisk/generic/quat.py +142 -142
- basilisk/generic/quat_methods.py +7 -7
- basilisk/generic/raycast_result.py +26 -26
- basilisk/generic/vec3.py +143 -143
- basilisk/input/__init__.py +0 -0
- basilisk/input/mouse.py +62 -0
- basilisk/input/path.py +14 -0
- basilisk/input_output/IO_handler.py +91 -91
- basilisk/input_output/clock.py +49 -49
- basilisk/input_output/keys.py +43 -43
- basilisk/input_output/mouse.py +90 -90
- basilisk/input_output/path.py +14 -14
- basilisk/mesh/cube.py +33 -33
- basilisk/mesh/mesh.py +233 -233
- basilisk/mesh/mesh_from_data.py +150 -150
- basilisk/mesh/model.py +271 -271
- basilisk/mesh/narrow_aabb.py +89 -89
- basilisk/mesh/narrow_bvh.py +91 -91
- basilisk/mesh/narrow_primative.py +23 -23
- basilisk/nodes/helper.py +28 -28
- basilisk/nodes/node.py +709 -704
- basilisk/nodes/node_handler.py +97 -97
- basilisk/particles/particle_handler.py +64 -64
- basilisk/particles/particle_renderer.py +93 -93
- basilisk/physics/impulse.py +112 -112
- basilisk/physics/physics_body.py +43 -43
- basilisk/physics/physics_engine.py +35 -35
- basilisk/render/batch.py +103 -103
- basilisk/render/bloom.py +107 -107
- basilisk/render/camera.py +260 -260
- basilisk/render/chunk.py +108 -108
- basilisk/render/chunk_handler.py +167 -167
- basilisk/render/frame.py +110 -110
- basilisk/render/framebuffer.py +202 -202
- basilisk/render/image.py +120 -120
- basilisk/render/image_handler.py +120 -120
- basilisk/render/light.py +96 -96
- basilisk/render/light_handler.py +58 -58
- basilisk/render/material.py +232 -232
- basilisk/render/material_handler.py +133 -133
- basilisk/render/post_process.py +146 -146
- basilisk/render/shader.py +134 -134
- basilisk/render/shader_handler.py +85 -85
- basilisk/render/sky.py +120 -120
- basilisk/scene.py +290 -290
- basilisk/shaders/batch.frag +289 -289
- basilisk/shaders/batch.vert +117 -117
- basilisk/shaders/bloom_downsample.frag +42 -42
- basilisk/shaders/bloom_frame.frag +24 -24
- basilisk/shaders/bloom_upsample.frag +33 -33
- basilisk/shaders/crt.frag +31 -31
- basilisk/shaders/draw.frag +25 -25
- basilisk/shaders/draw.vert +25 -25
- basilisk/shaders/filter.frag +22 -22
- basilisk/shaders/frame.frag +12 -12
- basilisk/shaders/frame.vert +13 -13
- basilisk/shaders/geometry.frag +10 -10
- basilisk/shaders/geometry.vert +41 -41
- basilisk/shaders/normal.frag +62 -62
- basilisk/shaders/normal.vert +96 -96
- basilisk/shaders/particle.frag +76 -76
- basilisk/shaders/particle.vert +86 -86
- basilisk/shaders/sky.frag +23 -23
- basilisk/shaders/sky.vert +13 -13
- {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.dist-info}/METADATA +89 -89
- basilisk_engine-0.1.40.dist-info/RECORD +114 -0
- {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.dist-info}/WHEEL +1 -1
- basilisk_engine-0.1.38.dist-info/RECORD +0 -111
- {basilisk_engine-0.1.38.dist-info → basilisk_engine-0.1.40.dist-info}/top_level.txt +0 -0
basilisk/render/image.py
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
import numpy as np
|
|
4
|
-
import moderngl as mgl
|
|
5
|
-
import glm
|
|
6
|
-
import pygame as pg
|
|
7
|
-
from PIL import Image as PIL_Image
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
texture_sizes = (8, 64, 512, 1024, 2048)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Image():
|
|
14
|
-
name: str
|
|
15
|
-
"""Name of the image"""
|
|
16
|
-
index: glm.ivec2
|
|
17
|
-
"""Location of the image in the texture arrays"""
|
|
18
|
-
data: np.ndarray
|
|
19
|
-
"""Array of the texture data"""
|
|
20
|
-
size: int
|
|
21
|
-
"""The width and height in pixels of the image"""
|
|
22
|
-
texture: mgl.Texture | None=None
|
|
23
|
-
"""Texture of the image. Only created and retrived if needed by other module"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, path: str | os.PathLike | pg.Surface | mgl.Texture) -> None:
|
|
26
|
-
"""
|
|
27
|
-
A basilisk image object that contains a moderngl texture
|
|
28
|
-
Args:
|
|
29
|
-
path: str | os.PathLike | pg.Surface
|
|
30
|
-
The string path to the image. Can also read a pygame surface
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
# Check if the user is loading a pygame surface
|
|
34
|
-
if isinstance(path, str) or isinstance(path, os.PathLike):
|
|
35
|
-
return self._from_path(path)
|
|
36
|
-
elif isinstance(path, pg.Surface):
|
|
37
|
-
return self._from_surface(path)
|
|
38
|
-
elif isinstance(path, mgl.Texture):
|
|
39
|
-
return self._from_texture(path)
|
|
40
|
-
|
|
41
|
-
raise TypeError(f'Invalid path type: {type(path)}. Expected a string or os.PathLike')
|
|
42
|
-
|
|
43
|
-
def _from_path(self, path: str | os.PathLike) -> None:
|
|
44
|
-
"""
|
|
45
|
-
Loads a basilisk image from a pygame surface
|
|
46
|
-
Args:
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
# Get name from path
|
|
50
|
-
self.name = path.split('/')[-1].split('\\')[-1].split('.')[0]
|
|
51
|
-
|
|
52
|
-
# Load image
|
|
53
|
-
img = PIL_Image.open(path).convert('RGBA')
|
|
54
|
-
# Set the size in one of the size buckets
|
|
55
|
-
size_buckets = texture_sizes
|
|
56
|
-
self.size = size_buckets[np.argmin(np.array([abs(size - img.size[0]) for size in size_buckets]))]
|
|
57
|
-
img = img.resize((self.size, self.size))
|
|
58
|
-
# Get the image data
|
|
59
|
-
self.data = img.tobytes()
|
|
60
|
-
|
|
61
|
-
# Default index value (to be set by image handler)
|
|
62
|
-
self.index = glm.ivec2(1, 1)
|
|
63
|
-
|
|
64
|
-
def _from_surface(self, surf: pg.Surface) -> None:
|
|
65
|
-
"""
|
|
66
|
-
Loads a basilisk image from a pygame surface
|
|
67
|
-
Args:
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
# Set the size in one of the size buckets
|
|
71
|
-
size_buckets = texture_sizes
|
|
72
|
-
self.size = size_buckets[np.argmin(np.array([abs(size - surf.get_size()[0]) for size in size_buckets]))]
|
|
73
|
-
surf = pg.transform.scale(surf, (self.size, self.size)).convert_alpha()
|
|
74
|
-
# Get image data
|
|
75
|
-
self.data = pg.image.tobytes(surf, 'RGBA')
|
|
76
|
-
|
|
77
|
-
# Default index value (to be set by image handler)
|
|
78
|
-
self.index = glm.ivec2(1, 1)
|
|
79
|
-
|
|
80
|
-
def _from_texture(self, texture: mgl.Texture):
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
"""
|
|
84
|
-
...
|
|
85
|
-
|
|
86
|
-
def build_texture(self, ctx: mgl.Context) -> mgl.Texture:
|
|
87
|
-
"""
|
|
88
|
-
Builds a texture from the image data
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
# Release existing memory
|
|
92
|
-
if self.texture: self.texture.release()
|
|
93
|
-
|
|
94
|
-
# Make the texture from image data
|
|
95
|
-
self.texture = ctx.texture((self.size, self.size), components=4, data=self.data)
|
|
96
|
-
# Texture formatting
|
|
97
|
-
self.texture.build_mipmaps()
|
|
98
|
-
self.texture.filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
|
|
99
|
-
self.texture.anisotropy = 32.0
|
|
100
|
-
|
|
101
|
-
return self.texture
|
|
102
|
-
|
|
103
|
-
def use(self, slot: int) -> None:
|
|
104
|
-
"""
|
|
105
|
-
Use the image at the given slot
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
if not self.texture:
|
|
109
|
-
raise LookupError("bsk.Image: cannot use an image without a texture. Use texture.build_texture() before texture.use()")
|
|
110
|
-
|
|
111
|
-
# Bind to the given slot
|
|
112
|
-
self.texture.use(location=slot)
|
|
113
|
-
|
|
114
|
-
def __repr__(self) -> str:
|
|
115
|
-
"""
|
|
116
|
-
Returns a string representation of the object
|
|
117
|
-
"""
|
|
118
|
-
return f'<Basilisk Image | {self.name}, ({self.size}x{self.size}), {sys.getsizeof(self.data) / 1024 / 1024:.2} mb>'
|
|
119
|
-
|
|
120
|
-
def __del__(self) -> None:
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import numpy as np
|
|
4
|
+
import moderngl as mgl
|
|
5
|
+
import glm
|
|
6
|
+
import pygame as pg
|
|
7
|
+
from PIL import Image as PIL_Image
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
texture_sizes = (8, 64, 512, 1024, 2048)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Image():
|
|
14
|
+
name: str
|
|
15
|
+
"""Name of the image"""
|
|
16
|
+
index: glm.ivec2
|
|
17
|
+
"""Location of the image in the texture arrays"""
|
|
18
|
+
data: np.ndarray
|
|
19
|
+
"""Array of the texture data"""
|
|
20
|
+
size: int
|
|
21
|
+
"""The width and height in pixels of the image"""
|
|
22
|
+
texture: mgl.Texture | None=None
|
|
23
|
+
"""Texture of the image. Only created and retrived if needed by other module"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, path: str | os.PathLike | pg.Surface | mgl.Texture) -> None:
|
|
26
|
+
"""
|
|
27
|
+
A basilisk image object that contains a moderngl texture
|
|
28
|
+
Args:
|
|
29
|
+
path: str | os.PathLike | pg.Surface
|
|
30
|
+
The string path to the image. Can also read a pygame surface
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
# Check if the user is loading a pygame surface
|
|
34
|
+
if isinstance(path, str) or isinstance(path, os.PathLike):
|
|
35
|
+
return self._from_path(path)
|
|
36
|
+
elif isinstance(path, pg.Surface):
|
|
37
|
+
return self._from_surface(path)
|
|
38
|
+
elif isinstance(path, mgl.Texture):
|
|
39
|
+
return self._from_texture(path)
|
|
40
|
+
|
|
41
|
+
raise TypeError(f'Invalid path type: {type(path)}. Expected a string or os.PathLike')
|
|
42
|
+
|
|
43
|
+
def _from_path(self, path: str | os.PathLike) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Loads a basilisk image from a pygame surface
|
|
46
|
+
Args:
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Get name from path
|
|
50
|
+
self.name = path.split('/')[-1].split('\\')[-1].split('.')[0]
|
|
51
|
+
|
|
52
|
+
# Load image
|
|
53
|
+
img = PIL_Image.open(path).convert('RGBA')
|
|
54
|
+
# Set the size in one of the size buckets
|
|
55
|
+
size_buckets = texture_sizes
|
|
56
|
+
self.size = size_buckets[np.argmin(np.array([abs(size - img.size[0]) for size in size_buckets]))]
|
|
57
|
+
img = img.resize((self.size, self.size))
|
|
58
|
+
# Get the image data
|
|
59
|
+
self.data = img.tobytes()
|
|
60
|
+
|
|
61
|
+
# Default index value (to be set by image handler)
|
|
62
|
+
self.index = glm.ivec2(1, 1)
|
|
63
|
+
|
|
64
|
+
def _from_surface(self, surf: pg.Surface) -> None:
|
|
65
|
+
"""
|
|
66
|
+
Loads a basilisk image from a pygame surface
|
|
67
|
+
Args:
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
# Set the size in one of the size buckets
|
|
71
|
+
size_buckets = texture_sizes
|
|
72
|
+
self.size = size_buckets[np.argmin(np.array([abs(size - surf.get_size()[0]) for size in size_buckets]))]
|
|
73
|
+
surf = pg.transform.scale(surf, (self.size, self.size)).convert_alpha()
|
|
74
|
+
# Get image data
|
|
75
|
+
self.data = pg.image.tobytes(surf, 'RGBA')
|
|
76
|
+
|
|
77
|
+
# Default index value (to be set by image handler)
|
|
78
|
+
self.index = glm.ivec2(1, 1)
|
|
79
|
+
|
|
80
|
+
def _from_texture(self, texture: mgl.Texture):
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
"""
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
def build_texture(self, ctx: mgl.Context) -> mgl.Texture:
|
|
87
|
+
"""
|
|
88
|
+
Builds a texture from the image data
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
# Release existing memory
|
|
92
|
+
if self.texture: self.texture.release()
|
|
93
|
+
|
|
94
|
+
# Make the texture from image data
|
|
95
|
+
self.texture = ctx.texture((self.size, self.size), components=4, data=self.data)
|
|
96
|
+
# Texture formatting
|
|
97
|
+
self.texture.build_mipmaps()
|
|
98
|
+
self.texture.filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
|
|
99
|
+
self.texture.anisotropy = 32.0
|
|
100
|
+
|
|
101
|
+
return self.texture
|
|
102
|
+
|
|
103
|
+
def use(self, slot: int) -> None:
|
|
104
|
+
"""
|
|
105
|
+
Use the image at the given slot
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
if not self.texture:
|
|
109
|
+
raise LookupError("bsk.Image: cannot use an image without a texture. Use texture.build_texture() before texture.use()")
|
|
110
|
+
|
|
111
|
+
# Bind to the given slot
|
|
112
|
+
self.texture.use(location=slot)
|
|
113
|
+
|
|
114
|
+
def __repr__(self) -> str:
|
|
115
|
+
"""
|
|
116
|
+
Returns a string representation of the object
|
|
117
|
+
"""
|
|
118
|
+
return f'<Basilisk Image | {self.name}, ({self.size}x{self.size}), {sys.getsizeof(self.data) / 1024 / 1024:.2} mb>'
|
|
119
|
+
|
|
120
|
+
def __del__(self) -> None:
|
|
121
121
|
if self.texture: self.texture.release()
|
basilisk/render/image_handler.py
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
import moderngl as mgl
|
|
2
|
-
import glm
|
|
3
|
-
import numpy as np
|
|
4
|
-
|
|
5
|
-
texture_sizes = (8, 64, 512, 1024, 2048)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class ImageHandler():
|
|
9
|
-
engine: ...
|
|
10
|
-
"""Back refernce to the parent engine"""
|
|
11
|
-
ctx: mgl.Context
|
|
12
|
-
"""Back reference to the Context used by the scene/engine"""
|
|
13
|
-
images: list
|
|
14
|
-
"""List of basilisk Images containing all the loaded images given to the scene"""
|
|
15
|
-
texture_arrays: dict
|
|
16
|
-
"""Dictionary of textures arrays for writting textures to GPU"""
|
|
17
|
-
|
|
18
|
-
def __init__(self, engine) -> None:
|
|
19
|
-
"""
|
|
20
|
-
Container for all the basilisk image objects in the scene.
|
|
21
|
-
Handles the managment and writting of all image textures.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
# Set back references
|
|
25
|
-
self.engine = engine
|
|
26
|
-
self.ctx = engine.ctx
|
|
27
|
-
|
|
28
|
-
self.images = []
|
|
29
|
-
self.texture_arrays = {size : [] for size in texture_sizes}
|
|
30
|
-
|
|
31
|
-
def add(self, image: any) -> None:
|
|
32
|
-
"""
|
|
33
|
-
Adds an existing basilisk image object to the handler for writting
|
|
34
|
-
Args:
|
|
35
|
-
image: bsk.Image
|
|
36
|
-
The existing image that is to be added to the scene.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
if image in self.images: return
|
|
40
|
-
|
|
41
|
-
self.images.append(image)
|
|
42
|
-
self.write(regenerate=True)
|
|
43
|
-
|
|
44
|
-
def generate_texture_array(self) -> None:
|
|
45
|
-
"""
|
|
46
|
-
Generates texutre arrays for all the images. Updates the index of the image instance
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
# Release any existsing texture arrays
|
|
50
|
-
for texture_array in self.texture_arrays.values():
|
|
51
|
-
if not texture_array: continue
|
|
52
|
-
texture_array.release()
|
|
53
|
-
|
|
54
|
-
self.texture_arrays = {size : [] for size in texture_sizes}
|
|
55
|
-
|
|
56
|
-
for image in self.images:
|
|
57
|
-
# Add the image data to the array
|
|
58
|
-
self.texture_arrays[image.size].append(image.data)
|
|
59
|
-
# Update the image index
|
|
60
|
-
image.index = glm.ivec2(texture_sizes.index(image.size), len(self.texture_arrays[image.size]) - 1)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
for size in self.texture_arrays:
|
|
64
|
-
# Check that there are textures in the bucket
|
|
65
|
-
if not len(self.texture_arrays[size]): continue
|
|
66
|
-
array_data = np.array(self.texture_arrays[size])
|
|
67
|
-
dim = (size, size, len(self.texture_arrays[size]))
|
|
68
|
-
|
|
69
|
-
# Make the array
|
|
70
|
-
self.texture_arrays[size] = self.ctx.texture_array(size=dim, components=4, data=array_data)
|
|
71
|
-
# Texture OpenGl settings
|
|
72
|
-
self.texture_arrays[size].build_mipmaps()
|
|
73
|
-
if size > 32: self.texture_arrays[size].filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
|
|
74
|
-
else: self.texture_arrays[size].filter = (mgl.NEAREST, mgl.NEAREST)
|
|
75
|
-
self.texture_arrays[size].anisotropy = 32.0
|
|
76
|
-
|
|
77
|
-
def write(self, regenerate=False) -> None:
|
|
78
|
-
"""
|
|
79
|
-
Writes all texture arrays to shaders that use images
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
if not self.engine.shader_handler: return
|
|
83
|
-
|
|
84
|
-
if regenerate: self.generate_texture_array()
|
|
85
|
-
|
|
86
|
-
if not self.texture_arrays: return
|
|
87
|
-
|
|
88
|
-
for shader in self.engine.shader_handler.shaders:
|
|
89
|
-
if 'textureArrays[5]' not in shader.uniforms: continue
|
|
90
|
-
|
|
91
|
-
for i, size in enumerate(texture_sizes):
|
|
92
|
-
if not size in self.texture_arrays: continue
|
|
93
|
-
if not self.texture_arrays[size]: continue
|
|
94
|
-
shader.program[f'textureArrays[{i}].array'] = i + 3
|
|
95
|
-
self.texture_arrays[size].use(location=i+3)
|
|
96
|
-
|
|
97
|
-
def get(self, identifier: str | int) -> any:
|
|
98
|
-
"""
|
|
99
|
-
Gets the basilisk image with the given name or index
|
|
100
|
-
Args:
|
|
101
|
-
identifier: str | int
|
|
102
|
-
The name string or index of the desired image
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
# Simply use index if given
|
|
106
|
-
if isinstance(identifier, int): return self.images[identifier]
|
|
107
|
-
|
|
108
|
-
# Else, search the list for an image with the given name
|
|
109
|
-
for image in self.images:
|
|
110
|
-
if image.name != identifier: continue
|
|
111
|
-
return image
|
|
112
|
-
|
|
113
|
-
# No matching image found
|
|
114
|
-
return None
|
|
115
|
-
|
|
116
|
-
def __del__(self):
|
|
117
|
-
"""
|
|
118
|
-
Deallocates all texture arrays
|
|
119
|
-
"""
|
|
120
|
-
|
|
1
|
+
import moderngl as mgl
|
|
2
|
+
import glm
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
texture_sizes = (8, 64, 512, 1024, 2048)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ImageHandler():
|
|
9
|
+
engine: ...
|
|
10
|
+
"""Back refernce to the parent engine"""
|
|
11
|
+
ctx: mgl.Context
|
|
12
|
+
"""Back reference to the Context used by the scene/engine"""
|
|
13
|
+
images: list
|
|
14
|
+
"""List of basilisk Images containing all the loaded images given to the scene"""
|
|
15
|
+
texture_arrays: dict
|
|
16
|
+
"""Dictionary of textures arrays for writting textures to GPU"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, engine) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Container for all the basilisk image objects in the scene.
|
|
21
|
+
Handles the managment and writting of all image textures.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# Set back references
|
|
25
|
+
self.engine = engine
|
|
26
|
+
self.ctx = engine.ctx
|
|
27
|
+
|
|
28
|
+
self.images = []
|
|
29
|
+
self.texture_arrays = {size : [] for size in texture_sizes}
|
|
30
|
+
|
|
31
|
+
def add(self, image: any) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Adds an existing basilisk image object to the handler for writting
|
|
34
|
+
Args:
|
|
35
|
+
image: bsk.Image
|
|
36
|
+
The existing image that is to be added to the scene.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
if image in self.images: return
|
|
40
|
+
|
|
41
|
+
self.images.append(image)
|
|
42
|
+
self.write(regenerate=True)
|
|
43
|
+
|
|
44
|
+
def generate_texture_array(self) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Generates texutre arrays for all the images. Updates the index of the image instance
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Release any existsing texture arrays
|
|
50
|
+
for texture_array in self.texture_arrays.values():
|
|
51
|
+
if not texture_array: continue
|
|
52
|
+
texture_array.release()
|
|
53
|
+
|
|
54
|
+
self.texture_arrays = {size : [] for size in texture_sizes}
|
|
55
|
+
|
|
56
|
+
for image in self.images:
|
|
57
|
+
# Add the image data to the array
|
|
58
|
+
self.texture_arrays[image.size].append(image.data)
|
|
59
|
+
# Update the image index
|
|
60
|
+
image.index = glm.ivec2(texture_sizes.index(image.size), len(self.texture_arrays[image.size]) - 1)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
for size in self.texture_arrays:
|
|
64
|
+
# Check that there are textures in the bucket
|
|
65
|
+
if not len(self.texture_arrays[size]): continue
|
|
66
|
+
array_data = np.array(self.texture_arrays[size])
|
|
67
|
+
dim = (size, size, len(self.texture_arrays[size]))
|
|
68
|
+
|
|
69
|
+
# Make the array
|
|
70
|
+
self.texture_arrays[size] = self.ctx.texture_array(size=dim, components=4, data=array_data)
|
|
71
|
+
# Texture OpenGl settings
|
|
72
|
+
self.texture_arrays[size].build_mipmaps()
|
|
73
|
+
if size > 32: self.texture_arrays[size].filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
|
|
74
|
+
else: self.texture_arrays[size].filter = (mgl.NEAREST, mgl.NEAREST)
|
|
75
|
+
self.texture_arrays[size].anisotropy = 32.0
|
|
76
|
+
|
|
77
|
+
def write(self, regenerate=False) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Writes all texture arrays to shaders that use images
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
if not self.engine.shader_handler: return
|
|
83
|
+
|
|
84
|
+
if regenerate: self.generate_texture_array()
|
|
85
|
+
|
|
86
|
+
if not self.texture_arrays: return
|
|
87
|
+
|
|
88
|
+
for shader in self.engine.shader_handler.shaders:
|
|
89
|
+
if 'textureArrays[5]' not in shader.uniforms: continue
|
|
90
|
+
|
|
91
|
+
for i, size in enumerate(texture_sizes):
|
|
92
|
+
if not size in self.texture_arrays: continue
|
|
93
|
+
if not self.texture_arrays[size]: continue
|
|
94
|
+
shader.program[f'textureArrays[{i}].array'] = i + 3
|
|
95
|
+
self.texture_arrays[size].use(location=i+3)
|
|
96
|
+
|
|
97
|
+
def get(self, identifier: str | int) -> any:
|
|
98
|
+
"""
|
|
99
|
+
Gets the basilisk image with the given name or index
|
|
100
|
+
Args:
|
|
101
|
+
identifier: str | int
|
|
102
|
+
The name string or index of the desired image
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
# Simply use index if given
|
|
106
|
+
if isinstance(identifier, int): return self.images[identifier]
|
|
107
|
+
|
|
108
|
+
# Else, search the list for an image with the given name
|
|
109
|
+
for image in self.images:
|
|
110
|
+
if image.name != identifier: continue
|
|
111
|
+
return image
|
|
112
|
+
|
|
113
|
+
# No matching image found
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
def __del__(self):
|
|
117
|
+
"""
|
|
118
|
+
Deallocates all texture arrays
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
121
|
# [texture_array.release() for texture_array in self.texture_arrays]
|