basilisk-engine 0.1.37__py3-none-any.whl → 0.1.39__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 (98) hide show
  1. basilisk/__init__.py +26 -26
  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 +226 -226
  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 +53 -53
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +178 -178
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +165 -165
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +70 -70
  25. basilisk/generic/input_validation.py +82 -82
  26. basilisk/generic/math.py +18 -7
  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/__init__.py +0 -0
  34. basilisk/input/mouse.py +62 -0
  35. basilisk/input/path.py +14 -0
  36. basilisk/input_output/IO_handler.py +91 -91
  37. basilisk/input_output/clock.py +49 -49
  38. basilisk/input_output/keys.py +43 -43
  39. basilisk/input_output/mouse.py +90 -90
  40. basilisk/input_output/path.py +14 -14
  41. basilisk/mesh/cube.py +33 -33
  42. basilisk/mesh/mesh.py +233 -233
  43. basilisk/mesh/mesh_from_data.py +150 -150
  44. basilisk/mesh/model.py +271 -271
  45. basilisk/mesh/narrow_aabb.py +89 -89
  46. basilisk/mesh/narrow_bvh.py +91 -91
  47. basilisk/mesh/narrow_primative.py +23 -23
  48. basilisk/nodes/helper.py +28 -28
  49. basilisk/nodes/node.py +709 -704
  50. basilisk/nodes/node_handler.py +97 -97
  51. basilisk/particles/particle_handler.py +64 -64
  52. basilisk/particles/particle_renderer.py +93 -93
  53. basilisk/physics/impulse.py +112 -112
  54. basilisk/physics/physics_body.py +43 -43
  55. basilisk/physics/physics_engine.py +35 -35
  56. basilisk/render/batch.py +103 -103
  57. basilisk/render/bloom.py +107 -107
  58. basilisk/render/camera.py +260 -260
  59. basilisk/render/chunk.py +108 -108
  60. basilisk/render/chunk_handler.py +167 -167
  61. basilisk/render/frame.py +110 -109
  62. basilisk/render/framebuffer.py +202 -202
  63. basilisk/render/image.py +120 -120
  64. basilisk/render/image_handler.py +120 -120
  65. basilisk/render/light.py +96 -96
  66. basilisk/render/light_handler.py +58 -58
  67. basilisk/render/material.py +232 -232
  68. basilisk/render/material_handler.py +133 -133
  69. basilisk/render/post_process.py +147 -140
  70. basilisk/render/shader.py +134 -134
  71. basilisk/render/shader_handler.py +85 -85
  72. basilisk/render/sky.py +120 -120
  73. basilisk/render/tempCodeRunnerFile.py +1 -0
  74. basilisk/scene.py +290 -290
  75. basilisk/shaders/batch.frag +289 -289
  76. basilisk/shaders/batch.vert +117 -117
  77. basilisk/shaders/bloom_downsample.frag +42 -42
  78. basilisk/shaders/bloom_frame.frag +24 -24
  79. basilisk/shaders/bloom_upsample.frag +33 -33
  80. basilisk/shaders/crt.frag +31 -31
  81. basilisk/shaders/draw.frag +25 -25
  82. basilisk/shaders/draw.vert +25 -25
  83. basilisk/shaders/filter.frag +22 -22
  84. basilisk/shaders/frame.frag +12 -12
  85. basilisk/shaders/frame.vert +13 -13
  86. basilisk/shaders/geometry.frag +10 -10
  87. basilisk/shaders/geometry.vert +41 -41
  88. basilisk/shaders/normal.frag +62 -62
  89. basilisk/shaders/normal.vert +96 -96
  90. basilisk/shaders/particle.frag +76 -76
  91. basilisk/shaders/particle.vert +86 -86
  92. basilisk/shaders/sky.frag +23 -23
  93. basilisk/shaders/sky.vert +13 -13
  94. {basilisk_engine-0.1.37.dist-info → basilisk_engine-0.1.39.dist-info}/METADATA +89 -89
  95. basilisk_engine-0.1.39.dist-info/RECORD +114 -0
  96. {basilisk_engine-0.1.37.dist-info → basilisk_engine-0.1.39.dist-info}/WHEEL +1 -1
  97. basilisk_engine-0.1.37.dist-info/RECORD +0 -110
  98. {basilisk_engine-0.1.37.dist-info → basilisk_engine-0.1.39.dist-info}/top_level.txt +0 -0
