diff options
author | 3gg <3gg@shellblade.net> | 2024-09-16 19:56:58 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2024-09-16 19:56:58 -0700 |
commit | 68ba3c0f45faa71b989b0a05fd974405a21cfd7b (patch) | |
tree | 93ee8c2605cbb7711e2827bb47f88e12d2eeb4a4 /game | |
parent | 420970c8b83f20a4a2411af687e9d4a38a5fe81a (diff) |
Add camera control.
Diffstat (limited to 'game')
-rw-r--r-- | game/src/plugins/viewer.c | 113 |
1 files changed, 100 insertions, 13 deletions
diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c index f621b00..5fc4be7 100644 --- a/game/src/plugins/viewer.c +++ b/game/src/plugins/viewer.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "plugin.h" | 1 | #include "plugin.h" |
2 | 2 | ||
3 | #include <gfx/app.h> | ||
3 | #include <gfx/asset.h> | 4 | #include <gfx/asset.h> |
4 | #include <gfx/renderer.h> | 5 | #include <gfx/renderer.h> |
5 | #include <gfx/scene.h> | 6 | #include <gfx/scene.h> |
@@ -27,11 +28,33 @@ static const char* BOXES = | |||
27 | 28 | ||
28 | #define DEFAULT_SCENE_FILE GIRL | 29 | #define DEFAULT_SCENE_FILE GIRL |
29 | 30 | ||
30 | struct State { | 31 | static const bool RenderBoundingBoxes = false; |
31 | Scene* scene; | 32 | static const R DefaultCameraSpeed = (R)6.0; |
32 | Model* model; | 33 | static const R DefaultMouseSensitivity = (R)(10 * TO_RAD); |
33 | SceneCamera* camera; | 34 | static const vec3 DefaultCameraPosition = (vec3){0, 2, 5}; |
34 | }; | 35 | |
36 | typedef struct CameraCommand { | ||
37 | bool CameraMoveLeft : 1; | ||
38 | bool CameraMoveRight : 1; | ||
39 | bool CameraMoveForward : 1; | ||
40 | bool CameraMoveBackward : 1; | ||
41 | } CameraCommand; | ||
42 | |||
43 | typedef struct CameraController { | ||
44 | R camera_speed; // Camera movement speed. | ||
45 | R mouse_sensitivity; // Controls the degree with which mouse movements | ||
46 | // rotate the camera. | ||
47 | vec2 prev_mouse_position; // Mouse position in the previous frame. | ||
48 | bool rotating; // When true, subsequent mouse movements cause the | ||
49 | // camera to rotate. | ||
50 | } CameraController; | ||
51 | |||
52 | typedef struct State { | ||
53 | Scene* scene; | ||
54 | Model* model; | ||
55 | SceneCamera* camera; | ||
56 | CameraController camera_controller; | ||
57 | } State; | ||
35 | 58 | ||
36 | /// Load the skyquad texture. | 59 | /// Load the skyquad texture. |
37 | static const Texture* load_environment_map(Gfx* gfx) { | 60 | static const Texture* load_environment_map(Gfx* gfx) { |
@@ -131,8 +154,21 @@ bool init(Game* game, State** pp_state) { | |||
131 | if (anima) { | 154 | if (anima) { |
132 | gfx_play_animation( | 155 | gfx_play_animation( |
133 | anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); | 156 | anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); |
157 | // TODO: Interpolate animations. | ||
158 | /*gfx_play_animation( | ||
159 | anima, | ||
160 | &(AnimationPlaySettings){.name = "Jumping-jack-lower", .loop = true}); | ||
161 | gfx_play_animation( | ||
162 | anima, &(AnimationPlaySettings){ | ||
163 | .name = "Jumping-jack-arms-mid", .loop = true});*/ | ||
134 | } | 164 | } |
135 | 165 | ||
166 | spatial3_set_position( | ||
167 | &gfx_get_camera_camera(state->camera)->spatial, DefaultCameraPosition); | ||
168 | |||
169 | state->camera_controller.camera_speed = DefaultCameraSpeed; | ||
170 | state->camera_controller.mouse_sensitivity = DefaultMouseSensitivity; | ||
171 | |||
136 | *pp_state = state; | 172 | *pp_state = state; |
137 | return true; | 173 | return true; |
138 | 174 | ||
@@ -153,19 +189,68 @@ void shutdown(Game* game, State* state) { | |||
153 | } | 189 | } |
154 | } | 190 | } |
155 | 191 | ||
192 | static void update_camera( | ||
193 | CameraController* controller, R dt, vec2 mouse_position, | ||
194 | CameraCommand command, Spatial3* camera) { | ||
195 | assert(controller); | ||
196 | assert(camera); | ||
197 | |||
198 | // Translation. | ||
199 | const R move_x = (R)(command.CameraMoveLeft ? -1 : 0) + | ||
200 | (R)(command.CameraMoveRight ? 1 : 0); | ||
201 | const R move_y = (R)(command.CameraMoveForward ? 1 : 0) + | ||
202 | (R)(command.CameraMoveBackward ? -1 : 0); | ||
203 | const vec2 translation = | ||
204 | vec2_scale(vec2_make(move_x, move_y), controller->camera_speed * dt); | ||
205 | spatial3_move_right(camera, translation.x); | ||
206 | spatial3_move_forwards(camera, translation.y); | ||
207 | |||
208 | // Rotation. | ||
209 | if (controller->rotating) { | ||
210 | const vec2 mouse_delta = | ||
211 | vec2_sub(mouse_position, controller->prev_mouse_position); | ||
212 | |||
213 | const vec2 rotation = | ||
214 | vec2_scale(mouse_delta, controller->mouse_sensitivity * dt); | ||
215 | |||
216 | spatial3_global_yaw(camera, -rotation.x); | ||
217 | spatial3_pitch(camera, -rotation.y); | ||
218 | } | ||
219 | |||
220 | // Update controller state. | ||
221 | controller->prev_mouse_position = mouse_position; | ||
222 | } | ||
223 | |||
156 | void update(Game* game, State* state, double t, double dt) { | 224 | void update(Game* game, State* state, double t, double dt) { |
157 | assert(game); | 225 | assert(game); |
158 | assert(state); | 226 | assert(state); |
159 | assert(state->scene); | 227 | assert(state->scene); |
160 | assert(state->camera); | 228 | assert(state->camera); |
161 | 229 | ||
162 | const vec3 orbit_point = vec3_make(0, 2, 0); | 230 | double mouse_x, mouse_y; |
163 | Camera* camera = gfx_get_camera_camera(state->camera); | 231 | gfx_app_get_mouse_position(&mouse_x, &mouse_y); |
164 | spatial3_orbit( | 232 | const vec2 mouse_position = {(R)mouse_x, (R)mouse_y}; |
165 | &camera->spatial, orbit_point, | 233 | |
166 | /*radius=*/5, | 234 | const CameraCommand camera_command = (CameraCommand){ |
167 | /*azimuth=*/(R)(t * 0.5), /*zenith=*/0); | 235 | .CameraMoveLeft = gfx_app_is_key_pressed(KeyA), |
168 | spatial3_lookat(&camera->spatial, orbit_point); | 236 | .CameraMoveRight = gfx_app_is_key_pressed(KeyD), |
237 | .CameraMoveForward = gfx_app_is_key_pressed(KeyW), | ||
238 | .CameraMoveBackward = gfx_app_is_key_pressed(KeyS), | ||
239 | }; | ||
240 | |||
241 | state->camera_controller.rotating = gfx_app_is_mouse_button_pressed(LMB); | ||
242 | |||
243 | update_camera( | ||
244 | &state->camera_controller, (R)dt, mouse_position, camera_command, | ||
245 | &gfx_get_camera_camera(state->camera)->spatial); | ||
246 | |||
247 | // const vec3 orbit_point = vec3_make(0, 2, 0); | ||
248 | // Camera* camera = gfx_get_camera_camera(state->camera); | ||
249 | // spatial3_orbit( | ||
250 | // &camera->spatial, orbit_point, | ||
251 | // /*radius=*/5, | ||
252 | // /*azimuth=*/(R)(t * 0.5), /*zenith=*/0); | ||
253 | // spatial3_lookat(&camera->spatial, orbit_point); | ||
169 | 254 | ||
170 | gfx_update(state->scene, state->camera, (R)t); | 255 | gfx_update(state->scene, state->camera, (R)t); |
171 | } | 256 | } |
@@ -261,7 +346,9 @@ void render(const Game* game, const State* state) { | |||
261 | .scene = state->scene, | 346 | .scene = state->scene, |
262 | .camera = state->camera}); | 347 | .camera = state->camera}); |
263 | 348 | ||
264 | render_bounding_boxes(game, state); | 349 | if (RenderBoundingBoxes) { |
350 | render_bounding_boxes(game, state); | ||
351 | } | ||
265 | } | 352 | } |
266 | 353 | ||
267 | void resize(Game* game, State* state, int width, int height) { | 354 | void resize(Game* game, State* state, int width, int height) { |