terrain

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

commit 3a705c1c04cacb3565003db5b1ecea490602979e
parent baaa759198978be8812d1af4754ab63c3fd097dc
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sun, 11 Jul 2021 18:53:21 -0700

Moveable camera

Diffstat:
Ainclude/camera.h | 39+++++++++++++++++++++++++++++++++++++++
Mshaders/basic.vs | 4+++-
Asrc/camera.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.c | 32++++++++++++++++++++++++++++++++
4 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/include/camera.h b/include/camera.h @@ -0,0 +1,39 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include <cglm/cglm.h> + +typedef struct { + vec3 position; + float yaw; + float pitch; + + vec3 world_up; + float fovy; + float aspect; + float near; + float far; + float speed; + float sensitivity; + + vec3 front; + vec3 up; + vec3 right; + + mat4 matrix; +} Camera; + +Camera Camera_create(float x, float y, float z, float yaw, float pitch); + +void Camera_defaultSettings(Camera* camera); + +void Camera_updateRotation(Camera* camera, float dx, float dy); +void Camera_updatePosition(Camera* camera, float z, float x, float y); + +// Update camera 'front', 'right', 'up' vectors. +void Camera_updateVectors(Camera* camera); + +// Update the (projection * view) matrix of the camera. +void Camera_updateMatrix(Camera* camera); + +#endif diff --git a/shaders/basic.vs b/shaders/basic.vs @@ -4,8 +4,10 @@ layout(location = 0) in vec3 in_position; out vec4 position; +uniform mat4 camera; + void main() { - position = vec4(in_position, 1.0); + position = camera * vec4(in_position, 1.0); gl_Position = position; } diff --git a/src/camera.c b/src/camera.c @@ -0,0 +1,87 @@ +#include "camera.h" + +Camera Camera_create(float x, float y, float z, float yaw, float pitch) +{ + Camera camera; + camera.position[0] = x; + camera.position[1] = y; + camera.position[2] = z; + camera.yaw = yaw; + camera.pitch = pitch; + Camera_defaultSettings(&camera); + Camera_updateVectors(&camera); + Camera_updateMatrix(&camera); + return camera; +} + +void Camera_defaultSettings(Camera* camera) +{ + camera->world_up[0] = 0.0f; + camera->world_up[1] = 1.0f; + camera->world_up[2] = 0.0f; + camera->fovy = 90.0f; + camera->aspect = 1.0f; + camera->near = 0.1f; + camera->far = 100.0f; + camera->speed = 0.1f; + camera->sensitivity = 0.3f; +} + +void Camera_updateRotation(Camera* camera, float dx, float dy) +{ + camera->yaw += dx * camera->sensitivity; + + camera->pitch += dy * camera->sensitivity; + if (camera->pitch > 85.0f) camera->pitch = 85.0f; + if (camera->pitch < -85.0f) camera->pitch = -85.0f; +} + +void Camera_updatePosition(Camera* camera, float x, float y, float z) +{ + vec3 movement_x; + glm_vec3_scale(camera->right, x, movement_x); + + vec3 movement_y; + glm_vec3_scale(camera->up, y, movement_y); + + vec3 movement_z; + glm_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); + + glm_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); + + glm_vec3_cross(camera->front, camera->world_up, camera->right); + glm_vec3_normalize(camera->right); + + glm_vec3_cross(camera->right, camera->front, camera->up); + glm_vec3_normalize(camera->up); +} + +void Camera_updateMatrix(Camera* camera) +{ + vec3 camera_target; + glm_vec3_add(camera->position, camera->front, camera_target); + + mat4 view; + glm_lookat(camera->position, camera_target, camera->up, view); + + mat4 projection; + glm_perspective(glm_rad(camera->fovy), camera->aspect, camera->near, + camera->far, projection); + + glm_mat4_mul(projection, view, camera->matrix); +} diff --git a/src/main.c b/src/main.c @@ -1,3 +1,4 @@ +#include "camera.h" #include "glh/buffer.h" #include "glh/shader.h" @@ -11,6 +12,22 @@ const int WIDTH = 512, HEIGHT = 512; +void Camera_update(Camera* camera) +{ + int dx, dy; + SDL_GetRelativeMouseState(&dx, &dy); + Camera_updateRotation(camera, dx, -dy); + + const Uint8* kb = SDL_GetKeyboardState(NULL); + float x = kb[SDL_SCANCODE_D] - kb[SDL_SCANCODE_A]; + 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); +} + int main(int argc, char** argv) { if (SDL_Init(SDL_INIT_VIDEO) < 0) @@ -39,6 +56,11 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + SDL_ShowCursor(SDL_DISABLE); + SDL_SetRelativeMouseMode(SDL_TRUE); + + Camera camera = Camera_create(0, 0, 3, -90, 0); + gladLoadGLLoader(SDL_GL_GetProcAddress); glViewport(0, 0, WIDTH, HEIGHT); @@ -70,6 +92,8 @@ int main(int argc, char** argv) Shader shader = Shader_create("shaders/basic.vs", "shaders/basic.fs"); glUseProgram(shader.program); + GLint cam_loc = glGetUniformLocation(shader.program, "camera"); + SDL_Event window_event; while (true) { @@ -81,15 +105,23 @@ int main(int argc, char** argv) } switch (window_event.key.keysym.sym) { + case SDLK_ESCAPE: + SDL_ShowCursor(SDL_ENABLE); + SDL_SetRelativeMouseMode(SDL_FALSE); + break; case SDLK_r: Shader_reload(&shader); glUseProgram(shader.program); + cam_loc = glGetUniformLocation(shader.program, "camera"); break; } } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + Camera_update(&camera); + glUniformMatrix4fv(cam_loc, 1, GL_FALSE, camera.matrix[0]); + glBindVertexArray(vertex_array); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);