oculus1

annotate src/vr.cc @ 15:402cbb6d9ce3

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