From 3f75bb7ef6286edf144ec979d1e806ad69bbba3a Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 29 Oct 2020 21:12:51 -0500 Subject: [PATCH] added moving camera --- include/utils.h | 54 +++++++++++++++++++----------------- res/shaders/planet_vert.glsl | 5 ++-- src/sim.cpp | 43 ++++++++++++++++------------ src/utils.cpp | 44 ++++++++++++++++------------- 4 files changed, 82 insertions(+), 64 deletions(-) diff --git a/include/utils.h b/include/utils.h index 09b3217..604edbf 100644 --- a/include/utils.h +++ b/include/utils.h @@ -42,28 +42,28 @@ struct FixedArenaAllocator T* base_ptr; T* end_ptr; T* curr_ptr; - + void init(i32 max_members = 16) { base_ptr = (T *) malloc(sizeof(T) * max_members); curr_ptr = base_ptr; end_ptr = base_ptr + max_members; } - + void free_all() { free(base_ptr); } - + void reset() { curr_ptr = base_ptr; } - + T* alloc() { if (curr_ptr >= end_ptr) return nullptr; - + auto res = curr_ptr; curr_ptr += 1; return res; @@ -75,24 +75,24 @@ struct AABB { float x, y; float w, h; - + bool contains(float ox, float oy) const; bool intersects(AABB other) const; }; -#define QUAD_TREE_POINTS_PER_NODE 8 +#define QUAD_TREE_POINTS_PER_NODE 4 template struct QuadTree { T* points[QUAD_TREE_POINTS_PER_NODE]; u32 point_count; AABB region; - + QuadTree* nw; QuadTree* ne; QuadTree* sw; QuadTree* se; - + void init(AABB initial_region) { region = initial_region; @@ -101,63 +101,63 @@ struct QuadTree sw = nullptr; se = nullptr; point_count = 0; - + foreach (i, 0, QUAD_TREE_POINTS_PER_NODE) { points[i] = nullptr; } } - + void subdivide(FixedArenaAllocator>* a) { if (nw != nullptr) return; - + auto hw = region.w / 2.0f; auto hh = region.h / 2.0f; - + nw = a->alloc(); ne = a->alloc(); sw = a->alloc(); se = a->alloc(); - + nw->init(AABB { region.x, region.y, hw, hh }); ne->init(AABB { region.x + hw, region.y, hw, hh }); sw->init(AABB { region.x, region.y + hh, hw, hh }); se->init(AABB { region.x + hw, region.y + hh, hw, hh }); } - + bool insert(T* t, FixedArenaAllocator>* a) { V2f pos = t->pos; // T is expected to have a 'pos' member. - + if (!region.contains(pos.x, pos.y)) return false; - + if (point_count < QUAD_TREE_POINTS_PER_NODE && nw == nullptr) { points[point_count] = t; point_count += 1; return true; } - + if (nw == nullptr) this->subdivide(a); - + if (nw->insert(t, a)) return true; if (ne->insert(t, a)) return true; if (sw->insert(t, a)) return true; if (se->insert(t, a)) return true; - + return false; } - + void query(AABB r, Array* point_list) const { if (!region.intersects(r)) return; - + foreach (i, 0, point_count) if (r.contains(points[i]->pos.x, points[i]->pos.y)) point_list->push(points[i]); - + if (nw == nullptr) return; - + nw->query(r, point_list); ne->query(r, point_list); sw->query(r, point_list); @@ -170,9 +170,11 @@ struct Camera { V2f offset; f32 scale; + i32 window_width, window_height; }; -void camera_to_mat4(Camera cam, mat4* mat); +void camera_ortho_mat4(Camera cam, mat4* mat); +void camera_world_mat4(Camera cam, mat4* mat); u32 load_shader(u32 shader_type, const char* shader_loc); @@ -223,4 +225,4 @@ operator*(defer_dummy, F f) #endif // defer -#endif //UTILS_H \ No newline at end of file +#endif //UTILS_H diff --git a/res/shaders/planet_vert.glsl b/res/shaders/planet_vert.glsl index ee7ccde..2579da6 100644 --- a/res/shaders/planet_vert.glsl +++ b/res/shaders/planet_vert.glsl @@ -10,9 +10,10 @@ layout(location = 3) in float a_planet_color_idx; out float planet_color_idx; uniform mat4 u_proj; +uniform mat4 u_camera; void main() { - gl_Position = u_proj * vec4(a_shape_pos * a_mass + a_obj_pos, 0, 1); + gl_Position = u_proj * u_camera * vec4(a_shape_pos * a_mass + a_obj_pos, 0, 1); planet_color_idx = a_planet_color_idx; -} \ No newline at end of file +} diff --git a/src/sim.cpp b/src/sim.cpp index d8f28d3..5103e72 100644 --- a/src/sim.cpp +++ b/src/sim.cpp @@ -18,6 +18,7 @@ #include "ui.h" #include "log.h" +// TODO(Brendan): Move this #define PI 3.141592653589793238462643383 #define WINDOW_WIDTH 1600 @@ -25,8 +26,9 @@ #define WINDOW_TITLE "N-Body Simulation" // :ArbitraryConstant -#define PARTICLE_COUNT 1500 +#define PARTICLE_COUNT 2500 +// TODO(Brendan): Maybe this can be removed because it isn't really necessary? internal void glfw_key_handler(GLFWwindow* window, i32 key, i32 scancode, i32 action, i32 mods) { @@ -34,16 +36,6 @@ glfw_key_handler(GLFWwindow* window, i32 key, i32 scancode, i32 action, i32 mods glfwSetWindowShouldClose(window, 1); } -internal i32 window_width; -internal i32 window_height; - -internal void -glfw_resize_handler(GLFWwindow* window, i32 width, i32 height) -{ - window_width = width; - window_height = height; -} - internal void glfw_error_handler(i32 error, const char* desc) { @@ -66,7 +58,6 @@ init_glfw() glfwSwapInterval(1); glfwSetKeyCallback(window, glfw_key_handler); - glfwSetFramebufferSizeCallback(window, glfw_resize_handler); // NOTE(Brendan): This may need to be changed if the screen orientation changes. glEnable(GL_CULL_FACE); @@ -132,6 +123,8 @@ struct SimState Array bodies; QuadTree qt_bodies; FixedArenaAllocator> qt_body_allocator; + + Camera camera; }; internal void @@ -152,15 +145,28 @@ sim_state_init(SimState* state) } state->qt_body_allocator.init(PARTICLE_COUNT); + + state->camera.offset = V2f { 0, 0 }; + state->camera.scale = 1.0f; } // NOTE(Brendan): dt is expected to be in units of "per second". internal void update(SimState* state, f64 dt) { + glfwGetWindowSize(window, &state->camera.window_width, &state->camera.window_height); + + persist const f32 camera_move_speed = 6; + if (glfwGetKey(window, GLFW_KEY_UP)) state->camera.offset.y -= camera_move_speed; + if (glfwGetKey(window, GLFW_KEY_DOWN)) state->camera.offset.y += camera_move_speed; + if (glfwGetKey(window, GLFW_KEY_LEFT)) state->camera.offset.x -= camera_move_speed; + if (glfwGetKey(window, GLFW_KEY_RIGHT)) state->camera.offset.x += camera_move_speed; + if (glfwGetKey(window, GLFW_KEY_Q)) state->camera.scale *= 1.01f; + if (glfwGetKey(window, GLFW_KEY_A)) state->camera.scale /= 1.01f; + persist const f64 step = 0.01; - state->qt_bodies.init(AABB { -(f32) window_width, -(f32)window_height, (f32) window_width * 2, (f32) window_height * 2 }); + state->qt_bodies.init(AABB { -2000, -2000, 4000, 4000 }); state->qt_body_allocator.reset(); For (state->bodies) state->qt_bodies.insert(&it, &state->qt_body_allocator); @@ -187,10 +193,15 @@ draw(SimState* state) glUseProgram(body_program); mat4 ortho_mat; - mat4_ortho(&ortho_mat, 0, window_width, 0, window_height, 0.0f, 100.0f); + camera_ortho_mat4(state->camera, &ortho_mat); GLuint ortho_mat_loc = glGetUniformLocation(body_program, "u_proj"); glUniformMatrix4fv(ortho_mat_loc, 1, false, (f32 *) ortho_mat); - glViewport(0, 0, window_width, window_height); + glViewport(0, 0, state->camera.window_width, state->camera.window_height); + + mat4 camera_mat; + camera_world_mat4(state->camera, &camera_mat); + GLuint camera_mat_loc = glGetUniformLocation(body_program, "u_camera"); + glUniformMatrix4fv(camera_mat_loc, 1, false, (f32 *) camera_mat); // NOTE(Brendan): Clear the screen. glClearColor(0.1, 0.1, 0.1, 1.0); @@ -240,8 +251,6 @@ loop(SimState* state) frame_delta += delta; if (frame_delta >= 1.0) { - // logprint(LOG_LEVEL_INFO, "AVG UPD CLK: %10.6f", (f64) (total_clock_delta / frame_count) / CLOCKS_PER_SEC); - total_clock_delta = 0; frame_delta -= 1.0; frame_rate = frame_count; diff --git a/src/utils.cpp b/src/utils.cpp index c080cca..c408c70 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -11,17 +11,17 @@ void panic_and_die(const char* msg, ...) { puts("************ PANIC ************"); - + va_list va; va_start(va, msg); logvprint(LOG_LEVEL_ERROR, msg, va); va_end(va); - + #ifdef DEBUG // NOTE: This allows for a debugger to stop here. __asm("int $3"); #endif - + exit(1); } @@ -51,7 +51,13 @@ bool AABB::intersects(AABB other) const void -camera_to_mat4(Camera cam, mat4* mat) +camera_ortho_mat4(Camera cam, mat4* mat) +{ + mat4_ortho(mat, 0, cam.window_width, 0, cam.window_height, 0.0f, 100.0f); +} + +void +camera_world_mat4(Camera cam, mat4* mat) { (*mat)[0] = cam.scale; (*mat)[1] = 0.0f; @@ -65,8 +71,8 @@ camera_to_mat4(Camera cam, mat4* mat) (*mat)[9] = 0.0f; (*mat)[10] = 0.0f; (*mat)[11] = 0.0f; - (*mat)[12] = cam.scale * cam.offset.x; - (*mat)[13] = cam.scale * cam.offset.y; + (*mat)[12] = cam.scale * -cam.offset.x + (1 - cam.scale) * (cam.window_width / 2); + (*mat)[13] = cam.scale * -cam.offset.y + (1 - cam.scale) * (cam.window_height / 2); (*mat)[14] = 0.0f; (*mat)[15] = 1.0f; } @@ -76,26 +82,26 @@ GLuint load_shader(GLenum shader_type, const char* shader_loc) { logprint(LOG_LEVEL_INFO, "Loading shader: %s", shader_loc); - + GLuint shader = glCreateShader(shader_type); - + FILE* shader_file = fopen(shader_loc, "rb"); defer { fclose(shader_file); }; if (shader_file == NULL) panic_and_die("Shader file not found: %s\n", shader_loc); - + fseek(shader_file, 0, SEEK_END); i32 shader_file_size = ftell(shader_file); fseek(shader_file, 0, SEEK_SET); - + char* shader_buffer = (char *) malloc(shader_file_size + 1); defer { free(shader_buffer); }; fread(shader_buffer, 1, shader_file_size, shader_file); - + shader_buffer[shader_file_size] = 0; - + glShaderSource(shader, 1, (const char* const*) &shader_buffer, NULL); glCompileShader(shader); - + GLint successful; glGetShaderiv(shader, GL_COMPILE_STATUS, &successful); if (successful != GL_TRUE) @@ -104,12 +110,12 @@ load_shader(GLenum shader_type, const char* shader_loc) GLchar shader_log[1024]; glGetShaderInfoLog(shader, 1023, &log_length, shader_log); shader_log[log_length] = 0; - + panic_and_die("Error compiling shader %s:\n%s\n", shader_loc, shader_log); } - + return shader; } @@ -117,12 +123,12 @@ GLuint create_program(GLuint vertex_shader, GLuint fragment_shader) { logprint(LOG_LEVEL_INFO, "Linking GL program"); - + GLuint program = glCreateProgram(); glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); glLinkProgram(program); - + GLint successful; glGetProgramiv(program, GL_LINK_STATUS, &successful); if (successful != GL_TRUE) @@ -131,9 +137,9 @@ create_program(GLuint vertex_shader, GLuint fragment_shader) GLchar program_log[1024]; glGetProgramInfoLog(program, 1023, &log_length, program_log); program_log[log_length] = 0; - + panic_and_die("Error linking program:\n%s", program_log); } - + return program; } -- 2.25.1