rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <stdlib.h>
|
nuclear@0
|
3 #include <SDL2/SDL.h>
|
nuclear@0
|
4 #include <GL/glew.h>
|
nuclear@0
|
5
|
nuclear@0
|
6 #include <OVR_CAPI.h>
|
nuclear@0
|
7 #include <OVR_CAPI_GL.h>
|
nuclear@0
|
8
|
nuclear@0
|
9 int init();
|
nuclear@0
|
10 void cleanup();
|
nuclear@0
|
11 void display();
|
nuclear@0
|
12 void update_rtarg(int width, int height);
|
nuclear@0
|
13 int handle_event(SDL_Event *ev);
|
nuclear@0
|
14 int key_event(int key, int state);
|
nuclear@0
|
15 void reshape(int x, int y);
|
nuclear@0
|
16 unsigned int next_pow2(unsigned int x);
|
nuclear@0
|
17
|
nuclear@0
|
18 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enable);
|
nuclear@0
|
19
|
nuclear@0
|
20 static SDL_Window *win;
|
nuclear@0
|
21 static SDL_GLContext ctx;
|
nuclear@0
|
22
|
nuclear@0
|
23 static unsigned int fbo, fb_tex, fb_depth;
|
nuclear@0
|
24 static int fb_width, fb_height;
|
nuclear@0
|
25 static int fb_tex_width, fb_tex_height;
|
nuclear@0
|
26
|
nuclear@0
|
27 static ovrHmd hmd;
|
nuclear@0
|
28 static ovrSizei eyeres[2];
|
nuclear@0
|
29
|
nuclear@0
|
30
|
nuclear@0
|
31 int main(void)
|
nuclear@0
|
32 {
|
nuclear@0
|
33 if(init() == -1) {
|
nuclear@0
|
34 return 1;
|
nuclear@0
|
35 }
|
nuclear@0
|
36
|
nuclear@0
|
37 for(;;) {
|
nuclear@0
|
38 SDL_Event ev;
|
nuclear@0
|
39
|
nuclear@0
|
40 while(SDL_PollEvent(&ev)) {
|
nuclear@0
|
41 if(handle_event(&ev) == -1) {
|
nuclear@0
|
42 goto done;
|
nuclear@0
|
43 }
|
nuclear@0
|
44 }
|
nuclear@0
|
45
|
nuclear@0
|
46 display();
|
nuclear@0
|
47 }
|
nuclear@0
|
48
|
nuclear@0
|
49 done:
|
nuclear@0
|
50 cleanup();
|
nuclear@0
|
51 return 0;
|
nuclear@0
|
52 }
|
nuclear@0
|
53
|
nuclear@0
|
54
|
nuclear@0
|
55 int init()
|
nuclear@0
|
56 {
|
nuclear@0
|
57 int x, y;
|
nuclear@0
|
58 unsigned int flags, dcaps;
|
nuclear@0
|
59 union ovrGLConfig glcfg;
|
nuclear@0
|
60 ovrEyeRenderDesc eye_rdesc[2];
|
nuclear@0
|
61
|
nuclear@0
|
62 // this must be called before any OpenGL init according to the docs
|
nuclear@0
|
63 ovr_Initialize();
|
nuclear@0
|
64
|
nuclear@0
|
65 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
nuclear@0
|
66
|
nuclear@0
|
67 x = y = SDL_WINDOWPOS_UNDEFINED;
|
nuclear@0
|
68 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
nuclear@0
|
69 if(!(win = SDL_CreateWindow("simple oculus example", x, y, 1280, 800, flags))) {
|
nuclear@0
|
70 fprintf(stderr, "failed to create window\n");
|
nuclear@0
|
71 return -1;
|
nuclear@0
|
72 }
|
nuclear@0
|
73 if(!(ctx = SDL_GL_CreateContext(win))) {
|
nuclear@0
|
74 fprintf(stderr, "failed to create OpenGL context\n");
|
nuclear@0
|
75 return -1;
|
nuclear@0
|
76 }
|
nuclear@0
|
77
|
nuclear@0
|
78 glewInit();
|
nuclear@0
|
79
|
nuclear@0
|
80 if(!(hmd = ovrHmd_Create(0))) {
|
nuclear@0
|
81 fprintf(stderr, "failed to open Oculus HMD, falling back to virtual debug HMD\n");
|
nuclear@0
|
82 if(!(hmd = ovrHmd_CreateDebug())) {
|
nuclear@0
|
83 fprintf(stderr, "failed to create virtual debug HMD\n");
|
nuclear@0
|
84 return -1;
|
nuclear@0
|
85 }
|
nuclear@0
|
86 }
|
nuclear@0
|
87 printf("initialized HMD: %s - %s\n", hmd->Manufacturer, hmd->ProductName);
|
nuclear@0
|
88
|
nuclear@0
|
89 SDL_SetWindowSize(hmd->Resolution.w, hmd->Resolution.h);
|
nuclear@0
|
90
|
nuclear@0
|
91 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0);
|
nuclear@0
|
92 eyeres[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0);
|
nuclear@0
|
93 eyeres[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0);
|
nuclear@0
|
94
|
nuclear@0
|
95 fb_width = eyeres[0].w + eyres[1].w;
|
nuclear@0
|
96 fb_height = eyeres[0].h > eyeres[1].h ? eyeres[0].h : eyeres[1].h;
|
nuclear@0
|
97 update_rtarg(fb_width, fb_height);
|
nuclear@0
|
98
|
nuclear@0
|
99 memset(&glcfg, 0, sizeof glcfg);
|
nuclear@0
|
100 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
|
nuclear@0
|
101 glcfg.OGL.Header.RTSize = hmd->Resolution;
|
nuclear@0
|
102 glcfg.OGL.Header.Multisample = 1;
|
nuclear@0
|
103
|
nuclear@0
|
104 if(hmd->HmdCaps & ovrHmdCap_ExtendDesktop) {
|
nuclear@0
|
105 printf("running in \"extended desktop\" mode\n");
|
nuclear@0
|
106 } else {
|
nuclear@0
|
107 printf("running in \"direct-hmd\" mode\n");
|
nuclear@0
|
108 #ifdef WIN32
|
nuclear@0
|
109 ovrHmd_AttachToWindow(hmd, GetActiveWindow(), 0, 0);
|
nuclear@0
|
110 #endif
|
nuclear@0
|
111 }
|
nuclear@0
|
112 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCaps_DynamicPrediction);
|
nuclear@0
|
113
|
nuclear@0
|
114 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWrap;
|
nuclear@0
|
115 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, hmd->DefaultEyeFov, eye_rdesc)) {
|
nuclear@0
|
116 fprintf(stderr, "failed to configure distortion renderer\n");
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
|
nuclear@0
|
120
|
nuclear@0
|
121
|
nuclear@0
|
122 glEnable(GL_DEPTH_TEST);
|
nuclear@0
|
123 glEnable(GL_CULL_FACE);
|
nuclear@0
|
124 glEnable(GL_LIGHTING);
|
nuclear@0
|
125 glEnable(GL_LIGHT0);
|
nuclear@0
|
126
|
nuclear@0
|
127 glClearColor(0.05, 0.05, 0.05, 1);
|
nuclear@0
|
128
|
nuclear@0
|
129 return 0;
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@0
|
132 void cleanup()
|
nuclear@0
|
133 {
|
nuclear@0
|
134 if(hmd) {
|
nuclear@0
|
135 ovrHmd_Destroy(hmd);
|
nuclear@0
|
136 }
|
nuclear@0
|
137 ovr_Shutdown();
|
nuclear@0
|
138
|
nuclear@0
|
139 SDL_Quit();
|
nuclear@0
|
140 }
|
nuclear@0
|
141
|
nuclear@0
|
142 void display()
|
nuclear@0
|
143 {
|
nuclear@0
|
144 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@0
|
145
|
nuclear@0
|
146 SDL_GL_SwapWindow(win);
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 void update_rtarg(int width, int height)
|
nuclear@0
|
150 {
|
nuclear@0
|
151 if(!fbo) {
|
nuclear@0
|
152 glGenFramebuffers(1, &fbo);
|
nuclear@0
|
153 glGenTextures(1, &fb_tex);
|
nuclear@0
|
154 glGenRenderbuffers(1, &fb_depth);
|
nuclear@0
|
155
|
nuclear@0
|
156 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@0
|
157 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@0
|
158 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@0
|
159 }
|
nuclear@0
|
160
|
nuclear@0
|
161 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
nuclear@0
|
162
|
nuclear@0
|
163 fb_tex_width = next_pow2(width);
|
nuclear@0
|
164 fb_tex_height = next_pow2(height);
|
nuclear@0
|
165
|
nuclear@0
|
166 glBindTexture(GL_TEXTURE_2D, fb_tex);
|
nuclear@0
|
167 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0,
|
nuclear@0
|
168 GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
nuclear@0
|
169 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
|
nuclear@0
|
170
|
nuclear@0
|
171 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
|
nuclear@0
|
172 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height);
|
nuclear@0
|
173 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
|
nuclear@0
|
174
|
nuclear@0
|
175 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
nuclear@0
|
176 fprintf(stderr, "incomplete framebuffer!\n");
|
nuclear@0
|
177 }
|
nuclear@0
|
178
|
nuclear@0
|
179 glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
nuclear@0
|
180 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height);
|
nuclear@0
|
181 }
|
nuclear@0
|
182
|
nuclear@0
|
183 int handle_event(SDL_Event *ev)
|
nuclear@0
|
184 {
|
nuclear@0
|
185 switch(ev->type) {
|
nuclear@0
|
186 case SDL_KEYDOWN:
|
nuclear@0
|
187 case SDL_KEYUP:
|
nuclear@0
|
188 if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) {
|
nuclear@0
|
189 return -1;
|
nuclear@0
|
190 }
|
nuclear@0
|
191 break;
|
nuclear@0
|
192
|
nuclear@0
|
193 default:
|
nuclear@0
|
194 break;
|
nuclear@0
|
195 }
|
nuclear@0
|
196
|
nuclear@0
|
197 return 0;
|
nuclear@0
|
198 }
|
nuclear@0
|
199
|
nuclear@0
|
200 int key_event(int key, int state)
|
nuclear@0
|
201 {
|
nuclear@0
|
202 if(state) {
|
nuclear@0
|
203 switch(key) {
|
nuclear@0
|
204 case 27:
|
nuclear@0
|
205 return -1;
|
nuclear@0
|
206
|
nuclear@0
|
207 default:
|
nuclear@0
|
208 break;
|
nuclear@0
|
209 }
|
nuclear@0
|
210 }
|
nuclear@0
|
211 return 0;
|
nuclear@0
|
212 }
|