commit 3a705c1c04cacb3565003db5b1ecea490602979e
parent baaa759198978be8812d1af4754ab63c3fd097dc
Author: Christian Ermann <christianermann@gmail.com>
Date: Sun, 11 Jul 2021 18:53:21 -0700
Moveable camera
Diffstat:
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);