From: John Tsiombikas Date: Mon, 14 Nov 2016 17:50:56 +0000 (+0200) Subject: VR mode X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=commitdiff_plain;h=c5c29f4044110dd153ee5ca3b018c812d518a053 VR mode --- diff --git a/Makefile b/Makefile index e43c5ac..85c4046 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ warn = -pedantic -Wall CFLAGS = $(warn) $(opt) $(dbg) $(incpath) CXXFLAGS = -std=c++11 $(warn) $(opt) $(dbg) $(incpath) LDFLAGS = $(libpath) $(libgl_$(sys)) -lm -lgmath -lvmath -limago -lresman \ - -lpthread -lassimp -ltreestore -ldrawtext `pkg-config --libs sdl2` + -lpthread -lassimp -ltreestore -ldrawtext -loptcfg -lgoatvr `pkg-config --libs sdl2` sys = $(shell uname -s) libgl_Linux = -lGL -lGLU -lGLEW diff --git a/src/app.cc b/src/app.cc index 065e581..d3b5657 100644 --- a/src/app.cc +++ b/src/app.cc @@ -1,5 +1,6 @@ #include #include +#include #include "app.h" #include "opengl.h" #include "sdr.h" @@ -10,6 +11,10 @@ #include "metascene.h" #include "datamap.h" #include "ui.h" +#include "opt.h" + +#define NEAR_CLIP 5.0 +#define FAR_CLIP 10000.0 static void draw_scene(); @@ -27,11 +32,13 @@ static float user_eye_height = 165; static float walk_speed = 300.0f; static bool show_walk_mesh, noclip = false; +static bool have_headtracking, should_swap; + static int prev_mx, prev_my; static bool bnstate[8]; static bool keystate[256]; -static Mat4 view_matrix; +static Mat4 view_matrix, mouse_view_matrix, proj_matrix; static TextureSet texman; static Scene *scn; static unsigned int sdr; @@ -39,8 +46,29 @@ static unsigned int sdr; static long prev_msec; -bool app_init() +bool app_init(int argc, char **argv) { + if(!init_options(argc, argv, "demo.conf")) { + return false; + } + app_resize(opt.width, opt.height); + app_fullscreen(opt.fullscreen); + + if(opt.vr) { + if(goatvr_init() == -1) { + return false; + } + goatvr_set_origin_mode(GOATVR_HEAD); + goatvr_set_units_scale(100.0f); + + goatvr_startvr(); + should_swap = goatvr_should_swap() != 0; + user_eye_height = goatvr_get_eye_height(); + have_headtracking = goatvr_have_headtracking(); + + goatvr_recenter(); + } + glEnable(GL_FRAMEBUFFER_SRGB); glEnable(GL_MULTISAMPLE); glEnable(GL_DEPTH_TEST); @@ -53,6 +81,8 @@ bool app_init() float ambient[] = {0.0, 0.0, 0.0, 0.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); + glClearColor(0.2, 0.2, 0.2, 1.0); + scn = new Scene(&texman); if(!load_scene(scn, "data/museum.scene")) { return false; @@ -76,11 +106,19 @@ bool app_init() set_uniform_int(sdr, "lightmap", 1); glUseProgram(0); + + if(opt.vr || opt.fullscreen) { + app_grab_mouse(true); + } return true; } void app_cleanup() { + app_grab_mouse(false); + if(opt.vr) { + goatvr_shutdown(); + } texman.clear(); } @@ -160,6 +198,15 @@ static void update(float dt) } floor_y = cam_pos.y - user_eye_height; } + + // calculate mouselook view matrix + mouse_view_matrix = Mat4::identity; + mouse_view_matrix.pre_translate(0, 0, -cam_dist); + if(!have_headtracking) { + mouse_view_matrix.pre_rotate_x(deg_to_rad(cam_phi)); + } + mouse_view_matrix.pre_rotate_y(deg_to_rad(cam_theta)); + mouse_view_matrix.pre_translate(-cam_pos.x, -cam_pos.y, -cam_pos.z); } static void set_light(int idx, const Vec3 &pos, const Vec3 &color) @@ -179,34 +226,59 @@ void app_display() float dt = (float)(time_msec - prev_msec) / 1000.0f; prev_msec = time_msec; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + update(dt); - view_matrix = Mat4::identity; - view_matrix.pre_translate(0, 0, -cam_dist); - view_matrix.pre_rotate(deg_to_rad(cam_phi), 1, 0, 0); - view_matrix.pre_rotate(deg_to_rad(cam_theta), 0, 1, 0); - view_matrix.pre_translate(-cam_pos.x, -cam_pos.y, -cam_pos.z); + if(opt.vr) { + // VR mode + goatvr_draw_start(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(view_matrix[0]); + for(int i=0; i<2; i++) { + // for each eye + goatvr_draw_eye(i); - static const Vec3 lpos[] = { Vec3(-50, 75, 100), Vec3(100, 0, 30), Vec3(-10, -10, 60) }; - set_light(0, lpos[0], Vec3(1.0, 0.8, 0.7) * 0.8); - set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6); - set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3); + proj_matrix = goatvr_projection_matrix(i, NEAR_CLIP, FAR_CLIP); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj_matrix[0]); - update(dt); + view_matrix = mouse_view_matrix * Mat4(goatvr_view_matrix(i)); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(view_matrix[0]); - draw_scene(); - draw_ui(); + draw_scene(); + } + goatvr_draw_done(); + + if(should_swap) { + app_swap_buffers(); + } + + } else { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + proj_matrix.perspective(deg_to_rad(50.0), win_aspect, NEAR_CLIP, FAR_CLIP); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj_matrix[0]); + + view_matrix = mouse_view_matrix; + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(view_matrix[0]); - app_swap_buffers(); + draw_scene(); + + app_swap_buffers(); + } assert(glGetError() == GL_NO_ERROR); } static void draw_scene() { + static const Vec3 lpos[] = { Vec3(-50, 75, 100), Vec3(100, 0, 30), Vec3(-10, -10, 60) }; + set_light(0, lpos[0], Vec3(1.0, 0.8, 0.7) * 0.8); + set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6); + set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3); + glUseProgram(sdr); scn->draw(); glUseProgram(0); @@ -228,16 +300,15 @@ static void draw_scene() glPopAttrib(); } + + draw_ui(); } void app_reshape(int x, int y) { glViewport(0, 0, x, y); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(50.0, (float)x / (float)y, 1.0, 10000.0); + goatvr_set_fb_size(x, y, 1.0f); } void app_keyboard(int key, bool pressed) diff --git a/src/app.h b/src/app.h index 2867309..02db8db 100644 --- a/src/app.h +++ b/src/app.h @@ -12,7 +12,7 @@ enum { MOD_CTRL = 4 }; -bool app_init(); +bool app_init(int argc, char **argv); void app_cleanup(); void app_display(); diff --git a/src/main.cc b/src/main.cc index f21c406..01c9d12 100644 --- a/src/main.cc +++ b/src/main.cc @@ -5,7 +5,7 @@ #include #include "app.h" -static bool init(); +static bool init(int argc, char **argv); static void process_event(SDL_Event *ev); static void proc_modkeys(); @@ -51,7 +51,7 @@ int main(int argc, char **argv) SDL_GL_GetDrawableSize(win, &win_width, &win_height); win_aspect = (float)win_width / (float)win_height; - if(!init()) { + if(!init(argc, argv)) { SDL_Quit(); return 1; } @@ -113,9 +113,8 @@ bool app_is_fullscreen() void app_grab_mouse(bool grab) { - /*SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE); + SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE); SDL_ShowCursor(grab ? 1 : 0); - */ SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE); mouse_grabbed = grab; } @@ -131,11 +130,11 @@ bool app_is_mouse_grabbed() } -static bool init() +static bool init(int argc, char **argv) { glewInit(); - if(!app_init()) { + if(!app_init(argc, argv)) { return false; } diff --git a/src/opt.cc b/src/opt.cc new file mode 100644 index 0000000..9226785 --- /dev/null +++ b/src/opt.cc @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include "opt.h" + +Options opt; + +Options def_opt = { + 1280, 800, + false, // vr + false // fullscreen +}; + +enum { + OPT_SIZE, + OPT_VR, + OPT_SRGB, + OPT_FULLSCREEN, + OPT_WINDOWED, + OPT_HELP +}; + +static optcfg_option options[] = { + // short, long, id, desc + {'s', "size", OPT_SIZE, "window size (WxH)"}, + {0, "vr", OPT_VR, "enable VR mode"}, + {'f', "fullscreen", OPT_FULLSCREEN, "run in fullscreen mode"}, + {'w', "windowed", OPT_WINDOWED, "run in windowed mode"}, + {'h', "help", OPT_HELP, "print usage and exit"}, + OPTCFG_OPTIONS_END +}; + +static int opt_handler(optcfg *oc, int opt, void *cls); +static int arg_handler(optcfg *oc, const char *arg, void *cls); + +bool init_options(int argc, char **argv, const char *cfgfile) +{ + // default options + opt = def_opt; + + optcfg *oc = optcfg_init(options); + optcfg_set_opt_callback(oc, opt_handler, 0); + optcfg_set_arg_callback(oc, arg_handler, 0); + + if(cfgfile) { + optcfg_parse_config_file(oc, cfgfile); + } + + if(argv && optcfg_parse_args(oc, argc, argv) == -1) { + fprintf(stderr, "invalid option\n"); + optcfg_destroy(oc); + return false; + } + + optcfg_destroy(oc); + return true; +} + +static bool is_enabled(optcfg *oc) +{ + int res; + optcfg_enabled_value(oc, &res); + return res != 0; +} + +static int opt_handler(optcfg *oc, int optid, void *cls) +{ + switch(optid) { + case OPT_SIZE: + { + char *valstr = optcfg_next_value(oc); + if(!valstr || sscanf(valstr, "%dx%d", &opt.width, &opt.height) != 2) { + fprintf(stderr, "size must be in the form: WIDTHxHEIGHT\n"); + return -1; + } + } + break; + + case OPT_VR: + opt.vr = is_enabled(oc); + break; + + case OPT_FULLSCREEN: + opt.fullscreen = is_enabled(oc); + break; + + case OPT_WINDOWED: + opt.fullscreen = !is_enabled(oc); + break; + + case OPT_HELP: + printf("Usage: vrfileman [options]\nOptions:\n"); + optcfg_print_options(oc); + exit(0); + } + return 0; +} + +static int arg_handler(optcfg *oc, const char *arg, void *cls) +{ + fprintf(stderr, "unexpected argument: %s\n", arg); + return -1; +} diff --git a/src/opt.h b/src/opt.h new file mode 100644 index 0000000..176dd61 --- /dev/null +++ b/src/opt.h @@ -0,0 +1,14 @@ +#ifndef OPT_H_ +#define OPT_H_ + +struct Options { + int width, height; + bool vr; + bool fullscreen; +}; + +extern Options opt, def_opt; + +bool init_options(int argc, char **argv, const char *cfgfile); + +#endif // OPT_H_