conworlds

annotate src/vr/vr_libovr.c @ 11:5dc4e2b8f6f5

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