# HG changeset patch # User John Tsiombikas # Date 1428394616 -10800 # Node ID 393ef1143c9cba5e340e6121f47f1dbc9e57f9b2 VR seasons diff -r 000000000000 -r 393ef1143c9c .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,3 @@ +\.o$ +\.d$ +\.swp$ diff -r 000000000000 -r 393ef1143c9c Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,41 @@ +csrc = $(wildcard src/*.c) +ccsrc = $(wildcard src/*.cc) +obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) +dep = $(obj:.o=.d) +bin = vrseasons + +sys = $(shell uname -s) + +use_glut = 1 + +CFLAGS = -pedantic -Wall -g +CXXFLAGS = $(CFLAGS) +LDFLAGS = $(libgl_$(sys)) -ldl -lgoatvr + +libgl_Linux = -lGL -lGLU -lGLEW +libgl_Darwin = -framework OpenGL -lGLEW + +ifdef use_glut + CFLAGS += -DUSE_GLUT + libgl_Linux += -lglut + libgl_Darwin += -framework GLUT +endif + +$(bin): $(obj) + $(CXX) -o $@ $(obj) $(LDFLAGS) + +-include $(dep) + +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +%.d: %.cc + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +.PHONY: clean +clean: + rm -f $(obj) $(bin) + +.PHONY: cleandep +cleandep: + rm -f $(dep) diff -r 000000000000 -r 393ef1143c9c src/game.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/game.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,137 @@ +#include +#include "opengl.h" +#include "game.h" +#include +#include +#include "main.h" +#include "scene.h" +#include "timer.h" +#include "rtarg.h" +#include "opt.h" + +static bool vr_mode = true; +static int win_width, win_height; +static RenderTarget vr_rtarg; + +bool game_init(int argc, char **argv) +{ + if(!parse_args(argc, argv)) { + return false; + } + + init_gl(); + + if(vr_mode) { + if(vr_init() == -1) { + return false; + } + + win_width = vr_geti_def(VR_DISPLAY_WIDTH, 1280); + win_height = vr_geti_def(VR_DISPLAY_HEIGHT, 800); + resize_window(win_width, win_height); + + int rt_width = vr_geti_def(VR_RENDER_XRES, win_width); + int rt_height = vr_geti_def(VR_RENDER_YRES, win_height); + vr_rtarg.create(rt_width, rt_height); + } + + return true; +} + +void game_shutdown() +{ + vr_shutdown(); +} + +void game_draw() +{ + static unsigned long prev_msec; + unsigned long msec = get_msec(); + float dt = (float)(msec - prev_msec) / 1000.0; + + update_scene(msec, dt); + + if(vr_mode) { + set_render_target(&vr_rtarg); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + for(int i=0; i<2; i++) { + vr_begin(i); + + glViewport(i == VR_EYE_LEFT ? 0 : vr_rtarg.get_width() / 2, 0, vr_rtarg.get_width() / 2, vr_rtarg.get_height()); + + glMatrixMode(GL_PROJECTION); + float proj[16]; + if(vr_proj_matrix(i, 0.5, 500.0, proj)) { + glLoadMatrixf(proj); + } else { + glLoadIdentity(); + gluPerspective(50.0, (float)win_width / 2.0 / (float)win_height, 0.5, 500.0); + } + + float view[16]; + vr_view_matrix(i, view); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(view); + glTranslatef(0, -vr_getf(VR_EYE_HEIGHT), 0); + + draw_scene(); + + vr_end(); + } + + set_render_target(0); + glViewport(0, 0, win_width, win_height); + + vr_swap_buffers(); + + } else { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + draw_scene(); + + swap_buffers(); + } + + assert(glGetError() == GL_NO_ERROR); +} + +void game_reshape(int x, int y) +{ + glViewport(0, 0, x, y); + + if(vr_mode) { + vr_rtarg.resize(x, y); + + float umax = (float)vr_rtarg.get_width() / (float)vr_rtarg.get_tex_width(); + float vmax = (float)vr_rtarg.get_height() / (float)vr_rtarg.get_tex_height(); + vr_output_texture(vr_rtarg.get_texture(), 0, 0, umax, vmax); + } +} + +void game_keyboard(int key, bool press) +{ + if(press) { + switch(key) { + case 27: + quit(); + + case ' ': + if(vr_mode) { + vr_recenter(); + } + break; + } + } +} + +void game_mbutton(int bn, bool press, int x, int y) +{ +} + +void game_mmotion(int x, int y) +{ +} diff -r 000000000000 -r 393ef1143c9c src/game.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/game.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,13 @@ +#ifndef GAME_H_ +#define GAME_H_ + +bool game_init(int argc, char **argv); +void game_shutdown(); + +void game_draw(); +void game_reshape(int x, int y); +void game_keyboard(int key, bool press); +void game_mbutton(int bn, bool press, int x, int y); +void game_mmotion(int x, int y); + +#endif /* GAME_H_ */ diff -r 000000000000 -r 393ef1143c9c src/main.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,16 @@ +#ifndef MAIN_H_ +#define MAIN_H_ + +/* functions defined by the various main_whatever frontends */ + +void quit(); +void swap_buffers(); +void redisplay(); +void fullscreen(); +void windowed(); +void move_window(int x, int y); +void window_position(int *xout, int *yout); +void resize_window(int x, int y); +void window_size(int *xout, int *yout); + +#endif /* MAIN_H_ */ diff -r 000000000000 -r 393ef1143c9c src/main_glut.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main_glut.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,150 @@ +#ifdef USE_GLUT + +#include + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include "game.h" + +static void display(); +static void idle(); +static void reshape(int x, int y); +static void key_press(unsigned char key, int x, int y); +static void key_release(unsigned char key, int x, int y); +static void mouse(int bn, int st, int x, int y); +static void motion(int x, int y); + +static bool state_fullscreen; +static int prev_width, prev_height; +static int win_width, win_height; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitWindowSize(800, 600); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow("GLUT"); + + glutDisplayFunc(display); + glutIdleFunc(idle); + glutReshapeFunc(reshape); + glutKeyboardFunc(key_press); + glutKeyboardUpFunc(key_release); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + if(!game_init(argc, argv)) { + return 1; + } + atexit(game_shutdown); + + glutMainLoop(); + return 0; +} + +void quit() +{ + exit(0); +} + +void swap_buffers() +{ + glutSwapBuffers(); +} + +void redisplay() +{ + glutPostRedisplay(); +} + +void idle() +{ + glutPostRedisplay(); +} + +void fullscreen() +{ + if(!state_fullscreen) { + prev_width = win_width; + prev_height = win_height; + + glutFullScreen(); + state_fullscreen = true; + } +} + +void windowed() +{ + if(state_fullscreen) { + glutReshapeWindow(prev_width, prev_height); + state_fullscreen = false; + } +} + +void move_window(int x, int y) +{ + if(!state_fullscreen) { + glutPositionWindow(x, y); + } +} + +void window_position(int *xout, int *yout) +{ + *xout = glutGet(GLUT_WINDOW_X); + *yout = glutGet(GLUT_WINDOW_Y); +} + +void resize_window(int x, int y) +{ + if(!state_fullscreen) { + glutReshapeWindow(x, y); + } +} + +void window_size(int *xout, int *yout) +{ + *xout = win_width; + *yout = win_height; +} + + +static void display() +{ + game_draw(); +} + +static void reshape(int x, int y) +{ + win_width = x; + win_height = y; + game_reshape(x, y); +} + +static void key_press(unsigned char key, int x, int y) +{ + game_keyboard(key, true); +} + +static void key_release(unsigned char key, int x, int y) +{ + game_keyboard(key, false); +} + +static void mouse(int bn, int st, int x, int y) +{ + game_mbutton(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y); +} + +static void motion(int x, int y) +{ + game_mmotion(x, y); +} + +int using_glut; +#else +int not_using_glut; +#endif diff -r 000000000000 -r 393ef1143c9c src/opengl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,11 @@ +#include "opengl.h" + +void init_gl() +{ + glewInit(); +} + +bool check_extension(const char *name) +{ + return glewIsSupported(name); +} diff -r 000000000000 -r 393ef1143c9c src/opengl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opengl.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,10 @@ +#ifndef OPENGL_H_ +#define OPENGL_H_ + +#include + +void init_gl(); + +bool check_extension(const char *name); + +#endif /* OPENGL_H_ */ diff -r 000000000000 -r 393ef1143c9c src/opt.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opt.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,71 @@ +#include +#include "opt.h" + +enum { + OPT_SIZE, + OPT_FULLSCREEN, + OPT_WINDOWED, + OPT_VR, + OPT_HELP, + + NUM_OPTS +}; +static const char *optname[] = { + "size", "fullscreen", "windowed", "vr", "help", 0 +}; + +static int get_option(const char *str); + +void default_opt(Options *opt) +{ + opt->xres = 1280; + opt->yres = 800; + opt->fov = 50.0; + opt->fullscreen = false; + opt->use_vr = false; +} + +bool parse_args(Options *opt, int argc, char **argv) +{ + for(int i=1; ixres, &opt->yres) != 2) { + fprintf(stderr, "invalid argument to option: %s\n", argv[i - 1]); + return false; + } + break; + + case OPT_FULLSCREEN: + opt->fullscreen = true; + break; + case OPT_WINDOWED: + opt->fullscreen = false; + break; + + case OPT_VR: + opt->use_vr = true; + break; + + case OPT_HELP: + printf("options:\n"); + for(int j=0; optname[j]; j++) { + printf(" -%s\n", optname[j]); + } + break; + } + } + } +} + +static int get_option(const char *str) +{ + for(int i=0; optname[i], i++) { + if(strcmp(str, optname[i]) == 0) { + return i; + } + } + return -1; +} diff -r 000000000000 -r 393ef1143c9c src/opt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/opt.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,16 @@ +#ifndef OPT_H_ +#define OPT_H_ + +struct Options { + int xres, yres; + float fov; + bool fullscreen; + bool use_vr; +}; + +void default_opt(Options *opt); +bool parse_args(Options *opt, int argc, char **argv); +bool parse_cfg(Options *opt, const char *cfgfname); +bool write_cfg(const Options *opt, const char *cfgname); + +#endif /* OPT_H_ */ diff -r 000000000000 -r 393ef1143c9c src/rtarg.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rtarg.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,135 @@ +#include "opengl.h" +#include "rtarg.h" + +static int next_pow2(int x); + +RenderTarget::RenderTarget() +{ + xsz = ysz = 0; + fbo = color = depth = 0; + + tex_fmt = 0; + tex_xsz = tex_ysz = 0; +} + +RenderTarget::~RenderTarget() +{ + destroy(); +} + +bool RenderTarget::create(int xsz, int ysz) +{ + destroy(); + + this->xsz = xsz; + this->ysz = ysz; + + tex_xsz = next_pow2(xsz); + tex_ysz = next_pow2(ysz); + tex_fmt = check_extension("GL_ARB_texture_float") ? GL_RGB16F : GL_RGB; + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glGenTextures(1, &color); + glBindTexture(GL_TEXTURE_2D, color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0); + + glGenRenderbuffers(1, &depth); + glBindRenderbuffer(GL_RENDERBUFFER, depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); + + return true; +} + +bool RenderTarget::resize(int xsz, int ysz) +{ + if(!fbo) { + return create(xsz, ysz); + } + + this->xsz = xsz; + this->ysz = ysz; + int new_tex_xsz = next_pow2(xsz); + int new_tex_ysz = next_pow2(ysz); + + if(tex_xsz != new_tex_xsz || tex_ysz != new_tex_ysz) { + glBindTexture(GL_TEXTURE_2D, color); + glTexImage2D(GL_TEXTURE_2D, 0, tex_fmt, tex_xsz, tex_ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, tex_xsz, tex_ysz); + + tex_xsz = new_tex_xsz; + tex_ysz = new_tex_ysz; + } + return true; +} + +void RenderTarget::destroy() +{ + if(fbo) { + glDeleteFramebuffers(1, &fbo); + } + if(color) { + glDeleteTextures(1, &color); + } + if(depth) { + glDeleteRenderbuffers(1, &depth); + } + fbo = color = depth = 0; +} + +bool RenderTarget::is_valid() const +{ + return fbo != 0; +} + +unsigned int RenderTarget::get_texture() const +{ + return color; +} + +int RenderTarget::get_width() const +{ + return xsz; +} + +int RenderTarget::get_height() const +{ + return ysz; +} + +int RenderTarget::get_tex_width() const +{ + return tex_xsz; +} + +int RenderTarget::get_tex_height() const +{ + return tex_ysz; +} + +void set_render_target(const RenderTarget *rtarg) +{ + if(rtarg) { + glBindFramebuffer(GL_FRAMEBUFFER, rtarg->color); + } else { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } +} + +static int next_pow2(int x) +{ + x--; + x = (x >> 1) | x; + x = (x >> 2) | x; + x = (x >> 4) | x; + x = (x >> 8) | x; + x = (x >> 16) | x; + return x + 1; +} diff -r 000000000000 -r 393ef1143c9c src/rtarg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rtarg.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,33 @@ +#ifndef RTARG_H_ +#define RTARG_H_ + +class RenderTarget { +private: + int xsz, ysz, tex_xsz, tex_ysz; + unsigned int fbo; + unsigned int color, depth; + unsigned int tex_fmt; + +public: + RenderTarget(); + ~RenderTarget(); + + bool create(int xsz, int ysz); + bool resize(int xsz, int ysz); + void destroy(); + + bool is_valid() const; + + unsigned int get_texture() const; + + int get_width() const; + int get_height() const; + int get_tex_width() const; + int get_tex_height() const; + + friend void set_render_target(const RenderTarget *rtarg); +}; + +void set_render_target(const RenderTarget *rtarg); + +#endif /* RTARG_H_ */ diff -r 000000000000 -r 393ef1143c9c src/scene.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scene.cc Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,17 @@ +#include "opengl.h" +#include "scene.h" + +void update_scene(long tmsec, float dt) +{ +} + +void draw_scene() +{ + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-10, 0, 10); + glVertex3f(10, 0, 10); + glVertex3f(10, 0, -10); + glVertex3f(-10, 0, -10); + glEnd(); +} diff -r 000000000000 -r 393ef1143c9c src/scene.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/scene.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,7 @@ +#ifndef SCENE_H_ +#define SCENE_H_ + +void update_scene(long tmsec, float dt); +void draw_scene(); + +#endif /* SCENE_H_ */ diff -r 000000000000 -r 393ef1143c9c src/timer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.c Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,23 @@ +#include "timer.h" + +#if defined(__unix__) || defined(__APPLE__) +#include + +unsigned long get_msec(void) +{ + struct timespec ts; + if(clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { + clock_gettime(CLOCK_REALTIME, &ts); + } + return ts.tv_sec * 1000ul + ts.tv_nsec / 1000000ul; +} + +#elif defined(WIN32) +#include + +unsigned long get_msec(void) +{ + return timeGetTime(); +} + +#endif diff -r 000000000000 -r 393ef1143c9c src/timer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.h Tue Apr 07 11:16:56 2015 +0300 @@ -0,0 +1,15 @@ +#ifndef TIMER_H_ +#define TIMER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned long get_msec(void); + +#ifdef __cplusplus +} +#endif + + +#endif /* TIMER_H_ */