basilisk-engine 0.1.43__py3-none-any.whl → 0.1.45__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 +225 -225
- 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 +181 -178
- basilisk/draw/font_renderer.py +28 -28
- basilisk/engine.py +168 -169
- 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 +17 -17
- 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 -709
- 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 +117 -117
- basilisk/render/camera.py +260 -260
- basilisk/render/chunk.py +113 -113
- basilisk/render/chunk_handler.py +167 -167
- basilisk/render/frame.py +130 -130
- basilisk/render/framebuffer.py +192 -192
- 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 +180 -180
- basilisk/render/shader.py +135 -135
- basilisk/render/shader_handler.py +109 -109
- basilisk/render/sky.py +119 -119
- basilisk/scene.py +287 -287
- basilisk/shaders/batch.frag +291 -293
- basilisk/shaders/batch.vert +117 -117
- basilisk/shaders/bloom_downsample.frag +23 -23
- basilisk/shaders/bloom_frame.frag +25 -0
- basilisk/shaders/bloom_upsample.frag +33 -33
- basilisk/shaders/crt.frag +34 -34
- basilisk/shaders/draw.frag +27 -27
- basilisk/shaders/draw.vert +25 -25
- basilisk/shaders/filter.frag +22 -22
- basilisk/shaders/frame.frag +13 -13
- basilisk/shaders/frame.vert +13 -13
- basilisk/shaders/frame_hdr.frag +27 -27
- 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 +81 -81
- basilisk/shaders/particle.vert +86 -86
- basilisk/shaders/sky.frag +23 -23
- basilisk/shaders/sky.vert +13 -13
- {basilisk_engine-0.1.43.dist-info → basilisk_engine-0.1.45.dist-info}/METADATA +89 -89
- basilisk_engine-0.1.45.dist-info/RECORD +115 -0
- {basilisk_engine-0.1.43.dist-info → basilisk_engine-0.1.45.dist-info}/WHEEL +1 -1
- basilisk_engine-0.1.43.dist-info/RECORD +0 -111
- {basilisk_engine-0.1.43.dist-info → basilisk_engine-0.1.45.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)
|