#include "game.h" 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: { 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(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: break; } } void draw_line(GameState *state, Vec3 position, Vec2 size, r32 rotation, Vec3 color) { glUseProgram(state->line_sp); Mat4 model = calcify_ident4m(); 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); 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->line_sp, "Model"); 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}); } } }