terrain

Real-time terrain generation using marching cubes
git clone git://git.christianermann.dev/terrain
Log | Files | Refs | README | LICENSE

commit c390e429cf5a91ab3c0361e1136a3371f4175247
parent 24b64e7c7a2da19bacc8182032629da42299a463
Author: Christian Ermann <christianermann@gmail.com>
Date:   Fri, 19 Nov 2021 14:55:23 -0800

Implemented vector and matrix operations

Diffstat:
Minclude/camera.h | 15++++++++-------
Minclude/vec.h | 36++++++++++++++++++++++++++++++++++++
Msrc/camera.c | 61++++++++++++++++++++++++++++++-------------------------------
Msrc/vec.c | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 230 insertions(+), 38 deletions(-)

diff --git a/include/camera.h b/include/camera.h @@ -1,14 +1,14 @@ #ifndef CAMERA_H #define CAMERA_H -#include <cglm/cglm.h> +#include "vec.h" typedef struct { - vec3 position; + Vec3 position; float yaw; float pitch; - vec3 world_up; + Vec3 world_up; float fovy; float aspect; float near; @@ -16,11 +16,11 @@ typedef struct { float speed; float sensitivity; - vec3 front; - vec3 up; - vec3 right; + Vec3 front; + Vec3 up; + Vec3 right; - mat4 matrix; + Mat4 matrix; } Camera; Camera *Camera_make(float x, float y, float z, float yaw, float pitch); @@ -37,6 +37,7 @@ void Camera_updateVectors(Camera* camera); // Update the (projection * view) matrix of the camera. void Camera_updateMatrix(Camera* camera); +// Process user input to adjust camera's position and orientation void Camera_move(Camera *camera); #endif diff --git a/include/vec.h b/include/vec.h @@ -3,11 +3,47 @@ #include <stdbool.h> +float radians(float degrees); + typedef int IVec3[3]; bool IVec3_equal(const IVec3 a, const IVec3 b); typedef float Vec3[3]; + +// dst = src * scale +void Vec3_scale(Vec3 src, float scale, Vec3 dst); + +// dst = src_a + src_b +void Vec3_add(Vec3 src_a, Vec3 src_b, Vec3 dst); + +// dst = src_a - src_b +void Vec3_sub(Vec3 src_a, Vec3 src_b, Vec3 dst); + +// dst = src_a x src_b +void Vec3_mul(Vec3 src_a, Vec3 src_b, Vec3 dst); + +// dst = src / ||src|| +void Vec3_normalize(Vec3 src, Vec3 dst); + +// src_a * src_b +float Vec3_dot(Vec3 src_a, Vec3 src_b); + +// ||src||^2 +float Vec3_magSquared(Vec3 src); + +// ||src|| +float Vec3_mag(Vec3 src); + typedef float Mat4[4][4]; +// dst = src_a * src_b +void Mat4_mul(Mat4 src_a, Mat4 src_b, Mat4 dst); + +// Computes the view matrix. +void Mat4_lookAt(Vec3 camera, Vec3 target, Vec3 up, Mat4 dst); + +// Computes the perspective projection matrix. +void Mat4_perspective(float fov, float aspect, float near, float far, Mat4 dst); + #endif diff --git a/src/camera.c b/src/camera.c @@ -48,52 +48,52 @@ void Camera_updateRotation(Camera* camera, float dx, float dy) void Camera_updatePosition(Camera* camera, float x, float y, float z) { - vec3 movement_x; - glm_vec3_scale(camera->right, x, movement_x); + Vec3 movement_x; + Vec3_scale(camera->right, x, movement_x); - vec3 movement_y; - glm_vec3_scale(camera->up, y, movement_y); + Vec3 movement_y; + Vec3_scale(camera->up, y, movement_y); - vec3 movement_z; - glm_vec3_scale(camera->front, z, movement_z); + Vec3 movement_z; + Vec3_scale(camera->front, z, movement_z); - vec3 movement; - glm_vec3_add(movement_x, movement_y, movement); - glm_vec3_add(movement_z, movement, movement); - glm_vec3_normalize(movement); - glm_vec3_scale(movement, 0.1f, movement); + Vec3 movement; + Vec3_add(movement_x, movement_y, movement); + Vec3_add(movement_z, movement, movement); + Vec3_normalize(movement, movement); + Vec3_scale(movement, 0.1f, movement); - glm_vec3_add(camera->position, movement, camera->position); + Vec3_add(camera->position, movement, camera->position); } void Camera_updateVectors(Camera* camera) { - vec3 front; - front[0] = cosf(glm_rad(camera->yaw)) * cosf(glm_rad(camera->pitch)); - front[1] = sinf(glm_rad(camera->pitch)); - front[2] = sinf(glm_rad(camera->yaw)) * cosf(glm_rad(camera->pitch)); - glm_vec3_normalize_to(front, camera->front); + Vec3 front; + front[0] = cosf(radians(camera->yaw)) * cosf(radians(camera->pitch)); + front[1] = sinf(radians(camera->pitch)); + front[2] = sinf(radians(camera->yaw)) * cosf(radians(camera->pitch)); + Vec3_normalize(front, camera->front); - glm_vec3_cross(camera->front, camera->world_up, camera->right); - glm_vec3_normalize(camera->right); + Vec3_mul(camera->front, camera->world_up, camera->right); + Vec3_normalize(camera->right, camera->right); - glm_vec3_cross(camera->right, camera->front, camera->up); - glm_vec3_normalize(camera->up); + Vec3_mul(camera->right, camera->front, camera->up); + Vec3_normalize(camera->up, camera->up); } void Camera_updateMatrix(Camera* camera) { - vec3 camera_target; - glm_vec3_add(camera->position, camera->front, camera_target); + Vec3 camera_target; + Vec3_add(camera->position, camera->front, camera_target); - mat4 view; - glm_lookat(camera->position, camera_target, camera->up, view); + Mat4 view; + Mat4_lookAt(camera->position, camera_target, camera->up, view); - mat4 projection; - glm_perspective(glm_rad(camera->fovy), camera->aspect, camera->near, + Mat4 projection; + Mat4_perspective(radians(camera->fovy), camera->aspect, camera->near, camera->far, projection); - glm_mat4_mul(projection, view, camera->matrix); + Mat4_mul(projection, view, camera->matrix); } void Camera_move(Camera *camera) @@ -107,7 +107,7 @@ void Camera_move(Camera *camera) float y = kb[SDL_SCANCODE_SPACE] - kb[SDL_SCANCODE_LSHIFT]; float z = kb[SDL_SCANCODE_W] - kb[SDL_SCANCODE_S]; Camera_updatePosition(camera, x, y, z); - + Camera_updateVectors(camera); Camera_updateMatrix(camera); -} -\ No newline at end of file +} diff --git a/src/vec.c b/src/vec.c @@ -1,6 +1,162 @@ #include "vec.h" +#include <math.h> + +float radians(float degrees) +{ + return degrees * (M_PI / 180.0f); +} + bool IVec3_equal(const IVec3 a, const IVec3 b) { return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]); } + +void Vec3_scale(Vec3 src, float scale, Vec3 dst) +{ + dst[0] = src[0] * scale; + dst[1] = src[1] * scale; + dst[2] = src[2] * scale; +} + +void Vec3_add(Vec3 src_a, Vec3 src_b, Vec3 dst) +{ + dst[0] = src_a[0] + src_b[0]; + dst[1] = src_a[1] + src_b[1]; + dst[2] = src_a[2] + src_b[2]; +} + +void Vec3_sub(Vec3 src_a, Vec3 src_b, Vec3 dst) +{ + dst[0] = src_a[0] - src_b[0]; + dst[1] = src_a[1] - src_b[1]; + dst[2] = src_a[2] - src_b[2]; +} + +void Vec3_mul(Vec3 src_a, Vec3 src_b, Vec3 dst) +{ + dst[0] = src_a[1] * src_b[2] - src_a[2] * src_b[1]; + dst[1] = src_a[2] * src_b[0] - src_a[0] * src_b[2]; + dst[2] = src_a[0] * src_b[1] - src_a[1] * src_b[0]; +} + +void Vec3_normalize(Vec3 src, Vec3 dst) +{ + float m = Vec3_mag(src); + if (m > 0.0f) + { + dst[0] = src[0] / m; + dst[1] = src[1] / m; + dst[2] = src[2] / m; + } +} + +float Vec3_dot(Vec3 src_a, Vec3 src_b) +{ + return src_a[0] * src_b[0] + src_a[1] * src_b[1] + src_a[2] * src_b[2]; +} + +float Vec3_magSquared(Vec3 src) +{ + return Vec3_dot(src, src); +} + +float Vec3_mag(Vec3 src) +{ + return sqrtf(Vec3_magSquared(src)); +} + +void Mat4_mul(Mat4 src_a, Mat4 src_b, Mat4 dst) +{ + // x basis + dst[0][0] = src_a[0][0] * src_b[0][0] + src_a[1][0] * src_b[0][1] + src_a[2][0] * src_b[0][2] + src_a[3][0] * src_b[0][3]; + dst[0][1] = src_a[0][1] * src_b[0][0] + src_a[1][1] * src_b[0][1] + src_a[2][1] * src_b[0][2] + src_a[3][1] * src_b[0][3]; + dst[0][2] = src_a[0][2] * src_b[0][0] + src_a[1][2] * src_b[0][1] + src_a[2][2] * src_b[0][2] + src_a[3][2] * src_b[0][3]; + dst[0][3] = src_a[0][3] * src_b[0][0] + src_a[1][3] * src_b[0][1] + src_a[2][3] * src_b[0][2] + src_a[3][3] * src_b[0][3]; + + // y basis + dst[1][0] = src_a[0][0] * src_b[1][0] + src_a[1][0] * src_b[1][1] + src_a[2][0] * src_b[1][2] + src_a[3][0] * src_b[1][3]; + dst[1][1] = src_a[0][1] * src_b[1][0] + src_a[1][1] * src_b[1][1] + src_a[2][1] * src_b[1][2] + src_a[3][1] * src_b[1][3]; + dst[1][2] = src_a[0][2] * src_b[1][0] + src_a[1][2] * src_b[1][1] + src_a[2][2] * src_b[1][2] + src_a[3][2] * src_b[1][3]; + dst[1][3] = src_a[0][3] * src_b[1][0] + src_a[1][3] * src_b[1][1] + src_a[2][3] * src_b[1][2] + src_a[3][3] * src_b[1][3]; + + // z basis + dst[2][0] = src_a[0][0] * src_b[2][0] + src_a[1][0] * src_b[2][1] + src_a[2][0] * src_b[2][2] + src_a[3][0] * src_b[2][3]; + dst[2][1] = src_a[0][1] * src_b[2][0] + src_a[1][1] * src_b[2][1] + src_a[2][1] * src_b[2][2] + src_a[3][1] * src_b[2][3]; + dst[2][2] = src_a[0][2] * src_b[2][0] + src_a[1][2] * src_b[2][1] + src_a[2][2] * src_b[2][2] + src_a[3][2] * src_b[2][3]; + dst[2][3] = src_a[0][3] * src_b[2][0] + src_a[1][3] * src_b[2][1] + src_a[2][3] * src_b[2][2] + src_a[3][3] * src_b[2][3]; + + // w basis + dst[3][0] = src_a[0][0] * src_b[3][0] + src_a[1][0] * src_b[3][1] + src_a[2][0] * src_b[3][2] + src_a[3][0] * src_b[3][3]; + dst[3][1] = src_a[0][1] * src_b[3][0] + src_a[1][1] * src_b[3][1] + src_a[2][1] * src_b[3][2] + src_a[3][1] * src_b[3][3]; + dst[3][2] = src_a[0][2] * src_b[3][0] + src_a[1][2] * src_b[3][1] + src_a[2][2] * src_b[3][2] + src_a[3][2] * src_b[3][3]; + dst[3][3] = src_a[0][3] * src_b[3][0] + src_a[1][3] * src_b[3][1] + src_a[2][3] * src_b[3][2] + src_a[3][3] * src_b[3][3]; +} + +void Mat4_lookAt(Vec3 camera, Vec3 target, Vec3 up, Mat4 dst) +{ + Vec3 f; + Vec3_sub(target, camera, f); + Vec3_normalize(f, f); + + Vec3 s; + Vec3_mul(f, up, s); + Vec3_normalize(s, s); + + Vec3 u; + Vec3_mul(s, f, u); + Vec3_normalize(s, s); + + // x basis + dst[0][0] = s[0]; + dst[0][1] = u[0]; + dst[0][2] = -f[0]; + dst[0][3] = 0.0f; + + // y basis + dst[1][0] = s[1]; + dst[1][1] = u[1]; + dst[1][2] = -f[1]; + dst[1][3] = 0.0f; + + // z basis + dst[2][0] = s[2]; + dst[2][1] = u[2]; + dst[2][2] = -f[2]; + dst[2][3] = 0.0f; + + // w basis + dst[3][0] = -Vec3_dot(s, camera); + dst[3][1] = -Vec3_dot(u, camera); + dst[3][2] = Vec3_dot(f, camera); + dst[3][3] = 1.0f; +} + +void Mat4_perspective(float fov, float aspect, float near, float far, Mat4 dst) +{ + float tan_half_fov = tanf(fov * 0.5f); + + // x basis + dst[0][0] = 1.0f / (aspect * tan_half_fov); + dst[0][1] = 0.0f; + dst[0][2] = 0.0f; + dst[0][3] = 0.0f; + + // y basis + dst[1][0] = 0.0f; + dst[1][1] = 1.0f / (tan_half_fov); + dst[1][2] = 0.0f; + dst[1][3] = 0.0f; + + // z basis + dst[2][0] = 0.0f; + dst[2][1] = 0.0f; + dst[2][2] = -(far + near) / (far - near); + dst[2][3] = -1.0f; + + // w basis + dst[3][0] = 0.0f; + dst[3][1] = 0.0f; + dst[3][2] = -(2 * far * near) / (far - near); + dst[3][3] = 0.0f; +}