failed to add orbiting camera
This commit is contained in:
parent
67101e29f9
commit
a096c3b02c
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -10,6 +10,5 @@ int main(int argc, char** argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return launch_application(&app);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
32
src/scene.c
32
src/scene.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
144
src/scenes/spinning_cubes.c
Normal 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);
|
||||
}
|
9
src/scenes/spinning_cubes.h
Normal file
9
src/scenes/spinning_cubes.h
Normal 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
63
src/util/dynarray.c
Normal 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
25
src/util/dynarray.h
Normal 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
|
Loading…
Reference in a new issue