From a096c3b02c90ae58ed6b4e425945389518b4baaa Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Wed, 19 Oct 2022 14:23:31 +0200 Subject: [PATCH] failed to add orbiting camera --- src/CMakeLists.txt | 2 +- src/application.c | 8 +- src/main.c | 1 - src/renderer/camera.c | 16 +++- src/renderer/camera.h | 6 ++ src/renderer/object.c | 15 +++- src/renderer/object.h | 6 +- src/scene.c | 32 ++++++-- src/scene.h | 8 +- src/scenes/spinning_cubes.c | 144 ++++++++++++++++++++++++++++++++++++ src/scenes/spinning_cubes.h | 9 +++ src/util/dynarray.c | 63 ++++++++++++++++ src/util/dynarray.h | 25 +++++++ 13 files changed, 315 insertions(+), 20 deletions(-) create mode 100644 src/scenes/spinning_cubes.c create mode 100644 src/scenes/spinning_cubes.h create mode 100644 src/util/dynarray.c create mode 100644 src/util/dynarray.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 09b5d97..40b1428 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(solver "renderer/buffer.c" "renderer/shader.c" "renderer/camera.c" - "objects/cube.c" "renderer/object.c") + "objects/cube.c" "renderer/object.c" "util/dynarray.h" "util/dynarray.c" "scenes/spinning_cubes.h" "scenes/spinning_cubes.c") target_include_directories(solver PRIVATE ${CMAKE_CURRENT_LIST_DIR} diff --git a/src/application.c b/src/application.c index cc77974..3a0f915 100644 --- a/src/application.c +++ b/src/application.c @@ -5,6 +5,7 @@ #include "renderer/context.h" #include "objects/cube.h" +#include "scenes/spinning_cubes.h" static void on_window_size_change(Application* app, int width, int height) { @@ -35,11 +36,7 @@ int init_application(Application* app, const char* name) app->scenes = (Scene*)malloc(1 * sizeof(Scene)); app->active_scene = app->scenes; // First scene is active scene - create_scene(app->scenes); - Cube* obj = (Cube*)malloc(sizeof(Cube)); - create_cube(obj); - - scene_add_object(app->active_scene, &obj->object); + create_spinning_cubes_scene(&app->window, app->scenes); return 0; } @@ -50,6 +47,7 @@ int launch_application(Application* app) { glfwPollEvents(); + update_scene(app->active_scene); render_scene(app->active_scene); glfwSwapBuffers(app->window.window); diff --git a/src/main.c b/src/main.c index 8e98adb..0f90a09 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,5 @@ int main(int argc, char** argv) return 1; } - return launch_application(&app); } diff --git a/src/renderer/camera.c b/src/renderer/camera.c index c21da5c..455942d 100644 --- a/src/renderer/camera.c +++ b/src/renderer/camera.c @@ -4,19 +4,29 @@ #include #include +static const vec3 up = { 0.0f, 1.0f, 0.0f }; + int create_camera(Camera* camera) { assert(camera); - glm_mat4_identity(camera->view); - glm_rotate(camera->view, glm_rad(35.0f), (vec3) { 1.0f, 0.0f, 0.0f }); - glm_translate(camera->view, (vec3) { 0.0f, -1.5f, -3.0f }); + init_object(&camera->object); + glm_mat4_identity(camera->view); glm_perspective(glm_rad(90.0f), 1.0f, 0.001f, 100.0f, camera->projection); return 0; } +vec4* get_camera_view(Camera* camera) +{ + glm_mat4_identity(camera->view); + glm_lookat(camera->object.position, camera->look_at, up, camera->view); + // glm_scale(camera->view, camera->object.scale); + + return camera->view; +} + void set_camera_perspective(Camera* camera, float fov, float ar) { glm_perspective(glm_rad(fov), ar, 0.01f, 100.0f, camera->projection); diff --git a/src/renderer/camera.h b/src/renderer/camera.h index 4233719..6600a2f 100644 --- a/src/renderer/camera.h +++ b/src/renderer/camera.h @@ -2,14 +2,20 @@ #define CAMERA_H #include +#include "object.h" typedef struct Camera { + Object object; + vec3 look_at; + mat4 view; mat4 projection; } Camera; int create_camera(Camera* camera); + +vec4* get_camera_view(Camera* camera); void set_camera_perspective(Camera* camera, float fov, float ar); #endif // CAMERA_H \ No newline at end of file diff --git a/src/renderer/object.c b/src/renderer/object.c index 30f281e..dbb4bd5 100644 --- a/src/renderer/object.c +++ b/src/renderer/object.c @@ -2,6 +2,7 @@ #include #include "context.h" +#include "camera.h" void init_object(Object* obj) { @@ -25,12 +26,12 @@ void render_object(Object* obj, Camera* camera) vec3 normalized_rot; glm_vec3_normalize_to(obj->rotation, normalized_rot); - glm_scale(obj->transform, obj->scale); + glm_translate(obj->transform, obj->position); glm_rotate(obj->transform, angle, normalized_rot); glm_scale(obj->transform, obj->scale); set_uniform_mat4(obj->shader, "model", obj->transform); - set_uniform_mat4(obj->shader, "view", camera->view); + set_uniform_mat4(obj->shader, "view", get_camera_view(camera)); set_uniform_mat4(obj->shader, "projection", camera->projection); obj->on_shader_use(obj->child); @@ -42,3 +43,13 @@ void destroy_object(Object obj) { obj.on_destroy(obj.child); } + +void object_set_position(Object* obj, vec3 position) +{ + glm_vec3_copy(position, obj->position); +} + +void object_move(Object* obj, vec3 direction) +{ + glm_vec3_add(obj->position, direction, obj->position); +} diff --git a/src/renderer/object.h b/src/renderer/object.h index 88783f9..a32063f 100644 --- a/src/renderer/object.h +++ b/src/renderer/object.h @@ -5,7 +5,8 @@ #include "shader.h" #include "buffer.h" -#include "camera.h" + +typedef struct Camera Camera; typedef struct Object { @@ -26,6 +27,9 @@ typedef struct Object void init_object(Object* obj); void destroy_object(Object obj); +void object_set_position(Object* obj, vec3 position); +void object_move(Object* obj, vec3 direction); + void update_object(Object* obj); void render_object(Object* obj, Camera* camera); diff --git a/src/scene.c b/src/scene.c index b2f7f8f..35befbe 100644 --- a/src/scene.c +++ b/src/scene.c @@ -4,6 +4,7 @@ #include #include +#include #include "objects/cube.h" @@ -17,19 +18,26 @@ int create_scene(Scene* scene) return 1; } - scene->objects = (Object*)malloc(sizeof(Object)); + scene->objects = create_dynamic_array(Object*); + scene->on_update = NULL; + scene->last_frame_start = glfwGetTime(); } void destroy_scene(Scene scene) { - destroy_object(*(scene.objects)); + for (size_t i = 0; i < scene.objects.size; i++) + { + Object* obj = *(Object**)dynamic_array_get(&scene.objects, i); + destroy_object(*obj); + } + + destroy_dynamic_array(scene.objects); } void scene_add_object(Scene* scene, Object* object) { assert(scene); - - scene->objects = object; + dynamic_array_push(&scene->objects, (void*)&object); } void scene_update_size(Scene* scene, int width, int height) @@ -38,11 +46,23 @@ void scene_update_size(Scene* scene, int width, int height) set_camera_perspective(&scene->camera, 90.0f, (float)width / (float)height); } +void update_scene(Scene* scene) +{ + double frametime = glfwGetTime() - scene->last_frame_start; + scene->last_frame_start = glfwGetTime(); + + scene->on_update(scene, frametime); +} + void render_scene(Scene* scene) { assert(scene); ctx_clear_screen(0.0f, 0.0f, 0.0f, 1.0f); - update_object(scene->objects); - render_object(scene->objects, &scene->camera); + for (size_t i = 0; i < scene->objects.size; i++) + { + Object* obj = *(Object**)dynamic_array_get(&scene->objects, i); + update_object(obj); + render_object(obj, &scene->camera); + } } diff --git a/src/scene.h b/src/scene.h index 64acafc..031b270 100644 --- a/src/scene.h +++ b/src/scene.h @@ -3,11 +3,16 @@ #include "renderer/camera.h" #include "renderer/object.h" +#include "util/dynarray.h" typedef struct Scene { Camera camera; - Object* objects; + DynamicArray objects; + + void* child; + void(*on_update)(void*, double); + double last_frame_start; } Scene; int create_scene(Scene* scene); @@ -16,6 +21,7 @@ void destroy_scene(Scene scene); void scene_add_object(Scene* scene, Object* object); void scene_update_size(Scene* scene, int width, int height); +void update_scene(Scene* scene); void render_scene(Scene* scene); #endif \ No newline at end of file diff --git a/src/scenes/spinning_cubes.c b/src/scenes/spinning_cubes.c new file mode 100644 index 0000000..6a7eb46 --- /dev/null +++ b/src/scenes/spinning_cubes.c @@ -0,0 +1,144 @@ +#include "spinning_cubes.h" + +#include +#include +#include + +#include +#include + +#include "objects/cube.h" +#include "application.h" + +typedef struct SpinningCubes +{ + struct { + double x, y; + } last_cursor_pos; + + bool dragging; + double drag_speed; + double camera_distance; +} SpinningCubes; + +static void init_spinning_cubes_data(SpinningCubes* scene) +{ + assert(scene); + + scene->camera_distance = 6.5f; + scene->dragging = false; + scene->drag_speed = 0.01f; +} + +static void get_arcball_vector(vec3 dest, double width, double height, double x, double y) +{ + dest[0] = 1.0 * x / width * 2 - 1.0; + dest[1] = 1.0 * y / height * 2 - 1.0; + dest[2] = 0.0; + + dest[2] = -dest[2]; + float OP_squared = dest[0] * dest[0] + dest[1] * dest[1]; + if (OP_squared <= 1) + dest[2] = sqrt(1 - OP_squared); + else + glm_normalize(dest); +} + +static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + Application* app = glfwGetWindowUserPointer(window); + Scene* scene = app->active_scene; + SpinningCubes* data = scene->child; + + switch (button) + { + case GLFW_MOUSE_BUTTON_LEFT: + { + if (action == GLFW_PRESS) + { + data->dragging = true; + + glfwGetCursorPos(window, &data->last_cursor_pos.x, &data->last_cursor_pos.y); + } + else if (action == GLFW_RELEASE) + { + data->dragging = false; + } + } break; + + default: + break; + } +} + +static void mouse_moved_callback(GLFWwindow* window, double xpos, double ypos) +{ + return; + + Application* app = glfwGetWindowUserPointer(window); + Scene* scene = app->active_scene; + SpinningCubes* data = scene->child; + + if (data->dragging && (xpos != data->last_cursor_pos.x || ypos != data->last_cursor_pos.y)) + { + Object* camera = &scene->camera.object; + int width, height; + glfwGetWindowSize(window, &width, &height); + + vec3 va; get_arcball_vector(va, width, height, data->last_cursor_pos.x, data->last_cursor_pos.y); + vec3 vb; get_arcball_vector(vb, width, height, xpos, ypos); + + vec3 diff; glm_vec3_sub(vb, va, diff); + + object_move(camera, diff); + vec3 look_dir; glm_vec3_sub(scene->camera.look_at, camera->position, look_dir); + double cam_distance = glm_vec3_norm(look_dir); + if (cam_distance != data->camera_distance) + { + double correction = data->camera_distance - cam_distance; + glm_normalize(look_dir); + glm_vec3_scale(look_dir, correction, look_dir); + + object_move(camera, look_dir); + } + + data->last_cursor_pos.x = xpos; + data->last_cursor_pos.y = ypos; + } +} + +static void on_update(Scene* scene, double frametime) +{ +} + +void create_spinning_cubes_scene(Window* window, Scene* scene) +{ + assert(scene); + + create_scene(scene); + scene->on_update = on_update; + scene->child = malloc(sizeof(SpinningCubes)); + init_spinning_cubes_data(scene->child); + + for (int i = 0; i < 4; i++) + { + Cube* obj = (Cube*)malloc(sizeof(Cube)); + create_cube(obj); + + vec3 position = { + ((i % 2) ? -1 : 1) * 1.5f, + 0.0f, + ((i < 2) ? -1 : 1) * 1.5 + }; + object_set_position(&obj->object, position); + + scene_add_object(scene, &obj->object); + } + + vec3 cam_pos = { 0.0f, 4.0f, -3.0 }; + object_set_position(&scene->camera.object, cam_pos); + glm_vec3_zero(&scene->camera.look_at); + + glfwSetMouseButtonCallback(window->window, mouse_button_callback); + glfwSetCursorPosCallback(window->window, mouse_moved_callback); +} diff --git a/src/scenes/spinning_cubes.h b/src/scenes/spinning_cubes.h new file mode 100644 index 0000000..a239879 --- /dev/null +++ b/src/scenes/spinning_cubes.h @@ -0,0 +1,9 @@ +#ifndef SCENE_SPINNING_CUBES_H +#define SCENE_SPINNING_CUBES_H + +#include "scene.h" +#include "renderer/window.h" + +void create_spinning_cubes_scene(Window* window, Scene* scene); + +#endif // SCENE_SPINNING_CUBES_H \ No newline at end of file diff --git a/src/util/dynarray.c b/src/util/dynarray.c new file mode 100644 index 0000000..9b9f5f9 --- /dev/null +++ b/src/util/dynarray.c @@ -0,0 +1,63 @@ +#include "dynarray.h" + +#include +#include +#include +#include + +DynamicArray create_dynamic_array_from_size(size_t type_size) +{ + DynamicArray array; + + array.capacity = 5; + array.size = 0; + array.element_size = type_size; + + array.data = malloc(type_size * array.capacity); + if (array.data == NULL) + { + array.capacity = 0; + fprintf(stderr, "Failed to allocate memory for dynamic array\n"); + } + + return array; +} + +void destroy_dynamic_array(DynamicArray array) +{ + assert(array.capacity > 0); + + free(array.data); + array.capacity = 0; +} + +void* dynamic_array_get(DynamicArray* array, size_t i) +{ + return (void*)((char*)array->data + (i * array->element_size)); +} + +void dynamic_array_push(DynamicArray* array, void* element) +{ + assert(array->capacity > 0); + + if (array->size == array->capacity) + { + array->capacity *= (3 / 2); + array->data = realloc(array->data, array->element_size * array->capacity); + } + + memcpy((void*)((char*)array->data + (array->size * array->element_size)), element, array->element_size); + array->size++; +} + +void dynamic_array_pop(DynamicArray* array) +{ + assert(array->capacity > 0); + + array->size -= 1; + if (array->size <= array->capacity / 2 && array->capacity > 5) + { + array->capacity = (2 / 3) * array->capacity + 1; + array->data = realloc(array->data, array->capacity); + } +} diff --git a/src/util/dynarray.h b/src/util/dynarray.h new file mode 100644 index 0000000..3b3cb42 --- /dev/null +++ b/src/util/dynarray.h @@ -0,0 +1,25 @@ +#ifndef DYNARRAY_H +#define DYNARRAY_H + +#include + +#define create_dynamic_array( type ) create_dynamic_array_from_size(sizeof( type )) + +typedef struct DynamicArray +{ + void* data; + + size_t element_size; + size_t size; + size_t capacity; +} DynamicArray; + +DynamicArray create_dynamic_array_from_size(size_t type_size); +void destroy_dynamic_array(DynamicArray array); + +void* dynamic_array_get(DynamicArray* array, size_t i); + +void dynamic_array_push(DynamicArray* array, void* element); +void dynamic_array_pop(DynamicArray* array); + +#endif // DYNARRAY_H \ No newline at end of file