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 +}