conworlds

annotate src/vr/vr_libovr.c @ 7:bd8202d6d28d

some progress...
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Aug 2014 16:55:16 +0300
parents 3c36bc28c6c2
children 90abf4b93cc9
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@7 89
nuclear@7 90 deferred_init_done = 1;
nuclear@7 91
nuclear@5 92 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0);
nuclear@5 93
nuclear@5 94 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
nuclear@5 95 glcfg.OGL.Header.RTSize = hmd->Resolution;
nuclear@5 96 glcfg.OGL.Header.Multisample = 0;
nuclear@7 97 #ifdef WIN32
nuclear@7 98 glcfg.OGL.Window = GetActiveWindow();
nuclear@7 99 glcfg.OGL.DC = wglGetCurrentDC();
nuclear@7 100 ovrHmd_AttachToWindow(hmd, glcfg.OGL.Window, 0, 0);
nuclear@7 101 assert(glcfg.OGL.Window);
nuclear@7 102 #endif
nuclear@5 103
nuclear@7 104 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp |
nuclear@7 105 ovrDistortionCap_Overdrive | ovrDistortionCap_FlipInput;
nuclear@7 106
nuclear@7 107 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) {
nuclear@5 108 fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
nuclear@5 109 }
nuclear@7 110
nuclear@7 111 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
nuclear@4 112 }
nuclear@4 113
nuclear@4 114 static void cleanup(void)
nuclear@4 115 {
nuclear@5 116 if(hmd) {
nuclear@5 117 ovrHmd_Destroy(hmd);
nuclear@7 118 ovr_Shutdown();
nuclear@5 119 }
nuclear@4 120 }
nuclear@4 121
nuclear@7 122 static int set_option(const char *opt, enum opt_type type, void *valp)
nuclear@4 123 {
nuclear@7 124 switch(type) {
nuclear@7 125 case OTYPE_INT:
nuclear@7 126 set_option_int(optdb, opt, *(int*)valp);
nuclear@7 127 break;
nuclear@7 128
nuclear@7 129 case OTYPE_FLOAT:
nuclear@7 130 set_option_float(optdb, opt, *(float*)valp);
nuclear@7 131 break;
nuclear@7 132 }
nuclear@7 133 return 0;
nuclear@4 134 }
nuclear@4 135
nuclear@7 136 static int get_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 return get_option_int(optdb, opt, valp);
nuclear@7 141 case OTYPE_FLOAT:
nuclear@7 142 return get_option_float(optdb, opt, valp);
nuclear@7 143 }
nuclear@7 144 return -1;
nuclear@4 145 }
nuclear@4 146
nuclear@7 147 static int translation(int eye, float *vec)
nuclear@7 148 {
nuclear@7 149 if(!hmd) {
nuclear@7 150 vec[0] = vec[1] = vec[2] = 0;
nuclear@7 151 return -1;
nuclear@7 152 }
nuclear@7 153
nuclear@7 154 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
nuclear@7 155 vec[0] = pose[eye].Position.x;
nuclear@7 156 vec[1] = pose[eye].Position.y;
nuclear@7 157 vec[2] = pose[eye].Position.z;
nuclear@7 158 return 0;
nuclear@7 159 }
nuclear@7 160
nuclear@7 161 static int rotation(int eye, float *quat)
nuclear@7 162 {
nuclear@7 163 if(!hmd) {
nuclear@7 164 quat[0] = quat[1] = quat[2] = 0.0f;
nuclear@7 165 quat[3] = 1.0f;
nuclear@7 166 return -1;
nuclear@7 167 }
nuclear@7 168
nuclear@7 169 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
nuclear@7 170 quat[0] = pose[eye].Orientation.x;
nuclear@7 171 quat[1] = pose[eye].Orientation.y;
nuclear@7 172 quat[2] = pose[eye].Orientation.z;
nuclear@7 173 quat[3] = pose[eye].Orientation.w;
nuclear@7 174 return 0;
nuclear@7 175 }
nuclear@7 176
nuclear@7 177 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
nuclear@7 178
nuclear@7 179 static void proj_matrix(int eye, float znear, float zfar, float *mat)
nuclear@7 180 {
nuclear@7 181 ovrMatrix4f vmat;
nuclear@7 182
nuclear@7 183 if(!hmd) {
nuclear@7 184 memcpy(mat, idmat, sizeof idmat);
nuclear@7 185 return;
nuclear@7 186 }
nuclear@7 187
nuclear@7 188 vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1);
nuclear@7 189 memcpy(mat, vmat.M[0], 16 * sizeof(float));
nuclear@7 190 }
nuclear@7 191
nuclear@7 192 static int new_frame = 1;
nuclear@7 193
nuclear@5 194 static void begin(int eye)
nuclear@4 195 {
nuclear@7 196 if(!hmd) return;
nuclear@4 197
nuclear@7 198 if(!deferred_init_done) {
nuclear@7 199 deferred_init();
nuclear@7 200 }
nuclear@7 201
nuclear@7 202 if(new_frame) {
nuclear@7 203 ovrHmd_BeginFrame(hmd, 0);
nuclear@7 204 new_frame = 0;
nuclear@7 205 }
nuclear@5 206 }
nuclear@5 207
nuclear@5 208 static void present(void)
nuclear@5 209 {
nuclear@7 210 if(!hmd) return;
nuclear@7 211
nuclear@7 212 ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
nuclear@7 213 new_frame = 1;
nuclear@5 214 }
nuclear@5 215
nuclear@7 216 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
nuclear@7 217 {
nuclear@7 218 ovrSizei texsz;
nuclear@7 219 ovrRecti rect;
nuclear@7 220
nuclear@7 221 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@7 222 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w);
nuclear@7 223 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h);
nuclear@7 224
nuclear@7 225 rect.Pos.x = (int)(umin * texsz.w);
nuclear@7 226 rect.Pos.y = (int)(vmin * texsz.h);
nuclear@7 227 rect.Size.w = (int)((umax - umin) * texsz.w);
nuclear@7 228 rect.Size.h = (int)((vmax - vmin) * texsz.h);
nuclear@7 229
nuclear@7 230 eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
nuclear@7 231 eye_tex[eye].OGL.Header.TextureSize = texsz;
nuclear@7 232 eye_tex[eye].OGL.Header.RenderViewport = rect;
nuclear@7 233 eye_tex[eye].OGL.TexId = tex;
nuclear@7 234 }
nuclear@7 235
nuclear@7 236 static void recenter(void)
nuclear@7 237 {
nuclear@7 238 if(hmd) {
nuclear@7 239 ovrHmd_RecenterPose(hmd);
nuclear@7 240 }
nuclear@7 241 }
nuclear@5 242
nuclear@4 243 struct vr_module *vr_module_libovr(void)
nuclear@4 244 {
nuclear@4 245 static struct vr_module m;
nuclear@4 246
nuclear@4 247 if(!m.init) {
nuclear@4 248 m.name = "libovr";
nuclear@4 249 m.init = init;
nuclear@4 250 m.cleanup = cleanup;
nuclear@7 251 m.set_option = set_option;
nuclear@7 252 m.get_option = get_option;
nuclear@7 253 m.translation = translation;
nuclear@7 254 m.rotation = rotation;
nuclear@4 255 m.proj_matrix = proj_matrix;
nuclear@5 256 m.begin = begin;
nuclear@5 257 m.present = present;
nuclear@7 258 m.set_eye_texture = set_eye_texture;
nuclear@7 259 m.recenter = recenter;
nuclear@4 260 }
nuclear@4 261 return &m;
nuclear@4 262 }
nuclear@6 263
nuclear@6 264 #else /* no libovr */
nuclear@6 265
nuclear@6 266 static int init(void)
nuclear@6 267 {
nuclear@6 268 return -1;
nuclear@6 269 }
nuclear@6 270
nuclear@6 271 struct vr_module *vr_module_libovr(void)
nuclear@6 272 {
nuclear@6 273 static struct vr_module m;
nuclear@6 274
nuclear@6 275 if(!m.init) {
nuclear@6 276 m.name = "libovr";
nuclear@6 277 m.init = init;
nuclear@6 278 }
nuclear@6 279 return &m;
nuclear@6 280 }
nuclear@6 281
nuclear@6 282 #endif /* USE_LIBOVR */