moving along
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 23 Feb 2019 05:31:23 +0000 (07:31 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 23 Feb 2019 05:31:23 +0000 (07:31 +0200)
Makefile
src/game.c
src/game.h
src/osd.c
src/osd.h
src/screen.c [new file with mode: 0644]
src/screen.h [new file with mode: 0644]

index a773a6e..3b1335d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@ bin = vrtris
 
 
 CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl2`
-LDFLAGS = $(libsys) $(libgl) `pkg-config --libs sdl2` -ldrawtext
+LDFLAGS = $(libsys) $(libgl) `pkg-config --libs sdl2` -ldrawtext -lgoatvr \
+                 -limago -lm
 
 sys ?= $(shell uname -s | sed 's/MINGW.*/mingw/')
 
index 399a5ea..00f81cc 100644 (file)
@@ -1,8 +1,19 @@
 #include <assert.h>
+#include <goatvr.h>
+#include <cgmath/cgmath.h>
 #include "opengl.h"
 #include "game.h"
+#include "screen.h"
+#include "osd.h"
 #include "opt.h"
 
+static void calc_framerate(void);
+static void print_framerate(void);
+
+static float view_matrix[16], proj_matrix[16];
+static int should_swap;
+static unsigned long framerate;
+
 int game_init(int argc, char **argv)
 {
        if(init_opengl() == -1) {
@@ -13,43 +24,150 @@ int game_init(int argc, char **argv)
                return -1;
        }
 
+       if(init_screens() == -1) {
+               return -1;
+       }
+
+       if(opt.flags & OPT_VR) {
+               if(goatvr_init() == -1) {
+                       return -1;
+               }
+               goatvr_set_origin_mode(GOATVR_HEAD);
+
+               goatvr_startvr();
+               should_swap = goatvr_should_swap();
+       }
        return 0;
 }
 
 void game_cleanup()
 {
+       if(opt.flags & OPT_VR) {
+               goatvr_shutdown();
+       }
+       cleanup_screens();
 }
 
-void game_display()
+static void update(float dt)
 {
-       glClear(GL_COLOR_BUFFER_BIT);
+       int num_vr_sticks;
+
+       if((num_vr_sticks = goatvr_num_sticks()) > 0) {
+               float p[2];
+               goatvr_stick_pos(0, p);
+               /* TODO */
+       }
+
+       screen->update(dt);
+}
+
+void game_display(void)
+{
+       static long prev_msec;
+       int i;
+       float dt = (float)(time_msec - prev_msec) / 1000.0f;
+       prev_msec = time_msec;
+
+       update(dt);
+
+       if(opt.flags & OPT_VR) {
+               goatvr_draw_start();
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+               for(i=0; i<2; i++) {
+                       /* for each eye */
+                       goatvr_draw_eye(i);
+
+                       cgm_mcopy(proj_matrix, goatvr_projection_matrix(i, 0.5, 500.0));
+                       glMatrixMode(GL_PROJECTION);
+                       glLoadMatrixf(proj_matrix);
+
+                       cgm_mcopy(view_matrix, goatvr_view_matrix(i));
+                       glMatrixMode(GL_MODELVIEW);
+                       glLoadMatrixf(view_matrix);
+
+                       screen->draw();
+                       print_framerate();
+                       draw_osd();
+               }
+
+               goatvr_draw_done();
+
+               if(should_swap) {
+                       game_swap_buffers();
+               }
+
+       } else {
+               /* non-VR mode */
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+               cgm_mperspective(proj_matrix, cgm_deg_to_rad(50.0), win_aspect, 0.5, 500.0);
+               glMatrixMode(GL_PROJECTION);
+               glLoadMatrixf(proj_matrix);
+
+               cgm_midentity(view_matrix);
+               glMatrixMode(GL_MODELVIEW);
+               glLoadMatrixf(view_matrix);
+
+               screen->draw();
+               print_framerate();
+               draw_osd();
+
+               game_swap_buffers();
+       }
 
-       game_swap_buffers();
        assert(glGetError() == GL_NO_ERROR);
+
+       calc_framerate();
 }
 
 void game_reshape(int x, int y)
 {
+       glViewport(0, 0, x, y);
+       goatvr_set_fb_size(x, y, 1.0f);
+
+       reshape_screens(x, y);
 }
 
 void game_keyboard(int key, int pressed)
 {
+       unsigned int mod = game_get_modifiers();
+
+       if(pressed) {
+               switch(key) {
+               case 27:
+                       game_quit();
+                       return;
+
+               case '\n':
+               case '\r':
+                       if(mod & MOD_ALT) {
+                               game_toggle_fullscreen();
+                               return;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       screen->keyboard(key, pressed);
 }
 
 void game_mouse_button(int bn, int pressed, int x, int y)
 {
+       screen->mouse(bn, pressed, x, y);
 }
 
 void game_mouse_motion(int x, int y)
 {
-}
-
-void game_mouse_delta(int dx, int dy)
-{
+       screen->motion(x, y);
 }
 
 void game_mouse_wheel(int dir)
 {
+       screen->wheel(dir);
 }
 
 
@@ -60,3 +178,23 @@ void game_gamepad_axis(int axis, float val)
 void game_gamepad_button(int bn, int pressed)
 {
 }
+
+static void calc_framerate(void)
+{
+       static unsigned long nframes;
+       static long prev_upd;
+
+       long elapsed = time_msec - prev_upd;
+       if(elapsed >= 1000) {
+               framerate = nframes * 10000 / elapsed;
+               nframes = 1;
+               prev_upd = time_msec;
+       } else {
+               ++nframes;
+       }
+}
+
+static void print_framerate(void)
+{
+       print_text(9 * win_width / 10, 20, 1, 1, 0, "fps: %d.%d", framerate / 10, framerate % 10);
+}
index a3455f0..0bcd229 100644 (file)
@@ -58,28 +58,27 @@ enum {
 };
 
 int game_init(int argc, char **argv);
-void game_cleanup();
+void game_cleanup(void);
 
-void game_display();
+void game_display(void);
 void game_reshape(int x, int y);
 
 void game_keyboard(int key, int pressed);
 void game_mouse_button(int bn, int pressed, int x, int y);
 void game_mouse_motion(int x, int y);
-void game_mouse_delta(int dx, int dy);
 void game_mouse_wheel(int dir);
 
 void game_gamepad_axis(int axis, float val);
 void game_gamepad_button(int bn, int pressed);
 
 /* the following functions are implemented by the backend (main.c) */
-void game_quit();
-void game_swap_buffers();
-unsigned int game_get_modifiers();
+void game_quit(void);
+void game_swap_buffers(void);
+unsigned int game_get_modifiers(void);
 
 void game_resize(int x, int y);
 void game_fullscreen(int fs);
-void game_toggle_fullscreen();
-int game_is_fullscreen();
+void game_toggle_fullscreen(void);
+int game_is_fullscreen(void);
 
 #endif // GAME_H_
index b40424f..8b139bd 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -128,7 +128,7 @@ void print_textv(float x, float y, float r, float g, float b, const char *fmt, v
        txlist = tx;
 }
 
-void draw_ui()
+void draw_osd(void)
 {
        if(!ui_font) return;
 
@@ -191,7 +191,7 @@ void draw_ui()
        glPopMatrix();
 }
 
-static int init()
+static int init(void)
 {
        static int done_init;
        if(done_init) return 0;
index dc0028b..c475150 100644 (file)
--- a/src/osd.h
+++ b/src/osd.h
@@ -16,6 +16,6 @@ void show_messagev(long timeout, float r, float g, float b, const char *fmt, va_
 void print_text(float x, float y, float r, float g, float b, const char *fmt, ...);
 void print_textv(float x, float y, float r, float g, float b, const char *fmt, va_list ap);
 
-void draw_ui(void);
+void draw_osd(void);
 
 #endif /* OSD_H_ */
diff --git a/src/screen.c b/src/screen.c
new file mode 100644 (file)
index 0000000..6638b4e
--- /dev/null
@@ -0,0 +1,54 @@
+#include "screen.h"
+
+static struct game_screen *screens[16];
+static int num_screens;
+
+static struct game_screen *stack;
+
+int init_screens(void)
+{
+       int i;
+
+       for(i=0; i<num_screens; i++) {
+               if(screens[i]->init() == -1) {
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+void cleanup_screens(void)
+{
+       int i;
+
+       for(i=0; i<num_screens; i++) {
+               screens[i]->cleanup();
+       }
+}
+
+void reshape_screens(int x, int y)
+{
+       struct game_screen *s = stack;
+       while(s) {
+               s->reshape(x, y);
+               s = s->next;
+       }
+}
+
+void push_screen(struct game_screen *s)
+{
+       s->next = stack;
+       stack = s;
+       s->start();
+}
+
+int pop_screen(void)
+{
+       struct game_screen *s;
+
+       if(!stack->next) return -1;
+       s = stack;
+       stack = stack->next;
+       s->stop();
+       return 0;
+}
diff --git a/src/screen.h b/src/screen.h
new file mode 100644 (file)
index 0000000..33897dc
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef SCREEN_H_
+#define SCREEN_H_
+
+struct game_screen {
+       const char *name;
+       int opaque;     /* if 0, the next screen is visible, so keep update/drawing it */
+
+       struct game_screen *next;
+
+       int (*init)(void);
+       void (*cleanup)(void);
+
+       void (*start)(void);
+       void (*stop)(void);
+
+       void (*update)(float dt);
+       void (*draw)(void);
+       void (*reshape)(int, int);
+       /* these functions return 1 if they handled the event, or 0
+        * if it should propagate to the next screen in the stack */
+       int (*keyboard)(int, int);
+       int (*mouse)(int, int, int, int);
+       int (*motion)(int, int);
+       int (*wheel)(int dir);
+};
+
+/* this always points to the top screen on the stack
+ * there's always at least one screen, this will never be null
+ */
+struct game_screen *screen;
+
+int init_screens(void);
+void cleanup_screens(void);
+void reshape_screens(int x, int y);
+
+void push_screen(struct game_screen *s);
+int pop_screen(void);
+
+#endif /* SCREEN_H_ */