libgoatvr
view src/vr_libovr.c @ 14:604a9a0a8c37
fixed call to ovrHmd_ConfigureTracking to stop setting the ovrTrackingCap_Idle bit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 25 Sep 2014 07:52:49 +0300 |
parents | 34d4643d61f9 |
children | 27fcd4c2969d |
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_EYE_HEIGHT, ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT));
95 set_option_float(optdb, VR_IPD, ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD));
96 set_option_int(optdb, VR_WIN_XOFFS, hmd->WindowsPos.x);
97 set_option_int(optdb, VR_WIN_YOFFS, hmd->WindowsPos.y);
98 }
100 deferred_init_done = 0;
101 return 0;
102 }
104 static void deferred_init(void)
105 {
106 union ovrGLConfig glcfg;
107 unsigned int dcaps;
108 void *win = 0;
110 deferred_init_done = 1;
112 memset(&glcfg, 0, sizeof glcfg);
113 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
114 glcfg.OGL.Header.RTSize = hmd->Resolution;
115 glcfg.OGL.Header.Multisample = 1;
116 #ifdef WIN32
117 win = GetActiveWindow();
118 /*glcfg.OGL.Window = win;
119 glcfg.OGL.DC = wglGetCurrentDC();
120 assert(glcfg.OGL.Window);
121 assert(glcfg.OGL.DC);*/
122 #endif
124 if(!(hmd->HmdCaps & ovrHmdCap_ExtendDesktop)) {
125 ovrHmd_AttachToWindow(hmd, win, 0, 0);
126 printf("running in \"direct-to-rift\" mode\n");
127 } else {
128 printf("running in \"extended desktop\" mode\n");
129 }
130 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
132 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp |
133 ovrDistortionCap_Overdrive | ovrDistortionCap_NoRestore;
135 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) {
136 fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
137 }
139 #ifdef DISABLE_RETARDED_HEALTH_WARNING
140 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
141 #endif
142 }
144 static void cleanup(void)
145 {
146 if(hmd) {
147 ovrHmd_Destroy(hmd);
148 ovr_Shutdown();
149 }
150 destroy_options(optdb);
151 }
153 static int set_option(const char *opt, enum opt_type type, void *valp)
154 {
155 switch(type) {
156 case OTYPE_INT:
157 set_option_int(optdb, opt, *(int*)valp);
158 break;
160 case OTYPE_FLOAT:
161 set_option_float(optdb, opt, *(float*)valp);
162 break;
163 }
164 return 0;
165 }
167 static int get_option(const char *opt, enum opt_type type, void *valp)
168 {
169 switch(type) {
170 case OTYPE_INT:
171 return get_option_int(optdb, opt, valp);
172 case OTYPE_FLOAT:
173 return get_option_float(optdb, opt, valp);
174 }
175 return -1;
176 }
178 static void translation(int eye, float *vec)
179 {
180 if(!hmd) {
181 vec[0] = vec[1] = vec[2] = 0;
182 return;
183 }
185 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
186 vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x;
187 vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y;
188 vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z;
189 }
191 static void rotation(int eye, float *quat)
192 {
193 if(!hmd) {
194 quat[0] = quat[1] = quat[2] = 0.0f;
195 quat[3] = 1.0f;
196 return;
197 }
199 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
200 quat[0] = pose[eye].Orientation.x;
201 quat[1] = pose[eye].Orientation.y;
202 quat[2] = pose[eye].Orientation.z;
203 quat[3] = pose[eye].Orientation.w;
204 }
206 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
208 static void proj_matrix(int eye, float znear, float zfar, float *mat)
209 {
210 int i, j;
211 ovrMatrix4f vmat;
213 if(!hmd) {
214 memcpy(mat, idmat, sizeof idmat);
215 return;
216 }
218 vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1);
220 for(i=0; i<4; i++) {
221 for(j=0; j<4; j++) {
222 *mat++ = vmat.M[j][i];
223 }
224 }
225 }
227 static int new_frame = 1;
229 static void begin(int eye)
230 {
231 if(!hmd) return;
233 if(!deferred_init_done) {
234 deferred_init();
235 }
237 if(new_frame) {
238 ovrHmd_BeginFrame(hmd, 0);
239 new_frame = 0;
240 }
241 }
243 static int present(void)
244 {
245 if(!hmd) return 0;
247 ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
248 new_frame = 1;
250 return 1;
251 }
253 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
254 {
255 ovrSizei texsz;
256 ovrRecti rect;
258 glBindTexture(GL_TEXTURE_2D, tex);
259 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w);
260 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h);
262 rect.Pos.x = (int)(umin * texsz.w);
263 rect.Pos.y = (int)((vmin + 1.0 - vmax) * texsz.h);
264 rect.Size.w = (int)((umax - umin) * texsz.w);
265 rect.Size.h = (int)((vmax - vmin) * texsz.h);
267 eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
268 eye_tex[eye].OGL.Header.TextureSize = texsz;
269 eye_tex[eye].OGL.Header.RenderViewport = rect;
270 eye_tex[eye].OGL.TexId = tex;
271 }
273 static void recenter(void)
274 {
275 if(hmd) {
276 ovrHmd_RecenterPose(hmd);
277 }
278 }
280 struct vr_module *vr_module_libovr(void)
281 {
282 static struct vr_module m;
284 if(!m.init) {
285 m.name = "libovr";
286 m.init = init;
287 m.cleanup = cleanup;
288 m.set_option = set_option;
289 m.get_option = get_option;
290 m.translation = translation;
291 m.rotation = rotation;
292 m.proj_matrix = proj_matrix;
293 m.begin = begin;
294 m.present = present;
295 m.set_eye_texture = set_eye_texture;
296 m.recenter = recenter;
297 }
298 return &m;
299 }
301 #else /* no libovr */
303 static int init(void)
304 {
305 return -1;
306 }
308 struct vr_module *vr_module_libovr(void)
309 {
310 static struct vr_module m;
312 if(!m.init) {
313 m.name = "libovr";
314 m.init = init;
315 }
316 return &m;
317 }
319 #endif /* USE_LIBOVR */