oculus1

annotate src/vr.cc @ 18:1b107de821c1

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