failed to add orbiting camera

This commit is contained in:
Lauchmelder 2022-10-19 14:23:31 +02:00
parent 67101e29f9
commit a096c3b02c
13 changed files with 315 additions and 20 deletions

View file

@ -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}

View file

@ -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);

View file

@ -10,6 +10,5 @@ int main(int argc, char** argv)
return 1;
}
return launch_application(&app);
}

View file

@ -4,19 +4,29 @@
#include <cglm/cam.h>
#include <assert.h>
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);

View file

@ -2,14 +2,20 @@
#define CAMERA_H
#include <cglm/mat4.h>
#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

View file

@ -2,6 +2,7 @@
#include <cglm/affine.h>
#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);
}

View file

@ -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);

View file

@ -4,6 +4,7 @@
#include <stdio.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#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);
}
}

View file

@ -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

144
src/scenes/spinning_cubes.c Normal file
View file

@ -0,0 +1,144 @@
#include "spinning_cubes.h"
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
#include <GLFW/glfw3.h>
#include <cglm/affine.h>
#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);
}

View file

@ -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

63
src/util/dynarray.c Normal file
View file

@ -0,0 +1,63 @@
#include "dynarray.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <memory.h>
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);
}
}

25
src/util/dynarray.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef DYNARRAY_H
#define DYNARRAY_H
#include <stdint.h>
#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