rev |
line source |
nuclear@0
|
1 #ifdef WIN32
|
nuclear@0
|
2 #define OVR_OS_WIN32
|
nuclear@0
|
3 #endif
|
nuclear@9
|
4 #ifdef __APPLE__
|
nuclear@9
|
5 #define OVR_OS_MAC
|
nuclear@9
|
6 #endif
|
nuclear@0
|
7
|
nuclear@0
|
8 #include "vr_impl.h"
|
nuclear@0
|
9
|
nuclear@0
|
10 #ifdef USE_LIBOVR
|
nuclear@0
|
11 #include <stdio.h>
|
nuclear@0
|
12 #include <stdlib.h>
|
nuclear@9
|
13 #include <string.h>
|
nuclear@0
|
14 #include <assert.h>
|
nuclear@0
|
15 #include "opt.h"
|
nuclear@0
|
16
|
nuclear@0
|
17 #include <OVR_CAPI.h>
|
nuclear@0
|
18 #include <OVR_CAPI_GL.h>
|
nuclear@0
|
19
|
nuclear@0
|
20 #define DISABLE_RETARDED_HEALTH_WARNING
|
nuclear@0
|
21
|
nuclear@0
|
22 /* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */
|
nuclear@0
|
23 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled);
|
nuclear@0
|
24
|
nuclear@0
|
25 static ovrHmd hmd;
|
nuclear@0
|
26 static void *optdb;
|
nuclear@0
|
27 static ovrEyeRenderDesc eye_render_desc[2];
|
nuclear@0
|
28 static ovrSizei eye_res[2];
|
nuclear@0
|
29 static ovrGLTexture eye_tex[2];
|
nuclear@0
|
30 static ovrFovPort eye_fov[2];
|
nuclear@0
|
31 static ovrPosef pose[2];
|
nuclear@0
|
32 static int deferred_init_done;
|
nuclear@0
|
33
|
nuclear@0
|
34 static int init(void)
|
nuclear@0
|
35 {
|
nuclear@0
|
36 int i, num_hmds;
|
nuclear@9
|
37 int use_fake = 0;
|
nuclear@14
|
38 ovrTrackingCaps tracking;
|
nuclear@0
|
39
|
nuclear@0
|
40 if(!ovr_Initialize()) {
|
nuclear@0
|
41 return -1;
|
nuclear@0
|
42 }
|
nuclear@0
|
43 printf("initialized LibOVR %s\n", ovr_GetVersionString());
|
nuclear@0
|
44
|
nuclear@0
|
45 if(!(num_hmds = ovrHmd_Detect())) {
|
nuclear@9
|
46 if(getenv("VR_LIBOVR_FAKE")) {
|
nuclear@9
|
47 use_fake = 1;
|
nuclear@9
|
48 num_hmds = 1;
|
nuclear@9
|
49 } else {
|
nuclear@9
|
50 ovr_Shutdown();
|
nuclear@9
|
51 return -1;
|
nuclear@9
|
52 }
|
nuclear@0
|
53 }
|
nuclear@0
|
54 printf("%d Oculus HMD(s) found\n", num_hmds);
|
nuclear@0
|
55
|
nuclear@0
|
56 hmd = 0;
|
nuclear@0
|
57 for(i=0; i<num_hmds; i++) {
|
nuclear@9
|
58 ovrHmd h = use_fake ? ovrHmd_CreateDebug(ovrHmd_DK2) : ovrHmd_Create(i);
|
nuclear@9
|
59 if(!h) {
|
nuclear@0
|
60 break;
|
nuclear@0
|
61 }
|
nuclear@0
|
62 printf(" [%d]: %s - %s\n", i, h->Manufacturer, h->ProductName);
|
nuclear@0
|
63
|
nuclear@0
|
64 if(!hmd) {
|
nuclear@0
|
65 hmd = h;
|
nuclear@0
|
66 } else {
|
nuclear@0
|
67 ovrHmd_Destroy(h);
|
nuclear@0
|
68 }
|
nuclear@0
|
69 }
|
nuclear@0
|
70
|
nuclear@0
|
71 if(!hmd) {
|
nuclear@0
|
72 fprintf(stderr, "failed to initialize any Oculus HMDs\n");
|
nuclear@0
|
73 return -1;
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@14
|
76 tracking = ovrTrackingCap_Orientation | ovrTrackingCap_Position |
|
nuclear@14
|
77 ovrTrackingCap_MagYawCorrection;
|
nuclear@14
|
78 ovrHmd_ConfigureTracking(hmd, tracking, 0);
|
nuclear@0
|
79
|
nuclear@0
|
80 eye_fov[0] = hmd->DefaultEyeFov[0];
|
nuclear@0
|
81 eye_fov[1] = hmd->DefaultEyeFov[1];
|
nuclear@0
|
82
|
nuclear@0
|
83 eye_res[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, eye_fov[0], 1.0);
|
nuclear@0
|
84 eye_res[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, eye_fov[1], 1.0);
|
nuclear@0
|
85
|
nuclear@0
|
86 /* create the options database */
|
nuclear@0
|
87 if((optdb = create_options())) {
|
nuclear@11
|
88 set_option_int(optdb, VR_DISPLAY_WIDTH, hmd->Resolution.w);
|
nuclear@11
|
89 set_option_int(optdb, VR_DISPLAY_HEIGHT, hmd->Resolution.h);
|
nuclear@11
|
90 set_option_int(optdb, VR_LEYE_XRES, eye_res[0].w);
|
nuclear@11
|
91 set_option_int(optdb, VR_LEYE_YRES, eye_res[0].h);
|
nuclear@11
|
92 set_option_int(optdb, VR_REYE_XRES, eye_res[1].w);
|
nuclear@11
|
93 set_option_int(optdb, VR_REYE_YRES, eye_res[1].h);
|
nuclear@15
|
94 set_option_float(optdb, VR_EYE_RES_SCALE, 1.0);
|
nuclear@11
|
95 set_option_float(optdb, VR_EYE_HEIGHT, ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT));
|
nuclear@11
|
96 set_option_float(optdb, VR_IPD, ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD));
|
nuclear@11
|
97 set_option_int(optdb, VR_WIN_XOFFS, hmd->WindowsPos.x);
|
nuclear@11
|
98 set_option_int(optdb, VR_WIN_YOFFS, hmd->WindowsPos.y);
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 deferred_init_done = 0;
|
nuclear@0
|
102 return 0;
|
nuclear@0
|
103 }
|
nuclear@0
|
104
|
nuclear@0
|
105 static void deferred_init(void)
|
nuclear@0
|
106 {
|
nuclear@0
|
107 union ovrGLConfig glcfg;
|
nuclear@0
|
108 unsigned int dcaps;
|
nuclear@0
|
109 void *win = 0;
|
nuclear@0
|
110
|
nuclear@0
|
111 deferred_init_done = 1;
|
nuclear@0
|
112
|
nuclear@0
|
113 memset(&glcfg, 0, sizeof glcfg);
|
nuclear@0
|
114 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
|
nuclear@0
|
115 glcfg.OGL.Header.RTSize = hmd->Resolution;
|
nuclear@0
|
116 glcfg.OGL.Header.Multisample = 1;
|
nuclear@0
|
117 #ifdef WIN32
|
nuclear@0
|
118 win = GetActiveWindow();
|
nuclear@0
|
119 /*glcfg.OGL.Window = win;
|
nuclear@0
|
120 glcfg.OGL.DC = wglGetCurrentDC();
|
nuclear@0
|
121 assert(glcfg.OGL.Window);
|
nuclear@0
|
122 assert(glcfg.OGL.DC);*/
|
nuclear@0
|
123 #endif
|
nuclear@0
|
124
|
nuclear@0
|
125 if(!(hmd->HmdCaps & ovrHmdCap_ExtendDesktop)) {
|
nuclear@0
|
126 ovrHmd_AttachToWindow(hmd, win, 0, 0);
|
nuclear@0
|
127 printf("running in \"direct-to-rift\" mode\n");
|
nuclear@0
|
128 } else {
|
nuclear@0
|
129 printf("running in \"extended desktop\" mode\n");
|
nuclear@0
|
130 }
|
nuclear@0
|
131 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
|
nuclear@0
|
132
|
nuclear@0
|
133 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp |
|
nuclear@0
|
134 ovrDistortionCap_Overdrive | ovrDistortionCap_NoRestore;
|
nuclear@0
|
135
|
nuclear@0
|
136 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) {
|
nuclear@0
|
137 fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 #ifdef DISABLE_RETARDED_HEALTH_WARNING
|
nuclear@0
|
141 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
|
nuclear@0
|
142 #endif
|
nuclear@0
|
143 }
|
nuclear@0
|
144
|
nuclear@0
|
145 static void cleanup(void)
|
nuclear@0
|
146 {
|
nuclear@0
|
147 if(hmd) {
|
nuclear@0
|
148 ovrHmd_Destroy(hmd);
|
nuclear@0
|
149 ovr_Shutdown();
|
nuclear@0
|
150 }
|
nuclear@5
|
151 destroy_options(optdb);
|
nuclear@0
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 static int set_option(const char *opt, enum opt_type type, void *valp)
|
nuclear@0
|
155 {
|
nuclear@15
|
156 float fval;
|
nuclear@15
|
157
|
nuclear@0
|
158 switch(type) {
|
nuclear@0
|
159 case OTYPE_INT:
|
nuclear@15
|
160 fval = (float)*(int*)valp;
|
nuclear@0
|
161 set_option_int(optdb, opt, *(int*)valp);
|
nuclear@0
|
162 break;
|
nuclear@0
|
163
|
nuclear@0
|
164 case OTYPE_FLOAT:
|
nuclear@15
|
165 fval = *(float*)valp;
|
nuclear@15
|
166 set_option_float(optdb, opt, fval);
|
nuclear@0
|
167 break;
|
nuclear@0
|
168 }
|
nuclear@15
|
169
|
nuclear@15
|
170 if(hmd && strcmp(opt, VR_EYE_RES_SCALE) == 0) {
|
nuclear@15
|
171 eye_res[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, eye_fov[0], fval);
|
nuclear@15
|
172 eye_res[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, eye_fov[1], fval);
|
nuclear@15
|
173
|
nuclear@15
|
174 set_option_int(optdb, VR_LEYE_XRES, eye_res[0].w);
|
nuclear@15
|
175 set_option_int(optdb, VR_LEYE_YRES, eye_res[0].h);
|
nuclear@15
|
176 set_option_int(optdb, VR_REYE_XRES, eye_res[1].w);
|
nuclear@15
|
177 set_option_int(optdb, VR_REYE_YRES, eye_res[1].h);
|
nuclear@15
|
178 }
|
nuclear@15
|
179
|
nuclear@0
|
180 return 0;
|
nuclear@0
|
181 }
|
nuclear@0
|
182
|
nuclear@0
|
183 static int get_option(const char *opt, enum opt_type type, void *valp)
|
nuclear@0
|
184 {
|
nuclear@0
|
185 switch(type) {
|
nuclear@0
|
186 case OTYPE_INT:
|
nuclear@0
|
187 return get_option_int(optdb, opt, valp);
|
nuclear@0
|
188 case OTYPE_FLOAT:
|
nuclear@0
|
189 return get_option_float(optdb, opt, valp);
|
nuclear@0
|
190 }
|
nuclear@0
|
191 return -1;
|
nuclear@0
|
192 }
|
nuclear@0
|
193
|
nuclear@7
|
194 static void translation(int eye, float *vec)
|
nuclear@0
|
195 {
|
nuclear@0
|
196 if(!hmd) {
|
nuclear@0
|
197 vec[0] = vec[1] = vec[2] = 0;
|
nuclear@9
|
198 return;
|
nuclear@0
|
199 }
|
nuclear@0
|
200
|
nuclear@0
|
201 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
|
nuclear@0
|
202 vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x;
|
nuclear@0
|
203 vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y;
|
nuclear@0
|
204 vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z;
|
nuclear@0
|
205 }
|
nuclear@0
|
206
|
nuclear@7
|
207 static void rotation(int eye, float *quat)
|
nuclear@0
|
208 {
|
nuclear@0
|
209 if(!hmd) {
|
nuclear@0
|
210 quat[0] = quat[1] = quat[2] = 0.0f;
|
nuclear@0
|
211 quat[3] = 1.0f;
|
nuclear@9
|
212 return;
|
nuclear@0
|
213 }
|
nuclear@0
|
214
|
nuclear@0
|
215 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
|
nuclear@0
|
216 quat[0] = pose[eye].Orientation.x;
|
nuclear@0
|
217 quat[1] = pose[eye].Orientation.y;
|
nuclear@0
|
218 quat[2] = pose[eye].Orientation.z;
|
nuclear@0
|
219 quat[3] = pose[eye].Orientation.w;
|
nuclear@0
|
220 }
|
nuclear@0
|
221
|
nuclear@0
|
222 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
nuclear@0
|
223
|
nuclear@0
|
224 static void proj_matrix(int eye, float znear, float zfar, float *mat)
|
nuclear@0
|
225 {
|
nuclear@0
|
226 int i, j;
|
nuclear@0
|
227 ovrMatrix4f vmat;
|
nuclear@0
|
228
|
nuclear@0
|
229 if(!hmd) {
|
nuclear@0
|
230 memcpy(mat, idmat, sizeof idmat);
|
nuclear@0
|
231 return;
|
nuclear@0
|
232 }
|
nuclear@0
|
233
|
nuclear@0
|
234 vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1);
|
nuclear@0
|
235
|
nuclear@0
|
236 for(i=0; i<4; i++) {
|
nuclear@0
|
237 for(j=0; j<4; j++) {
|
nuclear@0
|
238 *mat++ = vmat.M[j][i];
|
nuclear@0
|
239 }
|
nuclear@0
|
240 }
|
nuclear@0
|
241 }
|
nuclear@0
|
242
|
nuclear@0
|
243 static int new_frame = 1;
|
nuclear@0
|
244
|
nuclear@0
|
245 static void begin(int eye)
|
nuclear@0
|
246 {
|
nuclear@0
|
247 if(!hmd) return;
|
nuclear@0
|
248
|
nuclear@0
|
249 if(!deferred_init_done) {
|
nuclear@0
|
250 deferred_init();
|
nuclear@0
|
251 }
|
nuclear@0
|
252
|
nuclear@0
|
253 if(new_frame) {
|
nuclear@0
|
254 ovrHmd_BeginFrame(hmd, 0);
|
nuclear@0
|
255 new_frame = 0;
|
nuclear@0
|
256 }
|
nuclear@0
|
257 }
|
nuclear@0
|
258
|
nuclear@0
|
259 static int present(void)
|
nuclear@0
|
260 {
|
nuclear@0
|
261 if(!hmd) return 0;
|
nuclear@0
|
262
|
nuclear@0
|
263 ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
|
nuclear@0
|
264 new_frame = 1;
|
nuclear@0
|
265
|
nuclear@0
|
266 return 1;
|
nuclear@0
|
267 }
|
nuclear@0
|
268
|
nuclear@0
|
269 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
|
nuclear@0
|
270 {
|
nuclear@0
|
271 ovrSizei texsz;
|
nuclear@0
|
272 ovrRecti rect;
|
nuclear@0
|
273
|
nuclear@0
|
274 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@0
|
275 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w);
|
nuclear@0
|
276 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h);
|
nuclear@0
|
277
|
nuclear@0
|
278 rect.Pos.x = (int)(umin * texsz.w);
|
nuclear@0
|
279 rect.Pos.y = (int)((vmin + 1.0 - vmax) * texsz.h);
|
nuclear@0
|
280 rect.Size.w = (int)((umax - umin) * texsz.w);
|
nuclear@0
|
281 rect.Size.h = (int)((vmax - vmin) * texsz.h);
|
nuclear@0
|
282
|
nuclear@0
|
283 eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
|
nuclear@0
|
284 eye_tex[eye].OGL.Header.TextureSize = texsz;
|
nuclear@0
|
285 eye_tex[eye].OGL.Header.RenderViewport = rect;
|
nuclear@0
|
286 eye_tex[eye].OGL.TexId = tex;
|
nuclear@0
|
287 }
|
nuclear@0
|
288
|
nuclear@0
|
289 static void recenter(void)
|
nuclear@0
|
290 {
|
nuclear@0
|
291 if(hmd) {
|
nuclear@0
|
292 ovrHmd_RecenterPose(hmd);
|
nuclear@0
|
293 }
|
nuclear@0
|
294 }
|
nuclear@0
|
295
|
nuclear@0
|
296 struct vr_module *vr_module_libovr(void)
|
nuclear@0
|
297 {
|
nuclear@0
|
298 static struct vr_module m;
|
nuclear@0
|
299
|
nuclear@0
|
300 if(!m.init) {
|
nuclear@0
|
301 m.name = "libovr";
|
nuclear@0
|
302 m.init = init;
|
nuclear@0
|
303 m.cleanup = cleanup;
|
nuclear@0
|
304 m.set_option = set_option;
|
nuclear@0
|
305 m.get_option = get_option;
|
nuclear@0
|
306 m.translation = translation;
|
nuclear@0
|
307 m.rotation = rotation;
|
nuclear@0
|
308 m.proj_matrix = proj_matrix;
|
nuclear@0
|
309 m.begin = begin;
|
nuclear@0
|
310 m.present = present;
|
nuclear@0
|
311 m.set_eye_texture = set_eye_texture;
|
nuclear@0
|
312 m.recenter = recenter;
|
nuclear@0
|
313 }
|
nuclear@0
|
314 return &m;
|
nuclear@0
|
315 }
|
nuclear@0
|
316
|
nuclear@0
|
317 #else /* no libovr */
|
nuclear@0
|
318
|
nuclear@0
|
319 static int init(void)
|
nuclear@0
|
320 {
|
nuclear@0
|
321 return -1;
|
nuclear@0
|
322 }
|
nuclear@0
|
323
|
nuclear@0
|
324 struct vr_module *vr_module_libovr(void)
|
nuclear@0
|
325 {
|
nuclear@0
|
326 static struct vr_module m;
|
nuclear@0
|
327
|
nuclear@0
|
328 if(!m.init) {
|
nuclear@0
|
329 m.name = "libovr";
|
nuclear@0
|
330 m.init = init;
|
nuclear@0
|
331 }
|
nuclear@0
|
332 return &m;
|
nuclear@0
|
333 }
|
nuclear@0
|
334
|
nuclear@0
|
335 #endif /* USE_LIBOVR */
|