From 9044db4794e95ef9dbc2d5bfde4215ddc82d6ae8 Mon Sep 17 00:00:00 2001 From: talha Date: Mon, 29 Dec 2025 13:45:53 +0500 Subject: added 2d "meshes" --- source/calcify.h | 42 ++++++++++++ source/core.h | 4 ++ source/game/game.cpp | 144 ++++++++++++++++++++++++++++++++------- source/game/game.h | 22 +++++- source/sdlmain.cpp | 187 ++++++++++++++++++++++++++++++++++++--------------- 5 files changed, 317 insertions(+), 82 deletions(-) (limited to 'source') diff --git a/source/calcify.h b/source/calcify.h index d0c3499..0814df7 100644 --- a/source/calcify.h +++ b/source/calcify.h @@ -22,6 +22,15 @@ typedef int8_t b8; #define ABS(x) ((x) > 0 ? (x) : -(x)) #define MIN(x, y) ((x) < (y) ? (y) : (x)) #define MAX(x, y) ((x) > (y) ? (y) : (x)) +#define CLAMP(x, lo, hi) ((x) <= (lo) ? (lo) : ((x) >= (hi) ? (hi) : (x))) + +union Vec2 { + struct { + r32 x; + r32 y; + }; + r32 buffer[2]; +}; union Vec3 { struct { @@ -53,6 +62,7 @@ union Mat4 { r32 buffer[16]; }; +Vec3 calcify_normalize3v(Vec3 v); Mat4 calcify_init4m(void); Mat4 calcify_ident4m(void); Mat4 calcify_multiply4mv(Mat4 a, Mat4 b); @@ -60,6 +70,14 @@ Mat4 calcify_multiply4m(Mat4 a, Mat4 b); Mat4 calcify_translation_matrix4m(r32 x, r32 y, r32 z); Mat4 calcify_ortho4m(r32 left, r32 right, r32 top, r32 bot, r32 near, r32 far); +Vec3 calcify_normalize3v(Vec3 v) { + Vec3 res = {}; + r32 len = sqrt((v.x*v.x) + (v.y*v.y) + (v.z*v.z)); + res = (Vec3){v.x/len, v.y/len, v.z/len}; + + return res; +} + Mat4 calcify_init4m(void) { Mat4 res; memset(&res, 0, sizeof(Mat4)); @@ -132,6 +150,30 @@ Mat4 calcify_scaling_matrix4m(r32 x, r32 y) { return scale; } +Mat4 calcify_rotation_matrix4m(r32 angle_radians, Vec3 axis) +{ + Mat4 res = calcify_ident4m(); + axis = calcify_normalize3v(axis); + + r32 cos_theta = cosf(angle_radians); + r32 sin_theta = sinf(angle_radians); + r32 cos_value = 1.0f - cos_theta; + + res.array[0][0] = (axis.x * axis.x * cos_value) + cos_theta; + res.array[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta); + res.array[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta); + + res.array[1][0] = (axis.x * axis.y * cos_value) - (axis.z * sin_theta); + res.array[1][1] = (axis.y * axis.y * cos_value) + cos_theta; + res.array[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta); + + res.array[2][0] = (axis.x * axis.z * cos_value) + (axis.y * sin_theta); + res.array[2][1] = (axis.y * axis.z * cos_value) - (axis.x * sin_theta); + res.array[2][2] = (axis.z * axis.z * cos_value) + cos_value; + + return res; +} + Mat4 calcify_ortho4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far) { Mat4 res = calcify_init4m(); res.array[0][0] = 2.0f/(right - left); diff --git a/source/core.h b/source/core.h index fe9daf9..0befdfc 100644 --- a/source/core.h +++ b/source/core.h @@ -24,8 +24,12 @@ struct GameState { u32 triangle_sp; u32 triangle_vao; u32 triangle_vbo; + u32 line_sp; + u32 line_vao; + u32 line_vbo; i32 width; i32 height; + r32 run_i; }; enum GameEventType { diff --git a/source/game/game.cpp b/source/game/game.cpp index 337fe11..4229483 100644 --- a/source/game/game.cpp +++ b/source/game/game.cpp @@ -1,25 +1,86 @@ #include "game.h" -void game_setup(GameState *state) { - glUseProgram(state->triangle_sp); +Cloth game_cloth = { + .width = 32, + .elasticity = 10.0f, + .padding = 30.0f, +}; + +void game_init(GameState *state) { + i32 cloth_rows = NUM_POINTS / game_cloth.width; + Vec2 start_pos = { + .x = state->width / 4.0f, + .y = state->height - state->height/4.0f + }; + + i32 max_rows = NUM_POINTS / game_cloth.width; + i32 max_cols = game_cloth.width; + i32 curr_row = 0, curr_col = 0; + Vec2 running_pos = start_pos; + for (i32 i = 0; i < NUM_POINTS; i++) { + Point p = { + .id = i, + .active = 1, + .prev_pos = running_pos, + .curr_pos = running_pos, + .force = {0.0f,0.0f} + }; + { + // @fixme + i32 left_ind = i%max_cols == 0 ? -1 : i-1; + i32 right_ind = i%max_cols == max_cols - 1 ? -1 : i+1; + i32 top_ind = i/max_cols == 0 ? -1 : i - max_cols; + i32 bot_ind = i/max_cols == max_rows-1 ? -1 : i + max_cols; + p.constraints[0] = left_ind; + p.constraints[1] = top_ind; + p.constraints[2] = right_ind; + p.constraints[3] = bot_ind; + } + game_cloth.points[i] = p; + + // next position + i32 next_row = (i+1)/max_cols; + i32 next_col = (i+1)%max_cols; + Vec2 next_pos = { + start_pos.x + game_cloth.padding*next_col, + start_pos.y - game_cloth.padding*next_row + }; + running_pos = next_pos; + } +} + +void game_shader_init_uniforms(GameState *state) { Mat4 projection = calcify_ortho4m(0.0f, state->width, 0.0f, state->height, 0.1f, 10.0f); + + glUseProgram(state->triangle_sp); i32 triangle_proj_loc = glGetUniformLocation(state->triangle_sp, "Projection"); glUniformMatrix4fv(triangle_proj_loc, 1, 0, projection.buffer); + + glUseProgram(state->line_sp); + i32 line_proj_loc = glGetUniformLocation(state->line_sp, "Projection"); + glUniformMatrix4fv(line_proj_loc, 1, 0, projection.buffer); + glUseProgram(0); }; void game_handle_event(GameState *state, GameEventType type) { switch (type) { case GAME_EVENT_RESIZE: { - glUseProgram(state->triangle_sp); glViewport(0, 0, state->width, state->height); - Mat4 projection = calcify_ortho4m(0.0f, state->width, 0.0f, state->height, 1.0f, 10.0f); + + glUseProgram(state->triangle_sp); + // @step: update triangle sp i32 triangle_proj_loc = glGetUniformLocation(state->triangle_sp, "Projection"); glUniformMatrix4fv(triangle_proj_loc, 1, 0, projection.buffer); - glUseProgram(0); + glUseProgram(state->line_sp); + // @step: update line sp + i32 line_proj_loc = glGetUniformLocation(state->line_sp, "Projection"); + glUniformMatrix4fv(line_proj_loc, + 1, 0, + projection.buffer); } break; default: @@ -27,30 +88,61 @@ void game_handle_event(GameState *state, GameEventType type) { } } -void game_update_and_render(GameState *state) { - glClearColor(0.1f, 0.1f, 0.1f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); +void draw_line(GameState *state, Vec3 position, Vec2 size, r32 rotation, Vec3 color) { + glUseProgram(state->line_sp); - glUseProgram(state->triangle_sp); Mat4 model = calcify_ident4m(); - Mat4 scale = calcify_scaling_matrix4m(105.0f, 95.0f); - model = calcify_multiply4m(scale, model); + Mat4 rotate = calcify_rotation_matrix4m(rotation, {.x=0,.y=0,.z=1}); + Mat4 origin_set = calcify_translation_matrix4m(size.x/2.0f, + 0.0f, + 0.0f); + Mat4 scale = calcify_scaling_matrix4m(size.x, size.y); + Mat4 pos = calcify_translation_matrix4m(position.x, + position.y, + position.z); - Mat4 pos = calcify_translation_matrix4m(350.0f, 950.0f, -1.0f); + model = calcify_multiply4m(scale, model); + model = calcify_multiply4m(origin_set, model); + model = calcify_multiply4m(rotate, model); model = calcify_multiply4m(pos, model); - i32 model_loc = glGetUniformLocation(state->triangle_sp, + + i32 model_loc = glGetUniformLocation(state->line_sp, "Model"); - glUniformMatrix4fv( - model_loc, - 1, 0, - model.buffer - ); - - Vec3 Color = (Vec3){.r=0.4,.g=0.9,.b=0.7}; - glUniform3f(glGetUniformLocation(state->triangle_sp, - "Color"), - Color.r, Color.g, Color.b); - glBindVertexArray(state->triangle_vao); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); + glUniformMatrix4fv(model_loc, + 1, 0, + model.buffer); + i32 color_loc = glGetUniformLocation(state->line_sp, + "Color"); + glUniform3f(color_loc, color.x, color.y, color.z); + + glBindVertexArray(state->line_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glUseProgram(0); +} + +void game_update_and_render(GameState *state) { + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + for (int i = 0; i < NUM_POINTS; i++) { + Point p = game_cloth.points[i]; + if (!p.active) continue; + + for (int c = 2; c < 4; c++) { + i32 ci = p.constraints[c]; + if (ci == -1) continue; + Point constraint = game_cloth.points[ci]; + Vec2 a = p.curr_pos; + Vec2 b = constraint.curr_pos; + Vec2 dir_vector = {b.x - a.x, b.y - a.y}; + r32 line_length = sqrt(dir_vector.x*dir_vector.x + + dir_vector.y*dir_vector.y); + r32 rot_angle = atan2(dir_vector.y,dir_vector.x); + draw_line(state, + {a.x, a.y, -1.0f}, + {line_length, 3.0f}, + rot_angle, + {0.4f, 0.5f, 0.7f}); + } + } } diff --git a/source/game/game.h b/source/game/game.h index 4c6f1f2..6cd5d56 100644 --- a/source/game/game.h +++ b/source/game/game.h @@ -12,9 +12,29 @@ #endif extern "C" { + EXPORT void game_init(GameState *state); + EXPORT void game_shader_init_uniforms(GameState *state); EXPORT void game_handle_event(GameState *state, GameEventType type); - EXPORT void game_setup(GameState *state); EXPORT void game_update_and_render(GameState *state); } +struct Point { + i32 id; + b8 active; + Vec2 prev_pos; + Vec2 curr_pos; + Vec2 force; + i32 constraints[4]; +}; +typedef struct Point Point; + +#define NUM_POINTS 1024 +struct Cloth { + i32 width; + r32 elasticity; + r32 padding; + Point points[NUM_POINTS]; +}; +typedef struct Cloth Cloth; + #endif // AMR_GAME_H diff --git a/source/sdlmain.cpp b/source/sdlmain.cpp index 372758a..bc269c9 100644 --- a/source/sdlmain.cpp +++ b/source/sdlmain.cpp @@ -18,14 +18,16 @@ #endif // GAME LIBRARY FUNCTIONS +typedef void (*GameInit)(GameState*); +typedef void (*GameShaderInitUniforms)(GameState*); typedef void (*GameHandleEvent)(GameState*, GameEventType); -typedef void (*GameSetup)(GameState*); typedef void (*GameUpdateAndRender)(GameState*); struct GameLayer { void *lib; + GameInit init; + GameShaderInitUniforms shader_init_uniforms; GameHandleEvent handle_event; - GameSetup setup; GameUpdateAndRender update_and_render; }; internal GameLayer game_layer; @@ -40,12 +42,15 @@ bool load_game_layer() if (game_layer.lib == NULL) { return false; } + game_layer.init = + (GameInit)SDL_LoadFunction(game_layer.lib, + "game_init"); + game_layer.shader_init_uniforms = + (GameShaderInitUniforms)SDL_LoadFunction(game_layer.lib, + "game_shader_init_uniforms"); game_layer.handle_event = (GameHandleEvent)SDL_LoadFunction(game_layer.lib, "game_handle_event"); - game_layer.setup = - (GameSetup)SDL_LoadFunction(game_layer.lib, - "game_setup"); game_layer.update_and_render = (GameUpdateAndRender)SDL_LoadFunction(game_layer.lib, "game_update_and_render"); @@ -53,19 +58,6 @@ bool load_game_layer() return true; } -bool game_file_update(fswatcher_event_handler *handler, - fswatcher_event_type evtype, - const char *src, - const char *dst) { - return load_game_layer(); -} - -//bool game_shader_update(fswatcher_event_handler *handler, -// fswatcher_event_type evtype, -// const char *src, -// const char *dst) { -//} - u32 gl_shader_program(char *vs, char *fs) { //============== @@ -166,8 +158,112 @@ u32 gl_shader_program_from_path(const char *vspath, const char *fspath) return shader_program; } +void setup_shaders(GameState *state, bool reinit=false) { + if (reinit) { + // we have to delete previous state + glDeleteVertexArrays(1, &state->triangle_vao); + glDeleteBuffers(1, &state->triangle_vbo); + glDeleteProgram(state->triangle_sp); + + glDeleteVertexArrays(1, &state->line_vao); + glDeleteBuffers(1, &state->line_vbo); + glDeleteProgram(state->line_sp); + } + // triangle shader program + u32 triangle_shader_program = gl_shader_program_from_path("./shaders/quad.vs.glsl", + "./shaders/quad.fs.glsl"); + + state->triangle_sp = triangle_shader_program; + glUseProgram(state->triangle_sp); + + // @func: gl_setup_triangle + { + GLfloat vertices[9] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f + }; + + GLuint VBO, VAO; + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + state->triangle_vao = VAO; + state->triangle_vbo = VBO; + } + glUseProgram(0); + + // line shader program + u32 line_shader_program = gl_shader_program_from_path("./shaders/quad.vs.glsl", + "./shaders/quad.fs.glsl"); + state->line_sp = line_shader_program; + glUseProgram(state->line_sp); + + // @func: gl_setup_line + { + GLfloat vertices[12] = { + -0.5f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + }; + + GLuint VBO, VAO; + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + state->line_vao = VAO; + state->line_vbo = VBO; + + } +} + +bool game_file_update(fswatcher_event_handler *handler, + fswatcher_event_type evtype, + const char *src, + const char *dst) { + GameState *state = (GameState*)handler->custom_data; + load_game_layer(); + game_layer.init(state); + return 1; +} + +bool shader_file_update(fswatcher_event_handler *handler, + fswatcher_event_type evtype, + const char *src, + const char *dst) { + GameState *state = (GameState*)handler->custom_data; + setup_shaders(state, true); + game_layer.shader_init_uniforms(state); + return 1; +} + int main(int argc, char *argv[]) { + GameState state = {}; + i32 raw_width = 1920; i32 raw_height = 1080; i32 dpi_width; @@ -177,8 +273,6 @@ int main(int argc, char *argv[]) i32 width; i32 height; - GameState state = {}; - if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("Error initialising SDL2: %s\n", SDL_GetError()); @@ -225,52 +319,29 @@ int main(int argc, char *argv[]) SDL_GL_SetSwapInterval(1); - u32 shader_program = gl_shader_program_from_path("./shaders/quad.vs.glsl", - "./shaders/quad.fs.glsl"); - - state.triangle_sp = shader_program; - glUseProgram(state.triangle_sp); - - // @func: gl_setup_triangle - { - GLfloat vertices[9] = { - -0.5f, -0.5f, 0.0f, - 0.5f, -0.5f, 0.0f, - 0.0f, 0.5f, 0.0f - }; - - GLuint VBO, VAO; - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - - glBindVertexArray(VAO); - - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - - state.triangle_vao = VAO; - state.triangle_vbo = VBO; - } - glUseProgram(0); + setup_shaders(&state); + // add shader watcher + fswatcher_t shader_watcher = fswatcher_create(FSWATCHER_CREATE_DEFAULT, + FSWATCHER_EVENT_MODIFY, + "shaders", NULL); + fswatcher_event_handler shader_file_update_handler; + shader_file_update_handler.callback = shader_file_update; + shader_file_update_handler.custom_data = &state; // add file watcher fswatcher_t game_watcher = fswatcher_create(FSWATCHER_CREATE_DEFAULT, FSWATCHER_EVENT_MODIFY, "source/game", NULL); fswatcher_event_handler game_file_update_handler; game_file_update_handler.callback = game_file_update; + game_file_update_handler.custom_data = &state; // load game layer if (!load_game_layer()) { return -1; } - game_layer.setup(&state); + game_layer.init(&state); + game_layer.shader_init_uniforms(&state); for(;;) { @@ -296,16 +367,22 @@ int main(int argc, char *argv[]) } } fswatcher_poll(game_watcher, &game_file_update_handler, NULL); + fswatcher_poll(shader_watcher, &shader_file_update_handler, NULL); - // opengl rendering code here game_layer.update_and_render(&state); + SDL_GL_SwapWindow(window); } // filewatcher fswatcher_destroy(game_watcher); + fswatcher_destroy(shader_watcher); // opengl free calls + glDeleteVertexArrays(1, &state.line_vao); + glDeleteBuffers(1, &state.line_vbo); + glDeleteProgram(state.line_sp); + glDeleteVertexArrays(1, &state.triangle_vao); glDeleteBuffers(1, &state.triangle_vbo); glDeleteProgram(state.triangle_sp); -- cgit v1.2.3