oculus1

annotate src/vr.cc @ 14:cceffea995a4

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