oculus1

annotate src/vr.cc @ 26:75ab0d4ce2bb

backed out the shaderless oculus distortion method, as it's completely pointless
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 04 Oct 2013 14:57:33 +0300
parents ef4c9d8eeca7
children
rev   line source
nuclear@1 1 #include <stdio.h>
nuclear@12 2 #include <GL/glew.h>
nuclear@1 3 #include "vr.h"
nuclear@1 4 #include "vr_impl.h"
nuclear@15 5 #include "vr_sdr.h"
nuclear@12 6
nuclear@19 7 #ifndef WIN32
nuclear@19 8 #include <alloca.h>
nuclear@19 9 #else
nuclear@19 10 #include <malloc.h>
nuclear@19 11 #endif
nuclear@19 12
nuclear@18 13 static void init_ctx();
nuclear@1 14 static bool init_ovr();
nuclear@12 15 static bool init_sdr();
nuclear@1 16
nuclear@3 17 VRContext vr_ctx;
nuclear@12 18 static unsigned int sdrprog;
nuclear@1 19
nuclear@1 20 extern "C" int vr_init(enum vr_init_mode mode)
nuclear@1 21 {
nuclear@12 22 glewInit();
nuclear@12 23
nuclear@18 24 init_ctx();
nuclear@18 25
nuclear@1 26 if(!init_ovr()) {
nuclear@1 27 return -1;
nuclear@1 28 }
nuclear@12 29
nuclear@12 30 if(!init_sdr()) {
nuclear@12 31 return -1;
nuclear@12 32 }
nuclear@12 33
nuclear@1 34 return 0;
nuclear@1 35 }
nuclear@1 36
nuclear@1 37 extern "C" void vr_shutdown(void)
nuclear@1 38 {
nuclear@15 39 delete [] vr_ctx.info.display;
nuclear@3 40 //System::Destroy();
nuclear@1 41 }
nuclear@1 42
nuclear@18 43 static void init_ctx()
nuclear@18 44 {
nuclear@18 45 vr_ctx.info.width = 1280;
nuclear@18 46 vr_ctx.info.height = 800;
nuclear@18 47 vr_ctx.info.fov = M_PI / 2.0;
nuclear@18 48 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
nuclear@18 49 vr_ctx.info.ipd = 0.035;
nuclear@18 50 vr_ctx.info.scale = 1.0;
nuclear@18 51 }
nuclear@18 52
nuclear@1 53 static bool init_ovr()
nuclear@1 54 {
nuclear@8 55 LogMaskConstants log_level = LogMask_All;
nuclear@1 56 // initialize Oculus SDK
nuclear@5 57 const char *logenv = getenv("VR_LOGLEVEL");
nuclear@5 58 if(logenv) {
nuclear@5 59 switch(atoi(logenv)) {
nuclear@5 60 case 0:
nuclear@5 61 log_level = LogMask_None;
nuclear@5 62 break;
nuclear@5 63 case 1:
nuclear@5 64 log_level = LogMask_Regular;
nuclear@5 65 break;
nuclear@5 66 case 2:
nuclear@5 67 default:
nuclear@5 68 log_level = LogMask_All;
nuclear@5 69 break;
nuclear@5 70 }
nuclear@5 71 }
nuclear@5 72
nuclear@5 73 System::Init(Log::ConfigureDefaultLog(log_level));
nuclear@3 74 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
nuclear@1 75 fprintf(stderr, "failed to create OVR device manager\n");
nuclear@1 76 return false;
nuclear@1 77 }
nuclear@1 78
nuclear@1 79 // create the display device
nuclear@4 80 HMDInfo info;
nuclear@3 81 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
nuclear@1 82 fprintf(stderr, "no oculus rift devices found\n");
nuclear@4 83 } else {
nuclear@4 84 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
nuclear@4 85 printf("oculus device info:\n");
nuclear@4 86 printf(" name: %s\n", info.DisplayDeviceName);
nuclear@4 87 printf(" ipd: %f\n", info.InterpupillaryDistance);
nuclear@4 88 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
nuclear@4 89 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
nuclear@4 90 }
nuclear@1 91
nuclear@4 92 // calculate and store viewing parameters
nuclear@4 93 vr_ctx.info.width = info.HResolution;
nuclear@4 94 vr_ctx.info.height = info.VResolution;
nuclear@4 95 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
nuclear@4 96
nuclear@4 97 vr_ctx.info.ipd = info.InterpupillaryDistance;
nuclear@4 98 for(int i=0; i<4; i++) {
nuclear@4 99 vr_ctx.info.distort[i] = info.DistortionK[i];
nuclear@4 100 }
nuclear@12 101
nuclear@14 102 Util::Render::StereoConfig stereohelp;
nuclear@14 103 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
nuclear@14 104 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
nuclear@14 105 stereohelp.SetHMDInfo(info);
nuclear@14 106 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
nuclear@14 107
nuclear@14 108 vr_ctx.info.scale = stereohelp.GetDistortionScale();
nuclear@13 109
nuclear@13 110 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
nuclear@13 111 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
nuclear@13 112
nuclear@13 113 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
nuclear@13 114
nuclear@13 115 // calculate center of projection shift to match the lens positions
nuclear@13 116 float center_dist_meters = info.HScreenSize * 0.25;
nuclear@13 117 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
nuclear@13 118 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
nuclear@15 119
nuclear@16 120 // grab the display info
nuclear@15 121 vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
nuclear@15 122 strcpy(vr_ctx.info.display, info.DisplayDeviceName);
nuclear@16 123
nuclear@16 124 vr_ctx.info.display_xoffs = info.DesktopX;
nuclear@16 125 vr_ctx.info.display_yoffs = info.DesktopY;
nuclear@16 126
nuclear@16 127 printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
nuclear@16 128 vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
nuclear@1 129 }
nuclear@1 130
nuclear@1 131 // get the sensor device
nuclear@4 132 if(vr_ctx.ovr_hmd_dev) {
nuclear@4 133 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
nuclear@4 134 fprintf(stderr, "failed to get oculus sensor device\n");
nuclear@4 135 }
nuclear@4 136 } else {
nuclear@4 137 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
nuclear@4 138 fprintf(stderr, "failed to get oculus sensor device\n");
nuclear@4 139 }
nuclear@1 140 }
nuclear@1 141
nuclear@4 142 if(vr_ctx.ovr_sensor_dev) {
nuclear@4 143 SensorInfo sinfo;
nuclear@4 144 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
nuclear@4 145 printf("oculus sensor device info:\n");
nuclear@4 146 printf(" name: %s\n", sinfo.ProductName);
nuclear@4 147 }
nuclear@4 148
nuclear@4 149 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
nuclear@1 150 }
nuclear@1 151 return true;
nuclear@1 152 }
nuclear@3 153
nuclear@13 154 #define EXTERNAL_SHADER
nuclear@13 155
nuclear@12 156 static bool init_sdr()
nuclear@12 157 {
nuclear@12 158 int status;
nuclear@12 159
nuclear@13 160 #ifdef EXTERNAL_SHADER
nuclear@17 161 FILE *fp = fopen("sdr/sdr.glsl", "rb");
nuclear@13 162 if(!fp) {
nuclear@13 163 perror("failed to load sdr.glsl");
nuclear@13 164 return false;
nuclear@13 165 }
nuclear@13 166 fseek(fp, 0, SEEK_END);
nuclear@13 167 long sz = ftell(fp);
nuclear@13 168 rewind(fp);
nuclear@13 169
nuclear@13 170 char *buf = (char*)alloca(sz + 1);
nuclear@13 171 fread(buf, 1, sz, fp);
nuclear@13 172 buf[sz] = 0;
nuclear@13 173 sdr_src = buf;
nuclear@13 174
nuclear@13 175 fclose(fp);
nuclear@13 176 #endif
nuclear@13 177
nuclear@12 178 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
nuclear@12 179 glShaderSource(sdr, 1, &sdr_src, 0);
nuclear@12 180 glCompileShader(sdr);
nuclear@12 181 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
nuclear@12 182 if(!status) {
nuclear@12 183 fprintf(stderr, "failed to compile distortion shader\n");
nuclear@14 184
nuclear@14 185 int loglen;
nuclear@14 186 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
nuclear@14 187
nuclear@14 188 if(loglen > 0) {
nuclear@14 189 char *log = (char*)alloca(loglen);
nuclear@14 190 glGetShaderInfoLog(sdr, loglen, &loglen, log);
nuclear@14 191 fprintf(stderr, "%s\n", log);
nuclear@14 192 }
nuclear@14 193
nuclear@12 194 return false;
nuclear@12 195 }
nuclear@12 196
nuclear@12 197 sdrprog = glCreateProgram();
nuclear@12 198 glAttachShader(sdrprog, sdr);
nuclear@12 199 glLinkProgram(sdrprog);
nuclear@12 200 if(!status) {
nuclear@12 201 fprintf(stderr, "failed to link distortion shader program\n");
nuclear@12 202 glDeleteShader(sdr);
nuclear@12 203 return false;
nuclear@12 204 }
nuclear@12 205
nuclear@12 206 int loc;
nuclear@12 207
nuclear@12 208 glUseProgram(sdrprog);
nuclear@12 209
nuclear@12 210 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
nuclear@12 211 glUniform1i(loc, 0);
nuclear@12 212 }
nuclear@13 213 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
nuclear@13 214 glUniform1f(loc, 0);
nuclear@12 215 }
nuclear@12 216 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
nuclear@12 217 glUniform2f(loc, 0, 0);
nuclear@12 218 }
nuclear@12 219 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
nuclear@13 220 glUniform1f(loc, vr_ctx.info.scale);
nuclear@13 221 }
nuclear@13 222 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
nuclear@13 223 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
nuclear@13 224 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
nuclear@12 225 }
nuclear@12 226 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
nuclear@12 227 glUniform2f(loc, 1, 1);
nuclear@12 228 }
nuclear@13 229 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
nuclear@12 230 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
nuclear@12 231 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
nuclear@12 232 }
nuclear@12 233
nuclear@12 234 return true;
nuclear@12 235 }
nuclear@12 236
nuclear@16 237 extern "C" const char *vr_get_display_name(void)
nuclear@16 238 {
nuclear@16 239 return vr_ctx.info.display;
nuclear@16 240 }
nuclear@16 241
nuclear@16 242 extern "C" void vr_get_display_pos(int *xptr, int *yptr)
nuclear@16 243 {
nuclear@16 244 *xptr = vr_ctx.info.display_xoffs;
nuclear@16 245 *yptr = vr_ctx.info.display_yoffs;
nuclear@16 246 }
nuclear@16 247
nuclear@3 248 extern "C" int vr_get_width(void)
nuclear@3 249 {
nuclear@3 250 return vr_ctx.info.width;
nuclear@3 251 }
nuclear@3 252
nuclear@3 253 extern "C" int vr_get_height(void)
nuclear@3 254 {
nuclear@3 255 return vr_ctx.info.height;
nuclear@3 256 }
nuclear@3 257
nuclear@3 258 extern "C" float vr_get_fov(void)
nuclear@3 259 {
nuclear@3 260 return vr_ctx.info.fov;
nuclear@3 261 }
nuclear@3 262
nuclear@3 263 extern "C" float vr_get_aspect(void)
nuclear@3 264 {
nuclear@3 265 return vr_ctx.info.aspect;
nuclear@3 266 }
nuclear@3 267
nuclear@3 268 extern "C" void vr_set_eyedist(float ipd)
nuclear@3 269 {
nuclear@3 270 vr_ctx.info.ipd = ipd;
nuclear@3 271 }
nuclear@3 272
nuclear@3 273 extern "C" float vr_get_eyedist(void)
nuclear@3 274 {
nuclear@3 275 return vr_ctx.info.ipd;
nuclear@3 276 }
nuclear@3 277
nuclear@3 278 extern "C" void vr_set_distort(const float *coef)
nuclear@3 279 {
nuclear@3 280 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
nuclear@3 281 }
nuclear@3 282
nuclear@3 283 extern "C" void vr_get_distort(float *coef)
nuclear@3 284 {
nuclear@3 285 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
nuclear@3 286 }
nuclear@3 287
nuclear@3 288 extern "C" void vr_set_prediction_sec(float dt)
nuclear@3 289 {
nuclear@3 290 vr_ctx.ovr_sfusion.SetPrediction(dt);
nuclear@3 291 }
nuclear@3 292
nuclear@3 293 extern "C" float vr_get_prediction_sec(void)
nuclear@3 294 {
nuclear@3 295 return vr_ctx.ovr_sfusion.GetPredictionDelta();
nuclear@3 296 }
nuclear@3 297
nuclear@13 298 extern "C" void vr_get_view_matrix(float *res, int eye)
nuclear@13 299 {
nuclear@13 300 // TODO
nuclear@13 301 }
nuclear@13 302
nuclear@13 303 extern "C" void vr_get_proj_matrix(float *res, int eye)
nuclear@13 304 {
nuclear@13 305 static float eye_scale[] = {0.0, 1.0, -1.0};
nuclear@13 306
nuclear@13 307 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
nuclear@13 308 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
nuclear@13 309
nuclear@13 310 memcpy(res, proj.M[0], 16 * sizeof(float));
nuclear@13 311 }
nuclear@13 312
nuclear@3 313 extern "C" void vr_get_translation(float *offs)
nuclear@3 314 {
nuclear@3 315 // current oculus devkit doesn't do translation
nuclear@3 316 offs[0] = offs[1] = offs[2] = 0.0f;
nuclear@3 317 }
nuclear@3 318
nuclear@3 319 extern "C" void vr_get_rotation(float *quat)
nuclear@3 320 {
nuclear@3 321 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
nuclear@3 322 quat[0] = oq.x;
nuclear@3 323 quat[1] = oq.y;
nuclear@3 324 quat[2] = oq.z;
nuclear@3 325 quat[3] = oq.w;
nuclear@3 326 }
nuclear@3 327
nuclear@3 328 extern "C" void vr_get_rotation_euler(float *euler)
nuclear@3 329 {
nuclear@3 330 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
nuclear@3 331 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
nuclear@3 332 }
nuclear@12 333
nuclear@18 334 extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
nuclear@12 335 {
nuclear@12 336 static const float rects[3][4] = {
nuclear@12 337 {-1, -1, 1, 1},
nuclear@12 338 {-1, -1, 0, 1},
nuclear@12 339 {0, -1, 1, 1}
nuclear@12 340 };
nuclear@12 341 static const float offs_scale[3] = {0.0, -1.0, 1.0};
nuclear@12 342
nuclear@12 343 glPushAttrib(GL_ENABLE_BIT);
nuclear@12 344 glDisable(GL_DEPTH_TEST);
nuclear@12 345 glDisable(GL_LIGHTING);
nuclear@26 346 glEnable(GL_TEXTURE_2D);
nuclear@26 347
nuclear@26 348 glMatrixMode(GL_MODELVIEW);
nuclear@26 349 glPushMatrix();
nuclear@26 350 glLoadIdentity();
nuclear@21 351
nuclear@21 352 glMatrixMode(GL_PROJECTION);
nuclear@21 353 glPushMatrix();
nuclear@21 354 glLoadIdentity();
nuclear@12 355
nuclear@26 356 glUseProgram(sdrprog);
nuclear@12 357
nuclear@26 358 if(sdrprog) {
nuclear@26 359 int loc;
nuclear@26 360 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
nuclear@26 361 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
nuclear@26 362 glUniform1f(loc, offset);
nuclear@13 363 }
nuclear@18 364
nuclear@26 365 if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
nuclear@26 366 glUniform2f(loc, tex_scale_x, tex_scale_y);
nuclear@18 367 }
nuclear@12 368 }
nuclear@12 369
nuclear@26 370 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@26 371 glBegin(GL_QUADS);
nuclear@26 372 glColor4f(1, 1, 1, 1);
nuclear@26 373 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
nuclear@26 374 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
nuclear@26 375 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
nuclear@26 376 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
nuclear@26 377 glEnd();
nuclear@26 378
nuclear@26 379 glUseProgram(0);
nuclear@26 380
nuclear@12 381 glPopMatrix();
nuclear@12 382 glMatrixMode(GL_MODELVIEW);
nuclear@12 383 glPopMatrix();
nuclear@12 384
nuclear@12 385 glPopAttrib();
nuclear@12 386 }