aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2018-05-03 13:49:44 +0100
committerTomasz Kramkowski <tk@the-tk.com>2018-05-03 13:49:44 +0100
commita1e93038af0a739b9af57bd40ffbee6963dc3242 (patch)
treeeebceb8f833c55fe8c9a1e15d4c26afd7defdfbc
parent362f70b04da8f8e9c0c159527bce7da65591c260 (diff)
downloadfaqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.tar.gz
faqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.tar.xz
faqe-a1e93038af0a739b9af57bd40ffbee6963dc3242.zip
Add a simple camera struct and camera controls
-rw-r--r--Makefile2
-rw-r--r--camera.c43
-rw-r--r--camera.h22
-rw-r--r--faqe.c64
-rw-r--r--math.h10
5 files changed, 125 insertions, 16 deletions
diff --git a/Makefile b/Makefile
index 9d66590..498123c 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/faqe.c b/faqe.c
index 1983464..3b81e24 100644
--- a/faqe.c
+++ b/faqe.c
@@ -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);
diff --git a/math.h b/math.h
new file mode 100644
index 0000000..e5b9724
--- /dev/null
+++ b/math.h
@@ -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