goat3dgfx

changeset 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 b4c9a24c946e
children 1868c5975f31
files Makefile.in configure src/camera.cc src/camera.h src/goat3dgfx.cc src/vr.h src/vr/vr.cc src/vr/vr_impl.h src/vr/vr_sdr.h
diffstat 9 files changed, 877 insertions(+), 1 deletions(-) [+]
line diff
     1.1 --- a/Makefile.in	Sun Nov 24 13:30:44 2013 +0200
     1.2 +++ b/Makefile.in	Sun Nov 24 14:00:14 2013 +0200
     1.3 @@ -1,6 +1,9 @@
     1.4 +ifdef use_vr
     1.5 +	vr_ccsrc = $(wildcard src/vr/*.cc)
     1.6 +endif
     1.7  
     1.8  csrc = $(wildcard src/*.c)
     1.9 -ccsrc = $(wildcard src/*.cc)
    1.10 +ccsrc = $(wildcard src/*.cc) $(vr_ccsrc)
    1.11  obj = $(csrc:.c=.o) $(ccsrc:.cc=.o)
    1.12  dep = $(obj:.o=.d)
    1.13  name = goat3dgfx
     2.1 --- a/configure	Sun Nov 24 13:30:44 2013 +0200
     2.2 +++ b/configure	Sun Nov 24 14:00:14 2013 +0200
     2.3 @@ -199,6 +199,8 @@
     2.4  	emit "cfg_cflags = $CFLAGS"
     2.5  	emit "cfg_ldflags = $LDFLAGS"
     2.6  
     2.7 +	if $vr; then emit 'use_vr = true'; fi
     2.8 +
     2.9  	cat Makefile.in >>Makefile
    2.10  }
    2.11  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/camera.cc	Sun Nov 24 14:00:14 2013 +0200
     3.3 @@ -0,0 +1,235 @@
     3.4 +#include "opengl.h"
     3.5 +#include "camera.h"
     3.6 +#include "vr.h"
     3.7 +
     3.8 +Camera::Camera()
     3.9 +{
    3.10 +	roll = 0.0;
    3.11 +	inval_cache();
    3.12 +}
    3.13 +
    3.14 +Camera::~Camera()
    3.15 +{
    3.16 +}
    3.17 +
    3.18 +void Camera::calc_inv_matrix(Matrix4x4 *mat) const
    3.19 +{
    3.20 +	*mat = matrix().inverse();
    3.21 +}
    3.22 +
    3.23 +const Matrix4x4 &Camera::matrix() const
    3.24 +{
    3.25 +	if(!mcache.valid) {
    3.26 +		calc_matrix(&mcache.mat);
    3.27 +		mcache.valid = true;
    3.28 +	}
    3.29 +	return mcache.mat;
    3.30 +}
    3.31 +
    3.32 +const Matrix4x4 &Camera::inv_matrix() const
    3.33 +{
    3.34 +	if(!mcache_inv.valid) {
    3.35 +		calc_inv_matrix(&mcache_inv.mat);
    3.36 +		mcache_inv.valid = true;
    3.37 +	}
    3.38 +	return mcache_inv.mat;
    3.39 +}
    3.40 +
    3.41 +void Camera::use() const
    3.42 +{
    3.43 +	mult_matrix(matrix());
    3.44 +}
    3.45 +
    3.46 +void Camera::use_inverse() const
    3.47 +{
    3.48 +	mult_matrix(inv_matrix());
    3.49 +}
    3.50 +
    3.51 +void Camera::input_move(float x, float y, float z)
    3.52 +{
    3.53 +}
    3.54 +
    3.55 +void Camera::input_rotate(float x, float y, float z)
    3.56 +{
    3.57 +}
    3.58 +
    3.59 +void Camera::input_zoom(float factor)
    3.60 +{
    3.61 +}
    3.62 +
    3.63 +
    3.64 +// ---- orbit camera ----
    3.65 +
    3.66 +OrbitCamera::OrbitCamera()
    3.67 +{
    3.68 +	theta = 0.0;
    3.69 +	phi = 0.0;
    3.70 +	rad = 10.0;
    3.71 +}
    3.72 +
    3.73 +OrbitCamera::~OrbitCamera()
    3.74 +{
    3.75 +}
    3.76 +
    3.77 +void OrbitCamera::calc_matrix(Matrix4x4 *mat) const
    3.78 +{
    3.79 +	mat->reset_identity();
    3.80 +	mat->translate(Vector3(0, 0, -rad));
    3.81 +	mat->rotate(Vector3(phi, 0, 0));
    3.82 +	mat->rotate(Vector3(0, theta, 0));
    3.83 +	mat->rotate(Vector3(0, 0, roll));
    3.84 +}
    3.85 +
    3.86 +void OrbitCamera::calc_inv_matrix(Matrix4x4 *mat) const
    3.87 +{
    3.88 +	mat->reset_identity();
    3.89 +	mat->rotate(Vector3(0, 0, roll));
    3.90 +	mat->rotate(Vector3(0, theta, 0));
    3.91 +	mat->rotate(Vector3(phi, 0, 0));
    3.92 +	mat->translate(Vector3(0, 0, -rad));
    3.93 +}
    3.94 +
    3.95 +void OrbitCamera::input_rotate(float x, float y, float z)
    3.96 +{
    3.97 +	theta += y;
    3.98 +	phi += x;
    3.99 +	roll += z;
   3.100 +
   3.101 +	if(phi < -M_PI / 2)
   3.102 +		phi = -M_PI / 2;
   3.103 +	if(phi > M_PI)
   3.104 +		phi = M_PI;
   3.105 +
   3.106 +	inval_cache();
   3.107 +}
   3.108 +
   3.109 +void OrbitCamera::input_zoom(float factor)
   3.110 +{
   3.111 +	rad += factor;
   3.112 +	if(rad < 0.0)
   3.113 +		rad = 0.0;
   3.114 +
   3.115 +	inval_cache();
   3.116 +}
   3.117 +
   3.118 +void FpsCamera::calc_matrix(Matrix4x4 *mat) const
   3.119 +{
   3.120 +	mat->reset_identity();
   3.121 +	mat->translate(Vector3(pos.x, pos.y, pos.z));
   3.122 +	mat->rotate(Vector3(0, theta, 0));
   3.123 +	mat->rotate(Vector3(phi, 0, 0));
   3.124 +	mat->rotate(Vector3(0, 0, roll));
   3.125 +}
   3.126 +
   3.127 +void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.128 +{
   3.129 +	mat->reset_identity();
   3.130 +	mat->rotate(Vector3(0, 0, roll));
   3.131 +	mat->rotate(Vector3(phi, 0, 0));
   3.132 +	mat->rotate(Vector3(0, theta, 0));
   3.133 +	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   3.134 +}
   3.135 +
   3.136 +void FpsCamera::input_move(float x, float y, float z)
   3.137 +{
   3.138 +	pos.x += x * cos(theta) - z * sin(theta);
   3.139 +	pos.z += x * sin(theta) + z * cos(theta);
   3.140 +	pos.y += y;
   3.141 +	inval_cache();
   3.142 +}
   3.143 +
   3.144 +const Vector3 &FpsCamera::get_position() const
   3.145 +{
   3.146 +	return pos;
   3.147 +}
   3.148 +
   3.149 +
   3.150 +FlyCamera::FlyCamera()
   3.151 +{
   3.152 +	pos.z = 10.0f;
   3.153 +}
   3.154 +
   3.155 +void FlyCamera::calc_matrix(Matrix4x4 *mat) const
   3.156 +{
   3.157 +	Matrix3x3 rmat = rot.get_rotation_matrix().transposed();
   3.158 +	Matrix4x4 tmat;
   3.159 +	tmat.set_translation(pos);
   3.160 +	*mat = tmat * Matrix4x4(rmat);
   3.161 +}
   3.162 +
   3.163 +/*void FlyCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.164 +{
   3.165 +}*/
   3.166 +
   3.167 +const Vector3 &FlyCamera::get_position() const
   3.168 +{
   3.169 +	return pos;
   3.170 +}
   3.171 +
   3.172 +const Quaternion &FlyCamera::get_rotation() const
   3.173 +{
   3.174 +	return rot;
   3.175 +}
   3.176 +
   3.177 +void FlyCamera::input_move(float x, float y, float z)
   3.178 +{
   3.179 +	static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0);
   3.180 +
   3.181 +	Vector3 k = vfwd.transformed(rot);
   3.182 +	Vector3	i = vright.transformed(rot);
   3.183 +	Vector3 j = cross_product(k, i);
   3.184 +
   3.185 +	pos += i * x + j * y + k * z;
   3.186 +	inval_cache();
   3.187 +}
   3.188 +
   3.189 +void FlyCamera::input_rotate(float x, float y, float z)
   3.190 +{
   3.191 +	Vector3 axis(x, y, z);
   3.192 +	float axis_len = axis.length();
   3.193 +	rot.rotate(axis / axis_len, axis_len);
   3.194 +	rot.normalize();
   3.195 +
   3.196 +	inval_cache();
   3.197 +}
   3.198 +
   3.199 +
   3.200 +// --- VR additions ---
   3.201 +VRFpsCamera::VRFpsCamera()
   3.202 +{
   3.203 +	neck_eye_dist = 0.14;	// default neck->eye distance 14cm
   3.204 +}
   3.205 +
   3.206 +void VRFpsCamera::calc_matrix(Matrix4x4 *mat) const
   3.207 +{
   3.208 +	mat->reset_identity();
   3.209 +	mat->translate(Vector3(pos.x, pos.y, pos.z));
   3.210 +	mat->rotate(Vector3(0, theta, 0));
   3.211 +	mat->rotate(Vector3(phi, 0, 0));
   3.212 +	mat->rotate(Vector3(0, 0, roll));
   3.213 +	mat->translate(Vector3(0, neck_eye_dist, 0));
   3.214 +}
   3.215 +
   3.216 +void VRFpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.217 +{
   3.218 +	mat->reset_identity();
   3.219 +	mat->translate(Vector3(0, -neck_eye_dist, 0));
   3.220 +	mat->rotate(Vector3(0, 0, roll));
   3.221 +	mat->rotate(Vector3(phi, 0, 0));
   3.222 +	mat->rotate(Vector3(0, theta, 0));
   3.223 +	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   3.224 +}
   3.225 +
   3.226 +void VRFpsCamera::track_vr()
   3.227 +{
   3.228 +	float euler[3];
   3.229 +	vr_get_rotation_euler(euler);
   3.230 +
   3.231 +	// input_rotate invalidates cache
   3.232 +	input_rotate(prev_angles[0] - euler[0], prev_angles[1] - euler[1], prev_angles[2] - euler[2]);
   3.233 +
   3.234 +	prev_angles[0] = euler[0];
   3.235 +	prev_angles[1] = euler[1];
   3.236 +	prev_angles[2] = euler[2];
   3.237 +}
   3.238 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/camera.h	Sun Nov 24 14:00:14 2013 +0200
     4.3 @@ -0,0 +1,98 @@
     4.4 +#ifndef CAMERA_H_
     4.5 +#define CAMERA_H_
     4.6 +
     4.7 +#include <vmath/vmath.h>
     4.8 +
     4.9 +class Camera {
    4.10 +protected:
    4.11 +	float roll;
    4.12 +
    4.13 +	mutable struct {
    4.14 +		bool valid;
    4.15 +		Matrix4x4 mat;
    4.16 +	} mcache, mcache_inv;
    4.17 +
    4.18 +	virtual void calc_matrix(Matrix4x4 *mat) const = 0;
    4.19 +	virtual void calc_inv_matrix(Matrix4x4 *mat) const;
    4.20 +
    4.21 +	void inval_cache() { mcache.valid = mcache_inv.valid = false; }
    4.22 +	void set_glmat(const Matrix4x4 &m) const;
    4.23 +
    4.24 +public:
    4.25 +	Camera();
    4.26 +	virtual ~Camera();
    4.27 +
    4.28 +	const Matrix4x4 &matrix() const;
    4.29 +	const Matrix4x4 &inv_matrix() const;
    4.30 +
    4.31 +	void use() const;
    4.32 +	void use_inverse() const;
    4.33 +
    4.34 +	// these do nothing, override to provide input handling
    4.35 +	virtual void input_move(float x, float y, float z);
    4.36 +	virtual void input_rotate(float x, float y, float z);
    4.37 +	virtual void input_zoom(float factor);
    4.38 +};
    4.39 +
    4.40 +class OrbitCamera : public Camera {
    4.41 +protected:
    4.42 +	float theta, phi, rad;
    4.43 +
    4.44 +	void calc_matrix(Matrix4x4 *mat) const;
    4.45 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.46 +
    4.47 +public:
    4.48 +	OrbitCamera();
    4.49 +	virtual ~OrbitCamera();
    4.50 +
    4.51 +	void input_rotate(float x, float y, float z);
    4.52 +	void input_zoom(float factor);
    4.53 +};
    4.54 +
    4.55 +class FpsCamera : public OrbitCamera {
    4.56 +protected:
    4.57 +	Vector3 pos;
    4.58 +
    4.59 +	void calc_matrix(Matrix4x4 *mat) const;
    4.60 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.61 +
    4.62 +public:
    4.63 +	void input_move(float x, float y, float z);
    4.64 +
    4.65 +	const Vector3 &get_position() const;
    4.66 +};
    4.67 +
    4.68 +class FlyCamera : public Camera {
    4.69 +private:
    4.70 +	Vector3 pos;
    4.71 +	Quaternion rot;
    4.72 +
    4.73 +	void calc_matrix(Matrix4x4 *mat) const;
    4.74 +	//void calc_inv_matrix(Matrix4x4 *mat) const;
    4.75 +
    4.76 +public:
    4.77 +	FlyCamera();
    4.78 +
    4.79 +	const Vector3 &get_position() const;
    4.80 +	const Quaternion &get_rotation() const;
    4.81 +
    4.82 +	void input_move(float x, float y, float z);
    4.83 +	void input_rotate(float x, float y, float z);
    4.84 +};
    4.85 +
    4.86 +
    4.87 +class VRFpsCamera : public FpsCamera {
    4.88 +private:
    4.89 +	float neck_eye_dist;
    4.90 +	float prev_angles[3];
    4.91 +
    4.92 +	void calc_matrix(Matrix4x4 *mat) const;
    4.93 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.94 +
    4.95 +public:
    4.96 +	VRFpsCamera();
    4.97 +
    4.98 +	void track_vr();
    4.99 +};
   4.100 +
   4.101 +#endif	// CAMERA_H_
     5.1 --- a/src/goat3dgfx.cc	Sun Nov 24 13:30:44 2013 +0200
     5.2 +++ b/src/goat3dgfx.cc	Sun Nov 24 14:00:14 2013 +0200
     5.3 @@ -1,4 +1,7 @@
     5.4 +#include "config.h"
     5.5  #include "goat3dgfx.h"
     5.6 +#include "vr.h"
     5.7 +#include "logger.h"
     5.8  
     5.9  bool init_goat_graphics()
    5.10  {
    5.11 @@ -6,6 +9,13 @@
    5.12  
    5.13  	glewInit();
    5.14  
    5.15 +#ifdef USE_VR
    5.16 +	if(vr_init() == -1) {
    5.17 +		log_fatal("failed to initialize the VR system\n");
    5.18 +		return false;
    5.19 +	}
    5.20 +#endif
    5.21 +
    5.22  	return true;
    5.23  }
    5.24  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/vr.h	Sun Nov 24 14:00:14 2013 +0200
     6.3 @@ -0,0 +1,63 @@
     6.4 +#ifndef GOAT3DGFX_VR_H_
     6.5 +#define GOAT3DGFX_VR_H_
     6.6 +
     6.7 +/* VR mode init options */
     6.8 +enum vr_init_mode {
     6.9 +	VR_INIT_NONE,
    6.10 +	VR_INIT_OCULUS,
    6.11 +	VR_INIT_STEREO
    6.12 +};
    6.13 +
    6.14 +/* possible eye values */
    6.15 +enum {
    6.16 +	VR_EYE_CENTER,
    6.17 +	VR_EYE_LEFT,
    6.18 +	VR_EYE_RIGHT
    6.19 +};
    6.20 +
    6.21 +#ifdef __cplusplus
    6.22 +extern "C" {
    6.23 +#endif
    6.24 +
    6.25 +int vr_init(enum vr_init_mode mode);
    6.26 +void vr_shutdown(void);
    6.27 +
    6.28 +const char *vr_get_display_name(void);
    6.29 +void vr_get_display_pos(int *xptr, int *yptr);
    6.30 +
    6.31 +int vr_get_width(void);
    6.32 +int vr_get_height(void);
    6.33 +
    6.34 +float vr_get_fov(void);
    6.35 +float vr_get_aspect(void);
    6.36 +
    6.37 +void vr_set_eyedist(float ipd);
    6.38 +float vr_get_eyedist(void);
    6.39 +
    6.40 +/* expects an array of 4 barrel distortion coefficients:
    6.41 + * polar scale: k_0 + k_1 r^2 + k_2 r^4 + k_3 r^6
    6.42 + */
    6.43 +void vr_set_distort(const float *coef);
    6.44 +void vr_get_distort(float *coef);
    6.45 +
    6.46 +void vr_set_prediction_sec(float dt);
    6.47 +float vr_get_prediction_sec(void);
    6.48 +
    6.49 +void vr_get_view_matrix(float *res, int eye);
    6.50 +void vr_get_proj_matrix(float *res, int eye);
    6.51 +
    6.52 +/* expects an array of at least 3 floats (x, y, z, offset). */
    6.53 +void vr_get_translation(float *offs);
    6.54 +/* expects an array of at least 4 floats (x, y, z, w, quaternion). */
    6.55 +void vr_get_rotation(float *quat);
    6.56 +/* expects an array of at least 3 floats (pitch, yaw, roll, angles). */
    6.57 +void vr_get_rotation_euler(float *euler);
    6.58 +
    6.59 +/* OpenGL stuff */
    6.60 +void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y);
    6.61 +
    6.62 +#ifdef __cplusplus
    6.63 +}
    6.64 +#endif
    6.65 +
    6.66 +#endif	/* GOAT3DGFX_VR_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/vr/vr.cc	Sun Nov 24 14:00:14 2013 +0200
     7.3 @@ -0,0 +1,384 @@
     7.4 +#include <stdio.h>
     7.5 +#include <GL/glew.h>
     7.6 +#include "vr.h"
     7.7 +#include "vr_impl.h"
     7.8 +#include "vr_sdr.h"
     7.9 +
    7.10 +#ifndef WIN32
    7.11 +#include <alloca.h>
    7.12 +#else
    7.13 +#include <malloc.h>
    7.14 +#endif
    7.15 +
    7.16 +static void init_ctx();
    7.17 +static bool init_ovr();
    7.18 +static bool init_sdr();
    7.19 +
    7.20 +VRContext vr_ctx;
    7.21 +static unsigned int sdrprog;
    7.22 +
    7.23 +extern "C" int vr_init(enum vr_init_mode mode)
    7.24 +{
    7.25 +	init_ctx();
    7.26 +
    7.27 +	if(!init_ovr()) {
    7.28 +		return -1;
    7.29 +	}
    7.30 +
    7.31 +	if(!init_sdr()) {
    7.32 +		return -1;
    7.33 +	}
    7.34 +
    7.35 +	return 0;
    7.36 +}
    7.37 +
    7.38 +extern "C" void vr_shutdown(void)
    7.39 +{
    7.40 +	delete [] vr_ctx.info.display;
    7.41 +	//System::Destroy();
    7.42 +}
    7.43 +
    7.44 +static void init_ctx()
    7.45 +{
    7.46 +	vr_ctx.info.width = 1280;
    7.47 +	vr_ctx.info.height = 800;
    7.48 +	vr_ctx.info.fov = M_PI / 2.0;
    7.49 +	vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
    7.50 +	vr_ctx.info.ipd = 0.035;
    7.51 +	vr_ctx.info.scale = 1.0;
    7.52 +}
    7.53 +
    7.54 +static bool init_ovr()
    7.55 +{
    7.56 +	LogMaskConstants log_level = LogMask_All;
    7.57 +	// initialize Oculus SDK
    7.58 +	const char *logenv = getenv("VR_LOGLEVEL");
    7.59 +	if(logenv) {
    7.60 +		switch(atoi(logenv)) {
    7.61 +		case 0:
    7.62 +			log_level = LogMask_None;
    7.63 +			break;
    7.64 +		case 1:
    7.65 +			log_level = LogMask_Regular;
    7.66 +			break;
    7.67 +		case 2:
    7.68 +		default:
    7.69 +			log_level = LogMask_All;
    7.70 +			break;
    7.71 +		}
    7.72 +	}
    7.73 +
    7.74 +	System::Init(Log::ConfigureDefaultLog(log_level));
    7.75 +	if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
    7.76 +		fprintf(stderr, "failed to create OVR device manager\n");
    7.77 +		return false;
    7.78 +	}
    7.79 +
    7.80 +	// create the display device
    7.81 +	HMDInfo info;
    7.82 +	if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
    7.83 +		fprintf(stderr, "no oculus rift devices found\n");
    7.84 +	} else {
    7.85 +		if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
    7.86 +			printf("oculus device info:\n");
    7.87 +			printf("  name: %s\n", info.DisplayDeviceName);
    7.88 +			printf("  ipd: %f\n", info.InterpupillaryDistance);
    7.89 +			printf("  distortion: %f %f %f %f\n", info.DistortionK[0],
    7.90 +					info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
    7.91 +		}
    7.92 +
    7.93 +		// calculate and store viewing parameters
    7.94 +		vr_ctx.info.width = info.HResolution;
    7.95 +		vr_ctx.info.height = info.VResolution;
    7.96 +		vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
    7.97 +
    7.98 +		vr_ctx.info.ipd = info.InterpupillaryDistance;
    7.99 +		for(int i=0; i<4; i++) {
   7.100 +			vr_ctx.info.distort[i] = info.DistortionK[i];
   7.101 +		}
   7.102 +
   7.103 +		Util::Render::StereoConfig stereohelp;
   7.104 +		stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
   7.105 +		stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
   7.106 +		stereohelp.SetHMDInfo(info);
   7.107 +		stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
   7.108 +
   7.109 +		vr_ctx.info.scale = stereohelp.GetDistortionScale();
   7.110 +
   7.111 +		float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
   7.112 +		vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
   7.113 +
   7.114 +		vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
   7.115 +
   7.116 +		// calculate center of projection shift to match the lens positions
   7.117 +		float center_dist_meters = info.HScreenSize * 0.25;
   7.118 +		float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
   7.119 +		vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
   7.120 +
   7.121 +		// grab the display info
   7.122 +		vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
   7.123 +		strcpy(vr_ctx.info.display, info.DisplayDeviceName);
   7.124 +
   7.125 +		vr_ctx.info.display_xoffs = info.DesktopX;
   7.126 +		vr_ctx.info.display_yoffs = info.DesktopY;
   7.127 +
   7.128 +		printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
   7.129 +				vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
   7.130 +	}
   7.131 +
   7.132 +	// get the sensor device
   7.133 +	if(vr_ctx.ovr_hmd_dev) {
   7.134 +		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
   7.135 +			fprintf(stderr, "failed to get oculus sensor device\n");
   7.136 +		}
   7.137 +	} else {
   7.138 +		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
   7.139 +			fprintf(stderr, "failed to get oculus sensor device\n");
   7.140 +		}
   7.141 +	}
   7.142 +
   7.143 +	if(vr_ctx.ovr_sensor_dev) {
   7.144 +		SensorInfo sinfo;
   7.145 +		if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
   7.146 +			printf("oculus sensor device info:\n");
   7.147 +			printf("  name: %s\n", sinfo.ProductName);
   7.148 +		}
   7.149 +
   7.150 +		vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
   7.151 +	}
   7.152 +	return true;
   7.153 +}
   7.154 +
   7.155 +#undef EXTERNAL_SHADER
   7.156 +
   7.157 +static bool init_sdr()
   7.158 +{
   7.159 +	int status;
   7.160 +
   7.161 +#ifdef EXTERNAL_SHADER
   7.162 +	FILE *fp = fopen("sdr/sdr.glsl", "rb");
   7.163 +	if(!fp) {
   7.164 +		perror("failed to load sdr.glsl");
   7.165 +		return false;
   7.166 +	}
   7.167 +	fseek(fp, 0, SEEK_END);
   7.168 +	long sz = ftell(fp);
   7.169 +	rewind(fp);
   7.170 +
   7.171 +	char *buf = (char*)alloca(sz + 1);
   7.172 +	fread(buf, 1, sz, fp);
   7.173 +	buf[sz] = 0;
   7.174 +	sdr_src = buf;
   7.175 +
   7.176 +	fclose(fp);
   7.177 +#endif
   7.178 +
   7.179 +	unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
   7.180 +	glShaderSource(sdr, 1, &sdr_src, 0);
   7.181 +	glCompileShader(sdr);
   7.182 +	glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
   7.183 +	if(!status) {
   7.184 +		fprintf(stderr, "failed to compile distortion shader\n");
   7.185 +
   7.186 +		int loglen;
   7.187 +		glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
   7.188 +
   7.189 +		if(loglen > 0) {
   7.190 +			char *log = (char*)alloca(loglen);
   7.191 +			glGetShaderInfoLog(sdr, loglen, &loglen, log);
   7.192 +			fprintf(stderr, "%s\n", log);
   7.193 +		}
   7.194 +
   7.195 +		return false;
   7.196 +	}
   7.197 +
   7.198 +	sdrprog = glCreateProgram();
   7.199 +	glAttachShader(sdrprog, sdr);
   7.200 +	glLinkProgram(sdrprog);
   7.201 +	if(!status) {
   7.202 +		fprintf(stderr, "failed to link distortion shader program\n");
   7.203 +		glDeleteShader(sdr);
   7.204 +		return false;
   7.205 +	}
   7.206 +
   7.207 +	int loc;
   7.208 +
   7.209 +	glUseProgram(sdrprog);
   7.210 +
   7.211 +	if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
   7.212 +		glUniform1i(loc, 0);
   7.213 +	}
   7.214 +	if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   7.215 +		glUniform1f(loc, 0);
   7.216 +	}
   7.217 +	if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
   7.218 +		glUniform2f(loc, 0, 0);
   7.219 +	}
   7.220 +	if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
   7.221 +		glUniform1f(loc, vr_ctx.info.scale);
   7.222 +	}
   7.223 +	if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
   7.224 +		printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
   7.225 +		glUniform1f(loc, vr_ctx.info.aspect / 2.0);
   7.226 +	}
   7.227 +	if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
   7.228 +		glUniform2f(loc, 1, 1);
   7.229 +	}
   7.230 +	if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
   7.231 +		glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
   7.232 +				vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
   7.233 +	}
   7.234 +
   7.235 +	return true;
   7.236 +}
   7.237 +
   7.238 +extern "C" const char *vr_get_display_name(void)
   7.239 +{
   7.240 +	return vr_ctx.info.display;
   7.241 +}
   7.242 +
   7.243 +extern "C" void vr_get_display_pos(int *xptr, int *yptr)
   7.244 +{
   7.245 +	*xptr = vr_ctx.info.display_xoffs;
   7.246 +	*yptr = vr_ctx.info.display_yoffs;
   7.247 +}
   7.248 +
   7.249 +extern "C" int vr_get_width(void)
   7.250 +{
   7.251 +	return vr_ctx.info.width;
   7.252 +}
   7.253 +
   7.254 +extern "C" int vr_get_height(void)
   7.255 +{
   7.256 +	return vr_ctx.info.height;
   7.257 +}
   7.258 +
   7.259 +extern "C" float vr_get_fov(void)
   7.260 +{
   7.261 +	return vr_ctx.info.fov;
   7.262 +}
   7.263 +
   7.264 +extern "C" float vr_get_aspect(void)
   7.265 +{
   7.266 +	return vr_ctx.info.aspect;
   7.267 +}
   7.268 +
   7.269 +extern "C" void vr_set_eyedist(float ipd)
   7.270 +{
   7.271 +	vr_ctx.info.ipd = ipd;
   7.272 +}
   7.273 +
   7.274 +extern "C" float vr_get_eyedist(void)
   7.275 +{
   7.276 +	return vr_ctx.info.ipd;
   7.277 +}
   7.278 +
   7.279 +extern "C" void vr_set_distort(const float *coef)
   7.280 +{
   7.281 +	memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
   7.282 +}
   7.283 +
   7.284 +extern "C" void vr_get_distort(float *coef)
   7.285 +{
   7.286 +	memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
   7.287 +}
   7.288 +
   7.289 +extern "C" void vr_set_prediction_sec(float dt)
   7.290 +{
   7.291 +	vr_ctx.ovr_sfusion.SetPrediction(dt);
   7.292 +}
   7.293 +
   7.294 +extern "C" float vr_get_prediction_sec(void)
   7.295 +{
   7.296 +	return vr_ctx.ovr_sfusion.GetPredictionDelta();
   7.297 +}
   7.298 +
   7.299 +extern "C" void vr_get_view_matrix(float *res, int eye)
   7.300 +{
   7.301 +	// TODO
   7.302 +}
   7.303 +
   7.304 +extern "C" void vr_get_proj_matrix(float *res, int eye)
   7.305 +{
   7.306 +	static float eye_scale[] = {0.0, 1.0, -1.0};
   7.307 +
   7.308 +	Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
   7.309 +	proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
   7.310 +
   7.311 +	memcpy(res, proj.M[0], 16 * sizeof(float));
   7.312 +}
   7.313 +
   7.314 +extern "C" void vr_get_translation(float *offs)
   7.315 +{
   7.316 +	// current oculus devkit doesn't do translation
   7.317 +	offs[0] = offs[1] = offs[2] = 0.0f;
   7.318 +}
   7.319 +
   7.320 +extern "C" void vr_get_rotation(float *quat)
   7.321 +{
   7.322 +	Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
   7.323 +	quat[0] = oq.x;
   7.324 +	quat[1] = oq.y;
   7.325 +	quat[2] = oq.z;
   7.326 +	quat[3] = oq.w;
   7.327 +}
   7.328 +
   7.329 +extern "C" void vr_get_rotation_euler(float *euler)
   7.330 +{
   7.331 +	Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
   7.332 +	oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
   7.333 +}
   7.334 +
   7.335 +extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
   7.336 +{
   7.337 +	static const float rects[3][4] = {
   7.338 +		{-1, -1, 1, 1},
   7.339 +		{-1, -1, 0, 1},
   7.340 +		{0, -1, 1, 1}
   7.341 +	};
   7.342 +	static const float offs_scale[3] = {0.0, -1.0, 1.0};
   7.343 +
   7.344 +	glPushAttrib(GL_ENABLE_BIT);
   7.345 +	glDisable(GL_DEPTH_TEST);
   7.346 +	glDisable(GL_LIGHTING);
   7.347 +	glEnable(GL_TEXTURE_2D);
   7.348 +
   7.349 +	glMatrixMode(GL_MODELVIEW);
   7.350 +	glPushMatrix();
   7.351 +	glLoadIdentity();
   7.352 +
   7.353 +	glMatrixMode(GL_PROJECTION);
   7.354 +	glPushMatrix();
   7.355 +	glLoadIdentity();
   7.356 +
   7.357 +	glUseProgram(sdrprog);
   7.358 +
   7.359 +	if(sdrprog) {
   7.360 +		int loc;
   7.361 +		if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   7.362 +			float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
   7.363 +			glUniform1f(loc, offset);
   7.364 +		}
   7.365 +
   7.366 +		if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
   7.367 +			glUniform2f(loc, tex_scale_x, tex_scale_y);
   7.368 +		}
   7.369 +	}
   7.370 +
   7.371 +	glBindTexture(GL_TEXTURE_2D, tex);
   7.372 +	glBegin(GL_QUADS);
   7.373 +	glColor4f(1, 1, 1, 1);
   7.374 +	glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
   7.375 +	glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
   7.376 +	glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
   7.377 +	glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
   7.378 +	glEnd();
   7.379 +
   7.380 +	glUseProgram(0);
   7.381 +
   7.382 +	glPopMatrix();
   7.383 +	glMatrixMode(GL_MODELVIEW);
   7.384 +	glPopMatrix();
   7.385 +
   7.386 +	glPopAttrib();
   7.387 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/vr/vr_impl.h	Sun Nov 24 14:00:14 2013 +0200
     8.3 @@ -0,0 +1,36 @@
     8.4 +#ifndef VR_IMPL_H_
     8.5 +#define VR_IMPL_H_
     8.6 +
     8.7 +#include <OVR.h>
     8.8 +
     8.9 +using namespace OVR;
    8.10 +
    8.11 +struct VRContext {
    8.12 +	DeviceManager *ovr_devman;
    8.13 +	HMDDevice *ovr_hmd_dev;
    8.14 +	SensorDevice *ovr_sensor_dev;
    8.15 +	SensorFusion ovr_sfusion;
    8.16 +
    8.17 +	struct {
    8.18 +		char *display;
    8.19 +		int display_xoffs, display_yoffs;
    8.20 +
    8.21 +		// the full width and height of the display (both eyes)
    8.22 +		int width, height;
    8.23 +		float fov;
    8.24 +		// the full aspect ratio of the display (both eyes)
    8.25 +		float aspect;
    8.26 +		float ipd;
    8.27 +		float distort[4];
    8.28 +		// the right lens center offset (negate for left)
    8.29 +		float lens_center_offset;
    8.30 +		float proj_center_offset;
    8.31 +		float scale;	// scaling to be applied to the two views to fill the screen
    8.32 +	} info;
    8.33 +};
    8.34 +
    8.35 +extern VRContext vr_ctx;
    8.36 +
    8.37 +bool vr_gl_init();
    8.38 +
    8.39 +#endif	// VR_IMPL_H_
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/vr/vr_sdr.h	Sun Nov 24 14:00:14 2013 +0200
     9.3 @@ -0,0 +1,45 @@
     9.4 +static const char *sdr_src =
     9.5 +	"uniform sampler2D tex;\n"
     9.6 +	"uniform float aspect, scale;\n"
     9.7 +	"uniform float lens_center_offset;\n"
     9.8 +	"uniform vec4 dist_factors;\n"
     9.9 +	"\n"
    9.10 +	"vec2 distort_texcoords(in vec2 tc);\n"
    9.11 +	"float barrel_scale(float x, in vec4 k);\n"
    9.12 +	"\n"
    9.13 +	"void main()\n"
    9.14 +	"{\n"
    9.15 +	"	vec2 tc = distort_texcoords(gl_TexCoord[0].xy);\n"
    9.16 +	"\n"
    9.17 +	"	float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;\n"
    9.18 +	"\n"
    9.19 +	"	gl_FragColor.rgb = texture2D(tex, tc).rgb * vis;\n"
    9.20 +	"	gl_FragColor.a = 1.0;\n"
    9.21 +	"}\n"
    9.22 +	"\n"
    9.23 +	"vec2 distort_texcoords(in vec2 tc)\n"
    9.24 +	"{\n"
    9.25 +	"	// map tc [0, 1] -> [-1, 1]\n"
    9.26 +	"	vec2 pt = tc * 2.0 - 1.0;\n"
    9.27 +	"\n"
    9.28 +	"	pt.x += lens_center_offset * 2.0;\n"
    9.29 +	"	pt.y /= aspect;	// correct for aspect ratio\n"
    9.30 +	"\n"
    9.31 +	"	float rad = barrel_scale(dot(pt, pt), dist_factors);\n"
    9.32 +	"	pt *= rad;	// scale the point by the computer distortion radius\n"
    9.33 +	"\n"
    9.34 +	"	pt /= scale;\n"
    9.35 +	"	pt.y *= aspect;\n"
    9.36 +	"	pt.x -= lens_center_offset * 2.0;\n"
    9.37 +	"\n"
    9.38 +	"	// map back to range [0, 1]\n"
    9.39 +	"	return pt * 0.5 + 0.5;\n"
    9.40 +	"}\n"
    9.41 +	"\n"
    9.42 +	"float barrel_scale(float rad, in vec4 k)\n"
    9.43 +	"{\n"
    9.44 +	"	float radsq = rad * rad;\n"
    9.45 +	"	float radquad = radsq * radsq;\n"
    9.46 +	"	return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq;\n"
    9.47 +	"}\n";
    9.48 +