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