libgoatvr
diff src/vr_libovr.c @ 0:ded3d0a74e19
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 29 Aug 2014 03:45:25 +0300 |
parents | |
children | e63cb28fc644 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/vr_libovr.c Fri Aug 29 03:45:25 2014 +0300 1.3 @@ -0,0 +1,308 @@ 1.4 +#ifdef WIN32 1.5 +#define OVR_OS_WIN32 1.6 +#endif 1.7 + 1.8 +#include "vr_impl.h" 1.9 + 1.10 +#ifdef USE_LIBOVR 1.11 +#include <stdio.h> 1.12 +#include <stdlib.h> 1.13 +#include <assert.h> 1.14 +#include "opt.h" 1.15 + 1.16 +#include <OVR_CAPI.h> 1.17 +#include <OVR_CAPI_GL.h> 1.18 + 1.19 +#define DISABLE_RETARDED_HEALTH_WARNING 1.20 + 1.21 +/* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */ 1.22 +OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled); 1.23 + 1.24 +static ovrHmd hmd; 1.25 +static void *optdb; 1.26 +static ovrEyeRenderDesc eye_render_desc[2]; 1.27 +static ovrSizei eye_res[2]; 1.28 +static ovrGLTexture eye_tex[2]; 1.29 +static ovrFovPort eye_fov[2]; 1.30 +static ovrPosef pose[2]; 1.31 +static int deferred_init_done; 1.32 + 1.33 +static int init(void) 1.34 +{ 1.35 + int i, num_hmds; 1.36 + 1.37 + if(!ovr_Initialize()) { 1.38 + return -1; 1.39 + } 1.40 + printf("initialized LibOVR %s\n", ovr_GetVersionString()); 1.41 + 1.42 + if(!(num_hmds = ovrHmd_Detect())) { 1.43 + ovr_Shutdown(); 1.44 + return -1; 1.45 + } 1.46 + printf("%d Oculus HMD(s) found\n", num_hmds); 1.47 + 1.48 + hmd = 0; 1.49 + for(i=0; i<num_hmds; i++) { 1.50 + ovrHmd h; 1.51 + if(!(h = ovrHmd_Create(i))) { 1.52 + break; 1.53 + } 1.54 + printf(" [%d]: %s - %s\n", i, h->Manufacturer, h->ProductName); 1.55 + 1.56 + if(!hmd) { 1.57 + hmd = h; 1.58 + } else { 1.59 + ovrHmd_Destroy(h); 1.60 + } 1.61 + } 1.62 + 1.63 + if(!hmd) { 1.64 + fprintf(stderr, "failed to initialize any Oculus HMDs\n"); 1.65 + return -1; 1.66 + } 1.67 + 1.68 + ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0); 1.69 + 1.70 + eye_fov[0] = hmd->DefaultEyeFov[0]; 1.71 + eye_fov[1] = hmd->DefaultEyeFov[1]; 1.72 + 1.73 + eye_res[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, eye_fov[0], 1.0); 1.74 + eye_res[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, eye_fov[1], 1.0); 1.75 + 1.76 + /* create the options database */ 1.77 + if((optdb = create_options())) { 1.78 + set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, hmd->Resolution.w); 1.79 + set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, hmd->Resolution.h); 1.80 + set_option_int(optdb, VR_OPT_LEYE_XRES, eye_res[0].w); 1.81 + set_option_int(optdb, VR_OPT_LEYE_YRES, eye_res[0].h); 1.82 + set_option_int(optdb, VR_OPT_REYE_XRES, eye_res[1].w); 1.83 + set_option_int(optdb, VR_OPT_REYE_YRES, eye_res[1].h); 1.84 + set_option_float(optdb, VR_OPT_EYE_HEIGHT, ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT)); 1.85 + set_option_float(optdb, VR_OPT_IPD, ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD)); 1.86 + set_option_int(optdb, VR_OPT_WIN_XOFFS, hmd->WindowsPos.x); 1.87 + set_option_int(optdb, VR_OPT_WIN_YOFFS, hmd->WindowsPos.y); 1.88 + } 1.89 + 1.90 + deferred_init_done = 0; 1.91 + return 0; 1.92 +} 1.93 + 1.94 +static void deferred_init(void) 1.95 +{ 1.96 + union ovrGLConfig glcfg; 1.97 + unsigned int dcaps; 1.98 + void *win = 0; 1.99 + 1.100 + deferred_init_done = 1; 1.101 + 1.102 + memset(&glcfg, 0, sizeof glcfg); 1.103 + glcfg.OGL.Header.API = ovrRenderAPI_OpenGL; 1.104 + glcfg.OGL.Header.RTSize = hmd->Resolution; 1.105 + glcfg.OGL.Header.Multisample = 1; 1.106 +#ifdef WIN32 1.107 + win = GetActiveWindow(); 1.108 + /*glcfg.OGL.Window = win; 1.109 + glcfg.OGL.DC = wglGetCurrentDC(); 1.110 + assert(glcfg.OGL.Window); 1.111 + assert(glcfg.OGL.DC);*/ 1.112 +#endif 1.113 + 1.114 + if(!(hmd->HmdCaps & ovrHmdCap_ExtendDesktop)) { 1.115 + ovrHmd_AttachToWindow(hmd, win, 0, 0); 1.116 + printf("running in \"direct-to-rift\" mode\n"); 1.117 + } else { 1.118 + printf("running in \"extended desktop\" mode\n"); 1.119 + } 1.120 + ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); 1.121 + 1.122 + dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | 1.123 + ovrDistortionCap_Overdrive | ovrDistortionCap_NoRestore; 1.124 + 1.125 + if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) { 1.126 + fprintf(stderr, "failed to configure LibOVR distortion renderer\n"); 1.127 + } 1.128 + 1.129 +#ifdef DISABLE_RETARDED_HEALTH_WARNING 1.130 + ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); 1.131 +#endif 1.132 +} 1.133 + 1.134 +static void cleanup(void) 1.135 +{ 1.136 + if(hmd) { 1.137 + ovrHmd_Destroy(hmd); 1.138 + ovr_Shutdown(); 1.139 + } 1.140 +} 1.141 + 1.142 +static int set_option(const char *opt, enum opt_type type, void *valp) 1.143 +{ 1.144 + switch(type) { 1.145 + case OTYPE_INT: 1.146 + set_option_int(optdb, opt, *(int*)valp); 1.147 + break; 1.148 + 1.149 + case OTYPE_FLOAT: 1.150 + set_option_float(optdb, opt, *(float*)valp); 1.151 + break; 1.152 + } 1.153 + return 0; 1.154 +} 1.155 + 1.156 +static int get_option(const char *opt, enum opt_type type, void *valp) 1.157 +{ 1.158 + switch(type) { 1.159 + case OTYPE_INT: 1.160 + return get_option_int(optdb, opt, valp); 1.161 + case OTYPE_FLOAT: 1.162 + return get_option_float(optdb, opt, valp); 1.163 + } 1.164 + return -1; 1.165 +} 1.166 + 1.167 +static int translation(int eye, float *vec) 1.168 +{ 1.169 + if(!hmd) { 1.170 + vec[0] = vec[1] = vec[2] = 0; 1.171 + return 0; 1.172 + } 1.173 + 1.174 + pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); 1.175 + vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x; 1.176 + vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y; 1.177 + vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z; 1.178 + 1.179 + return 1; 1.180 +} 1.181 + 1.182 +static int rotation(int eye, float *quat) 1.183 +{ 1.184 + if(!hmd) { 1.185 + quat[0] = quat[1] = quat[2] = 0.0f; 1.186 + quat[3] = 1.0f; 1.187 + return 0; 1.188 + } 1.189 + 1.190 + pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right); 1.191 + quat[0] = pose[eye].Orientation.x; 1.192 + quat[1] = pose[eye].Orientation.y; 1.193 + quat[2] = pose[eye].Orientation.z; 1.194 + quat[3] = pose[eye].Orientation.w; 1.195 + return 1; 1.196 +} 1.197 + 1.198 +static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; 1.199 + 1.200 +static void proj_matrix(int eye, float znear, float zfar, float *mat) 1.201 +{ 1.202 + int i, j; 1.203 + ovrMatrix4f vmat; 1.204 + 1.205 + if(!hmd) { 1.206 + memcpy(mat, idmat, sizeof idmat); 1.207 + return; 1.208 + } 1.209 + 1.210 + vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1); 1.211 + 1.212 + for(i=0; i<4; i++) { 1.213 + for(j=0; j<4; j++) { 1.214 + *mat++ = vmat.M[j][i]; 1.215 + } 1.216 + } 1.217 +} 1.218 + 1.219 +static int new_frame = 1; 1.220 + 1.221 +static void begin(int eye) 1.222 +{ 1.223 + if(!hmd) return; 1.224 + 1.225 + if(!deferred_init_done) { 1.226 + deferred_init(); 1.227 + } 1.228 + 1.229 + if(new_frame) { 1.230 + ovrHmd_BeginFrame(hmd, 0); 1.231 + new_frame = 0; 1.232 + } 1.233 +} 1.234 + 1.235 +static int present(void) 1.236 +{ 1.237 + if(!hmd) return 0; 1.238 + 1.239 + ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture); 1.240 + new_frame = 1; 1.241 + 1.242 + return 1; 1.243 +} 1.244 + 1.245 +static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax) 1.246 +{ 1.247 + ovrSizei texsz; 1.248 + ovrRecti rect; 1.249 + 1.250 + glBindTexture(GL_TEXTURE_2D, tex); 1.251 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w); 1.252 + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h); 1.253 + 1.254 + rect.Pos.x = (int)(umin * texsz.w); 1.255 + rect.Pos.y = (int)((vmin + 1.0 - vmax) * texsz.h); 1.256 + rect.Size.w = (int)((umax - umin) * texsz.w); 1.257 + rect.Size.h = (int)((vmax - vmin) * texsz.h); 1.258 + 1.259 + eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL; 1.260 + eye_tex[eye].OGL.Header.TextureSize = texsz; 1.261 + eye_tex[eye].OGL.Header.RenderViewport = rect; 1.262 + eye_tex[eye].OGL.TexId = tex; 1.263 +} 1.264 + 1.265 +static void recenter(void) 1.266 +{ 1.267 + if(hmd) { 1.268 + ovrHmd_RecenterPose(hmd); 1.269 + } 1.270 +} 1.271 + 1.272 +struct vr_module *vr_module_libovr(void) 1.273 +{ 1.274 + static struct vr_module m; 1.275 + 1.276 + if(!m.init) { 1.277 + m.name = "libovr"; 1.278 + m.init = init; 1.279 + m.cleanup = cleanup; 1.280 + m.set_option = set_option; 1.281 + m.get_option = get_option; 1.282 + m.translation = translation; 1.283 + m.rotation = rotation; 1.284 + m.proj_matrix = proj_matrix; 1.285 + m.begin = begin; 1.286 + m.present = present; 1.287 + m.set_eye_texture = set_eye_texture; 1.288 + m.recenter = recenter; 1.289 + } 1.290 + return &m; 1.291 +} 1.292 + 1.293 +#else /* no libovr */ 1.294 + 1.295 +static int init(void) 1.296 +{ 1.297 + return -1; 1.298 +} 1.299 + 1.300 +struct vr_module *vr_module_libovr(void) 1.301 +{ 1.302 + static struct vr_module m; 1.303 + 1.304 + if(!m.init) { 1.305 + m.name = "libovr"; 1.306 + m.init = init; 1.307 + } 1.308 + return &m; 1.309 +} 1.310 + 1.311 +#endif /* USE_LIBOVR */