From e412f21c7e3ca25283cdd8fe7db7d093bc63bc92 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Sat, 13 Mar 2021 01:35:36 -0500 Subject: [PATCH] add simple SDL input handling and callbacks --- README | 1 + examples/assimp_loading/main.cpp | 18 ++++++++++++++- examples/simple_mesh/main.cpp | 22 +++++++++++++++--- include/input.h | 16 +++++++++++++ include/renderer.h | 12 ++++++++-- src/input.cpp | 39 ++++++++++++++++++++++++++++++++ src/renderer.cpp | 30 +++++++++++++++--------- 7 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 include/input.h create mode 100644 src/input.cpp diff --git a/README b/README index 421f1d7..4d39492 100644 --- a/README +++ b/README @@ -13,6 +13,7 @@ TODO: add input abstraction for SDL store meshes separately from entities for reuse add a function to update camera transforms only once per frame, per shader + fix example Makefile dependenies Dependencies: assimp >= 5.0.0 diff --git a/examples/assimp_loading/main.cpp b/examples/assimp_loading/main.cpp index 05e8b02..39a13d4 100644 --- a/examples/assimp_loading/main.cpp +++ b/examples/assimp_loading/main.cpp @@ -4,6 +4,7 @@ #include "camera.h" #include "dumbLog.h" +#include "input.h" #include "entity.h" #include "renderer.h" #include "shader_program.h" @@ -12,11 +13,26 @@ void doFrameCallback(render_state* rs) { + static input_state is = {}; + inputProcessEvents(&is); + + if (is.window_closed || is.escape) { + rs->running = false; + return; + } + + int rotate_mod = 0; + + if (is.left) + rotate_mod = -1; + if (is.right) + rotate_mod = 1; + // NOTE: rotate mesh on z-axis every frame entity& e = rs->render_groups[0].entities[0]; static float angle = (float) M_PI_2 / 33; static glm::vec3 axis(0, 0, 1); - entRotate(e, angle, axis); + entRotate(e, angle * rotate_mod, axis); } // TODO: remove/refactor this when we get animation working diff --git a/examples/simple_mesh/main.cpp b/examples/simple_mesh/main.cpp index 343cbc4..e4cd0e3 100644 --- a/examples/simple_mesh/main.cpp +++ b/examples/simple_mesh/main.cpp @@ -2,18 +2,34 @@ #include #include "dumbLog.h" +#include "input.h" #include "mesh.h" #include "renderer.h" void -doFrameCallback(render_state* rs) +doFrameCallbackPre(render_state* rs) { + static input_state is = {}; + inputProcessEvents(&is); + + if (is.window_closed || is.escape) { + rs->running = false; + return; + } + + int rotate_mod = 0; + + if (is.left) + rotate_mod = -1; + if (is.right) + rotate_mod = 1; + // NOTE: rotate mesh on z-axis every frame entity& e = rs->render_groups[0].entities[0]; static float angle = (float) M_PI_2 / 33; static glm::vec3 axis(0, 0, 1); - entRotate(e, angle, axis); + entRotate(e, angle * rotate_mod, axis); } simple_mesh* @@ -65,7 +81,7 @@ main() glm::vec3(0,0,1) ); - renDoRenderLoop(rs, 60, doFrameCallback); + renDoRenderLoop(rs, 60, doFrameCallbackPre); renShutdown(rs); return 0; diff --git a/include/input.h b/include/input.h new file mode 100644 index 0000000..1be9403 --- /dev/null +++ b/include/input.h @@ -0,0 +1,16 @@ + +#pragma once + +struct input_state +{ + bool window_closed; + bool escape; + bool left; + bool right; + bool up; + bool down; +}; + +void +inputProcessEvents(input_state* is); + diff --git a/include/renderer.h b/include/renderer.h index 26f996b..cf7916c 100644 --- a/include/renderer.h +++ b/include/renderer.h @@ -47,6 +47,7 @@ struct render_state camera cam; util_RGBA clear_col; SDL_Handles* handles; + bool running; // TODO: this really needs to be a resizable array, or linked list, or // ...gasp, std::vector @@ -70,11 +71,18 @@ void renShutdown(render_state* rs); render_group* renAllocateGroup(uint entity_count, shader_wrapper shader); +// NOTE: callback function signature to use with renDoRenderLoop() typedef void (*frame_callback_fn) (render_state*); -void renDoRenderLoop(render_state* rs, +// NOTE: There are 2 callbacks to use here, cb_func_pre is called before +// the call to renRenderFrame(), cb_fun_post is called after +// NOTE: if you use cb_func_pre, you will have to use SDL_PollEvent() manually +// and at minimum set rs->running = false on SDL_QUIT event +void +renDoRenderLoop(render_state* rs, uint framerate = 60, - frame_callback_fn cb_func = nullptr); + frame_callback_fn cb_func_pre = nullptr, + frame_callback_fn cb_func_post = nullptr); void renRenderFrame(render_state* rs); diff --git a/src/input.cpp b/src/input.cpp new file mode 100644 index 0000000..4ff1248 --- /dev/null +++ b/src/input.cpp @@ -0,0 +1,39 @@ + +#include + +#include "input.h" + + +void +inputProcessEvents(input_state* is) +{ + SDL_Event e; + + while (SDL_PollEvent(&e)) { + switch (e.type) { + case SDL_QUIT: + is->window_closed = true; + break; + case SDL_KEYDOWN: + switch (e.key.keysym.sym) { + case SDLK_ESCAPE: is->escape = true; break; + case SDLK_LEFT: is->left = true; break; + case SDLK_RIGHT: is->right = true; break; + case SDLK_UP: is->up = true; break; + case SDLK_DOWN: is->down = true; break; + } + break; + case SDL_KEYUP: + switch (e.key.keysym.sym) { + case SDLK_ESCAPE: is->escape = false; break; + case SDLK_LEFT: is->left = false; break; + case SDLK_RIGHT: is->right = false; break; + case SDLK_UP: is->up = false; break; + case SDLK_DOWN: is->down = false; break; + } + break; + default: break; + } + } +} + diff --git a/src/renderer.cpp b/src/renderer.cpp index 6723245..d287e47 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -8,10 +8,11 @@ #include #include +#include "default_shaders.cpp" #include "dumbLog.h" +#include "input.h" #include "render_object.h" #include "renderer.h" -#include "default_shaders.cpp" #define CLEAR_COL_R 55.f / 255.f #define CLEAR_COL_G 55.f / 255.f @@ -94,27 +95,33 @@ renAllocateGroup(uint entity_count, shader_wrapper shader) return rg; } -// TODO: add a better structure for input void -renDoRenderLoop(render_state* rs, uint framerate, frame_callback_fn cb_func) +renDoRenderLoop(render_state* rs, + uint framerate, + frame_callback_fn cb_func_pre, + frame_callback_fn cb_func_post) { uint delay = (framerate > 0) ? 1 / framerate : 0; uint frameStart, frameTime; - bool running = true; - SDL_Event e; + static input_state is = {}; - while (running) { + while (rs->running) { frameStart = SDL_GetTicks(); - while (SDL_PollEvent(&e)) { - if ((e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) - || e.type == SDL_QUIT) { - running = false; + if (cb_func_pre != nullptr) { + cb_func_pre(rs); + } else { + inputProcessEvents(&is); + + if (is.window_closed || is.escape) { + rs->running = false; + return; } } - if (cb_func != nullptr) cb_func(rs); renRenderFrame(rs); + if (cb_func_post != nullptr) cb_func_post(rs); + SDL_GL_SwapWindow(rs->handles->window); frameTime = SDL_GetTicks() - frameStart; @@ -287,6 +294,7 @@ openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, void setDefaults(render_state* rs, glm::vec2 viewport_dims) { + rs->running = true; rs->viewport_dims = viewport_dims; rs->lights = lightsInit(); rs->clear_col.R = CLEAR_COL_R;