# HG changeset patch # User John Tsiombikas # Date 1409010917 -10800 # Node ID 0a4d6246938120bb4abd804b5153f8d0907c28b0 initial commit diff -r 000000000000 -r 0a4d62469381 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Tue Aug 26 02:55:17 2014 +0300 @@ -0,0 +1,19 @@ +src = $(wildcard src/*.c) +obj = $(src:.c=.o) +bin = oculus2 + +CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl2` +LDFLAGS = $(libgl) `pkg-config --libs sdl2` + +ifeq ($(shell uname -s), Darwin) + libgl = -framework OpenGL -lGLEW +else + libgl = -lGL -lGLU -lGLEW +endif + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONY: clean +clean: + rm -f $(obj) $(bin) diff -r 000000000000 -r 0a4d62469381 src/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Tue Aug 26 02:55:17 2014 +0300 @@ -0,0 +1,212 @@ +#include +#include +#include +#include + +#include +#include + +int init(); +void cleanup(); +void display(); +void update_rtarg(int width, int height); +int handle_event(SDL_Event *ev); +int key_event(int key, int state); +void reshape(int x, int y); +unsigned int next_pow2(unsigned int x); + +OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enable); + +static SDL_Window *win; +static SDL_GLContext ctx; + +static unsigned int fbo, fb_tex, fb_depth; +static int fb_width, fb_height; +static int fb_tex_width, fb_tex_height; + +static ovrHmd hmd; +static ovrSizei eyeres[2]; + + +int main(void) +{ + if(init() == -1) { + return 1; + } + + for(;;) { + SDL_Event ev; + + while(SDL_PollEvent(&ev)) { + if(handle_event(&ev) == -1) { + goto done; + } + } + + display(); + } + +done: + cleanup(); + return 0; +} + + +int init() +{ + int x, y; + unsigned int flags, dcaps; + union ovrGLConfig glcfg; + ovrEyeRenderDesc eye_rdesc[2]; + + // this must be called before any OpenGL init according to the docs + ovr_Initialize(); + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); + + x = y = SDL_WINDOWPOS_UNDEFINED; + flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + if(!(win = SDL_CreateWindow("simple oculus example", x, y, 1280, 800, flags))) { + fprintf(stderr, "failed to create window\n"); + return -1; + } + if(!(ctx = SDL_GL_CreateContext(win))) { + fprintf(stderr, "failed to create OpenGL context\n"); + return -1; + } + + glewInit(); + + if(!(hmd = ovrHmd_Create(0))) { + fprintf(stderr, "failed to open Oculus HMD, falling back to virtual debug HMD\n"); + if(!(hmd = ovrHmd_CreateDebug())) { + fprintf(stderr, "failed to create virtual debug HMD\n"); + return -1; + } + } + printf("initialized HMD: %s - %s\n", hmd->Manufacturer, hmd->ProductName); + + SDL_SetWindowSize(hmd->Resolution.w, hmd->Resolution.h); + + ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0); + eyeres[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0); + eyeres[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0); + + fb_width = eyeres[0].w + eyres[1].w; + fb_height = eyeres[0].h > eyeres[1].h ? eyeres[0].h : eyeres[1].h; + update_rtarg(fb_width, fb_height); + + memset(&glcfg, 0, sizeof glcfg); + glcfg.OGL.Header.API = ovrRenderAPI_OpenGL; + glcfg.OGL.Header.RTSize = hmd->Resolution; + glcfg.OGL.Header.Multisample = 1; + + if(hmd->HmdCaps & ovrHmdCap_ExtendDesktop) { + printf("running in \"extended desktop\" mode\n"); + } else { + printf("running in \"direct-hmd\" mode\n"); +#ifdef WIN32 + ovrHmd_AttachToWindow(hmd, GetActiveWindow(), 0, 0); +#endif + } + ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCaps_DynamicPrediction); + + dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWrap; + if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, hmd->DefaultEyeFov, eye_rdesc)) { + fprintf(stderr, "failed to configure distortion renderer\n"); + } + + ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); + + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + + glClearColor(0.05, 0.05, 0.05, 1); + + return 0; +} + +void cleanup() +{ + if(hmd) { + ovrHmd_Destroy(hmd); + } + ovr_Shutdown(); + + SDL_Quit(); +} + +void display() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SDL_GL_SwapWindow(win); +} + +void update_rtarg(int width, int height) +{ + if(!fbo) { + glGenFramebuffers(1, &fbo); + glGenTextures(1, &fb_tex); + glGenRenderbuffers(1, &fb_depth); + + glBindTexture(GL_TEXTURE_2D, fb_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + fb_tex_width = next_pow2(width); + fb_tex_height = next_pow2(height); + + glBindTexture(GL_TEXTURE_2D, fb_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, fb_depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth); + + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "incomplete framebuffer!\n"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height); +} + +int handle_event(SDL_Event *ev) +{ + switch(ev->type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) { + return -1; + } + break; + + default: + break; + } + + return 0; +} + +int key_event(int key, int state) +{ + if(state) { + switch(key) { + case 27: + return -1; + + default: + break; + } + } + return 0; +}