oculus2

view src/main.c @ 3:096b18432ba7

something is fucked
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 26 Aug 2014 18:37:24 +0300
parents 0984fa94b490
children d64830551c32
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <SDL2/SDL.h>
5 #include <GL/glew.h>
7 #ifdef WIN32
8 #define OVR_OS_WIN32
9 #endif
10 #ifdef __APPLE__
11 #define OVR_OS_MAC
12 #endif
14 #include <OVR_CAPI.h>
15 #include <OVR_CAPI_GL.h>
17 int init(void);
18 void cleanup(void);
19 void display(void);
20 void draw_scene(void);
21 void draw_box(float xsz, float ysz, float zsz, float norm_sign);
22 void update_rtarg(int width, int height);
23 int handle_event(SDL_Event *ev);
24 int key_event(int key, int state);
25 void reshape(int x, int y);
26 unsigned int next_pow2(unsigned int x);
28 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enable);
30 static SDL_Window *win;
31 static SDL_GLContext ctx;
32 static int win_width, win_height;
34 static unsigned int fbo, fb_tex, fb_depth;
35 static int fb_width, fb_height;
36 static int fb_tex_width, fb_tex_height;
38 static ovrHmd hmd;
39 static ovrSizei eyeres[2];
40 static ovrEyeRenderDesc eye_rdesc[2];
41 static ovrGLTexture fb_ovr_tex[2];
44 int main(void)
45 {
46 if(init() == -1) {
47 return 1;
48 }
50 for(;;) {
51 SDL_Event ev;
53 while(SDL_PollEvent(&ev)) {
54 if(handle_event(&ev) == -1) {
55 goto done;
56 }
57 }
59 display();
60 }
62 done:
63 cleanup();
64 return 0;
65 }
68 int init(void)
69 {
70 int i, x, y;
71 unsigned int flags, dcaps;
72 union ovrGLConfig glcfg;
74 // this must be called before any OpenGL init according to the docs
75 ovr_Initialize();
77 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
79 x = y = SDL_WINDOWPOS_UNDEFINED;
80 flags = SDL_WINDOW_OPENGL;
81 if(!(win = SDL_CreateWindow("simple oculus example", x, y, 1280, 800, flags))) {
82 fprintf(stderr, "failed to create window\n");
83 return -1;
84 }
85 if(!(ctx = SDL_GL_CreateContext(win))) {
86 fprintf(stderr, "failed to create OpenGL context\n");
87 return -1;
88 }
90 glewInit();
92 if(!(hmd = ovrHmd_Create(0))) {
93 fprintf(stderr, "failed to open Oculus HMD, falling back to virtual debug HMD\n");
94 if(!(hmd = ovrHmd_CreateDebug(ovrHmd_DK2))) {
95 fprintf(stderr, "failed to create virtual debug HMD\n");
96 return -1;
97 }
98 }
99 printf("initialized HMD: %s - %s\n", hmd->Manufacturer, hmd->ProductName);
101 SDL_SetWindowSize(win, hmd->Resolution.w, hmd->Resolution.h);
103 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0);
104 eyeres[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0);
105 eyeres[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0);
107 SDL_GetWindowSize(win, &win_width, &win_height);
109 fb_width = eyeres[0].w + eyeres[1].w;
110 fb_height = eyeres[0].h > eyeres[1].h ? eyeres[0].h : eyeres[1].h;
111 update_rtarg(fb_width, fb_height);
113 for(i=0; i<2; i++) {
114 fb_ovr_tex[i].OGL.Header.API = ovrRenderAPI_OpenGL;
115 fb_ovr_tex[i].OGL.Header.TextureSize.w = fb_tex_width;
116 fb_ovr_tex[i].OGL.Header.TextureSize.h = fb_tex_height;
117 fb_ovr_tex[i].OGL.Header.RenderViewport.Pos.x = i == 0 ? 0 : fb_width / 2.0;
118 fb_ovr_tex[i].OGL.Header.RenderViewport.Pos.y = fb_tex_height - fb_height;
119 fb_ovr_tex[i].OGL.Header.RenderViewport.Size.w = fb_width / 2.0;
120 fb_ovr_tex[i].OGL.Header.RenderViewport.Size.h = fb_height;
121 fb_ovr_tex[i].OGL.TexId = fb_tex;
122 }
124 memset(&glcfg, 0, sizeof glcfg);
125 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
126 glcfg.OGL.Header.RTSize = hmd->Resolution;
127 glcfg.OGL.Header.Multisample = 1;
129 if(hmd->HmdCaps & ovrHmdCap_ExtendDesktop) {
130 printf("running in \"extended desktop\" mode\n");
131 } else {
132 #ifdef WIN32
133 void *sys_win = GetActiveWindow();
134 glcfg.OGL.Window = sys_win;
135 glcfg.OGL.DC = wglGetCurrentDC();
136 ovrHmd_AttachToWindow(hmd, sys_win, 0, 0);
137 #endif
138 printf("running in \"direct-hmd\" mode\n");
139 }
140 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
142 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette;// | ovrDistortionCap_TimeWarp;
143 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, hmd->DefaultEyeFov, eye_rdesc)) {
144 fprintf(stderr, "failed to configure distortion renderer\n");
145 }
147 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
149 glEnable(GL_DEPTH_TEST);
150 glEnable(GL_CULL_FACE);
151 glEnable(GL_LIGHTING);
152 glEnable(GL_LIGHT0);
154 glClearColor(0.05, 0.05, 0.05, 1);
156 return 0;
157 }
159 void cleanup(void)
160 {
161 if(hmd) {
162 ovrHmd_Destroy(hmd);
163 }
164 ovr_Shutdown();
166 SDL_Quit();
167 }
169 void display(void)
170 {
171 int i;
172 ovrMatrix4f proj;
173 ovrPosef pose[2];
175 ovrHmd_BeginFrame(hmd, 0);
177 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
178 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
180 glViewport(0, 0, fb_width, fb_height);
182 /*glMatrixMode(GL_PROJECTION);
183 glLoadIdentity();
184 glMatrixMode(GL_MODELVIEW);
185 glLoadIdentity();
187 glPushAttrib(GL_ENABLE_BIT);
188 glDisable(GL_LIGHTING);
189 glDisable(GL_DEPTH_TEST);
191 glBegin(GL_QUADS);
192 glColor3f(1, 0, 0);
193 glVertex2f(-1, -1);
194 glVertex2f(0, -1);
195 glVertex2f(0, 1);
196 glVertex2f(-1, 1);
198 glColor3f(1, 0, 1);
199 glVertex2f(-0.6, -0.1);
200 glVertex2f(-0.4, -0.1);
201 glVertex2f(-0.4, 0.1);
202 glVertex2f(-0.6, 0.1);
204 glColor3f(0, 1, 0);
205 glVertex2f(0, -1);
206 glVertex2f(1, -1);
207 glVertex2f(1, 1);
208 glVertex2f(0, 1);
210 glColor3f(0, 1, 1);
211 glVertex2f(0.4, -0.1);
212 glVertex2f(0.6, -0.1);
213 glVertex2f(0.6, 0.1);
214 glVertex2f(0.4, 0.1);
215 glEnd();
217 glPopAttrib();*/
219 /* for each eye ... */
220 for(i=0; i<2; i++) {
221 int eye = hmd->EyeRenderOrder[i];
223 /* vport0(0, 0, width/2, height), vport1(width/2, 0, width/2, height) */
224 glViewport(eye == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
226 proj = ovrMatrix4f_Projection(hmd->DefaultEyeFov[eye], 0.5, 500.0, 1);
227 glMatrixMode(GL_PROJECTION);
228 //glLoadMatrixf(proj.M[0]);
229 glLoadIdentity();
230 gluPerspective(50.0, (float)fb_width / 2.0 / (float)fb_height, 0.5, 500.0);
232 pose[eye] = ovrHmd_GetEyePose(hmd, eye);
233 glMatrixMode(GL_MODELVIEW);
234 /* TODO: get HMD orientation data and use it */
235 //glTranslatef(0, -ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, 1.65), 0);
237 draw_scene();
238 }
240 glBindFramebuffer(GL_FRAMEBUFFER, 0);
241 glViewport(0, 0, win_width, win_height);
243 ovrHmd_EndFrame(hmd, pose, &fb_ovr_tex[0].Texture);
245 assert(glGetError() == GL_NO_ERROR);
246 }
248 void draw_scene(void)
249 {
250 int i;
251 float lpos[] = {0, 5, 0, 1};
252 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
254 glPushMatrix();
255 glTranslatef(0, 0, -8);
256 draw_box(2, 2, 2, 1.0);
257 glPopMatrix();
259 glTranslatef(0, 5, 0);
260 draw_box(20, 10, 20, -1.0);
262 for(i=0; i<4; i++) {
263 glPushMatrix();
264 if(i & 1) {
265 glTranslatef(0, 0, i & 2 ? 7.5 : -7.5);
266 } else {
267 glTranslatef(i & 2 ? 7.5 : -7.5, 0, 0);
268 }
269 draw_box(3, 0, 3, 1.0);
270 glPopMatrix();
271 }
272 }
274 void draw_box(float xsz, float ysz, float zsz, float norm_sign)
275 {
276 glMatrixMode(GL_MODELVIEW);
277 glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5);
279 if(norm_sign < 0.0) {
280 glFrontFace(GL_CW);
281 }
283 glBegin(GL_QUADS);
284 glNormal3f(0, 0, 1 * norm_sign);
285 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
286 glTexCoord2f(1, 0); glVertex3f(1, -1, 1);
287 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
288 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
289 glNormal3f(1 * norm_sign, 0, 0);
290 glTexCoord2f(0, 0); glVertex3f(1, -1, 1);
291 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
292 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
293 glTexCoord2f(0, 1); glVertex3f(1, 1, 1);
294 glNormal3f(0, 0, -1 * norm_sign);
295 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
296 glTexCoord2f(1, 0); glVertex3f(-1, -1, -1);
297 glTexCoord2f(1, 1); glVertex3f(-1, 1, -1);
298 glTexCoord2f(0, 1); glVertex3f(1, 1, -1);
299 glNormal3f(-1 * norm_sign, 0, 0);
300 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
301 glTexCoord2f(1, 0); glVertex3f(-1, -1, 1);
302 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
303 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
304 glNormal3f(0, 1 * norm_sign, 0);
305 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
306 glTexCoord2f(1, 0); glVertex3f(1, 1, 1);
307 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
308 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
309 glNormal3f(0, -1 * norm_sign, 0);
310 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
311 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
312 glTexCoord2f(1, 1); glVertex3f(1, -1, 1);
313 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
314 glEnd();
316 glFrontFace(GL_CCW);
317 }
319 void update_rtarg(int width, int height)
320 {
321 if(!fbo) {
322 glGenFramebuffers(1, &fbo);
323 glGenTextures(1, &fb_tex);
324 glGenRenderbuffers(1, &fb_depth);
326 glBindTexture(GL_TEXTURE_2D, fb_tex);
327 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
329 }
331 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
333 fb_tex_width = next_pow2(width);
334 fb_tex_height = next_pow2(height);
336 glBindTexture(GL_TEXTURE_2D, fb_tex);
337 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0,
338 GL_RGBA, GL_UNSIGNED_BYTE, 0);
339 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
341 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
342 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height);
343 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
345 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
346 fprintf(stderr, "incomplete framebuffer!\n");
347 }
349 glBindFramebuffer(GL_FRAMEBUFFER, 0);
350 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height);
351 }
353 int handle_event(SDL_Event *ev)
354 {
355 switch(ev->type) {
356 case SDL_KEYDOWN:
357 case SDL_KEYUP:
358 if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) {
359 return -1;
360 }
361 break;
363 default:
364 break;
365 }
367 return 0;
368 }
370 int key_event(int key, int state)
371 {
372 if(state) {
373 switch(key) {
374 case 27:
375 return -1;
377 default:
378 break;
379 }
380 }
381 return 0;
382 }
384 unsigned int next_pow2(unsigned int x)
385 {
386 x -= 1;
387 x |= x >> 1;
388 x |= x >> 2;
389 x |= x >> 4;
390 x |= x >> 8;
391 x |= x >> 16;
392 return x + 1;