diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2018-05-03 13:49:44 +0100 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2018-05-03 13:49:44 +0100 |
commit | a1e93038af0a739b9af57bd40ffbee6963dc3242 (patch) | |
tree | eebceb8f833c55fe8c9a1e15d4c26afd7defdfbc | |
parent | 362f70b04da8f8e9c0c159527bce7da65591c260 (diff) | |
download | faqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.tar.gz faqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.tar.xz faqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.zip |
Add a simple camera struct and camera controls
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | camera.c | 43 | ||||
-rw-r--r-- | camera.h | 22 | ||||
-rw-r--r-- | faqe.c | 64 | ||||
-rw-r--r-- | math.h | 10 |
5 files changed, 125 insertions, 16 deletions
@@ -15,7 +15,7 @@ CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBS)) -std=c11 -MMD -MP LDFLAGS += -Wl,--as-needed LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBS)) -lm -OBJ := faqe.o ensize.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o mtl.o tex.o +OBJ := faqe.o camera.o ensize.o eprintf.o fmd.o gl.o glprog.o ieee754.o model.o mtl.o tex.o all: $(PROG) diff --git a/camera.c b/camera.c new file mode 100644 index 0000000..6335d0e --- /dev/null +++ b/camera.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> + * SPDX-License-Identifier: MIT + */ +#include <assert.h> +#include <math.h> +#include <stdlib.h> + +#include "camera.h" +#include "math.h" + +#define PITCH_LIMIT (PI * 0.99) + +void camera_clamp(struct camera *cam) +{ + assert(cam != NULL); + + cam->yaw = fmod(cam->yaw, 2 * PI); + if (cam->pitch > PITCH_LIMIT / 2) + cam->pitch = PITCH_LIMIT / 2; + else if (cam->pitch < -PITCH_LIMIT / 2) + cam->pitch = -PITCH_LIMIT / 2; +} +void camera_dir(vec3 out, struct camera *cam) +{ + assert(out != NULL); + assert(cam != NULL); + + out[0] = cosf(cam->pitch) * cosf(cam->yaw); + out[1] = sinf(cam->pitch); + out[2] = cosf(cam->pitch) * sinf(cam->yaw); +} +void camera_lookat(mat4x4 out, struct camera *cam) +{ + vec3 at, dir; + + assert(out != NULL); + assert(cam != NULL); + + camera_dir(dir, cam); + vec3_add(at, cam->pos, dir); + mat4x4_look_at(out, cam->pos, at, (vec3){ 0, 1, 0 }); +} diff --git a/camera.h b/camera.h new file mode 100644 index 0000000..6d8bb94 --- /dev/null +++ b/camera.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> + * SPDX-License-Identifier: MIT + */ +#ifndef CAMERA_H +#define CAMERA_H + +#include "linmath.h" + +#define CAM_UP ((vec3){ 0.0, 1.0, 0.0 }) + +struct camera { + vec3 pos; + float pitch; + float yaw; +}; + +void camera_clamp(struct camera *cam); +void camera_dir(vec3 out, struct camera *cam); +void camera_lookat(mat4x4 out, struct camera *cam); + +#endif // CAMERA_H @@ -6,19 +6,20 @@ #include <stdbool.h> #include "assets.h" +#include "camera.h" #include "eprintf.h" #include "gl.h" #include "glprog.h" #include "linmath.h" -#include "nelem.h" +#include "math.h" #include "model.h" +#include "nelem.h" enum { WIDTH = 800, HEIGHT = 600, }; -#define PI 3.14159265358979323846 #define FOV (PI * 0.5) void viewport(GLuint proj, int width, int height) @@ -38,11 +39,14 @@ int main(int argc, char **argv) struct { GLint model, view, proj, tex; } uni; - mat4x4 view; FILE *cube_file; struct fmd cube_fmd; struct model cube_model; - vec3 pos = { 0, 0, 3 }; + struct camera cam = { .pos = { 0.0, 0.0, 3.0 }, .yaw = -PI/2 }; + struct { + bool w, a, s, d, spc, lct; + } key = { 0 }; + float tlast; setprogname(argc >= 1 && argv[0] != NULL ? argv[0] : "faqe"); @@ -61,6 +65,8 @@ int main(int argc, char **argv) if (win == NULL) eprintf("Failed to create window: %s", SDL_GetError()); + SDL_SetRelativeMouseMode(SDL_TRUE); + glc = SDL_GL_CreateContext(win); if (glc == NULL) eprintf("Failed to create OpenGL context: %s", SDL_GetError()); @@ -97,20 +103,33 @@ int main(int argc, char **argv) gl_enable(GL_FRAMEBUFFER_SRGB); gl_enable(GL_CULL_FACE); + tlast = SDL_GetTicks() * 0.0001; + while (running) { - mat4x4 model; + mat4x4 model, view; + vec3 dir, right, motion = { 0 }, strafe = { 0 }; SDL_Event ev; - float secs; - - secs = SDL_GetTicks() * 0.0001; - - mat4x4_look_at(view, pos, (vec3){ 0, 0, 0 }, (vec3){ 0, 1, 0 }); - gl_uni_setm4fv(uni.view, 1, GL_FALSE, view[0]); + float tdiff, tnow; while (SDL_PollEvent(&ev)) { + bool down; switch (ev.type) { + case SDL_MOUSEMOTION: + cam.yaw += ev.motion.xrel * 0.005; + cam.pitch += ev.motion.yrel * -0.005; + camera_clamp(&cam); + break; case SDL_KEYDOWN: case SDL_KEYUP: + down = ev.key.state == SDL_PRESSED; + switch (ev.key.keysym.sym) { + case SDLK_w: key.w = down; break; + case SDLK_a: key.a = down; break; + case SDLK_s: key.s = down; break; + case SDLK_d: key.d = down; break; + case SDLK_SPACE: key.spc = down; break; + case SDLK_LCTRL: key.lct = down; break; + } if (ev.key.state != SDL_RELEASED || ev.key.keysym.sym != SDLK_ESCAPE) break; @@ -129,13 +148,28 @@ int main(int argc, char **argv) } } + tnow = SDL_GetTicks() * 0.001; + tdiff = tnow - tlast; + tlast = tnow; + + camera_dir(dir, &cam); + vec3_mul_cross(right, dir, CAM_UP); + vec3_norm(right, right); + + if (key.w != key.s) vec3_scale(motion, dir, tdiff * (key.w ? 1 : -1)); + if (key.a != key.d) vec3_scale(strafe, right, tdiff * (key.d ? 1 : -1)); + if (key.spc != key.lct) cam.pos[1] += tdiff * (key.spc ? 1 : -1); + vec3_add(cam.pos, cam.pos, strafe); + vec3_add(cam.pos, cam.pos, motion); + + camera_lookat(view, &cam); + gl_clearcolor(0.2, 0.3, 0.3, 1.0); gl_clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - gl_prog_use(prog); mat4x4_identity(model); - mat4x4_rotate_X(model, model, secs * 3); - mat4x4_rotate_Y(model, model, secs * 2); - mat4x4_rotate_Z(model, model, secs * 4); + + gl_prog_use(prog); + gl_uni_setm4fv(uni.view, 1, GL_FALSE, view[0]); gl_uni_setm4fv(uni.model, 1, GL_FALSE, model[0]); model_render(&cube_model); gl_va_bind(0); @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2018 Tomasz Kramkowski <tk@the-tk.com> + * SPDX-License-Identifier: MIT + */ +#ifndef MATH_H +#define MATH_H + +#define PI 3.14159265358979323846 + +#endif // MATH_H |