libgoatvr

view src/vr_libovr.c @ 16:b2d902fff68d

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