basilisk/render/camera.py CHANGED
@@ -1,261 +1,261 @@
1
- import pygame as pg
2
- import glm
3
- import numpy as np
4
- from ..generic.vec3 import Vec3
5
- from ..generic.quat import Quat
6
-
7
-
8
- # Camera view constants
9
- FOV = 50 # Degrees
10
- NEAR = 0.1
11
- FAR = 350
12
-
13
- class Camera:
14
- engine: ...
15
- """Back reference to the parent engine"""
16
- scene: ...
17
- """Back reference to the parent scene"""
18
- aspect_ratio: float
19
- """Aspect ratio of the engine window"""
20
- position: glm.vec3
21
- """Location of the camera (maters)"""
22
- speed: float
23
- """The speed that the camera moves in space"""
24
- sensitivity: float
25
- """The speed at which the camera turns"""
26
-
27
- def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0), speed: float=10, sensitivity: float=2) -> None:
28
- """
29
- Camera object to get view and projection matricies. Movement built in
30
- """
31
-
32
- # Back references
33
- self.scene = None
34
- self.engine = None
35
- # transformations
36
- self.rotation = glm.quat(rotation)
37
- self.position = glm.vec3(position)
38
- # fov
39
- self.fov = 50
40
- # The initial aspect ratio of the screen
41
- self.aspect_ratio = 1.0
42
- # View matrix
43
- self.m_view = self.get_view_matrix()
44
- # Projection matrix
45
- self.m_proj = self.get_projection_matrix()
46
- # Movement attributes
47
- self.speed = speed
48
- self.sensitivity = sensitivity
49
-
50
- def update(self) -> None:
51
- """
52
- Updates the camera view matrix
53
- """
54
-
55
- # self.update_camera_vectors()
56
- self.m_view = self.get_view_matrix()
57
-
58
- def use(self):
59
- # Updated aspect ratio of the screen
60
- self.aspect_ratio = self.engine.win_size[0] / self.engine.win_size[1]
61
- # View matrix
62
- self.m_view = self.get_view_matrix()
63
- # Projection matrix
64
- self.m_proj = self.get_projection_matrix()
65
-
66
- def get_view_matrix(self) -> glm.mat4x4:
67
- return glm.lookAt(self.position, self.position + self.forward, self.up)
68
-
69
- def get_projection_matrix(self) -> glm.mat4x4:
70
- return glm.perspective(glm.radians(self.fov), self.aspect_ratio, NEAR, FAR)
71
-
72
- def get_params(self) -> tuple:
73
- return self.engine, self.position, self.yaw, self.pitch
74
-
75
- def look_at(self, other) -> None:
76
- forward = glm.normalize(other.position - self.position)
77
- self.yaw = np.degrees(np.arctan2(forward.z, forward.x))
78
- self.pitch = np.degrees(np.arctan2(forward.y, np.sqrt(forward.x ** 2 + forward.z ** 2)))
79
-
80
- def __repr__(self):
81
- return f'<Basilisk Camera | Position: {self.position}, Direction: {self.forward}>'
82
-
83
- @property
84
- def scene(self): return self._scene
85
- @property
86
- def position(self): return self._position
87
- @property
88
- def rotation(self) -> glm.quat: return self._rotation
89
- @property
90
- def direction(self): return self.rotation * (0, 0, -1)
91
- @property
92
- def forward(self): return self.rotation * (0, 0, -1)
93
- @property
94
- def pitch(self): return glm.pitch(self.rotation)
95
- @property
96
- def yaw(self): return glm.yaw(self.rotation)
97
- @property
98
- def roll(self): return glm.roll(self.rotation)
99
- @property
100
- def UP(self):
101
- up = (self.rotation.x, self.rotation.y, self.rotation.z)
102
- up = (0, 1, 0) # TODO ensure that this works with all up vectors
103
- return glm.normalize(up) if glm.length2(up) > 1e-7 else glm.vec3(0, 1, 0)
104
- @property
105
- def right(self): return glm.normalize(glm.cross(self.forward, self.UP))
106
- @property
107
- def up(self): return glm.normalize(glm.cross(self.right, self.forward))
108
- @property
109
- def horizontal(self): return glm.normalize(glm.cross(self.UP, self.right))
110
- @property
111
- def fov(self): return self._fov
112
-
113
- @scene.setter
114
- def scene(self, value):
115
- if value == None: return
116
- self._scene = value
117
- self.engine = self._scene.engine
118
- self.use()
119
-
120
- @position.setter
121
- def position(self, value: tuple | list | glm.vec3 | np.ndarray | Vec3):
122
- if isinstance(value, glm.vec3): self._position = glm.vec3(value)
123
- elif isinstance(value, Vec3): self._position = glm.vec3(value.data)
124
- elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
125
- if len(value) != 3: raise ValueError(f'Camera: Invalid number of values for position. Expected 3, got {len(value)}')
126
- self._position = glm.vec3(value)
127
- else: raise TypeError(f'Camera: Invalid position value type {type(value)}')
128
-
129
- @rotation.setter
130
- def rotation(self, value):
131
- if isinstance(value, (glm.vec3, glm.quat)): self._rotation = glm.quat(value)
132
- elif isinstance(value, (Vec3, Quat)): self._rotation = glm.quat(value.data)
133
- elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
134
- if not (2 < len(value) < 5): raise ValueError(f'Camera: Invalid number of values for rotation. Expected 3 or 4, got {len(value)}')
135
- self._position = glm.quat(value)
136
- else:
137
- try:
138
- self._rotation = glm.quat(value)
139
- except:
140
- raise TypeError(f'Camera: Invalid rotation value type {type(value)}')
141
-
142
- @direction.setter
143
- def direction(self, value: tuple | list | glm.vec3 | np.ndarray | Vec3):
144
- if isinstance(value, glm.vec3): self.forward = glm.normalize(value)
145
- elif isinstance(value, Vec3): self.forward = glm.normalize(value.data)
146
- elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
147
- if len(value) != 3: raise ValueError(f'Camera: Invalid number of values for direction. Expected 3, got {len(value)}')
148
- self.forward = glm.normalize(value)
149
- else: raise TypeError(f'Camera: Invalid direction value type {type(value)}')
150
-
151
- @forward.setter
152
- def forward(self, value):
153
- self._rotation = glm.quatLookAt(value, self.UP)
154
-
155
- @pitch.setter
156
- def pitch(self, value):
157
- self._rotation = glm.quat((value, self.yaw, self.roll))
158
-
159
- @yaw.setter
160
- def yaw(self, value):
161
- self._rotation = glm.quat((self.pitch, value, self.roll))
162
-
163
- @roll.setter
164
- def roll(self, value):
165
- self._rotation = glm.quat((self.pitch, self.yaw, value))
166
-
167
- @UP.setter
168
- def UP(self, value):
169
- self._rotation = glm.quatLookAt(self.forward, value)
170
-
171
- @fov.setter
172
- def fov(self, value):
173
- self._fov = value
174
- if self.engine: self.use()
175
-
176
-
177
- class FreeCamera(Camera):
178
- def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
179
- super().__init__(position, rotation)
180
-
181
- def update(self) -> None:
182
- """
183
- Updates the camera position and rotaiton based on user input
184
- """
185
-
186
- self.move()
187
- self.rotate()
188
- # self.update_camera_vectors()
189
- self.m_view = self.get_view_matrix()
190
-
191
- def rotate(self) -> None:
192
- """
193
- Rotates the camera based on the amount of mouse movement.
194
- """
195
- rel_x, rel_y = self.engine.mouse.relative
196
-
197
- yaw_rotation = glm.angleAxis(self.sensitivity / 1000 * rel_x, -self.UP)
198
- pitch_rotation = glm.angleAxis(self.sensitivity / 1000 * rel_y, -self.right)
199
- new_rotation = yaw_rotation * pitch_rotation * self.rotation
200
-
201
- v_new = new_rotation * self.UP
202
- pitch_angle = glm.degrees(glm.acos(glm.clamp(glm.dot(v_new, self.UP), -1.0, 1.0)))
203
- self.rotation = new_rotation if pitch_angle < 89 else yaw_rotation * self.rotation
204
-
205
- def move(self) -> None:
206
- """
207
- Checks for button presses and updates vectors accordingly.
208
- """
209
- velocity = (self.speed + self.engine.keys[pg.K_CAPSLOCK] * 10) * self.engine.delta_time
210
- keys = self.engine.keys
211
- if keys[pg.K_w]:
212
- self.position += glm.normalize(glm.vec3(self.forward.x, 0, self.forward.z)) * velocity
213
- if keys[pg.K_s]:
214
- self.position -= glm.normalize(glm.vec3(self.forward.x, 0, self.forward.z)) * velocity
215
- if keys[pg.K_a]:
216
- self.position -= self.right * velocity
217
- if keys[pg.K_d]:
218
- self.position += self.right * velocity
219
- if keys[pg.K_SPACE]:
220
- self.position += self.UP * velocity
221
- if keys[pg.K_LSHIFT]:
222
- self.position -= self.UP * velocity
223
-
224
- class FixedCamera(FreeCamera):
225
- def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
226
- super().__init__(position, rotation)
227
-
228
- def move(self): pass
229
-
230
- class FollowCamera(FreeCamera):
231
- def __init__(self, parent, position=(0, 0, 20), rotation=(1, 0, 0, 0), offset=(0, 0, 0)):
232
- super().__init__(position, rotation)
233
- self.parent = parent
234
- self.offest = glm.vec3(offset)
235
-
236
- def move(self) -> None:
237
- """
238
- Moves the camera to the parent node
239
- """
240
-
241
- self.position = self.parent.position + self.offest
242
-
243
- class OrbitCamera(FreeCamera):
244
- def __init__(self, parent, position=(0, 0, 20), rotation=(1, 0, 0, 0), distance=5, offset=(0, 0)):
245
- self.parent = parent
246
- self.distance = distance
247
- self.offset = glm.vec2(offset)
248
- super().__init__(position, rotation)
249
-
250
- def get_view_matrix(self) -> glm.mat4x4:
251
- return glm.lookAt(self.position, self.parent.position, self.up)
252
-
253
- def move(self) -> None:
254
- """
255
- Moves the camera to the parent node
256
- """
257
- self.position = self.parent.position - glm.normalize(self.forward) * self.distance
258
-
259
- class StaticCamera(Camera):
260
- def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
1
+ import pygame as pg
2
+ import glm
3
+ import numpy as np
4
+ from ..generic.vec3 import Vec3
5
+ from ..generic.quat import Quat
6
+
7
+
8
+ # Camera view constants
9
+ FOV = 50 # Degrees
10
+ NEAR = 0.1
11
+ FAR = 350
12
+
13
+ class Camera:
14
+ engine: ...
15
+ """Back reference to the parent engine"""
16
+ scene: ...
17
+ """Back reference to the parent scene"""
18
+ aspect_ratio: float
19
+ """Aspect ratio of the engine window"""
20
+ position: glm.vec3
21
+ """Location of the camera (maters)"""
22
+ speed: float
23
+ """The speed that the camera moves in space"""
24
+ sensitivity: float
25
+ """The speed at which the camera turns"""
26
+
27
+ def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0), speed: float=10, sensitivity: float=2) -> None:
28
+ """
29
+ Camera object to get view and projection matricies. Movement built in
30
+ """
31
+
32
+ # Back references
33
+ self.scene = None
34
+ self.engine = None
35
+ # transformations
36
+ self.rotation = glm.quat(rotation)
37
+ self.position = glm.vec3(position)
38
+ # fov
39
+ self.fov = 50
40
+ # The initial aspect ratio of the screen
41
+ self.aspect_ratio = 1.0
42
+ # View matrix
43
+ self.m_view = self.get_view_matrix()
44
+ # Projection matrix
45
+ self.m_proj = self.get_projection_matrix()
46
+ # Movement attributes
47
+ self.speed = speed
48
+ self.sensitivity = sensitivity
49
+
50
+ def update(self) -> None:
51
+ """
52
+ Updates the camera view matrix
53
+ """
54
+
55
+ # self.update_camera_vectors()
56
+ self.m_view = self.get_view_matrix()
57
+
58
+ def use(self):
59
+ # Updated aspect ratio of the screen
60
+ self.aspect_ratio = self.engine.win_size[0] / self.engine.win_size[1]
61
+ # View matrix
62
+ self.m_view = self.get_view_matrix()
63
+ # Projection matrix
64
+ self.m_proj = self.get_projection_matrix()
65
+
66
+ def get_view_matrix(self) -> glm.mat4x4:
67
+ return glm.lookAt(self.position, self.position + self.forward, self.up)
68
+
69
+ def get_projection_matrix(self) -> glm.mat4x4:
70
+ return glm.perspective(glm.radians(self.fov), self.aspect_ratio, NEAR, FAR)
71
+
72
+ def get_params(self) -> tuple:
73
+ return self.engine, self.position, self.yaw, self.pitch
74
+
75
+ def look_at(self, other) -> None:
76
+ forward = glm.normalize(other.position - self.position)
77
+ self.yaw = np.degrees(np.arctan2(forward.z, forward.x))
78
+ self.pitch = np.degrees(np.arctan2(forward.y, np.sqrt(forward.x ** 2 + forward.z ** 2)))
79
+
80
+ def __repr__(self):
81
+ return f'<Basilisk Camera | Position: {self.position}, Direction: {self.forward}>'
82
+
83
+ @property
84
+ def scene(self): return self._scene
85
+ @property
86
+ def position(self): return self._position
87
+ @property
88
+ def rotation(self) -> glm.quat: return self._rotation
89
+ @property
90
+ def direction(self): return self.rotation * (0, 0, -1)
91
+ @property
92
+ def forward(self): return self.rotation * (0, 0, -1)
93
+ @property
94
+ def pitch(self): return glm.pitch(self.rotation)
95
+ @property
96
+ def yaw(self): return glm.yaw(self.rotation)
97
+ @property
98
+ def roll(self): return glm.roll(self.rotation)
99
+ @property
100
+ def UP(self):
101
+ up = (self.rotation.x, self.rotation.y, self.rotation.z)
102
+ up = (0, 1, 0) # TODO ensure that this works with all up vectors
103
+ return glm.normalize(up) if glm.length2(up) > 1e-7 else glm.vec3(0, 1, 0)
104
+ @property
105
+ def right(self): return glm.normalize(glm.cross(self.forward, self.UP))
106
+ @property
107
+ def up(self): return glm.normalize(glm.cross(self.right, self.forward))
108
+ @property
109
+ def horizontal(self): return glm.normalize(glm.cross(self.UP, self.right))
110
+ @property
111
+ def fov(self): return self._fov
112
+
113
+ @scene.setter
114
+ def scene(self, value):
115
+ if value == None: return
116
+ self._scene = value
117
+ self.engine = self._scene.engine
118
+ self.use()
119
+
120
+ @position.setter
121
+ def position(self, value: tuple | list | glm.vec3 | np.ndarray | Vec3):
122
+ if isinstance(value, glm.vec3): self._position = glm.vec3(value)
123
+ elif isinstance(value, Vec3): self._position = glm.vec3(value.data)
124
+ elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
125
+ if len(value) != 3: raise ValueError(f'Camera: Invalid number of values for position. Expected 3, got {len(value)}')
126
+ self._position = glm.vec3(value)
127
+ else: raise TypeError(f'Camera: Invalid position value type {type(value)}')
128
+
129
+ @rotation.setter
130
+ def rotation(self, value):
131
+ if isinstance(value, (glm.vec3, glm.quat)): self._rotation = glm.quat(value)
132
+ elif isinstance(value, (Vec3, Quat)): self._rotation = glm.quat(value.data)
133
+ elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
134
+ if not (2 < len(value) < 5): raise ValueError(f'Camera: Invalid number of values for rotation. Expected 3 or 4, got {len(value)}')
135
+ self._position = glm.quat(value)
136
+ else:
137
+ try:
138
+ self._rotation = glm.quat(value)
139
+ except:
140
+ raise TypeError(f'Camera: Invalid rotation value type {type(value)}')
141
+
142
+ @direction.setter
143
+ def direction(self, value: tuple | list | glm.vec3 | np.ndarray | Vec3):
144
+ if isinstance(value, glm.vec3): self.forward = glm.normalize(value)
145
+ elif isinstance(value, Vec3): self.forward = glm.normalize(value.data)
146
+ elif isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
147
+ if len(value) != 3: raise ValueError(f'Camera: Invalid number of values for direction. Expected 3, got {len(value)}')
148
+ self.forward = glm.normalize(value)
149
+ else: raise TypeError(f'Camera: Invalid direction value type {type(value)}')
150
+
151
+ @forward.setter
152
+ def forward(self, value):
153
+ self._rotation = glm.quatLookAt(value, self.UP)
154
+
155
+ @pitch.setter
156
+ def pitch(self, value):
157
+ self._rotation = glm.quat((value, self.yaw, self.roll))
158
+
159
+ @yaw.setter
160
+ def yaw(self, value):
161
+ self._rotation = glm.quat((self.pitch, value, self.roll))
162
+
163
+ @roll.setter
164
+ def roll(self, value):
165
+ self._rotation = glm.quat((self.pitch, self.yaw, value))
166
+
167
+ @UP.setter
168
+ def UP(self, value):
169
+ self._rotation = glm.quatLookAt(self.forward, value)
170
+
171
+ @fov.setter
172
+ def fov(self, value):
173
+ self._fov = value
174
+ if self.engine: self.use()
175
+
176
+
177
+ class FreeCamera(Camera):
178
+ def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
179
+ super().__init__(position, rotation)
180
+
181
+ def update(self) -> None:
182
+ """
183
+ Updates the camera position and rotaiton based on user input
184
+ """
185
+
186
+ self.move()
187
+ self.rotate()
188
+ # self.update_camera_vectors()
189
+ self.m_view = self.get_view_matrix()
190
+
191
+ def rotate(self) -> None:
192
+ """
193
+ Rotates the camera based on the amount of mouse movement.
194
+ """
195
+ rel_x, rel_y = self.engine.mouse.relative
196
+
197
+ yaw_rotation = glm.angleAxis(self.sensitivity / 1000 * rel_x, -self.UP)
198
+ pitch_rotation = glm.angleAxis(self.sensitivity / 1000 * rel_y, -self.right)
199
+ new_rotation = yaw_rotation * pitch_rotation * self.rotation
200
+
201
+ v_new = new_rotation * self.UP
202
+ pitch_angle = glm.degrees(glm.acos(glm.clamp(glm.dot(v_new, self.UP), -1.0, 1.0)))
203
+ self.rotation = new_rotation if pitch_angle < 89 else yaw_rotation * self.rotation
204
+
205
+ def move(self) -> None:
206
+ """
207
+ Checks for button presses and updates vectors accordingly.
208
+ """
209
+ velocity = (self.speed + self.engine.keys[pg.K_CAPSLOCK] * 10) * self.engine.delta_time
210
+ keys = self.engine.keys
211
+ if keys[pg.K_w]:
212
+ self.position += glm.normalize(glm.vec3(self.forward.x, 0, self.forward.z)) * velocity
213
+ if keys[pg.K_s]:
214
+ self.position -= glm.normalize(glm.vec3(self.forward.x, 0, self.forward.z)) * velocity
215
+ if keys[pg.K_a]:
216
+ self.position -= self.right * velocity
217
+ if keys[pg.K_d]:
218
+ self.position += self.right * velocity
219
+ if keys[pg.K_SPACE]:
220
+ self.position += self.UP * velocity
221
+ if keys[pg.K_LSHIFT]:
222
+ self.position -= self.UP * velocity
223
+
224
+ class FixedCamera(FreeCamera):
225
+ def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
226
+ super().__init__(position, rotation)
227
+
228
+ def move(self): pass
229
+
230
+ class FollowCamera(FreeCamera):
231
+ def __init__(self, parent, position=(0, 0, 20), rotation=(1, 0, 0, 0), offset=(0, 0, 0)):
232
+ super().__init__(position, rotation)
233
+ self.parent = parent
234
+ self.offest = glm.vec3(offset)
235
+
236
+ def move(self) -> None:
237
+ """
238
+ Moves the camera to the parent node
239
+ """
240
+
241
+ self.position = self.parent.position + self.offest
242
+
243
+ class OrbitCamera(FreeCamera):
244
+ def __init__(self, parent, position=(0, 0, 20), rotation=(1, 0, 0, 0), distance=5, offset=(0, 0)):
245
+ self.parent = parent
246
+ self.distance = distance
247
+ self.offset = glm.vec2(offset)
248
+ super().__init__(position, rotation)
249
+
250
+ def get_view_matrix(self) -> glm.mat4x4:
251
+ return glm.lookAt(self.position, self.parent.position, self.up)
252
+
253
+ def move(self) -> None:
254
+ """
255
+ Moves the camera to the parent node
256
+ """
257
+ self.position = self.parent.position - glm.normalize(self.forward) * self.distance
258
+
259
+ class StaticCamera(Camera):
260
+ def __init__(self, position=(0, 0, 20), rotation=(1, 0, 0, 0)):
261
261
  super().__init__(position, rotation)