libgoatvr

annotate src/vr_libovr.c @ 7:6896f9cf9621

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