oculus2

view src/main.c @ 2:0984fa94b490

rendering almost works
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 26 Aug 2014 08:14:09 +0300
parents 0a4d62469381
children 096b18432ba7
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.y = 0;
118 fb_ovr_tex[i].OGL.Header.RenderViewport.Size.w = fb_width / 2.0;
119 fb_ovr_tex[i].OGL.Header.RenderViewport.Size.h = fb_height;
120 fb_ovr_tex[i].OGL.TexId = fb_tex;
121 }
122 fb_ovr_tex[0].OGL.Header.RenderViewport.Pos.x = 0;
123 fb_ovr_tex[1].OGL.Header.RenderViewport.Pos.x = fb_width / 2.0;
125 memset(&glcfg, 0, sizeof glcfg);
126 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
127 glcfg.OGL.Header.RTSize = hmd->Resolution;
128 glcfg.OGL.Header.Multisample = 1;
130 if(hmd->HmdCaps & ovrHmdCap_ExtendDesktop) {
131 printf("running in \"extended desktop\" mode\n");
132 } else {
133 #ifdef WIN32
134 void *sys_win = GetActiveWindow();
135 glcfg.OGL.Window = sys_win;
136 glcfg.OGL.DC = wglGetCurrentDC();
137 ovrHmd_AttachToWindow(hmd, sys_win, 0, 0);
138 #endif
139 printf("running in \"direct-hmd\" mode\n");
140 }
141 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
143 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp;
144 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, hmd->DefaultEyeFov, eye_rdesc)) {
145 fprintf(stderr, "failed to configure distortion renderer\n");
146 }
148 /* ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); */
151 glEnable(GL_DEPTH_TEST);
152 glEnable(GL_CULL_FACE);
153 glEnable(GL_LIGHTING);
154 glEnable(GL_LIGHT0);
156 glClearColor(0.5, 0.05, 0.05, 1);
158 return 0;
159 }
161 void cleanup(void)
162 {
163 if(hmd) {
164 ovrHmd_Destroy(hmd);
165 }
166 ovr_Shutdown();
168 SDL_Quit();
169 }
171 void display(void)
172 {
173 int i;
174 ovrMatrix4f proj;
175 ovrPosef pose[2];
177 ovrHmd_BeginFrame(hmd, 0);
179 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
180 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
182 /* for each eye ... */
183 for(i=0; i<2; i++) {
184 int eye = hmd->EyeRenderOrder[i];
186 /* vport0(0, 0, width/2, height), vport1(width/2, 0, width/2, height) */
187 glViewport(eye == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
189 proj = ovrMatrix4f_Projection(hmd->DefaultEyeFov[eye], 0.5, 500.0, 1);
190 glMatrixMode(GL_PROJECTION);
191 glLoadMatrixf(proj.M[0]);
193 pose[eye] = ovrHmd_GetEyePose(hmd, eye);
194 glMatrixMode(GL_MODELVIEW);
195 /* TODO: get HMD orientation data and use them */
196 glTranslatef(0, -ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, 1.65), 0);
198 draw_scene();
199 }
201 glBindFramebuffer(GL_FRAMEBUFFER, 0);
202 glViewport(0, 0, win_width, win_height);
204 ovrHmd_EndFrame(hmd, pose, &fb_ovr_tex[0].Texture);
206 assert(glGetError() == GL_NO_ERROR);
207 }
209 void draw_scene(void)
210 {
211 int i;
212 float lpos[] = {0, 5, 0, 1};
213 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
215 glTranslatef(0, 5, 0);
216 draw_box(20, 10, 20, -1.0);
218 for(i=0; i<4; i++) {
219 glPushMatrix();
220 if(i & 1) {
221 glTranslatef(0, 0, i & 2 ? 7.5 : -7.5);
222 } else {
223 glTranslatef(i & 2 ? 7.5 : -7.5, 0, 0);
224 }
225 draw_box(3, 0, 3, 1.0);
226 glPopMatrix();
227 }
228 }
230 void draw_box(float xsz, float ysz, float zsz, float norm_sign)
231 {
232 glMatrixMode(GL_MODELVIEW);
233 glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5);
235 if(norm_sign < 0.0) {
236 glFrontFace(GL_CW);
237 }
239 glBegin(GL_QUADS);
240 glNormal3f(0, 0, 1 * norm_sign);
241 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
242 glTexCoord2f(1, 0); glVertex3f(1, -1, 1);
243 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
244 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
245 glNormal3f(1 * norm_sign, 0, 0);
246 glTexCoord2f(0, 0); glVertex3f(1, -1, 1);
247 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
248 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
249 glTexCoord2f(0, 1); glVertex3f(1, 1, 1);
250 glNormal3f(0, 0, -1 * norm_sign);
251 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
252 glTexCoord2f(1, 0); glVertex3f(-1, -1, -1);
253 glTexCoord2f(1, 1); glVertex3f(-1, 1, -1);
254 glTexCoord2f(0, 1); glVertex3f(1, 1, -1);
255 glNormal3f(-1 * norm_sign, 0, 0);
256 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
257 glTexCoord2f(1, 0); glVertex3f(-1, -1, 1);
258 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
259 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
260 glNormal3f(0, 1 * norm_sign, 0);
261 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
262 glTexCoord2f(1, 0); glVertex3f(1, 1, 1);
263 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
264 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
265 glNormal3f(0, -1 * norm_sign, 0);
266 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
267 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
268 glTexCoord2f(1, 1); glVertex3f(1, -1, 1);
269 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
270 glEnd();
272 glFrontFace(GL_CCW);
273 }
275 void update_rtarg(int width, int height)
276 {
277 if(!fbo) {
278 glGenFramebuffers(1, &fbo);
279 glGenTextures(1, &fb_tex);
280 glGenRenderbuffers(1, &fb_depth);
282 glBindTexture(GL_TEXTURE_2D, fb_tex);
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
285 }
287 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
289 fb_tex_width = next_pow2(width);
290 fb_tex_height = next_pow2(height);
292 glBindTexture(GL_TEXTURE_2D, fb_tex);
293 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0,
294 GL_RGBA, GL_UNSIGNED_BYTE, 0);
295 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
297 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
298 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height);
299 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
301 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
302 fprintf(stderr, "incomplete framebuffer!\n");
303 }
305 glBindFramebuffer(GL_FRAMEBUFFER, 0);
306 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height);
307 }
309 int handle_event(SDL_Event *ev)
310 {
311 switch(ev->type) {
312 case SDL_KEYDOWN:
313 case SDL_KEYUP:
314 if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) {
315 return -1;
316 }
317 break;
319 default:
320 break;
321 }
323 return 0;
324 }
326 int key_event(int key, int state)
327 {
328 if(state) {
329 switch(key) {
330 case 27:
331 return -1;
333 default:
334 break;
335 }
336 }
337 return 0;
338 }
340 unsigned int next_pow2(unsigned int x)
341 {
342 x -= 1;
343 x |= x >> 1;
344 x |= x >> 2;
345 x |= x >> 4;
346 x |= x >> 8;
347 x |= x >> 16;
348 return x + 1;