conworlds

annotate src/vr/vr_libovr.c @ 10:e3f0ca1d008a

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