symmetry

changeset 0:a90a71a74f0b

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Feb 2014 19:53:34 +0200
parents
children 46fe847bba08
files .hgignore Makefile src/camera.cc src/camera.h src/main.cc src/opengl.cc src/opengl.h src/vr.h src/vr/vr.cc src/vr/vr_impl.h src/vr/vr_sdr.h
diffstat 11 files changed, 1179 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Tue Feb 25 19:53:34 2014 +0200
     1.3 @@ -0,0 +1,10 @@
     1.4 +\.o$
     1.5 +\.d$
     1.6 +\.swp$
     1.7 +\.suo$
     1.8 +\.obj$
     1.9 +\.exe$
    1.10 +Debug/
    1.11 +Release/
    1.12 +\.user$
    1.13 +symmetry$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Tue Feb 25 19:53:34 2014 +0200
     2.3 @@ -0,0 +1,31 @@
     2.4 +src = $(wildcard src/*.cc) $(wildcard src/vr/*.cc)
     2.5 +csrc = $(wildcard src/*.c) $(wildcard src/vr/*.c)
     2.6 +obj = $(src:.cc=.o) $(csrc:.c=.o)
     2.7 +dep = $(obj:.o=.d)
     2.8 +bin = symmetry
     2.9 +
    2.10 +CFLAGS = -pedantic -Wall -g -Isrc
    2.11 +CXXFLAGS = $(CFLAGS)
    2.12 +LDFLAGS = $(libgl) $(libovr) -lvmath -limago -lm
    2.13 +
    2.14 +ifeq ($(shell uname -s), Darwin)
    2.15 +	libgl = -framework OpenGL -framework GLUT -lGLEW
    2.16 +else
    2.17 +	libgl = -lX11 -lGL -lGLU -lglut -lGLEW
    2.18 +	libovr = -lXinerama -lovr -lpthread -ludev
    2.19 +endif
    2.20 +
    2.21 +$(bin): $(obj)
    2.22 +	$(CXX) -o $@ $(obj) $(LDFLAGS)
    2.23 +
    2.24 +-include $(dep)
    2.25 +
    2.26 +%.d: %.c
    2.27 +	@$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.28 +
    2.29 +%.d: %.cc
    2.30 +	@$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@
    2.31 +
    2.32 +.PHONY: clean
    2.33 +clean:
    2.34 +	rm -f $(obj) $(bin) $(dep)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/camera.cc	Tue Feb 25 19:53:34 2014 +0200
     3.3 @@ -0,0 +1,240 @@
     3.4 +#include "opengl.h"
     3.5 +#include "camera.h"
     3.6 +//#include "unistate.h"
     3.7 +#include "vr.h"
     3.8 +
     3.9 +using namespace goatgfx;
    3.10 +
    3.11 +Camera::Camera()
    3.12 +{
    3.13 +	roll = 0.0;
    3.14 +	inval_cache();
    3.15 +}
    3.16 +
    3.17 +Camera::~Camera()
    3.18 +{
    3.19 +}
    3.20 +
    3.21 +void Camera::calc_inv_matrix(Matrix4x4 *mat) const
    3.22 +{
    3.23 +	*mat = matrix().inverse();
    3.24 +}
    3.25 +
    3.26 +const Matrix4x4 &Camera::matrix() const
    3.27 +{
    3.28 +	if(!mcache.valid) {
    3.29 +		calc_matrix(&mcache.mat);
    3.30 +		mcache.valid = true;
    3.31 +	}
    3.32 +	return mcache.mat;
    3.33 +}
    3.34 +
    3.35 +const Matrix4x4 &Camera::inv_matrix() const
    3.36 +{
    3.37 +	if(!mcache_inv.valid) {
    3.38 +		calc_inv_matrix(&mcache_inv.mat);
    3.39 +		mcache_inv.valid = true;
    3.40 +	}
    3.41 +	return mcache_inv.mat;
    3.42 +}
    3.43 +
    3.44 +void Camera::use() const
    3.45 +{
    3.46 +	//set_view_matrix(matrix());
    3.47 +	mult_matrix(matrix());
    3.48 +}
    3.49 +
    3.50 +void Camera::use_inverse() const
    3.51 +{
    3.52 +	//set_view_matrix(inv_matrix());
    3.53 +	mult_matrix(inv_matrix());
    3.54 +}
    3.55 +
    3.56 +void Camera::input_move(float x, float y, float z)
    3.57 +{
    3.58 +}
    3.59 +
    3.60 +void Camera::input_rotate(float x, float y, float z)
    3.61 +{
    3.62 +}
    3.63 +
    3.64 +void Camera::input_zoom(float factor)
    3.65 +{
    3.66 +}
    3.67 +
    3.68 +
    3.69 +// ---- orbit camera ----
    3.70 +
    3.71 +OrbitCamera::OrbitCamera()
    3.72 +{
    3.73 +	theta = 0.0;
    3.74 +	phi = 0.0;
    3.75 +	rad = 10.0;
    3.76 +}
    3.77 +
    3.78 +OrbitCamera::~OrbitCamera()
    3.79 +{
    3.80 +}
    3.81 +
    3.82 +void OrbitCamera::calc_matrix(Matrix4x4 *mat) const
    3.83 +{
    3.84 +	mat->reset_identity();
    3.85 +	mat->translate(Vector3(0, 0, -rad));
    3.86 +	mat->rotate(Vector3(phi, 0, 0));
    3.87 +	mat->rotate(Vector3(0, theta, 0));
    3.88 +	mat->rotate(Vector3(0, 0, roll));
    3.89 +}
    3.90 +
    3.91 +void OrbitCamera::calc_inv_matrix(Matrix4x4 *mat) const
    3.92 +{
    3.93 +	mat->reset_identity();
    3.94 +	mat->rotate(Vector3(0, 0, roll));
    3.95 +	mat->rotate(Vector3(0, theta, 0));
    3.96 +	mat->rotate(Vector3(phi, 0, 0));
    3.97 +	mat->translate(Vector3(0, 0, -rad));
    3.98 +}
    3.99 +
   3.100 +void OrbitCamera::input_rotate(float x, float y, float z)
   3.101 +{
   3.102 +	theta += y;
   3.103 +	phi += x;
   3.104 +	roll += z;
   3.105 +
   3.106 +	if(phi < -M_PI / 2)
   3.107 +		phi = -M_PI / 2;
   3.108 +	if(phi > M_PI)
   3.109 +		phi = M_PI;
   3.110 +
   3.111 +	inval_cache();
   3.112 +}
   3.113 +
   3.114 +void OrbitCamera::input_zoom(float factor)
   3.115 +{
   3.116 +	rad += factor;
   3.117 +	if(rad < 0.0)
   3.118 +		rad = 0.0;
   3.119 +
   3.120 +	inval_cache();
   3.121 +}
   3.122 +
   3.123 +void FpsCamera::calc_matrix(Matrix4x4 *mat) const
   3.124 +{
   3.125 +	mat->reset_identity();
   3.126 +	mat->translate(Vector3(pos.x, pos.y, pos.z));
   3.127 +	mat->rotate(Vector3(0, theta, 0));
   3.128 +	mat->rotate(Vector3(phi, 0, 0));
   3.129 +	mat->rotate(Vector3(0, 0, roll));
   3.130 +}
   3.131 +
   3.132 +void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.133 +{
   3.134 +	mat->reset_identity();
   3.135 +	mat->rotate(Vector3(0, 0, roll));
   3.136 +	mat->rotate(Vector3(phi, 0, 0));
   3.137 +	mat->rotate(Vector3(0, theta, 0));
   3.138 +	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   3.139 +}
   3.140 +
   3.141 +void FpsCamera::input_move(float x, float y, float z)
   3.142 +{
   3.143 +	pos.x += x * cos(theta) - z * sin(theta);
   3.144 +	pos.z += x * sin(theta) + z * cos(theta);
   3.145 +	pos.y += y;
   3.146 +	inval_cache();
   3.147 +}
   3.148 +
   3.149 +const Vector3 &FpsCamera::get_position() const
   3.150 +{
   3.151 +	return pos;
   3.152 +}
   3.153 +
   3.154 +
   3.155 +FlyCamera::FlyCamera()
   3.156 +{
   3.157 +	pos.z = 10.0f;
   3.158 +}
   3.159 +
   3.160 +void FlyCamera::calc_matrix(Matrix4x4 *mat) const
   3.161 +{
   3.162 +	Matrix3x3 rmat = rot.get_rotation_matrix().transposed();
   3.163 +	Matrix4x4 tmat;
   3.164 +	tmat.set_translation(pos);
   3.165 +	*mat = tmat * Matrix4x4(rmat);
   3.166 +}
   3.167 +
   3.168 +/*void FlyCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.169 +{
   3.170 +}*/
   3.171 +
   3.172 +const Vector3 &FlyCamera::get_position() const
   3.173 +{
   3.174 +	return pos;
   3.175 +}
   3.176 +
   3.177 +const Quaternion &FlyCamera::get_rotation() const
   3.178 +{
   3.179 +	return rot;
   3.180 +}
   3.181 +
   3.182 +void FlyCamera::input_move(float x, float y, float z)
   3.183 +{
   3.184 +	static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0);
   3.185 +
   3.186 +	Vector3 k = vfwd.transformed(rot);
   3.187 +	Vector3	i = vright.transformed(rot);
   3.188 +	Vector3 j = cross_product(k, i);
   3.189 +
   3.190 +	pos += i * x + j * y + k * z;
   3.191 +	inval_cache();
   3.192 +}
   3.193 +
   3.194 +void FlyCamera::input_rotate(float x, float y, float z)
   3.195 +{
   3.196 +	Vector3 axis(x, y, z);
   3.197 +	float axis_len = axis.length();
   3.198 +	rot.rotate(axis / axis_len, axis_len);
   3.199 +	rot.normalize();
   3.200 +
   3.201 +	inval_cache();
   3.202 +}
   3.203 +
   3.204 +
   3.205 +// --- VR additions ---
   3.206 +VRFpsCamera::VRFpsCamera()
   3.207 +{
   3.208 +	neck_eye_dist = 0.14;	// default neck->eye distance 14cm
   3.209 +}
   3.210 +
   3.211 +void VRFpsCamera::calc_matrix(Matrix4x4 *mat) const
   3.212 +{
   3.213 +	mat->reset_identity();
   3.214 +	mat->translate(Vector3(pos.x, pos.y, pos.z));
   3.215 +	mat->rotate(Vector3(0, theta, 0));
   3.216 +	mat->rotate(Vector3(phi, 0, 0));
   3.217 +	mat->rotate(Vector3(0, 0, roll));
   3.218 +	mat->translate(Vector3(0, neck_eye_dist, 0));
   3.219 +}
   3.220 +
   3.221 +void VRFpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   3.222 +{
   3.223 +	mat->reset_identity();
   3.224 +	mat->translate(Vector3(0, -neck_eye_dist, 0));
   3.225 +	mat->rotate(Vector3(0, 0, roll));
   3.226 +	mat->rotate(Vector3(phi, 0, 0));
   3.227 +	mat->rotate(Vector3(0, theta, 0));
   3.228 +	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   3.229 +}
   3.230 +
   3.231 +void VRFpsCamera::track_vr()
   3.232 +{
   3.233 +	float euler[3];
   3.234 +	vr_get_rotation_euler(euler);
   3.235 +
   3.236 +	// input_rotate invalidates cache
   3.237 +	input_rotate(prev_angles[0] - euler[0], prev_angles[1] - euler[1], prev_angles[2] - euler[2]);
   3.238 +
   3.239 +	prev_angles[0] = euler[0];
   3.240 +	prev_angles[1] = euler[1];
   3.241 +	prev_angles[2] = euler[2];
   3.242 +}
   3.243 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/camera.h	Tue Feb 25 19:53:34 2014 +0200
     4.3 @@ -0,0 +1,102 @@
     4.4 +#ifndef CAMERA_H_
     4.5 +#define CAMERA_H_
     4.6 +
     4.7 +#include <vmath/vmath.h>
     4.8 +
     4.9 +namespace goatgfx {
    4.10 +
    4.11 +class Camera {
    4.12 +protected:
    4.13 +	float roll;
    4.14 +
    4.15 +	mutable struct {
    4.16 +		bool valid;
    4.17 +		Matrix4x4 mat;
    4.18 +	} mcache, mcache_inv;
    4.19 +
    4.20 +	virtual void calc_matrix(Matrix4x4 *mat) const = 0;
    4.21 +	virtual void calc_inv_matrix(Matrix4x4 *mat) const;
    4.22 +
    4.23 +	void inval_cache() { mcache.valid = mcache_inv.valid = false; }
    4.24 +	void set_glmat(const Matrix4x4 &m) const;
    4.25 +
    4.26 +public:
    4.27 +	Camera();
    4.28 +	virtual ~Camera();
    4.29 +
    4.30 +	const Matrix4x4 &matrix() const;
    4.31 +	const Matrix4x4 &inv_matrix() const;
    4.32 +
    4.33 +	void use() const;
    4.34 +	void use_inverse() const;
    4.35 +
    4.36 +	// these do nothing, override to provide input handling
    4.37 +	virtual void input_move(float x, float y, float z);
    4.38 +	virtual void input_rotate(float x, float y, float z);
    4.39 +	virtual void input_zoom(float factor);
    4.40 +};
    4.41 +
    4.42 +class OrbitCamera : public Camera {
    4.43 +protected:
    4.44 +	float theta, phi, rad;
    4.45 +
    4.46 +	void calc_matrix(Matrix4x4 *mat) const;
    4.47 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.48 +
    4.49 +public:
    4.50 +	OrbitCamera();
    4.51 +	virtual ~OrbitCamera();
    4.52 +
    4.53 +	void input_rotate(float x, float y, float z);
    4.54 +	void input_zoom(float factor);
    4.55 +};
    4.56 +
    4.57 +class FpsCamera : public OrbitCamera {
    4.58 +protected:
    4.59 +	Vector3 pos;
    4.60 +
    4.61 +	void calc_matrix(Matrix4x4 *mat) const;
    4.62 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.63 +
    4.64 +public:
    4.65 +	void input_move(float x, float y, float z);
    4.66 +
    4.67 +	const Vector3 &get_position() const;
    4.68 +};
    4.69 +
    4.70 +class FlyCamera : public Camera {
    4.71 +private:
    4.72 +	Vector3 pos;
    4.73 +	Quaternion rot;
    4.74 +
    4.75 +	void calc_matrix(Matrix4x4 *mat) const;
    4.76 +	//void calc_inv_matrix(Matrix4x4 *mat) const;
    4.77 +
    4.78 +public:
    4.79 +	FlyCamera();
    4.80 +
    4.81 +	const Vector3 &get_position() const;
    4.82 +	const Quaternion &get_rotation() const;
    4.83 +
    4.84 +	void input_move(float x, float y, float z);
    4.85 +	void input_rotate(float x, float y, float z);
    4.86 +};
    4.87 +
    4.88 +
    4.89 +class VRFpsCamera : public FpsCamera {
    4.90 +private:
    4.91 +	float neck_eye_dist;
    4.92 +	float prev_angles[3];
    4.93 +
    4.94 +	void calc_matrix(Matrix4x4 *mat) const;
    4.95 +	void calc_inv_matrix(Matrix4x4 *mat) const;
    4.96 +
    4.97 +public:
    4.98 +	VRFpsCamera();
    4.99 +
   4.100 +	void track_vr();
   4.101 +};
   4.102 +
   4.103 +}	// namespace goatgfx
   4.104 +
   4.105 +#endif	// CAMERA_H_
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/main.cc	Tue Feb 25 19:53:34 2014 +0200
     5.3 @@ -0,0 +1,174 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <assert.h>
     5.7 +#include <vector>
     5.8 +#include "opengl.h"
     5.9 +#include "camera.h"
    5.10 +
    5.11 +static bool init();
    5.12 +static void cleanup();
    5.13 +static void handle_input(float dt);
    5.14 +static void disp();
    5.15 +static void idle();
    5.16 +static void reshape(int x, int y);
    5.17 +static void keypress(unsigned char key, int x, int y);
    5.18 +static void keyrelease(unsigned char key, int x, int y);
    5.19 +static void mouse(int bn, int st, int x, int y);
    5.20 +static void motion(int x, int y);
    5.21 +
    5.22 +static goatgfx::VRFpsCamera cam;
    5.23 +static std::vector<bool> keystate(256);
    5.24 +
    5.25 +int main(int argc, char **argv)
    5.26 +{
    5.27 +	glutInitWindowSize(800, 600);
    5.28 +	glutInit(&argc, argv);
    5.29 +	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    5.30 +	glutCreateWindow("symmetry");
    5.31 +
    5.32 +	glutDisplayFunc(disp);
    5.33 +	glutIdleFunc(idle);
    5.34 +	glutReshapeFunc(reshape);
    5.35 +	glutKeyboardFunc(keypress);
    5.36 +	glutKeyboardUpFunc(keyrelease);
    5.37 +	glutMouseFunc(mouse);
    5.38 +	glutMotionFunc(motion);
    5.39 +
    5.40 +	if(!init()) {
    5.41 +		return 1;
    5.42 +	}
    5.43 +	atexit(cleanup);
    5.44 +
    5.45 +	glutMainLoop();
    5.46 +	return 0;
    5.47 +}
    5.48 +
    5.49 +
    5.50 +static bool init()
    5.51 +{
    5.52 +	glewInit();
    5.53 +
    5.54 +	glEnable(GL_DEPTH_TEST);
    5.55 +	glEnable(GL_CULL_FACE);
    5.56 +
    5.57 +	glEnable(GL_LIGHTING);
    5.58 +	glEnable(GL_LIGHT0);
    5.59 +
    5.60 +	cam.input_move(0, 1.65, 0);
    5.61 +
    5.62 +	return true;
    5.63 +}
    5.64 +
    5.65 +static void cleanup()
    5.66 +{
    5.67 +}
    5.68 +
    5.69 +static void disp()
    5.70 +{
    5.71 +	unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
    5.72 +	static unsigned int prev_msec;
    5.73 +	float dt = (float)(msec - prev_msec) / 1000.0f;
    5.74 +
    5.75 +	handle_input(dt);
    5.76 +
    5.77 +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    5.78 +
    5.79 +	glMatrixMode(GL_MODELVIEW);
    5.80 +	glLoadIdentity();
    5.81 +	cam.use_inverse();
    5.82 +
    5.83 +	glBegin(GL_QUADS);
    5.84 +	glNormal3f(0, 1, 0);
    5.85 +	glVertex3f(-5, 0, 5);
    5.86 +	glVertex3f(5, 0, 5);
    5.87 +	glVertex3f(5, 0, -5);
    5.88 +	glVertex3f(-5, 0, -5);
    5.89 +	glEnd();
    5.90 +
    5.91 +	glFrontFace(GL_CW);
    5.92 +	glutSolidTeapot(1.0);
    5.93 +	glFrontFace(GL_CCW);
    5.94 +
    5.95 +	glutSwapBuffers();
    5.96 +	assert(glGetError() == GL_NO_ERROR);
    5.97 +}
    5.98 +
    5.99 +
   5.100 +static void handle_input(float dt)
   5.101 +{
   5.102 +	Vector3 inpv;
   5.103 +	float offs = dt * 2.0;
   5.104 +
   5.105 +	if(keystate['w'] || keystate['W']) {
   5.106 +		inpv.z -= offs;
   5.107 +	}
   5.108 +	if(keystate['s'] || keystate['S']) {
   5.109 +		inpv.z += offs;
   5.110 +	}
   5.111 +	if(keystate['d'] || keystate['D']) {
   5.112 +		inpv.x += offs;
   5.113 +	}
   5.114 +	if(keystate['a'] || keystate['A']) {
   5.115 +		inpv.x -= offs;
   5.116 +	}
   5.117 +
   5.118 +	cam.input_move(inpv.x, inpv.y, inpv.z);
   5.119 +}
   5.120 +
   5.121 +static void idle()
   5.122 +{
   5.123 +	glutPostRedisplay();
   5.124 +}
   5.125 +
   5.126 +static void reshape(int x, int y)
   5.127 +{
   5.128 +	glViewport(0, 0, x, y);
   5.129 +
   5.130 +	glMatrixMode(GL_PROJECTION);
   5.131 +	glLoadIdentity();
   5.132 +	gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0);
   5.133 +}
   5.134 +
   5.135 +static void keypress(unsigned char key, int x, int y)
   5.136 +{
   5.137 +	keystate[key] = true;
   5.138 +
   5.139 +	switch(key) {
   5.140 +	case 27:
   5.141 +		exit(0);
   5.142 +	}
   5.143 +}
   5.144 +
   5.145 +static void keyrelease(unsigned char key, int x, int y)
   5.146 +{
   5.147 +	keystate[key] = false;
   5.148 +}
   5.149 +
   5.150 +static int prev_x, prev_y;
   5.151 +static bool bnstate[32];
   5.152 +
   5.153 +static void mouse(int bn, int st, int x, int y)
   5.154 +{
   5.155 +	prev_x = x;
   5.156 +	prev_y = y;
   5.157 +	bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
   5.158 +}
   5.159 +
   5.160 +static void motion(int x, int y)
   5.161 +{
   5.162 +	int dx = x - prev_x;
   5.163 +	int dy = y - prev_y;
   5.164 +	prev_x = x;
   5.165 +	prev_y = y;
   5.166 +
   5.167 +	if(!dx && !dy) {
   5.168 +		return;
   5.169 +	}
   5.170 +
   5.171 +	if(bnstate[0]) {
   5.172 +		float dtheta_deg = dy * 0.5;
   5.173 +		float dphi_deg = dx * 0.5;
   5.174 +
   5.175 +		cam.input_rotate(DEG_TO_RAD(dtheta_deg), DEG_TO_RAD(dphi_deg), 0);
   5.176 +	}
   5.177 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/opengl.cc	Tue Feb 25 19:53:34 2014 +0200
     6.3 @@ -0,0 +1,61 @@
     6.4 +#include "opengl.h"
     6.5 +#include <vmath/vmath.h>
     6.6 +
     6.7 +void load_matrix(const Matrix4x4 &m)
     6.8 +{
     6.9 +#ifdef SINGLE_PRECISION_MATH
    6.10 +	if(glLoadTransposeMatrixfARB) {
    6.11 +		glLoadTransposeMatrixfARB((float*)&m);
    6.12 +	} else {
    6.13 +		Matrix4x4 tmat = m.transposed();
    6.14 +		glLoadMatrixf((float*)&tmat);
    6.15 +	}
    6.16 +#else
    6.17 +	if(glLoadTransposeMatrixdARB) {
    6.18 +		glLoadTransposeMatrixdARB((double*)&m);
    6.19 +	} else {
    6.20 +		Matrix4x4 tmat = m.transposed();
    6.21 +		glLoadMatrixd((double*)&tmat);
    6.22 +	}
    6.23 +#endif
    6.24 +}
    6.25 +
    6.26 +void mult_matrix(const Matrix4x4 &m)
    6.27 +{
    6.28 +#ifdef SINGLE_PRECISION_MATH
    6.29 +	if(glMultTransposeMatrixfARB) {
    6.30 +		glMultTransposeMatrixfARB((float*)&m);
    6.31 +	} else {
    6.32 +		Matrix4x4 tmat = m.transposed();
    6.33 +		glMultMatrixf((float*)&tmat);
    6.34 +	}
    6.35 +#else
    6.36 +	if(glMultTransposeMatrixdARB) {
    6.37 +		glMultTransposeMatrixdARB((double*)&m);
    6.38 +	} else {
    6.39 +		Matrix4x4 tmat = m.transposed();
    6.40 +		glMultMatrixd((double*)&tmat);
    6.41 +	}
    6.42 +#endif
    6.43 +}
    6.44 +
    6.45 +const char *strglerr(int err)
    6.46 +{
    6.47 +	static const char *errnames[] = {
    6.48 +		"GL_INVALID_ENUM",
    6.49 +		"GL_INVALID_VALUE",
    6.50 +		"GL_INVALID_OPERATION",
    6.51 +		"GL_STACK_OVERFLOW",
    6.52 +		"GL_STACK_UNDERFLOW",
    6.53 +		"GL_OUT_OF_MEMORY",
    6.54 +		"GL_INVALID_FRAMEBUFFER_OPERATION"
    6.55 +	};
    6.56 +
    6.57 +	if(!err) {
    6.58 +		return "GL_NO_ERROR";
    6.59 +	}
    6.60 +	if(err < GL_INVALID_ENUM || err > GL_OUT_OF_MEMORY) {
    6.61 +		return "<invalid gl error>";
    6.62 +	}
    6.63 +	return errnames[err - GL_INVALID_ENUM];
    6.64 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/opengl.h	Tue Feb 25 19:53:34 2014 +0200
     7.3 @@ -0,0 +1,29 @@
     7.4 +#ifndef OPENGL_H_
     7.5 +#define OPENGL_H_
     7.6 +
     7.7 +#include <GL/glew.h>
     7.8 +
     7.9 +#ifndef __APPLE__
    7.10 +#include <GL/glut.h>
    7.11 +#else
    7.12 +#include <GLUT/glut.h>
    7.13 +#endif
    7.14 +
    7.15 +#define CHECKGLERR	\
    7.16 +	do { \
    7.17 +		int err = glGetError(); \
    7.18 +		if(err) { \
    7.19 +			fprintf(stderr, "%s:%d: OpenGL error 0x%x: %s\n", __FILE__, __LINE__, err, strglerr(err)); \
    7.20 +			abort(); \
    7.21 +		} \
    7.22 +	} while(0)
    7.23 +
    7.24 +
    7.25 +class Matrix4x4;
    7.26 +
    7.27 +void load_matrix(const Matrix4x4 &m);
    7.28 +void mult_matrix(const Matrix4x4 &m);
    7.29 +
    7.30 +const char *strglerr(int err);
    7.31 +
    7.32 +#endif	/* OPENGL_H_ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/vr.h	Tue Feb 25 19:53:34 2014 +0200
     8.3 @@ -0,0 +1,63 @@
     8.4 +#ifndef GOAT3DGFX_VR_H_
     8.5 +#define GOAT3DGFX_VR_H_
     8.6 +
     8.7 +/* VR mode init options */
     8.8 +enum vr_init_mode {
     8.9 +	VR_INIT_NONE,
    8.10 +	VR_INIT_OCULUS,
    8.11 +	VR_INIT_STEREO
    8.12 +};
    8.13 +
    8.14 +/* possible eye values */
    8.15 +enum {
    8.16 +	VR_EYE_CENTER,
    8.17 +	VR_EYE_LEFT,
    8.18 +	VR_EYE_RIGHT
    8.19 +};
    8.20 +
    8.21 +#ifdef __cplusplus
    8.22 +extern "C" {
    8.23 +#endif
    8.24 +
    8.25 +int vr_init(enum vr_init_mode mode);
    8.26 +void vr_shutdown(void);
    8.27 +
    8.28 +const char *vr_get_display_name(void);
    8.29 +void vr_get_display_pos(int *xptr, int *yptr);
    8.30 +
    8.31 +int vr_get_width(void);
    8.32 +int vr_get_height(void);
    8.33 +
    8.34 +float vr_get_fov(void);
    8.35 +float vr_get_aspect(void);
    8.36 +
    8.37 +void vr_set_eyedist(float ipd);
    8.38 +float vr_get_eyedist(void);
    8.39 +
    8.40 +/* expects an array of 4 barrel distortion coefficients:
    8.41 + * polar scale: k_0 + k_1 r^2 + k_2 r^4 + k_3 r^6
    8.42 + */
    8.43 +void vr_set_distort(const float *coef);
    8.44 +void vr_get_distort(float *coef);
    8.45 +
    8.46 +void vr_set_prediction_sec(float dt);
    8.47 +float vr_get_prediction_sec(void);
    8.48 +
    8.49 +void vr_get_view_matrix(float *res, int eye);
    8.50 +void vr_get_proj_matrix(float *res, int eye);
    8.51 +
    8.52 +/* expects an array of at least 3 floats (x, y, z, offset). */
    8.53 +void vr_get_translation(float *offs);
    8.54 +/* expects an array of at least 4 floats (x, y, z, w, quaternion). */
    8.55 +void vr_get_rotation(float *quat);
    8.56 +/* expects an array of at least 3 floats (pitch, yaw, roll, angles). */
    8.57 +void vr_get_rotation_euler(float *euler);
    8.58 +
    8.59 +/* OpenGL stuff */
    8.60 +void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y);
    8.61 +
    8.62 +#ifdef __cplusplus
    8.63 +}
    8.64 +#endif
    8.65 +
    8.66 +#endif	/* GOAT3DGFX_VR_H_ */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/vr/vr.cc	Tue Feb 25 19:53:34 2014 +0200
     9.3 @@ -0,0 +1,388 @@
     9.4 +#include <stdio.h>
     9.5 +#include <GL/glew.h>
     9.6 +#include "vr.h"
     9.7 +#include "vr_impl.h"
     9.8 +#include "vr_sdr.h"
     9.9 +
    9.10 +#ifndef WIN32
    9.11 +#include <alloca.h>
    9.12 +#else
    9.13 +#include <malloc.h>
    9.14 +#endif
    9.15 +
    9.16 +static void init_ctx();
    9.17 +static bool init_ovr();
    9.18 +static bool init_sdr();
    9.19 +
    9.20 +VRContext vr_ctx;
    9.21 +static unsigned int sdrprog;
    9.22 +
    9.23 +extern "C" int vr_init(enum vr_init_mode mode)
    9.24 +{
    9.25 +	init_ctx();
    9.26 +
    9.27 +	if(!init_ovr()) {
    9.28 +		return -1;
    9.29 +	}
    9.30 +
    9.31 +	if(!init_sdr()) {
    9.32 +		return -1;
    9.33 +	}
    9.34 +
    9.35 +	return 0;
    9.36 +}
    9.37 +
    9.38 +extern "C" void vr_shutdown(void)
    9.39 +{
    9.40 +	delete [] vr_ctx.info.display;
    9.41 +	delete vr_ctx.ovr_sfusion;
    9.42 +	//System::Destroy();
    9.43 +
    9.44 +	memset(&vr_ctx, 0, sizeof vr_ctx);
    9.45 +}
    9.46 +
    9.47 +static void init_ctx()
    9.48 +{
    9.49 +	vr_ctx.info.width = 1280;
    9.50 +	vr_ctx.info.height = 800;
    9.51 +	vr_ctx.info.fov = M_PI / 2.0;
    9.52 +	vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
    9.53 +	vr_ctx.info.ipd = 0.035;
    9.54 +	vr_ctx.info.scale = 1.0;
    9.55 +}
    9.56 +
    9.57 +static bool init_ovr()
    9.58 +{
    9.59 +	LogMaskConstants log_level = LogMask_All;
    9.60 +	// initialize Oculus SDK
    9.61 +	const char *logenv = getenv("VR_LOGLEVEL");
    9.62 +	if(logenv) {
    9.63 +		switch(atoi(logenv)) {
    9.64 +		case 0:
    9.65 +			log_level = LogMask_None;
    9.66 +			break;
    9.67 +		case 1:
    9.68 +			log_level = LogMask_Regular;
    9.69 +			break;
    9.70 +		case 2:
    9.71 +		default:
    9.72 +			log_level = LogMask_All;
    9.73 +			break;
    9.74 +		}
    9.75 +	}
    9.76 +
    9.77 +	System::Init(Log::ConfigureDefaultLog(log_level));
    9.78 +	if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
    9.79 +		fprintf(stderr, "failed to create OVR device manager\n");
    9.80 +		return false;
    9.81 +	}
    9.82 +
    9.83 +	// create the display device
    9.84 +	HMDInfo info;
    9.85 +	if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
    9.86 +		fprintf(stderr, "no oculus rift devices found\n");
    9.87 +	} else {
    9.88 +		if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
    9.89 +			printf("oculus device info:\n");
    9.90 +			printf("  name: %s\n", info.DisplayDeviceName);
    9.91 +			printf("  ipd: %f\n", info.InterpupillaryDistance);
    9.92 +			printf("  distortion: %f %f %f %f\n", info.DistortionK[0],
    9.93 +					info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
    9.94 +		}
    9.95 +
    9.96 +		// calculate and store viewing parameters
    9.97 +		vr_ctx.info.width = info.HResolution;
    9.98 +		vr_ctx.info.height = info.VResolution;
    9.99 +		vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
   9.100 +
   9.101 +		vr_ctx.info.ipd = info.InterpupillaryDistance;
   9.102 +		for(int i=0; i<4; i++) {
   9.103 +			vr_ctx.info.distort[i] = info.DistortionK[i];
   9.104 +		}
   9.105 +
   9.106 +		Util::Render::StereoConfig stereohelp;
   9.107 +		stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
   9.108 +		stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
   9.109 +		stereohelp.SetHMDInfo(info);
   9.110 +		stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
   9.111 +
   9.112 +		vr_ctx.info.scale = stereohelp.GetDistortionScale();
   9.113 +
   9.114 +		float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
   9.115 +		vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
   9.116 +
   9.117 +		vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
   9.118 +
   9.119 +		// calculate center of projection shift to match the lens positions
   9.120 +		float center_dist_meters = info.HScreenSize * 0.25;
   9.121 +		float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
   9.122 +		vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
   9.123 +
   9.124 +		// grab the display info
   9.125 +		vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
   9.126 +		strcpy(vr_ctx.info.display, info.DisplayDeviceName);
   9.127 +
   9.128 +		vr_ctx.info.display_xoffs = info.DesktopX;
   9.129 +		vr_ctx.info.display_yoffs = info.DesktopY;
   9.130 +
   9.131 +		printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
   9.132 +				vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
   9.133 +	}
   9.134 +
   9.135 +	// get the sensor device
   9.136 +	if(vr_ctx.ovr_hmd_dev) {
   9.137 +		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
   9.138 +			fprintf(stderr, "failed to get oculus sensor device\n");
   9.139 +		}
   9.140 +	} else {
   9.141 +		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
   9.142 +			fprintf(stderr, "failed to get oculus sensor device\n");
   9.143 +		}
   9.144 +	}
   9.145 +
   9.146 +	if(vr_ctx.ovr_sensor_dev) {
   9.147 +		SensorInfo sinfo;
   9.148 +		if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
   9.149 +			printf("oculus sensor device info:\n");
   9.150 +			printf("  name: %s\n", sinfo.ProductName);
   9.151 +		}
   9.152 +
   9.153 +		vr_ctx.ovr_sfusion = new SensorFusion;
   9.154 +		vr_ctx.ovr_sfusion->AttachToSensor(vr_ctx.ovr_sensor_dev);
   9.155 +	}
   9.156 +	return true;
   9.157 +}
   9.158 +
   9.159 +#undef EXTERNAL_SHADER
   9.160 +
   9.161 +static bool init_sdr()
   9.162 +{
   9.163 +	int status;
   9.164 +
   9.165 +#ifdef EXTERNAL_SHADER
   9.166 +	FILE *fp = fopen("sdr/sdr.glsl", "rb");
   9.167 +	if(!fp) {
   9.168 +		perror("failed to load sdr.glsl");
   9.169 +		return false;
   9.170 +	}
   9.171 +	fseek(fp, 0, SEEK_END);
   9.172 +	long sz = ftell(fp);
   9.173 +	rewind(fp);
   9.174 +
   9.175 +	char *buf = (char*)alloca(sz + 1);
   9.176 +	fread(buf, 1, sz, fp);
   9.177 +	buf[sz] = 0;
   9.178 +	sdr_src = buf;
   9.179 +
   9.180 +	fclose(fp);
   9.181 +#endif
   9.182 +
   9.183 +	unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
   9.184 +	glShaderSource(sdr, 1, &sdr_src, 0);
   9.185 +	glCompileShader(sdr);
   9.186 +	glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
   9.187 +	if(!status) {
   9.188 +		fprintf(stderr, "failed to compile distortion shader\n");
   9.189 +
   9.190 +		int loglen;
   9.191 +		glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
   9.192 +
   9.193 +		if(loglen > 0) {
   9.194 +			char *log = (char*)alloca(loglen);
   9.195 +			glGetShaderInfoLog(sdr, loglen, &loglen, log);
   9.196 +			fprintf(stderr, "%s\n", log);
   9.197 +		}
   9.198 +
   9.199 +		return false;
   9.200 +	}
   9.201 +
   9.202 +	sdrprog = glCreateProgram();
   9.203 +	glAttachShader(sdrprog, sdr);
   9.204 +	glLinkProgram(sdrprog);
   9.205 +	if(!status) {
   9.206 +		fprintf(stderr, "failed to link distortion shader program\n");
   9.207 +		glDeleteShader(sdr);
   9.208 +		return false;
   9.209 +	}
   9.210 +
   9.211 +	int loc;
   9.212 +
   9.213 +	glUseProgram(sdrprog);
   9.214 +
   9.215 +	if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
   9.216 +		glUniform1i(loc, 0);
   9.217 +	}
   9.218 +	if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   9.219 +		glUniform1f(loc, 0);
   9.220 +	}
   9.221 +	if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
   9.222 +		glUniform2f(loc, 0, 0);
   9.223 +	}
   9.224 +	if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
   9.225 +		glUniform1f(loc, vr_ctx.info.scale);
   9.226 +	}
   9.227 +	if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
   9.228 +		printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
   9.229 +		glUniform1f(loc, vr_ctx.info.aspect / 2.0);
   9.230 +	}
   9.231 +	if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
   9.232 +		glUniform2f(loc, 1, 1);
   9.233 +	}
   9.234 +	if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
   9.235 +		glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
   9.236 +				vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
   9.237 +	}
   9.238 +
   9.239 +	return true;
   9.240 +}
   9.241 +
   9.242 +extern "C" const char *vr_get_display_name(void)
   9.243 +{
   9.244 +	return vr_ctx.info.display;
   9.245 +}
   9.246 +
   9.247 +extern "C" void vr_get_display_pos(int *xptr, int *yptr)
   9.248 +{
   9.249 +	*xptr = vr_ctx.info.display_xoffs;
   9.250 +	*yptr = vr_ctx.info.display_yoffs;
   9.251 +}
   9.252 +
   9.253 +extern "C" int vr_get_width(void)
   9.254 +{
   9.255 +	return vr_ctx.info.width;
   9.256 +}
   9.257 +
   9.258 +extern "C" int vr_get_height(void)
   9.259 +{
   9.260 +	return vr_ctx.info.height;
   9.261 +}
   9.262 +
   9.263 +extern "C" float vr_get_fov(void)
   9.264 +{
   9.265 +	return vr_ctx.info.fov;
   9.266 +}
   9.267 +
   9.268 +extern "C" float vr_get_aspect(void)
   9.269 +{
   9.270 +	return vr_ctx.info.aspect;
   9.271 +}
   9.272 +
   9.273 +extern "C" void vr_set_eyedist(float ipd)
   9.274 +{
   9.275 +	vr_ctx.info.ipd = ipd;
   9.276 +}
   9.277 +
   9.278 +extern "C" float vr_get_eyedist(void)
   9.279 +{
   9.280 +	return vr_ctx.info.ipd;
   9.281 +}
   9.282 +
   9.283 +extern "C" void vr_set_distort(const float *coef)
   9.284 +{
   9.285 +	memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
   9.286 +}
   9.287 +
   9.288 +extern "C" void vr_get_distort(float *coef)
   9.289 +{
   9.290 +	memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
   9.291 +}
   9.292 +
   9.293 +extern "C" void vr_set_prediction_sec(float dt)
   9.294 +{
   9.295 +	vr_ctx.ovr_sfusion->SetPrediction(dt);
   9.296 +}
   9.297 +
   9.298 +extern "C" float vr_get_prediction_sec(void)
   9.299 +{
   9.300 +	return vr_ctx.ovr_sfusion->GetPredictionDelta();
   9.301 +}
   9.302 +
   9.303 +extern "C" void vr_get_view_matrix(float *res, int eye)
   9.304 +{
   9.305 +	// TODO
   9.306 +}
   9.307 +
   9.308 +extern "C" void vr_get_proj_matrix(float *res, int eye)
   9.309 +{
   9.310 +	static float eye_scale[] = {0.0, 1.0, -1.0};
   9.311 +
   9.312 +	Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
   9.313 +	proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
   9.314 +
   9.315 +	memcpy(res, proj.M[0], 16 * sizeof(float));
   9.316 +}
   9.317 +
   9.318 +extern "C" void vr_get_translation(float *offs)
   9.319 +{
   9.320 +	// current oculus devkit doesn't do translation
   9.321 +	offs[0] = offs[1] = offs[2] = 0.0f;
   9.322 +}
   9.323 +
   9.324 +extern "C" void vr_get_rotation(float *quat)
   9.325 +{
   9.326 +	Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
   9.327 +	quat[0] = oq.x;
   9.328 +	quat[1] = oq.y;
   9.329 +	quat[2] = oq.z;
   9.330 +	quat[3] = oq.w;
   9.331 +}
   9.332 +
   9.333 +extern "C" void vr_get_rotation_euler(float *euler)
   9.334 +{
   9.335 +	Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
   9.336 +	oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
   9.337 +}
   9.338 +
   9.339 +extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
   9.340 +{
   9.341 +	static const float rects[3][4] = {
   9.342 +		{-1, -1, 1, 1},
   9.343 +		{-1, -1, 0, 1},
   9.344 +		{0, -1, 1, 1}
   9.345 +	};
   9.346 +	static const float offs_scale[3] = {0.0, -1.0, 1.0};
   9.347 +
   9.348 +	glPushAttrib(GL_ENABLE_BIT);
   9.349 +	glDisable(GL_DEPTH_TEST);
   9.350 +	glDisable(GL_LIGHTING);
   9.351 +	glEnable(GL_TEXTURE_2D);
   9.352 +
   9.353 +	glMatrixMode(GL_MODELVIEW);
   9.354 +	glPushMatrix();
   9.355 +	glLoadIdentity();
   9.356 +
   9.357 +	glMatrixMode(GL_PROJECTION);
   9.358 +	glPushMatrix();
   9.359 +	glLoadIdentity();
   9.360 +
   9.361 +	glUseProgram(sdrprog);
   9.362 +
   9.363 +	if(sdrprog) {
   9.364 +		int loc;
   9.365 +		if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   9.366 +			float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
   9.367 +			glUniform1f(loc, offset);
   9.368 +		}
   9.369 +
   9.370 +		if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
   9.371 +			glUniform2f(loc, tex_scale_x, tex_scale_y);
   9.372 +		}
   9.373 +	}
   9.374 +
   9.375 +	glBindTexture(GL_TEXTURE_2D, tex);
   9.376 +	glBegin(GL_QUADS);
   9.377 +	glColor4f(1, 1, 1, 1);
   9.378 +	glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
   9.379 +	glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
   9.380 +	glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
   9.381 +	glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
   9.382 +	glEnd();
   9.383 +
   9.384 +	glUseProgram(0);
   9.385 +
   9.386 +	glPopMatrix();
   9.387 +	glMatrixMode(GL_MODELVIEW);
   9.388 +	glPopMatrix();
   9.389 +
   9.390 +	glPopAttrib();
   9.391 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/vr/vr_impl.h	Tue Feb 25 19:53:34 2014 +0200
    10.3 @@ -0,0 +1,36 @@
    10.4 +#ifndef VR_IMPL_H_
    10.5 +#define VR_IMPL_H_
    10.6 +
    10.7 +#include <OVR.h>
    10.8 +
    10.9 +using namespace OVR;
   10.10 +
   10.11 +struct VRContext {
   10.12 +	DeviceManager *ovr_devman;
   10.13 +	HMDDevice *ovr_hmd_dev;
   10.14 +	SensorDevice *ovr_sensor_dev;
   10.15 +	SensorFusion *ovr_sfusion;
   10.16 +
   10.17 +	struct {
   10.18 +		char *display;
   10.19 +		int display_xoffs, display_yoffs;
   10.20 +
   10.21 +		// the full width and height of the display (both eyes)
   10.22 +		int width, height;
   10.23 +		float fov;
   10.24 +		// the full aspect ratio of the display (both eyes)
   10.25 +		float aspect;
   10.26 +		float ipd;
   10.27 +		float distort[4];
   10.28 +		// the right lens center offset (negate for left)
   10.29 +		float lens_center_offset;
   10.30 +		float proj_center_offset;
   10.31 +		float scale;	// scaling to be applied to the two views to fill the screen
   10.32 +	} info;
   10.33 +};
   10.34 +
   10.35 +extern VRContext vr_ctx;
   10.36 +
   10.37 +bool vr_gl_init();
   10.38 +
   10.39 +#endif	// VR_IMPL_H_
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/vr/vr_sdr.h	Tue Feb 25 19:53:34 2014 +0200
    11.3 @@ -0,0 +1,45 @@
    11.4 +static const char *sdr_src =
    11.5 +	"uniform sampler2D tex;\n"
    11.6 +	"uniform float aspect, scale;\n"
    11.7 +	"uniform float lens_center_offset;\n"
    11.8 +	"uniform vec4 dist_factors;\n"
    11.9 +	"\n"
   11.10 +	"vec2 distort_texcoords(in vec2 tc);\n"
   11.11 +	"float barrel_scale(float x, in vec4 k);\n"
   11.12 +	"\n"
   11.13 +	"void main()\n"
   11.14 +	"{\n"
   11.15 +	"	vec2 tc = distort_texcoords(gl_TexCoord[0].xy);\n"
   11.16 +	"\n"
   11.17 +	"	float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;\n"
   11.18 +	"\n"
   11.19 +	"	gl_FragColor.rgb = texture2D(tex, tc).rgb * vis;\n"
   11.20 +	"	gl_FragColor.a = 1.0;\n"
   11.21 +	"}\n"
   11.22 +	"\n"
   11.23 +	"vec2 distort_texcoords(in vec2 tc)\n"
   11.24 +	"{\n"
   11.25 +	"	// map tc [0, 1] -> [-1, 1]\n"
   11.26 +	"	vec2 pt = tc * 2.0 - 1.0;\n"
   11.27 +	"\n"
   11.28 +	"	pt.x += lens_center_offset * 2.0;\n"
   11.29 +	"	pt.y /= aspect;	// correct for aspect ratio\n"
   11.30 +	"\n"
   11.31 +	"	float rad = barrel_scale(dot(pt, pt), dist_factors);\n"
   11.32 +	"	pt *= rad;	// scale the point by the computer distortion radius\n"
   11.33 +	"\n"
   11.34 +	"	pt /= scale;\n"
   11.35 +	"	pt.y *= aspect;\n"
   11.36 +	"	pt.x -= lens_center_offset * 2.0;\n"
   11.37 +	"\n"
   11.38 +	"	// map back to range [0, 1]\n"
   11.39 +	"	return pt * 0.5 + 0.5;\n"
   11.40 +	"}\n"
   11.41 +	"\n"
   11.42 +	"float barrel_scale(float rad, in vec4 k)\n"
   11.43 +	"{\n"
   11.44 +	"	float radsq = rad * rad;\n"
   11.45 +	"	float radquad = radsq * radsq;\n"
   11.46 +	"	return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq;\n"
   11.47 +	"}\n";
   11.48 +