From f21c8ca19954b45050bb86c381cc7c439383342c Mon Sep 17 00:00:00 2001 From: 0scar Date: Mon, 12 Feb 2024 17:26:31 +0100 Subject: Add camera --- src/core/include/engine/core/platform.h | 3 +- src/core/include/engine/engine.h | 1 - src/core/src/loop.c | 45 +++--------- src/ctrl/CMakeLists.txt | 1 + src/ctrl/include/engine/ctrl/input.h | 11 +-- src/ctrl/include/engine/ctrl/scancodes.h | 82 ++++++++++++++++++++++ src/ctrl/src/input.c | 65 ++++++++++++++++- src/rendering/include/engine/rendering/rendering.h | 13 ++++ src/rendering/src/gl.c | 2 - src/rendering/src/rendering.c | 27 ++++--- src/rendering/src/window.c | 2 +- 11 files changed, 196 insertions(+), 56 deletions(-) create mode 100644 src/ctrl/include/engine/ctrl/scancodes.h diff --git a/src/core/include/engine/core/platform.h b/src/core/include/engine/core/platform.h index 9dc9a8b..76137c9 100644 --- a/src/core/include/engine/core/platform.h +++ b/src/core/include/engine/core/platform.h @@ -32,8 +32,7 @@ typedef struct Platform { bool mouse_lclick; bool mouse_rclick; - i32 camera_x; - i32 camera_y; + Camera *cam; /* Global resources that live from engine_init to engine_free */ Resources* resources; diff --git a/src/core/include/engine/engine.h b/src/core/include/engine/engine.h index d5b0922..75f6313 100644 --- a/src/core/include/engine/engine.h +++ b/src/core/include/engine/engine.h @@ -39,7 +39,6 @@ void render_set_zoom(f32 new_zoom); void render_adjust_zoom(f32 diff); void render_add_unit(RenderUnit* u); - /* Input handling */ void engine_input_ctx_push(i_ctx* ctx); void engine_input_ctx_pop(void); diff --git a/src/core/src/loop.c b/src/core/src/loop.c index f9c100c..c4435fb 100644 --- a/src/core/src/loop.c +++ b/src/core/src/loop.c @@ -36,6 +36,10 @@ Platform* GLOBAL_PLATFORM = NULL; +static Camera default_camera = { + .pos = {3, 0, 0}, +}; + input_callback_t* callbacks[128]; usize callbacks_len; @@ -235,9 +239,6 @@ Platform* engine_init(const char* windowtitle, i32 windowWidth, i32 windowHeight p->mouse_lclick = false; p->mouse_rclick = false; - p->camera_x = 0; - p->camera_y = 0; - p->edit_text = NULL; p->edit_pos = 0; @@ -245,6 +246,9 @@ Platform* engine_init(const char* windowtitle, i32 windowWidth, i32 windowHeight p->bindings_sz = 0; p->bindings_len = 0; + p->cam = &default_camera; + glm_ortho_default(45.f, p->cam->per); + { int x,y,n; test_image = stbi_load(img_filename, &x, &y, &n, 0); @@ -351,8 +355,7 @@ i32 engine_run(Platform* p, StateType initial_state, void* state_arg) { // // } // -// i_flush_bindings(callbacks_len, mem->data, callbacks); -// callbacks_len = 0; + i_flush_bindings(dt, callbacks_len, callbacks, mem->data); // // /* update */ StateType next_state; @@ -368,6 +371,9 @@ i32 engine_run(Platform* p, StateType initial_state, void* state_arg) { engine_input_ctx_reset(); + // Reset camera to default camera + p->cam = &default_camera; + state = next_state; update_func = State_updateFunc(state); { @@ -381,35 +387,6 @@ i32 engine_run(Platform* p, StateType initial_state, void* state_arg) { render_begin(p->window); - //gl->UseProgram(p->testobject->shaderprogram); - - //{ - // vec3 cam = {4., 3., 3.}; // perspective - // mat4 per; // perspective - // mat4 v; // view - // mat4 model = GLM_MAT4_IDENTITY_INIT; - // mat4 modelviewprojection; - - // f32 ratio = (float)p->window->windowsize.x / (float)p->window->windowsize.y; - // //glm_perspective(45.f , 600.f / 400.f, 0.1, 100.0f, per); - // glm_ortho(-10 * ratio, 10 * ratio, -10, 10, -10, 10, per); - - // glm_lookat(cam, GLM_VEC3_ZERO, GLM_YUP, v); - - // { mat4 t; - // //modelviewprojection = p * v * model - // glm_mat4_mul(v, model, t); - // glm_rotate_at(t, (vec3){0,0,0}, get_time() / 2.f, (vec3){0,1,0}); //, (vec3)({0,1,0})); - // glm_mat4_mul(per, t, modelviewprojection); - // } - - // // TODO: Do this only once during initialization - // u32 matrix = gl->GetUniformLocation(p->testobject->shaderprogram, "MVP"); - - // gl->UniformMatrix4fv(matrix, 1, GL_FALSE, &modelviewprojection[0][0]); - //} - - //gl->EnableVertexAttribArray(0); //gl->BindBuffer(GL_ARRAY_BUFFER, p->testobject->vbo); //gl->VertexAttribPointer( diff --git a/src/ctrl/CMakeLists.txt b/src/ctrl/CMakeLists.txt index 3f76069..e7dd0a9 100644 --- a/src/ctrl/CMakeLists.txt +++ b/src/ctrl/CMakeLists.txt @@ -7,3 +7,4 @@ add_library(daw_ctrl ) target_include_directories(daw_ctrl PRIVATE ${DAW_INCLUDE_DIRS}) +target_link_libraries(daw_ctrl PRIVATE cglm glfw) diff --git a/src/ctrl/include/engine/ctrl/input.h b/src/ctrl/include/engine/ctrl/input.h index 26a5f5b..d06dcfe 100644 --- a/src/ctrl/include/engine/ctrl/input.h +++ b/src/ctrl/include/engine/ctrl/input.h @@ -1,9 +1,10 @@ -#ifndef INPUT_H -#define INPUT_H +#ifndef ENGINE_CTRL_INPUT_H +#define ENGINE_CTRL_INPUT_H #include +#include -typedef void input_callback_t(void*); +typedef void input_callback_t(f64, void*); typedef i32 scancode_t; typedef enum InputType { @@ -49,9 +50,11 @@ typedef struct i_ctx { void i_ctx_t_free(i_ctx* c); /* Executes all callbacks that has been pushed onto the callstack and resets the * callstack */ -void i_flush_bindings(usize numcalls, void* state_mem, input_callback_t* c[]); +void i_flush_bindings(f64 dt, usize numcalls, input_callback_t* c[], void* state_mem); action_t i_get_action(const i_ctx* restrict ctx, u32 time, scancode_t scancode); +void key_callback(void* window, int key, int scancode, int action, int mods); + void i_ctx_push(i_ctx* ctx); void i_ctx_pop(void); void i_ctx_reset(void); diff --git a/src/ctrl/include/engine/ctrl/scancodes.h b/src/ctrl/include/engine/ctrl/scancodes.h new file mode 100644 index 0000000..90bd749 --- /dev/null +++ b/src/ctrl/include/engine/ctrl/scancodes.h @@ -0,0 +1,82 @@ +#ifndef ENGINE_CTRL_SCANCODES_H + +// We want to reserve the following bytes marked with X for MODS, +// one bit per MODIFIER (shift, control, alt, super): +// XXXX 0000 0000 0000 0000 0000 0000 0000 +// +// We want to reserve the following bytes marked with X for ACTIONS +// enumerate by action type, pressed, released, repeat +// 0000 0000 XXXX 0000 0000 0000 0000 0000 +// +// We want to reserve the following bytes marked with X for the SCANCODE +// 0000 0000 0000 0000 XXXX XXXX XXXX XXXX +#define MOD(x) 1 << (32-4 + x) +#define ACTION(x) (1 << (32-8)) + x + +typedef enum { + KEY_SPACE = ' ', + KEY_APOSTROPHE = '\'', + KEY_COMMA = ',', + KEY_MINUS = '-', + KEY_PERIOD = '.', + KEY_SLASH = '/', + + KEY_0 = '0', + KEY_1 = '1', + KEY_2 = '2', + KEY_3 = '3', + KEY_4 = '4', + KEY_5 = '5', + KEY_6 = '6', + KEY_7 = '7', + KEY_8 = '8', + KEY_9 = '9', + + KEY_SEMICOLON = ';', + KEY_EQUAL = '=', + + KEY_A = 'A', + KEY_B = 'B', + KEY_C = 'C', + KEY_D = 'D', + KEY_E = 'E', + KEY_F = 'F', + KEY_G = 'G', + KEY_H = 'H', + KEY_I = 'I', + KEY_J = 'J', + KEY_K = 'K', + KEY_L = 'L', + KEY_M = 'M', + KEY_N = 'N', + KEY_O = 'O', + KEY_P = 'P', + KEY_Q = 'Q', + KEY_R = 'R', + KEY_S = 'S', + KEY_T = 'T', + KEY_U = 'U', + KEY_V = 'V', + KEY_W = 'W', + KEY_X = 'X', + KEY_Y = 'Y', + KEY_Z = 'Z', + + KEY_LEFT_BRACKET = '[', + KEY_BACKSLASH = '\\', + KEY_RIGHT_BRACKET = ']', + KEY_GRAVE_ACCENT = '`', + + ACTION_PRESS = ACTION(0), + ACTION_RELEASE = ACTION(1), + ACTION_REPEAT = ACTION(2), + + MOD_SHIFT = MOD(0), + MOD_CONTROL = MOD(1), + MOD_ALT = MOD(2), + MOD_SUPER = MOD(3), +} ScanCode; +#undef ACTION +#undef MOD + +#endif diff --git a/src/ctrl/src/input.c b/src/ctrl/src/input.c index 3b6a4df..5fe643e 100644 --- a/src/ctrl/src/input.c +++ b/src/ctrl/src/input.c @@ -1,8 +1,13 @@ #include #include +#include #include #include +extern input_callback_t* callbacks[128]; +extern usize callbacks_len; + +extern Platform* GLOBAL_PLATFORM; /* Lazy binds, used internally. They are similar to BindAction and friends. * The only difference is that we set callbacks and such to NULL, but populate * the function name strings such that can be reloaded. */ @@ -30,6 +35,60 @@ .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \ } +void key_callback(void* window, int key, int scancode, int action, int mods) { + + const i_ctx* bindings = *GLOBAL_PLATFORM->bindings; + const usize bindings_len = GLOBAL_PLATFORM->bindings_len; + + const f64 now = get_time(); + + for (usize b = 0; b < bindings_len; b++) { + const action_t a = i_get_action(&bindings[b], now, scancode); + switch (action) { + case GLFW_PRESS: + + switch (a.type) { + case InputType_action: + if (a.action.callback != NULL) { + callbacks[callbacks_len++] = a.action.callback; + } + break; + + case InputType_state: + if (a.state.activate != NULL) { + callbacks[callbacks_len++] = a.state.activate; + } + break; + case InputType_range: + WARN("Range inputs not supported yet!"); + break; + case InputType_error: + WARN("Unhandled scancode: %lu", scancode); + + default: + break; + } + break; + + case GLFW_RELEASE: + switch (a.type) { + case InputType_state: + if (a.state.deactivate != NULL) { + callbacks[callbacks_len++] = a.state.deactivate; + } + break; + default:break; + } + break; + case GLFW_REPEAT: + /* unhandled so far */ + break; + default: + break; + } + } +} + void binding_t_free(binding_t* b) { switch (b->action.type) { case InputType_error: @@ -129,10 +188,12 @@ bool i_update_unique_binding(i_ctx* ctx, binding_t* binding) { return false; } -void i_flush_bindings(usize numcalls, void* state_mem, input_callback_t* c[]) { +void i_flush_bindings(f64 dt, usize numcalls, input_callback_t* c[], void* state_mem) { for (usize i = 0; i < numcalls; i++) { - (c[i])(state_mem); + (c[i])(dt, state_mem); } + // reset callback len and be ready for more + callbacks_len = 0; } action_t i_get_action(const i_ctx* restrict ctx, u32 time, diff --git a/src/rendering/include/engine/rendering/rendering.h b/src/rendering/include/engine/rendering/rendering.h index ed066d6..bc9e07a 100644 --- a/src/rendering/include/engine/rendering/rendering.h +++ b/src/rendering/include/engine/rendering/rendering.h @@ -60,6 +60,14 @@ typedef struct { u32 mvp; } RenderObject; +typedef struct { + /* Position of the camera in world-space. */ + vec3 pos; + /* Perspective matrix. Initialize with r_perspective_ortho or r_perspective. */ + /* Alternatively, use `glm_perspective` or `glm_ortho`. */ + mat4 per; +} Camera; + /* Rendering functions */ void render_begin(Window* w); void render_present(Window* w); @@ -67,6 +75,11 @@ void drawcall_reset(void); void render(Window* w); /* Misc */ +void r_perspective(f32 ratio, f32 fov, Camera *c); +void r_perspective_ortho(f32 ratio, f32 sz, Camera *c); + +void r_set_camera(Camera* c); + //void window_size_callback(GLFWwindow* window, i32 width, i32 height); //void engine_window_resize_pointers(i32* w, i32* h); //void engine_window_resize_pointers_reset(void); diff --git a/src/rendering/src/gl.c b/src/rendering/src/gl.c index ab41f01..5ca5e91 100644 --- a/src/rendering/src/gl.c +++ b/src/rendering/src/gl.c @@ -190,8 +190,6 @@ RenderObject RenderObject_new(float* model, Shader* shader, usize sz, float* uv, //DEBUG("RenderObject got %d: %s\n", shader->program, ShaderType_str[shader->type]); - // TODO: implement index buffer! - gl->GenVertexArrays(1, &(o.vao)); gl->BindVertexArray(o.vao); diff --git a/src/rendering/src/rendering.c b/src/rendering/src/rendering.c index 77cd285..b74a146 100644 --- a/src/rendering/src/rendering.c +++ b/src/rendering/src/rendering.c @@ -32,6 +32,7 @@ void render_present(Window* w) { /* This is GL specific, TODO: move the GL-specific code elsewhere. Maybe make * this whole present GL specific? assign it as a fn ptr in the Window struct? */ GladGLContext *gl = w->context; + Camera c = *GLOBAL_PLATFORM->cam; const f32 ratio = (float)w->windowsize[0] / (float)w->windowsize[1]; for (i32 i = 0; i < drawcall_len; i++) { @@ -76,31 +77,25 @@ void render_present(Window* w) { { - vec3 cam = {-3., 2., -3.}; // perspective - mat4 per; // perspective mat4 v; // view mat4 model = GLM_MAT4_IDENTITY_INIT; mat4 modelviewprojection; - const float sz = 10.f; - //LOG("<%.1f, %.1f, %.1f>", pos[0], pos[1], pos[2]); model[3][0] = pos[0]; model[3][1] = pos[1]; model[3][2] = pos[2]; - //glm_perspective(45.f , 600.f / 400.f, 0.1, 100.0f, per); - glm_ortho(-sz * ratio, sz * ratio, -sz, sz, -sz, sz, per); - /* Lookat zero should be changed to whatever later */ - glm_lookat(cam, GLM_VEC3_ZERO, GLM_YUP, v); + glm_lookat(c.pos, GLM_VEC3_ZERO, GLM_YUP, v); { mat4 t; //modelviewprojection = p * v * model glm_mat4_mul(v, model, t); + // TODO: Remove this later - glm_rotate_at(t, (vec3){0,0,0}, get_time() / 2.f, GLM_YUP); //, (vec3)({0,1,0})); + //glm_rotate_at(t, (vec3){0,0,0}, get_time() / 2.f, GLM_YUP); //, (vec3)({0,1,0})); - glm_mat4_mul(per, t, modelviewprojection); + glm_mat4_mul(c.per, t, modelviewprojection); } // TODO: Do this only once during initialization @@ -168,6 +163,18 @@ void render_present(Window* w) { void drawcall_reset(void) { drawcall_len = 0; } +void r_perspective(f32 ratio, f32 fov, Camera *c) { + glm_perspective(fov , ratio, 0.1, 100.0f, c->per); +} + +void r_perspective_ortho(f32 ratio, f32 sz, Camera *c) { + glm_ortho(-sz * ratio, sz * ratio, -sz, sz, -sz, sz, c->per); +} + +void r_set_camera(Camera* c) { + GLOBAL_PLATFORM->cam = c; +} + void engine_window_resize_pointers(i32* w, i32* h) { //GLOBAL_PLATFORM->window->game_w = w; //GLOBAL_PLATFORM->window->game_h = h; diff --git a/src/rendering/src/window.c b/src/rendering/src/window.c index 9c04957..a1a5833 100644 --- a/src/rendering/src/window.c +++ b/src/rendering/src/window.c @@ -101,7 +101,7 @@ Window* init_window_glfw( // Setup callbacks // TODO: input handler callback glfwSetFramebufferSizeCallback(window, window_size_callback); - + glfwSetKeyCallback(window, (GLFWkeyfun)key_callback); //glfwMakeContextCurrent(window); //glfwSwapInterval(0); -- cgit v1.3