libgoatvr
changeset 5:e63cb28fc644
working on the linux side a bit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 18 Sep 2014 10:56:45 +0300 |
parents | 9ed0f1efd4cd |
children | b71314e80654 |
files | Makefile.in example/Makefile example/src/main.c src/opengl.c src/opengl.h src/vr.c src/vr_libovr.c src/vr_null.c |
diffstat | 8 files changed, 591 insertions(+), 91 deletions(-) [+] |
line diff
1.1 --- a/Makefile.in Fri Aug 29 07:37:19 2014 +0300 1.2 +++ b/Makefile.in Thu Sep 18 10:56:45 2014 +0300 1.3 @@ -30,7 +30,7 @@ 1.4 endif 1.5 1.6 .PHONY: all 1.7 -$(all): $(lib_so) $(lib_a) 1.8 +all: $(lib_so) $(lib_a) 1.9 1.10 $(lib_so): $(obj) 1.11 $(CC) -o $@ $(shared) $(obj) $(LDFLAGS)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/example/Makefile Thu Sep 18 10:56:45 2014 +0300 2.3 @@ -0,0 +1,26 @@ 2.4 +src = $(wildcard src/*.c) 2.5 +obj = $(src:.c=.o) 2.6 +bin = test 2.7 + 2.8 +vrlib_root = .. 2.9 +vrlib = $(vrlib_root)/libgoatvr.a 2.10 + 2.11 +CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl2` -I$(vrlib_root)/src 2.12 +LDFLAGS = $(libgl) `pkg-config --libs sdl2` $(vrlib) 2.13 + 2.14 +ifeq ($(shell uname -s), Darwin) 2.15 + libgl = -framework OpenGL -lGLEW 2.16 +else 2.17 + libgl = -lGL -lGLU -lGLEW 2.18 +endif 2.19 + 2.20 +$(bin): $(obj) $(vrlib) 2.21 + $(CC) -o $@ $(obj) $(LDFLAGS) 2.22 + 2.23 +.PHONY: $(vrlib) 2.24 +$(vrlib): 2.25 + $(MAKE) -C $(vrlib_root) 2.26 + 2.27 +.PHONY: clean 2.28 +clean: 2.29 + rm -f $(obj) $(bin)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/example/src/main.c Thu Sep 18 10:56:45 2014 +0300 3.3 @@ -0,0 +1,449 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <assert.h> 3.7 +#include <SDL2/SDL.h> 3.8 +#include <GL/glew.h> 3.9 +#include "vr.h" 3.10 + 3.11 +int init(void); 3.12 +void cleanup(void); 3.13 +void toggle_hmd_fullscreen(void); 3.14 +void display(void); 3.15 +void draw_scene(void); 3.16 +void draw_box(float xsz, float ysz, float zsz, float norm_sign); 3.17 +void update_rtarg(int width, int height); 3.18 +int handle_event(SDL_Event *ev); 3.19 +int key_event(int key, int state); 3.20 +void reshape(int x, int y); 3.21 +unsigned int next_pow2(unsigned int x); 3.22 +void quat_to_matrix(const float *quat, float *mat); 3.23 +unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1); 3.24 + 3.25 +static SDL_Window *win; 3.26 +static SDL_GLContext ctx; 3.27 +static int win_width, win_height; 3.28 + 3.29 +static unsigned int fbo, fb_tex, fb_depth; 3.30 +static int fb_width, fb_height; 3.31 +static int fb_tex_width, fb_tex_height; 3.32 + 3.33 +static unsigned int chess_tex; 3.34 + 3.35 + 3.36 +int main(int argc, char **argv) 3.37 +{ 3.38 + if(init() == -1) { 3.39 + return 1; 3.40 + } 3.41 + 3.42 + for(;;) { 3.43 + SDL_Event ev; 3.44 + while(SDL_PollEvent(&ev)) { 3.45 + if(handle_event(&ev) == -1) { 3.46 + goto done; 3.47 + } 3.48 + } 3.49 + display(); 3.50 + } 3.51 + 3.52 +done: 3.53 + cleanup(); 3.54 + return 0; 3.55 +} 3.56 + 3.57 + 3.58 +int init(void) 3.59 +{ 3.60 + int x, y; 3.61 + unsigned int flags; 3.62 + 3.63 + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); 3.64 + 3.65 + x = y = SDL_WINDOWPOS_UNDEFINED; 3.66 + flags = SDL_WINDOW_OPENGL; 3.67 + if(!(win = SDL_CreateWindow("press 'f' to move to the HMD", x, y, 1280, 800, flags))) { 3.68 + fprintf(stderr, "failed to create window\n"); 3.69 + return -1; 3.70 + } 3.71 + if(!(ctx = SDL_GL_CreateContext(win))) { 3.72 + fprintf(stderr, "failed to create OpenGL context\n"); 3.73 + return -1; 3.74 + } 3.75 + 3.76 + glewInit(); 3.77 + 3.78 + if(vr_init() == -1) { 3.79 + return -1; 3.80 + } 3.81 + 3.82 + /* resize our window to match the HMD resolution */ 3.83 + win_width = vr_get_opti(VR_OPT_DISPLAY_WIDTH); 3.84 + win_height = vr_get_opti(VR_OPT_DISPLAY_HEIGHT); 3.85 + if(!win_width || !win_height) { 3.86 + SDL_GetWindowSize(win, &win_width, &win_height); 3.87 + } else { 3.88 + SDL_SetWindowSize(win, win_width, win_height); 3.89 + SDL_SetWindowPosition(win, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); 3.90 + } 3.91 + 3.92 + /* and create a single render target texture to encompass both eyes */ 3.93 + fb_width = vr_get_opti(VR_OPT_LEYE_XRES) + vr_get_opti(VR_OPT_REYE_XRES); 3.94 + fb_height = vr_get_opti(VR_OPT_LEYE_YRES); /* assuming both are the same */ 3.95 + if(!fb_width || !fb_height) { 3.96 + fb_width = win_width; 3.97 + fb_height = win_height; 3.98 + } 3.99 + update_rtarg(fb_width, fb_height); 3.100 + 3.101 + /* set our render texture and its active area */ 3.102 + vr_output_texture(fb_tex, 0, (float)(fb_tex_height - fb_height) / (float)fb_tex_height, 3.103 + (float)fb_width / (float)fb_tex_width, 1.0); 3.104 + 3.105 + glEnable(GL_DEPTH_TEST); 3.106 + glEnable(GL_CULL_FACE); 3.107 + glEnable(GL_LIGHTING); 3.108 + glEnable(GL_LIGHT0); 3.109 + glEnable(GL_LIGHT1); 3.110 + glEnable(GL_NORMALIZE); 3.111 + 3.112 + glClearColor(0.5, 0.1, 0.1, 1); 3.113 + 3.114 + chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0); 3.115 + return 0; 3.116 +} 3.117 + 3.118 +void cleanup(void) 3.119 +{ 3.120 + vr_shutdown(); 3.121 + SDL_Quit(); 3.122 +} 3.123 + 3.124 +void toggle_hmd_fullscreen(void) 3.125 +{ 3.126 + static int fullscr, prev_x, prev_y; 3.127 + fullscr = !fullscr; 3.128 + 3.129 + if(fullscr) { 3.130 + /* going fullscreen on the rift. save current window position, and move it 3.131 + * to the rift's part of the desktop before going fullscreen 3.132 + */ 3.133 + SDL_GetWindowPosition(win, &prev_x, &prev_y); 3.134 + SDL_SetWindowPosition(win, vr_get_opti(VR_OPT_WIN_XOFFS), vr_get_opti(VR_OPT_WIN_YOFFS)); 3.135 + SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); 3.136 + } else { 3.137 + /* return to windowed mode and move the window back to its original position */ 3.138 + SDL_SetWindowFullscreen(win, 0); 3.139 + SDL_SetWindowPosition(win, prev_x, prev_y); 3.140 + } 3.141 +} 3.142 + 3.143 +void display(void) 3.144 +{ 3.145 + int i; 3.146 + float proj_mat[16]; 3.147 + float rot_mat[16], view_mat[16]; 3.148 + 3.149 + /* start drawing onto our texture render target */ 3.150 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3.151 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 3.152 + 3.153 + /* for each eye ... */ 3.154 + for(i=0; i<2; i++) { 3.155 + vr_begin(i); 3.156 + 3.157 + /* -- viewport transformation -- 3.158 + * setup the viewport to draw in the left half of the framebuffer when we're 3.159 + * rendering the left eye's view (0, 0, width/2, height), and in the right half 3.160 + * of the framebuffer for the right eye's view (width/2, 0, width/2, height) 3.161 + */ 3.162 + glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height); 3.163 + 3.164 + glMatrixMode(GL_PROJECTION); 3.165 + /* -- projection transformation -- 3.166 + * we'll just have to use the projection matrix supplied by the oculus SDK for this eye 3.167 + * note that libovr matrices are the transpose of what OpenGL expects, so we have to 3.168 + * use glLoadTransposeMatrixf instead of glLoadMatrixf to load it. 3.169 + */ 3.170 + if(vr_proj_matrix(i, 0.5, 500.0, proj_mat)) { 3.171 + glLoadTransposeMatrixf(proj_mat); 3.172 + } else { 3.173 + glLoadIdentity(); 3.174 + gluPerspective(50.0, (float)fb_width / 2.0 / (float)fb_height, 0.5, 500.0); 3.175 + } 3.176 + 3.177 + /* -- view/camera transformation -- 3.178 + * we need to construct a view matrix by combining all the information provided by the oculus 3.179 + * SDK, about the position and orientation of the user's head in the world. 3.180 + */ 3.181 + glMatrixMode(GL_MODELVIEW); 3.182 + vr_view_matrix(i, view_mat); 3.183 + glLoadTransposeMatrixf(view_mat); 3.184 + /* move the camera to the eye level of the user */ 3.185 + glTranslatef(0, -vr_get_optf(VR_OPT_EYE_HEIGHT), 0); 3.186 + 3.187 + /* finally draw the scene for this eye */ 3.188 + draw_scene(); 3.189 + 3.190 + vr_end(); 3.191 + } 3.192 + 3.193 + /* after drawing both eyes into the texture render target, revert to drawing directly to the 3.194 + * display, and we call ovrHmd_EndFrame, to let the Oculus SDK draw both images properly 3.195 + * compensated for lens distortion and chromatic abberation onto the HMD screen. 3.196 + */ 3.197 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 3.198 + glViewport(0, 0, win_width, win_height); 3.199 + 3.200 + vr_swap_buffers(); 3.201 + 3.202 + assert(glGetError() == GL_NO_ERROR); 3.203 +} 3.204 + 3.205 +void draw_scene(void) 3.206 +{ 3.207 + int i; 3.208 + float grey[] = {0.8, 0.8, 0.8, 1}; 3.209 + float col[] = {0, 0, 0, 1}; 3.210 + float lpos[][4] = { 3.211 + {-8, 2, 10, 1}, 3.212 + {0, 15, 0, 1} 3.213 + }; 3.214 + float lcol[][4] = { 3.215 + {0.8, 0.8, 0.8, 1}, 3.216 + {0.4, 0.3, 0.3, 1} 3.217 + }; 3.218 + 3.219 + for(i=0; i<2; i++) { 3.220 + glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]); 3.221 + glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]); 3.222 + } 3.223 + 3.224 + glMatrixMode(GL_MODELVIEW); 3.225 + 3.226 + glPushMatrix(); 3.227 + glTranslatef(0, 10, 0); 3.228 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey); 3.229 + glBindTexture(GL_TEXTURE_2D, chess_tex); 3.230 + glEnable(GL_TEXTURE_2D); 3.231 + draw_box(30, 20, 30, -1.0); 3.232 + glDisable(GL_TEXTURE_2D); 3.233 + glPopMatrix(); 3.234 + 3.235 + for(i=0; i<4; i++) { 3.236 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey); 3.237 + glPushMatrix(); 3.238 + glTranslatef(i & 1 ? 5 : -5, 1, i & 2 ? -5 : 5); 3.239 + draw_box(0.5, 2, 0.5, 1.0); 3.240 + glPopMatrix(); 3.241 + 3.242 + col[0] = i & 1 ? 1.0 : 0.3; 3.243 + col[1] = i == 0 ? 1.0 : 0.3; 3.244 + col[2] = i & 2 ? 1.0 : 0.3; 3.245 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 3.246 + 3.247 + glPushMatrix(); 3.248 + if(i & 1) { 3.249 + glTranslatef(0, 0.25, i & 2 ? 2 : -2); 3.250 + } else { 3.251 + glTranslatef(i & 2 ? 2 : -2, 0.25, 0); 3.252 + } 3.253 + draw_box(0.5, 0.5, 0.5, 1.0); 3.254 + glPopMatrix(); 3.255 + } 3.256 +} 3.257 + 3.258 +void draw_box(float xsz, float ysz, float zsz, float norm_sign) 3.259 +{ 3.260 + glMatrixMode(GL_MODELVIEW); 3.261 + glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5); 3.262 + 3.263 + if(norm_sign < 0.0) { 3.264 + glFrontFace(GL_CW); 3.265 + } 3.266 + 3.267 + glBegin(GL_QUADS); 3.268 + glNormal3f(0, 0, 1 * norm_sign); 3.269 + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); 3.270 + glTexCoord2f(1, 0); glVertex3f(1, -1, 1); 3.271 + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); 3.272 + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 3.273 + glNormal3f(1 * norm_sign, 0, 0); 3.274 + glTexCoord2f(0, 0); glVertex3f(1, -1, 1); 3.275 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 3.276 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 3.277 + glTexCoord2f(0, 1); glVertex3f(1, 1, 1); 3.278 + glNormal3f(0, 0, -1 * norm_sign); 3.279 + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); 3.280 + glTexCoord2f(1, 0); glVertex3f(-1, -1, -1); 3.281 + glTexCoord2f(1, 1); glVertex3f(-1, 1, -1); 3.282 + glTexCoord2f(0, 1); glVertex3f(1, 1, -1); 3.283 + glNormal3f(-1 * norm_sign, 0, 0); 3.284 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 3.285 + glTexCoord2f(1, 0); glVertex3f(-1, -1, 1); 3.286 + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); 3.287 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 3.288 + glEnd(); 3.289 + glBegin(GL_TRIANGLE_FAN); 3.290 + glNormal3f(0, 1 * norm_sign, 0); 3.291 + glTexCoord2f(0.5, 0.5); glVertex3f(0, 1, 0); 3.292 + glTexCoord2f(0, 0); glVertex3f(-1, 1, 1); 3.293 + glTexCoord2f(1, 0); glVertex3f(1, 1, 1); 3.294 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 3.295 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 3.296 + glTexCoord2f(0, 0); glVertex3f(-1, 1, 1); 3.297 + glEnd(); 3.298 + glBegin(GL_TRIANGLE_FAN); 3.299 + glNormal3f(0, -1 * norm_sign, 0); 3.300 + glTexCoord2f(0.5, 0.5); glVertex3f(0, -1, 0); 3.301 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 3.302 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 3.303 + glTexCoord2f(1, 1); glVertex3f(1, -1, 1); 3.304 + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 3.305 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 3.306 + glEnd(); 3.307 + 3.308 + glFrontFace(GL_CCW); 3.309 +} 3.310 + 3.311 +/* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */ 3.312 +void update_rtarg(int width, int height) 3.313 +{ 3.314 + if(!fbo) { 3.315 + /* if fbo does not exist, then nothing does... create every opengl object */ 3.316 + glGenFramebuffers(1, &fbo); 3.317 + glGenTextures(1, &fb_tex); 3.318 + glGenRenderbuffers(1, &fb_depth); 3.319 + 3.320 + glBindTexture(GL_TEXTURE_2D, fb_tex); 3.321 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 3.322 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 3.323 + } 3.324 + 3.325 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 3.326 + 3.327 + /* calculate the next power of two in both dimensions and use that as a texture size */ 3.328 + fb_tex_width = next_pow2(width); 3.329 + fb_tex_height = next_pow2(height); 3.330 + 3.331 + /* create and attach the texture that will be used as a color buffer */ 3.332 + glBindTexture(GL_TEXTURE_2D, fb_tex); 3.333 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0, 3.334 + GL_RGBA, GL_UNSIGNED_BYTE, 0); 3.335 + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0); 3.336 + 3.337 + /* create and attach the renderbuffer that will serve as our z-buffer */ 3.338 + glBindRenderbuffer(GL_RENDERBUFFER, fb_depth); 3.339 + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height); 3.340 + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth); 3.341 + 3.342 + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 3.343 + fprintf(stderr, "incomplete framebuffer!\n"); 3.344 + } 3.345 + 3.346 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 3.347 + printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height); 3.348 +} 3.349 + 3.350 +int handle_event(SDL_Event *ev) 3.351 +{ 3.352 + switch(ev->type) { 3.353 + case SDL_QUIT: 3.354 + return -1; 3.355 + 3.356 + case SDL_KEYDOWN: 3.357 + case SDL_KEYUP: 3.358 + if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) { 3.359 + return -1; 3.360 + } 3.361 + break; 3.362 + 3.363 + default: 3.364 + break; 3.365 + } 3.366 + 3.367 + return 0; 3.368 +} 3.369 + 3.370 +int key_event(int key, int state) 3.371 +{ 3.372 + if(state) { 3.373 + switch(key) { 3.374 + case 27: 3.375 + return -1; 3.376 + 3.377 + case ' ': 3.378 + /* allow the user to recenter by pressing space */ 3.379 + vr_recenter(); 3.380 + break; 3.381 + 3.382 + case 'f': 3.383 + /* press f to move the window to the HMD */ 3.384 + toggle_hmd_fullscreen(); 3.385 + break; 3.386 + 3.387 + default: 3.388 + break; 3.389 + } 3.390 + } 3.391 + return 0; 3.392 +} 3.393 + 3.394 +unsigned int next_pow2(unsigned int x) 3.395 +{ 3.396 + x -= 1; 3.397 + x |= x >> 1; 3.398 + x |= x >> 2; 3.399 + x |= x >> 4; 3.400 + x |= x >> 8; 3.401 + x |= x >> 16; 3.402 + return x + 1; 3.403 +} 3.404 + 3.405 +/* convert a quaternion to a rotation matrix */ 3.406 +void quat_to_matrix(const float *quat, float *mat) 3.407 +{ 3.408 + mat[0] = 1.0 - 2.0 * quat[1] * quat[1] - 2.0 * quat[2] * quat[2]; 3.409 + mat[4] = 2.0 * quat[0] * quat[1] + 2.0 * quat[3] * quat[2]; 3.410 + mat[8] = 2.0 * quat[2] * quat[0] - 2.0 * quat[3] * quat[1]; 3.411 + mat[12] = 0.0f; 3.412 + 3.413 + mat[1] = 2.0 * quat[0] * quat[1] - 2.0 * quat[3] * quat[2]; 3.414 + mat[5] = 1.0 - 2.0 * quat[0]*quat[0] - 2.0 * quat[2]*quat[2]; 3.415 + mat[9] = 2.0 * quat[1] * quat[2] + 2.0 * quat[3] * quat[0]; 3.416 + mat[13] = 0.0f; 3.417 + 3.418 + mat[2] = 2.0 * quat[2] * quat[0] + 2.0 * quat[3] * quat[1]; 3.419 + mat[6] = 2.0 * quat[1] * quat[2] - 2.0 * quat[3] * quat[0]; 3.420 + mat[10] = 1.0 - 2.0 * quat[0]*quat[0] - 2.0 * quat[1]*quat[1]; 3.421 + mat[14] = 0.0f; 3.422 + 3.423 + mat[3] = mat[7] = mat[11] = 0.0f; 3.424 + mat[15] = 1.0f; 3.425 +} 3.426 + 3.427 +/* generate a chessboard texture with tiles colored (r0, g0, b0) and (r1, g1, b1) */ 3.428 +unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1) 3.429 +{ 3.430 + int i, j; 3.431 + unsigned int tex; 3.432 + unsigned char img[8 * 8 * 3]; 3.433 + unsigned char *pix = img; 3.434 + 3.435 + for(i=0; i<8; i++) { 3.436 + for(j=0; j<8; j++) { 3.437 + int black = (i & 1) == (j & 1); 3.438 + pix[0] = (black ? r0 : r1) * 255; 3.439 + pix[1] = (black ? g0 : g1) * 255; 3.440 + pix[2] = (black ? b0 : b1) * 255; 3.441 + pix += 3; 3.442 + } 3.443 + } 3.444 + 3.445 + glGenTextures(1, &tex); 3.446 + glBindTexture(GL_TEXTURE_2D, tex); 3.447 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3.448 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3.449 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, img); 3.450 + 3.451 + return tex; 3.452 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/opengl.c Thu Sep 18 10:56:45 2014 +0300 4.3 @@ -0,0 +1,18 @@ 4.4 +#include "opengl.h" 4.5 + 4.6 +#ifdef __unix__ 4.7 +void vr_gl_swap_buffers(void) 4.8 +{ 4.9 + Display *dpy = glXGetCurrentDisplay(); 4.10 + Drawable win = glXGetCurrentDrawable(); 4.11 + glXSwapBuffers(dpy, win); 4.12 +} 4.13 +#endif 4.14 + 4.15 +#ifdef WIN32 4.16 +void vr_gl_swap_buffers(void) 4.17 +{ 4.18 + HDC dc = wglGetCurrentDC(); 4.19 + SwapBuffers(dc); 4.20 +} 4.21 +#endif
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/opengl.h Thu Sep 18 10:56:45 2014 +0300 5.3 @@ -0,0 +1,21 @@ 5.4 +#ifndef VR_OPENGL_H_ 5.5 +#define VR_OPENGL_H_ 5.6 + 5.7 +#ifdef WIN32 5.8 +#define WIN32_LEAN_AND_MEAN 1 5.9 +#include <windows.h> 5.10 +#endif 5.11 + 5.12 +#ifdef __APPLE__ 5.13 +#include <OpenGL/gl.h> 5.14 +#else 5.15 +#include <GL/gl.h> 5.16 +#endif 5.17 + 5.18 +#ifdef __unix__ 5.19 +#include <GL/glx.h> 5.20 +#endif 5.21 + 5.22 +void vr_gl_swap_buffers(void); 5.23 + 5.24 +#endif /* VR_OPENGL_H_ */
6.1 --- a/src/vr.c Fri Aug 29 07:37:19 2014 +0300 6.2 +++ b/src/vr.c Thu Sep 18 10:56:45 2014 +0300 6.3 @@ -1,11 +1,12 @@ 6.4 #include <stdio.h> 6.5 #include <string.h> 6.6 +#include "opengl.h" 6.7 #include "vr.h" 6.8 #include "vr_impl.h" 6.9 #include "mathutil.h" 6.10 6.11 6.12 -static void swap_buffers(void); 6.13 +static void fallback_present(void); 6.14 6.15 6.16 static struct vr_module *vrm; 6.17 @@ -19,10 +20,24 @@ 6.18 0, 0, 1, 1 6.19 }; 6.20 6.21 +static void *defopt; /* default options db */ 6.22 + 6.23 +static struct { 6.24 + float umin, umax, vmin, vmax; 6.25 + int tex; 6.26 +} rtarg[2]; 6.27 + 6.28 + 6.29 int vr_init(void) 6.30 { 6.31 int i, nmodules; 6.32 6.33 + /* create the default options database */ 6.34 + if(!defopt && (defopt = create_options())) { 6.35 + set_option_float(defopt, VR_OPT_EYE_HEIGHT, 1.675); 6.36 + set_option_float(defopt, VR_OPT_IPD, 0.064); 6.37 + } 6.38 + 6.39 if(vrm) { 6.40 vr_shutdown(); 6.41 } 6.42 @@ -99,6 +114,8 @@ 6.43 { 6.44 if(vrm && vrm->set_option) { 6.45 vrm->set_option(optname, OTYPE_INT, &val); 6.46 + } else { 6.47 + set_option_int(defopt, optname, val); 6.48 } 6.49 } 6.50 6.51 @@ -106,6 +123,8 @@ 6.52 { 6.53 if(vrm && vrm->set_option) { 6.54 vrm->set_option(optname, OTYPE_FLOAT, &val); 6.55 + } else { 6.56 + set_option_float(defopt, optname, val); 6.57 } 6.58 } 6.59 6.60 @@ -113,8 +132,8 @@ 6.61 { 6.62 int res = 0; 6.63 6.64 - if(vrm && vrm->get_option) { 6.65 - vrm->get_option(optname, OTYPE_INT, &res); 6.66 + if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_INT, &res) == -1) { 6.67 + get_option_int(defopt, optname, &res); /* fallback */ 6.68 } 6.69 return res; 6.70 } 6.71 @@ -123,8 +142,8 @@ 6.72 { 6.73 float res = 0.0f; 6.74 6.75 - if(vrm && vrm->get_option) { 6.76 - vrm->get_option(optname, OTYPE_FLOAT, &res); 6.77 + if(!vrm || !vrm->get_option || vrm->get_option(optname, OTYPE_FLOAT, &res) == -1) { 6.78 + get_option_float(defopt, optname, &res); /* fallback */ 6.79 } 6.80 return res; 6.81 } 6.82 @@ -166,6 +185,7 @@ 6.83 have_rot = vr_view_rotation(eye, quat); 6.84 6.85 if(!have_trans && !have_rot) { 6.86 + memcpy(mat, idmat, sizeof idmat); 6.87 return 0; 6.88 } 6.89 6.90 @@ -212,7 +232,8 @@ 6.91 } 6.92 6.93 if(!res) { 6.94 - swap_buffers(); 6.95 + fallback_present(); 6.96 + vr_gl_swap_buffers(); 6.97 } 6.98 return 0; 6.99 } 6.100 @@ -229,6 +250,12 @@ 6.101 { 6.102 if(vrm && vrm->set_eye_texture) { 6.103 vrm->set_eye_texture(eye, tex, umin, vmin, umax, vmax); 6.104 + } else { 6.105 + rtarg[eye].tex = tex; 6.106 + rtarg[eye].umin = umin; 6.107 + rtarg[eye].umax = umax; 6.108 + rtarg[eye].vmin = vmin; 6.109 + rtarg[eye].vmax = vmax; 6.110 } 6.111 } 6.112 6.113 @@ -239,22 +266,48 @@ 6.114 } 6.115 } 6.116 6.117 +static void fallback_present(void) 6.118 +{ 6.119 + int i; 6.120 6.121 -#ifdef __unix__ 6.122 -#include <GL/glx.h> 6.123 + glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT); 6.124 6.125 -static void swap_buffers(void) 6.126 -{ 6.127 - glXSwapBuffers(glXGetCurrentDisplay(), glXGetCurrentDrawable()); 6.128 + glDisable(GL_LIGHTING); 6.129 + glDisable(GL_DEPTH_TEST); 6.130 + glDisable(GL_ALPHA_TEST); 6.131 + glDisable(GL_STENCIL_TEST); 6.132 + glDisable(GL_FOG); 6.133 + 6.134 + glEnable(GL_TEXTURE_2D); 6.135 + 6.136 + glMatrixMode(GL_MODELVIEW); 6.137 + glPushMatrix(); 6.138 + glLoadIdentity(); 6.139 + glMatrixMode(GL_PROJECTION); 6.140 + glPushMatrix(); 6.141 + glLoadIdentity(); 6.142 + 6.143 + for(i=0; i<2; i++) { 6.144 + float x0 = i == 0 ? -1 : 0; 6.145 + float x1 = i == 0 ? 0 : 1; 6.146 + 6.147 + glBindTexture(GL_TEXTURE_2D, rtarg[i].tex); 6.148 + 6.149 + glBegin(GL_QUADS); 6.150 + glTexCoord2f(rtarg[i].umin, rtarg[i].vmin); 6.151 + glVertex2f(x0, -1); 6.152 + glTexCoord2f(rtarg[i].umax, rtarg[i].vmin); 6.153 + glVertex2f(x1, -1); 6.154 + glTexCoord2f(rtarg[i].umax, rtarg[i].vmax); 6.155 + glVertex2f(x1, 1); 6.156 + glTexCoord2f(rtarg[i].umin, rtarg[i].vmax); 6.157 + glVertex2f(x0, 1); 6.158 + glEnd(); 6.159 + } 6.160 + 6.161 + glPopMatrix(); 6.162 + glMatrixMode(GL_MODELVIEW); 6.163 + glPopMatrix(); 6.164 + 6.165 + glPopAttrib(); 6.166 } 6.167 - 6.168 -#endif 6.169 - 6.170 -#ifdef WIN32 6.171 -#include <windows.h> 6.172 - 6.173 -static void swap_buffers(void) 6.174 -{ 6.175 - SwapBuffers(wglGetCurrentDC()); 6.176 -} 6.177 -#endif
7.1 --- a/src/vr_libovr.c Fri Aug 29 07:37:19 2014 +0300 7.2 +++ b/src/vr_libovr.c Thu Sep 18 10:56:45 2014 +0300 7.3 @@ -134,6 +134,7 @@ 7.4 ovrHmd_Destroy(hmd); 7.5 ovr_Shutdown(); 7.6 } 7.7 + destroy_options(optdb); 7.8 } 7.9 7.10 static int set_option(const char *opt, enum opt_type type, void *valp)
8.1 --- a/src/vr_null.c Fri Aug 29 07:37:19 2014 +0300 8.2 +++ b/src/vr_null.c Thu Sep 18 10:56:45 2014 +0300 8.3 @@ -1,76 +1,10 @@ 8.4 -#ifdef WIN32 8.5 -#define WIN32_LEAN_AND_MEAN 8.6 -#include <windows.h> 8.7 -#endif 8.8 -#ifdef __APPLE__ 8.9 -#include <OpenGL/gl.h> 8.10 -#else 8.11 -#include <GL/gl.h> 8.12 -#endif 8.13 #include "vr_impl.h" 8.14 8.15 -static unsigned int eye_tex[2]; 8.16 -static float tex_umin[2], tex_umax[2]; 8.17 -static float tex_vmin[2], tex_vmax[2]; 8.18 - 8.19 static int init(void) 8.20 { 8.21 return 0; 8.22 } 8.23 8.24 -static int present(void) 8.25 -{ 8.26 - int i; 8.27 - 8.28 - glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT); 8.29 - 8.30 - glDisable(GL_LIGHTING); 8.31 - glDisable(GL_DEPTH_TEST); 8.32 - glDisable(GL_FOG); 8.33 - glDisable(GL_CULL_FACE); 8.34 - 8.35 - glEnable(GL_TEXTURE_2D); 8.36 - 8.37 - glMatrixMode(GL_MODELVIEW); 8.38 - glLoadIdentity(); 8.39 - glMatrixMode(GL_PROJECTION); 8.40 - glLoadIdentity(); 8.41 - 8.42 - for(i=0; i<2; i++) { 8.43 - float x0 = i == 0 ? -1 : 0; 8.44 - float x1 = i == 0 ? 0 : 1; 8.45 - 8.46 - glBindTexture(GL_TEXTURE_2D, eye_tex[i]); 8.47 - 8.48 - glBegin(GL_QUADS); 8.49 - glTexCoord2f(tex_umin[i], tex_vmin[i]); 8.50 - glVertex2f(x0, -1); 8.51 - glTexCoord2f(tex_umax[i], tex_vmin[i]); 8.52 - glVertex2f(x1, -1); 8.53 - glTexCoord2f(tex_umax[i], tex_vmax[i]); 8.54 - glVertex2f(x1, 1); 8.55 - glTexCoord2f(tex_umin[i], tex_vmax[i]); 8.56 - glVertex2f(x0, 1); 8.57 - glEnd(); 8.58 - } 8.59 - 8.60 - glPopMatrix(); 8.61 - glMatrixMode(GL_MODELVIEW); 8.62 - glPopMatrix(); 8.63 - 8.64 - glPopAttrib(); 8.65 - return 0; 8.66 -} 8.67 - 8.68 -static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax) 8.69 -{ 8.70 - eye_tex[eye] = tex; 8.71 - tex_umin[eye] = umin; 8.72 - tex_umax[eye] = umax; 8.73 - tex_vmin[eye] = vmin; 8.74 - tex_vmax[eye] = vmax; 8.75 -} 8.76 - 8.77 struct vr_module *vr_module_null(void) 8.78 { 8.79 static struct vr_module m; 8.80 @@ -78,8 +12,6 @@ 8.81 if(!m.init) { 8.82 m.name = "null"; 8.83 m.init = init; 8.84 - m.set_eye_texture = set_eye_texture; 8.85 - m.present = present; 8.86 } 8.87 return &m; 8.88 }