symmetry
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/vr/vr.cc Tue Feb 25 19:53:34 2014 +0200 1.3 @@ -0,0 +1,388 @@ 1.4 +#include <stdio.h> 1.5 +#include <GL/glew.h> 1.6 +#include "vr.h" 1.7 +#include "vr_impl.h" 1.8 +#include "vr_sdr.h" 1.9 + 1.10 +#ifndef WIN32 1.11 +#include <alloca.h> 1.12 +#else 1.13 +#include <malloc.h> 1.14 +#endif 1.15 + 1.16 +static void init_ctx(); 1.17 +static bool init_ovr(); 1.18 +static bool init_sdr(); 1.19 + 1.20 +VRContext vr_ctx; 1.21 +static unsigned int sdrprog; 1.22 + 1.23 +extern "C" int vr_init(enum vr_init_mode mode) 1.24 +{ 1.25 + init_ctx(); 1.26 + 1.27 + if(!init_ovr()) { 1.28 + return -1; 1.29 + } 1.30 + 1.31 + if(!init_sdr()) { 1.32 + return -1; 1.33 + } 1.34 + 1.35 + return 0; 1.36 +} 1.37 + 1.38 +extern "C" void vr_shutdown(void) 1.39 +{ 1.40 + delete [] vr_ctx.info.display; 1.41 + delete vr_ctx.ovr_sfusion; 1.42 + //System::Destroy(); 1.43 + 1.44 + memset(&vr_ctx, 0, sizeof vr_ctx); 1.45 +} 1.46 + 1.47 +static void init_ctx() 1.48 +{ 1.49 + vr_ctx.info.width = 1280; 1.50 + vr_ctx.info.height = 800; 1.51 + vr_ctx.info.fov = M_PI / 2.0; 1.52 + vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height; 1.53 + vr_ctx.info.ipd = 0.035; 1.54 + vr_ctx.info.scale = 1.0; 1.55 +} 1.56 + 1.57 +static bool init_ovr() 1.58 +{ 1.59 + LogMaskConstants log_level = LogMask_All; 1.60 + // initialize Oculus SDK 1.61 + const char *logenv = getenv("VR_LOGLEVEL"); 1.62 + if(logenv) { 1.63 + switch(atoi(logenv)) { 1.64 + case 0: 1.65 + log_level = LogMask_None; 1.66 + break; 1.67 + case 1: 1.68 + log_level = LogMask_Regular; 1.69 + break; 1.70 + case 2: 1.71 + default: 1.72 + log_level = LogMask_All; 1.73 + break; 1.74 + } 1.75 + } 1.76 + 1.77 + System::Init(Log::ConfigureDefaultLog(log_level)); 1.78 + if(!(vr_ctx.ovr_devman = DeviceManager::Create())) { 1.79 + fprintf(stderr, "failed to create OVR device manager\n"); 1.80 + return false; 1.81 + } 1.82 + 1.83 + // create the display device 1.84 + HMDInfo info; 1.85 + if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) { 1.86 + fprintf(stderr, "no oculus rift devices found\n"); 1.87 + } else { 1.88 + if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) { 1.89 + printf("oculus device info:\n"); 1.90 + printf(" name: %s\n", info.DisplayDeviceName); 1.91 + printf(" ipd: %f\n", info.InterpupillaryDistance); 1.92 + printf(" distortion: %f %f %f %f\n", info.DistortionK[0], 1.93 + info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]); 1.94 + } 1.95 + 1.96 + // calculate and store viewing parameters 1.97 + vr_ctx.info.width = info.HResolution; 1.98 + vr_ctx.info.height = info.VResolution; 1.99 + vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height; 1.100 + 1.101 + vr_ctx.info.ipd = info.InterpupillaryDistance; 1.102 + for(int i=0; i<4; i++) { 1.103 + vr_ctx.info.distort[i] = info.DistortionK[i]; 1.104 + } 1.105 + 1.106 + Util::Render::StereoConfig stereohelp; 1.107 + stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height)); 1.108 + stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass); 1.109 + stereohelp.SetHMDInfo(info); 1.110 + stereohelp.SetDistortionFitPointVP(-1.0, 0.0); 1.111 + 1.112 + vr_ctx.info.scale = stereohelp.GetDistortionScale(); 1.113 + 1.114 + float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5; 1.115 + vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance); 1.116 + 1.117 + vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize; 1.118 + 1.119 + // calculate center of projection shift to match the lens positions 1.120 + float center_dist_meters = info.HScreenSize * 0.25; 1.121 + float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5; 1.122 + vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize; 1.123 + 1.124 + // grab the display info 1.125 + vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1]; 1.126 + strcpy(vr_ctx.info.display, info.DisplayDeviceName); 1.127 + 1.128 + vr_ctx.info.display_xoffs = info.DesktopX; 1.129 + vr_ctx.info.display_yoffs = info.DesktopY; 1.130 + 1.131 + printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display, 1.132 + vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs); 1.133 + } 1.134 + 1.135 + // get the sensor device 1.136 + if(vr_ctx.ovr_hmd_dev) { 1.137 + if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) { 1.138 + fprintf(stderr, "failed to get oculus sensor device\n"); 1.139 + } 1.140 + } else { 1.141 + if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) { 1.142 + fprintf(stderr, "failed to get oculus sensor device\n"); 1.143 + } 1.144 + } 1.145 + 1.146 + if(vr_ctx.ovr_sensor_dev) { 1.147 + SensorInfo sinfo; 1.148 + if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) { 1.149 + printf("oculus sensor device info:\n"); 1.150 + printf(" name: %s\n", sinfo.ProductName); 1.151 + } 1.152 + 1.153 + vr_ctx.ovr_sfusion = new SensorFusion; 1.154 + vr_ctx.ovr_sfusion->AttachToSensor(vr_ctx.ovr_sensor_dev); 1.155 + } 1.156 + return true; 1.157 +} 1.158 + 1.159 +#undef EXTERNAL_SHADER 1.160 + 1.161 +static bool init_sdr() 1.162 +{ 1.163 + int status; 1.164 + 1.165 +#ifdef EXTERNAL_SHADER 1.166 + FILE *fp = fopen("sdr/sdr.glsl", "rb"); 1.167 + if(!fp) { 1.168 + perror("failed to load sdr.glsl"); 1.169 + return false; 1.170 + } 1.171 + fseek(fp, 0, SEEK_END); 1.172 + long sz = ftell(fp); 1.173 + rewind(fp); 1.174 + 1.175 + char *buf = (char*)alloca(sz + 1); 1.176 + fread(buf, 1, sz, fp); 1.177 + buf[sz] = 0; 1.178 + sdr_src = buf; 1.179 + 1.180 + fclose(fp); 1.181 +#endif 1.182 + 1.183 + unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER); 1.184 + glShaderSource(sdr, 1, &sdr_src, 0); 1.185 + glCompileShader(sdr); 1.186 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); 1.187 + if(!status) { 1.188 + fprintf(stderr, "failed to compile distortion shader\n"); 1.189 + 1.190 + int loglen; 1.191 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen); 1.192 + 1.193 + if(loglen > 0) { 1.194 + char *log = (char*)alloca(loglen); 1.195 + glGetShaderInfoLog(sdr, loglen, &loglen, log); 1.196 + fprintf(stderr, "%s\n", log); 1.197 + } 1.198 + 1.199 + return false; 1.200 + } 1.201 + 1.202 + sdrprog = glCreateProgram(); 1.203 + glAttachShader(sdrprog, sdr); 1.204 + glLinkProgram(sdrprog); 1.205 + if(!status) { 1.206 + fprintf(stderr, "failed to link distortion shader program\n"); 1.207 + glDeleteShader(sdr); 1.208 + return false; 1.209 + } 1.210 + 1.211 + int loc; 1.212 + 1.213 + glUseProgram(sdrprog); 1.214 + 1.215 + if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) { 1.216 + glUniform1i(loc, 0); 1.217 + } 1.218 + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { 1.219 + glUniform1f(loc, 0); 1.220 + } 1.221 + if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) { 1.222 + glUniform2f(loc, 0, 0); 1.223 + } 1.224 + if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) { 1.225 + glUniform1f(loc, vr_ctx.info.scale); 1.226 + } 1.227 + if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) { 1.228 + printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0); 1.229 + glUniform1f(loc, vr_ctx.info.aspect / 2.0); 1.230 + } 1.231 + if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) { 1.232 + glUniform2f(loc, 1, 1); 1.233 + } 1.234 + if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) { 1.235 + glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1], 1.236 + vr_ctx.info.distort[2], vr_ctx.info.distort[3]); 1.237 + } 1.238 + 1.239 + return true; 1.240 +} 1.241 + 1.242 +extern "C" const char *vr_get_display_name(void) 1.243 +{ 1.244 + return vr_ctx.info.display; 1.245 +} 1.246 + 1.247 +extern "C" void vr_get_display_pos(int *xptr, int *yptr) 1.248 +{ 1.249 + *xptr = vr_ctx.info.display_xoffs; 1.250 + *yptr = vr_ctx.info.display_yoffs; 1.251 +} 1.252 + 1.253 +extern "C" int vr_get_width(void) 1.254 +{ 1.255 + return vr_ctx.info.width; 1.256 +} 1.257 + 1.258 +extern "C" int vr_get_height(void) 1.259 +{ 1.260 + return vr_ctx.info.height; 1.261 +} 1.262 + 1.263 +extern "C" float vr_get_fov(void) 1.264 +{ 1.265 + return vr_ctx.info.fov; 1.266 +} 1.267 + 1.268 +extern "C" float vr_get_aspect(void) 1.269 +{ 1.270 + return vr_ctx.info.aspect; 1.271 +} 1.272 + 1.273 +extern "C" void vr_set_eyedist(float ipd) 1.274 +{ 1.275 + vr_ctx.info.ipd = ipd; 1.276 +} 1.277 + 1.278 +extern "C" float vr_get_eyedist(void) 1.279 +{ 1.280 + return vr_ctx.info.ipd; 1.281 +} 1.282 + 1.283 +extern "C" void vr_set_distort(const float *coef) 1.284 +{ 1.285 + memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort); 1.286 +} 1.287 + 1.288 +extern "C" void vr_get_distort(float *coef) 1.289 +{ 1.290 + memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort); 1.291 +} 1.292 + 1.293 +extern "C" void vr_set_prediction_sec(float dt) 1.294 +{ 1.295 + vr_ctx.ovr_sfusion->SetPrediction(dt); 1.296 +} 1.297 + 1.298 +extern "C" float vr_get_prediction_sec(void) 1.299 +{ 1.300 + return vr_ctx.ovr_sfusion->GetPredictionDelta(); 1.301 +} 1.302 + 1.303 +extern "C" void vr_get_view_matrix(float *res, int eye) 1.304 +{ 1.305 + // TODO 1.306 +} 1.307 + 1.308 +extern "C" void vr_get_proj_matrix(float *res, int eye) 1.309 +{ 1.310 + static float eye_scale[] = {0.0, 1.0, -1.0}; 1.311 + 1.312 + Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0); 1.313 + proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj; 1.314 + 1.315 + memcpy(res, proj.M[0], 16 * sizeof(float)); 1.316 +} 1.317 + 1.318 +extern "C" void vr_get_translation(float *offs) 1.319 +{ 1.320 + // current oculus devkit doesn't do translation 1.321 + offs[0] = offs[1] = offs[2] = 0.0f; 1.322 +} 1.323 + 1.324 +extern "C" void vr_get_rotation(float *quat) 1.325 +{ 1.326 + Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation(); 1.327 + quat[0] = oq.x; 1.328 + quat[1] = oq.y; 1.329 + quat[2] = oq.z; 1.330 + quat[3] = oq.w; 1.331 +} 1.332 + 1.333 +extern "C" void vr_get_rotation_euler(float *euler) 1.334 +{ 1.335 + Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation(); 1.336 + oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2); 1.337 +} 1.338 + 1.339 +extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y) 1.340 +{ 1.341 + static const float rects[3][4] = { 1.342 + {-1, -1, 1, 1}, 1.343 + {-1, -1, 0, 1}, 1.344 + {0, -1, 1, 1} 1.345 + }; 1.346 + static const float offs_scale[3] = {0.0, -1.0, 1.0}; 1.347 + 1.348 + glPushAttrib(GL_ENABLE_BIT); 1.349 + glDisable(GL_DEPTH_TEST); 1.350 + glDisable(GL_LIGHTING); 1.351 + glEnable(GL_TEXTURE_2D); 1.352 + 1.353 + glMatrixMode(GL_MODELVIEW); 1.354 + glPushMatrix(); 1.355 + glLoadIdentity(); 1.356 + 1.357 + glMatrixMode(GL_PROJECTION); 1.358 + glPushMatrix(); 1.359 + glLoadIdentity(); 1.360 + 1.361 + glUseProgram(sdrprog); 1.362 + 1.363 + if(sdrprog) { 1.364 + int loc; 1.365 + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { 1.366 + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; 1.367 + glUniform1f(loc, offset); 1.368 + } 1.369 + 1.370 + if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { 1.371 + glUniform2f(loc, tex_scale_x, tex_scale_y); 1.372 + } 1.373 + } 1.374 + 1.375 + glBindTexture(GL_TEXTURE_2D, tex); 1.376 + glBegin(GL_QUADS); 1.377 + glColor4f(1, 1, 1, 1); 1.378 + glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); 1.379 + glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); 1.380 + glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); 1.381 + glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); 1.382 + glEnd(); 1.383 + 1.384 + glUseProgram(0); 1.385 + 1.386 + glPopMatrix(); 1.387 + glMatrixMode(GL_MODELVIEW); 1.388 + glPopMatrix(); 1.389 + 1.390 + glPopAttrib(); 1.391 +}