Refactor camera system to use quaternion rotations
Added quaternion and vector structures from the cglm library for handling 3D rotations and directions. Added a new function `euler_to_quat` to convert Euler angles to a quaternion representation. Changed the `camera_t` structure to replace separate forward, up, and right vectors with a single rotation quaternion. Changed the `camera_create` function to accept a rotation quaternion instead of separate direction vectors. Changed the `scene_init` function to initialize the camera with a default rotation quaternion. Changed the `ensure_camera_aspect_ratio` function to maintain the camera's rotation quaternion. Changed the `screen_render_pixel`, `scene_render_tile`, and `scene_render` functions to compute camera coordinates based on the quaternion rotation.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#ifndef COMMON_H
|
#ifndef COMMON_H
|
||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
|
#include "cglm/struct/quat.h"
|
||||||
#include "cglm/struct/vec4.h"
|
#include "cglm/struct/vec4.h"
|
||||||
#include "cglm/struct/vec3.h"
|
#include "cglm/struct/vec3.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -27,14 +28,30 @@ inline bool has_flag(int flags, int flag)
|
|||||||
return (flags & flag) != 0;
|
return (flags & flag) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void angle_to_direction_vector(float yaw, float pitch, vec3s* forward, vec3s* right, vec3s* up)
|
|
||||||
{
|
|
||||||
forward->x = cosf(yaw) * cosf(pitch);
|
|
||||||
forward->y = sinf(pitch);
|
|
||||||
forward->z = sinf(yaw) * cosf(pitch);
|
|
||||||
|
|
||||||
*right = glms_vec3_cross(*forward, (vec3s){0.0f, 1.0f, 0.0f});
|
inline versors euler_to_quat(float x, float y, float z)
|
||||||
*up = glms_vec3_cross(*right, *forward);
|
{
|
||||||
|
versors qx = glms_quatv(glm_rad(x), (vec3s){1.0f, 0.0f, 0.0f});
|
||||||
|
versors qy = glms_quatv(glm_rad(y), (vec3s){0.0f, 1.0f, 0.0f});
|
||||||
|
versors qz = glms_quatv(glm_rad(z), (vec3s){0.0f, 0.0f, 1.0f});
|
||||||
|
|
||||||
|
return glms_quat_mul(glms_quat_mul(qz, qy), qx);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline vec3s quat_get_forward(versors quat)
|
||||||
|
{
|
||||||
|
vec3s forward = glms_quat_rotatev(quat, (vec3s){0.0f, 0.0f, -1.0f});
|
||||||
|
return forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline vec3s quat_get_up(versors quat)
|
||||||
|
{
|
||||||
|
return glms_quat_rotatev(quat, (vec3s){0.0f, 1.0f, 0.0f});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline vec3s quat_get_right(versors quat)
|
||||||
|
{
|
||||||
|
return glms_quat_rotatev(quat, (vec3s){1.0f, 0.0f, 0.0f});
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // COMMON_H
|
#endif // COMMON_H
|
||||||
|
|||||||
@@ -2,15 +2,11 @@
|
|||||||
#define CAMERA_H
|
#define CAMERA_H
|
||||||
|
|
||||||
#include "cglm/struct/vec3.h"
|
#include "cglm/struct/vec3.h"
|
||||||
#include "cglm/types-struct.h"
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// TODO: Use mat4s instead of vec3s for position, forward, up and right
|
|
||||||
vec3s position;
|
vec3s position;
|
||||||
vec3s forward;
|
versors rotation;
|
||||||
vec3s up;
|
|
||||||
vec3s right;
|
|
||||||
|
|
||||||
float focal_length;
|
float focal_length;
|
||||||
float size_x;
|
float size_x;
|
||||||
@@ -21,6 +17,6 @@ typedef struct
|
|||||||
float fov_y;
|
float fov_y;
|
||||||
} camera_t;
|
} camera_t;
|
||||||
|
|
||||||
camera_t camera_create(vec3s position, vec3s forward, vec3s up, float focal_length, float size_x, float aspect_ratio);
|
camera_t camera_create(vec3s position, versors rotation, float focal_length, float size_x, float aspect_ratio);
|
||||||
|
|
||||||
#endif // CAMERA_H
|
#endif // CAMERA_H
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
#include "Rendering/Camera.h"
|
#include "Rendering/Camera.h"
|
||||||
|
|
||||||
camera_t camera_create(vec3s position, vec3s forward, vec3s up, float focal_length, float size_x, float aspect_ratio)
|
camera_t camera_create(vec3s position, versors rotation, float focal_length, float size_x, float aspect_ratio)
|
||||||
{
|
{
|
||||||
camera_t camera =
|
camera_t camera =
|
||||||
{
|
{
|
||||||
.position = position,
|
.position = position,
|
||||||
.forward = glms_vec3_normalize(forward),
|
.rotation = rotation,
|
||||||
.up = glms_vec3_normalize(up),
|
|
||||||
.right = glms_vec3_cross(forward, up), // Assuming forward and up are not parallel
|
|
||||||
.focal_length = focal_length,
|
.focal_length = focal_length,
|
||||||
.size_x = size_x,
|
.size_x = size_x,
|
||||||
.size_y = size_x / aspect_ratio,
|
.size_y = size_x / aspect_ratio,
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ bool scene_init(uint64_t triangle_count, uint8_t material_count, uint32_t punctu
|
|||||||
|
|
||||||
temp.camera = camera_create(
|
temp.camera = camera_create(
|
||||||
(vec3s){0.0f, 0.0f, 5.0f},
|
(vec3s){0.0f, 0.0f, 5.0f},
|
||||||
(vec3s){0.0f, 0.0f, -1.0f},
|
glms_quat_identity(),
|
||||||
(vec3s){0.0f, 1.0f, 0.0f},
|
|
||||||
0.025f,
|
0.025f,
|
||||||
0.036f,
|
0.036f,
|
||||||
16.0f / 9.0f
|
16.0f / 9.0f
|
||||||
@@ -75,8 +74,7 @@ static inline void ensure_camera_aspect_ratio(camera_t* camera, rendering_confi
|
|||||||
{
|
{
|
||||||
*camera = camera_create(
|
*camera = camera_create(
|
||||||
camera->position,
|
camera->position,
|
||||||
camera->forward,
|
camera->rotation,
|
||||||
camera->up,
|
|
||||||
camera->focal_length,
|
camera->focal_length,
|
||||||
camera->size_x,
|
camera->size_x,
|
||||||
(float)config.width / (float)config.height
|
(float)config.width / (float)config.height
|
||||||
@@ -117,18 +115,20 @@ static void screen_render_pixel(scene_t* scene, rendering_config_t config, vec3s
|
|||||||
uint32_t pixel_id = y * config.width + x;
|
uint32_t pixel_id = y * config.width + x;
|
||||||
|
|
||||||
uint16_t sample_count = get_sample_count(config.sample_count, flag);
|
uint16_t sample_count = get_sample_count(config.sample_count, flag);
|
||||||
|
vec2s position_ndc = compute_ndc((float)x, (float)y, config.width, config.height);
|
||||||
|
vec3s camera_right = quat_get_right(scene->camera.rotation);
|
||||||
|
vec3s camera_up = quat_get_up(scene->camera.rotation);
|
||||||
|
|
||||||
for (uint16_t k = 0; k < sample_count; k++)
|
for (uint16_t k = 0; k < sample_count; k++)
|
||||||
{
|
{
|
||||||
vec2s position_ndc = compute_ndc((float)x, (float)y, config.width, config.height);
|
|
||||||
float screen_x = position_ndc.x * 2.0f - 1.0f;
|
float screen_x = position_ndc.x * 2.0f - 1.0f;
|
||||||
float screen_y = position_ndc.y * 2.0f - 1.0f;
|
float screen_y = position_ndc.y * 2.0f - 1.0f;
|
||||||
float sensor_offset_x = screen_x * scene->camera.size_x / 2.0f;
|
float sensor_offset_x = screen_x * scene->camera.size_x / 2.0f;
|
||||||
float sensor_offset_y = screen_y * scene->camera.size_y / 2.0f;
|
float sensor_offset_y = screen_y * scene->camera.size_y / 2.0f;
|
||||||
|
|
||||||
vec3s image_plane_point = coord;
|
vec3s image_plane_point = coord;
|
||||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(scene->camera.right, sensor_offset_x));
|
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_right, sensor_offset_x));
|
||||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(scene->camera.up, sensor_offset_y));
|
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_up, sensor_offset_y));
|
||||||
|
|
||||||
ray_t ray = {
|
ray_t ray = {
|
||||||
.origin = scene->camera.position,
|
.origin = scene->camera.position,
|
||||||
@@ -167,7 +167,7 @@ bool scene_render_tile(scene_t* scene, rendering_context_t* ctx, rendering_confi
|
|||||||
ensure_camera_aspect_ratio(&scene->camera, config);
|
ensure_camera_aspect_ratio(&scene->camera, config);
|
||||||
ctx->tile_count_x = (config.width + config.bucket_size - 1) / config.bucket_size;
|
ctx->tile_count_x = (config.width + config.bucket_size - 1) / config.bucket_size;
|
||||||
ctx->tile_count_y = (config.height + config.bucket_size - 1) / config.bucket_size;
|
ctx->tile_count_y = (config.height + config.bucket_size - 1) / config.bucket_size;
|
||||||
ctx->coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(scene->camera.forward, scene->camera.focal_length));
|
ctx->coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(quat_get_forward(scene->camera.rotation), scene->camera.focal_length));
|
||||||
ctx->is_init = true;
|
ctx->is_init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ bool scene_render(scene_t* scene, rendering_config_t config, int rendering_flag,
|
|||||||
uint32_t tile_count = tile_count_x * tile_count_y;
|
uint32_t tile_count = tile_count_x * tile_count_y;
|
||||||
|
|
||||||
float inv_sample = 1.0f / config.sample_count;
|
float inv_sample = 1.0f / config.sample_count;
|
||||||
vec3s coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(scene->camera.forward, scene->camera.focal_length));
|
vec3s coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(quat_get_forward(scene->camera.rotation), scene->camera.focal_length));
|
||||||
|
|
||||||
int64_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region. Also, they need to be signed integers. To avoid overflow, we need to use int64_t
|
int64_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region. Also, they need to be signed integers. To avoid overflow, we need to use int64_t
|
||||||
rendering_config_t config_copy = config;
|
rendering_config_t config_copy = config;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scene.camera.position = (vec3s){-7.5f, 2.0f, 0.0f};
|
scene.camera.position = (vec3s){-7.5f, 2.0f, 0.0f};
|
||||||
scene.camera.forward = glms_vec3_normalize((vec3s){1.0f, 0.0f, 0.0f});
|
scene.camera.rotation = euler_to_quat(10.0f, -90.0f, 0.0f);
|
||||||
|
|
||||||
light_entity_t sun = light_create_directional_light(&scene.lights);
|
light_entity_t sun = light_create_directional_light(&scene.lights);
|
||||||
directional_light_t* sun_light = &scene.lights.directional_lights[sun.id];
|
directional_light_t* sun_light = &scene.lights.directional_lights[sun.id];
|
||||||
|
|||||||
Reference in New Issue
Block a user