symmetry

annotate src/vr/vr.cc @ 0:a90a71a74f0b

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