symmetry

changeset 1:46fe847bba08 tip

using goat3dgfx
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 25 Feb 2014 23:47:20 +0200
parents a90a71a74f0b
children
files Makefile src/camera.cc src/camera.h src/main.cc src/terrain.cc src/terrain.h src/vr.h src/vr/vr.cc src/vr/vr_impl.h src/vr/vr_sdr.h
diffstat 10 files changed, 480 insertions(+), 896 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Tue Feb 25 19:53:34 2014 +0200
     1.2 +++ b/Makefile	Tue Feb 25 23:47:20 2014 +0200
     1.3 @@ -4,9 +4,9 @@
     1.4  dep = $(obj:.o=.d)
     1.5  bin = symmetry
     1.6  
     1.7 -CFLAGS = -pedantic -Wall -g -Isrc
     1.8 +CFLAGS = -pedantic -Wall -g -Isrc `pkg-config --cflags goat3dgfx`
     1.9  CXXFLAGS = $(CFLAGS)
    1.10 -LDFLAGS = $(libgl) $(libovr) -lvmath -limago -lm
    1.11 +LDFLAGS = `pkg-config --libs goat3dgfx`
    1.12  
    1.13  ifeq ($(shell uname -s), Darwin)
    1.14  	libgl = -framework OpenGL -framework GLUT -lGLEW
     2.1 --- a/src/camera.cc	Tue Feb 25 19:53:34 2014 +0200
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,240 +0,0 @@
     2.4 -#include "opengl.h"
     2.5 -#include "camera.h"
     2.6 -//#include "unistate.h"
     2.7 -#include "vr.h"
     2.8 -
     2.9 -using namespace goatgfx;
    2.10 -
    2.11 -Camera::Camera()
    2.12 -{
    2.13 -	roll = 0.0;
    2.14 -	inval_cache();
    2.15 -}
    2.16 -
    2.17 -Camera::~Camera()
    2.18 -{
    2.19 -}
    2.20 -
    2.21 -void Camera::calc_inv_matrix(Matrix4x4 *mat) const
    2.22 -{
    2.23 -	*mat = matrix().inverse();
    2.24 -}
    2.25 -
    2.26 -const Matrix4x4 &Camera::matrix() const
    2.27 -{
    2.28 -	if(!mcache.valid) {
    2.29 -		calc_matrix(&mcache.mat);
    2.30 -		mcache.valid = true;
    2.31 -	}
    2.32 -	return mcache.mat;
    2.33 -}
    2.34 -
    2.35 -const Matrix4x4 &Camera::inv_matrix() const
    2.36 -{
    2.37 -	if(!mcache_inv.valid) {
    2.38 -		calc_inv_matrix(&mcache_inv.mat);
    2.39 -		mcache_inv.valid = true;
    2.40 -	}
    2.41 -	return mcache_inv.mat;
    2.42 -}
    2.43 -
    2.44 -void Camera::use() const
    2.45 -{
    2.46 -	//set_view_matrix(matrix());
    2.47 -	mult_matrix(matrix());
    2.48 -}
    2.49 -
    2.50 -void Camera::use_inverse() const
    2.51 -{
    2.52 -	//set_view_matrix(inv_matrix());
    2.53 -	mult_matrix(inv_matrix());
    2.54 -}
    2.55 -
    2.56 -void Camera::input_move(float x, float y, float z)
    2.57 -{
    2.58 -}
    2.59 -
    2.60 -void Camera::input_rotate(float x, float y, float z)
    2.61 -{
    2.62 -}
    2.63 -
    2.64 -void Camera::input_zoom(float factor)
    2.65 -{
    2.66 -}
    2.67 -
    2.68 -
    2.69 -// ---- orbit camera ----
    2.70 -
    2.71 -OrbitCamera::OrbitCamera()
    2.72 -{
    2.73 -	theta = 0.0;
    2.74 -	phi = 0.0;
    2.75 -	rad = 10.0;
    2.76 -}
    2.77 -
    2.78 -OrbitCamera::~OrbitCamera()
    2.79 -{
    2.80 -}
    2.81 -
    2.82 -void OrbitCamera::calc_matrix(Matrix4x4 *mat) const
    2.83 -{
    2.84 -	mat->reset_identity();
    2.85 -	mat->translate(Vector3(0, 0, -rad));
    2.86 -	mat->rotate(Vector3(phi, 0, 0));
    2.87 -	mat->rotate(Vector3(0, theta, 0));
    2.88 -	mat->rotate(Vector3(0, 0, roll));
    2.89 -}
    2.90 -
    2.91 -void OrbitCamera::calc_inv_matrix(Matrix4x4 *mat) const
    2.92 -{
    2.93 -	mat->reset_identity();
    2.94 -	mat->rotate(Vector3(0, 0, roll));
    2.95 -	mat->rotate(Vector3(0, theta, 0));
    2.96 -	mat->rotate(Vector3(phi, 0, 0));
    2.97 -	mat->translate(Vector3(0, 0, -rad));
    2.98 -}
    2.99 -
   2.100 -void OrbitCamera::input_rotate(float x, float y, float z)
   2.101 -{
   2.102 -	theta += y;
   2.103 -	phi += x;
   2.104 -	roll += z;
   2.105 -
   2.106 -	if(phi < -M_PI / 2)
   2.107 -		phi = -M_PI / 2;
   2.108 -	if(phi > M_PI)
   2.109 -		phi = M_PI;
   2.110 -
   2.111 -	inval_cache();
   2.112 -}
   2.113 -
   2.114 -void OrbitCamera::input_zoom(float factor)
   2.115 -{
   2.116 -	rad += factor;
   2.117 -	if(rad < 0.0)
   2.118 -		rad = 0.0;
   2.119 -
   2.120 -	inval_cache();
   2.121 -}
   2.122 -
   2.123 -void FpsCamera::calc_matrix(Matrix4x4 *mat) const
   2.124 -{
   2.125 -	mat->reset_identity();
   2.126 -	mat->translate(Vector3(pos.x, pos.y, pos.z));
   2.127 -	mat->rotate(Vector3(0, theta, 0));
   2.128 -	mat->rotate(Vector3(phi, 0, 0));
   2.129 -	mat->rotate(Vector3(0, 0, roll));
   2.130 -}
   2.131 -
   2.132 -void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   2.133 -{
   2.134 -	mat->reset_identity();
   2.135 -	mat->rotate(Vector3(0, 0, roll));
   2.136 -	mat->rotate(Vector3(phi, 0, 0));
   2.137 -	mat->rotate(Vector3(0, theta, 0));
   2.138 -	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   2.139 -}
   2.140 -
   2.141 -void FpsCamera::input_move(float x, float y, float z)
   2.142 -{
   2.143 -	pos.x += x * cos(theta) - z * sin(theta);
   2.144 -	pos.z += x * sin(theta) + z * cos(theta);
   2.145 -	pos.y += y;
   2.146 -	inval_cache();
   2.147 -}
   2.148 -
   2.149 -const Vector3 &FpsCamera::get_position() const
   2.150 -{
   2.151 -	return pos;
   2.152 -}
   2.153 -
   2.154 -
   2.155 -FlyCamera::FlyCamera()
   2.156 -{
   2.157 -	pos.z = 10.0f;
   2.158 -}
   2.159 -
   2.160 -void FlyCamera::calc_matrix(Matrix4x4 *mat) const
   2.161 -{
   2.162 -	Matrix3x3 rmat = rot.get_rotation_matrix().transposed();
   2.163 -	Matrix4x4 tmat;
   2.164 -	tmat.set_translation(pos);
   2.165 -	*mat = tmat * Matrix4x4(rmat);
   2.166 -}
   2.167 -
   2.168 -/*void FlyCamera::calc_inv_matrix(Matrix4x4 *mat) const
   2.169 -{
   2.170 -}*/
   2.171 -
   2.172 -const Vector3 &FlyCamera::get_position() const
   2.173 -{
   2.174 -	return pos;
   2.175 -}
   2.176 -
   2.177 -const Quaternion &FlyCamera::get_rotation() const
   2.178 -{
   2.179 -	return rot;
   2.180 -}
   2.181 -
   2.182 -void FlyCamera::input_move(float x, float y, float z)
   2.183 -{
   2.184 -	static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0);
   2.185 -
   2.186 -	Vector3 k = vfwd.transformed(rot);
   2.187 -	Vector3	i = vright.transformed(rot);
   2.188 -	Vector3 j = cross_product(k, i);
   2.189 -
   2.190 -	pos += i * x + j * y + k * z;
   2.191 -	inval_cache();
   2.192 -}
   2.193 -
   2.194 -void FlyCamera::input_rotate(float x, float y, float z)
   2.195 -{
   2.196 -	Vector3 axis(x, y, z);
   2.197 -	float axis_len = axis.length();
   2.198 -	rot.rotate(axis / axis_len, axis_len);
   2.199 -	rot.normalize();
   2.200 -
   2.201 -	inval_cache();
   2.202 -}
   2.203 -
   2.204 -
   2.205 -// --- VR additions ---
   2.206 -VRFpsCamera::VRFpsCamera()
   2.207 -{
   2.208 -	neck_eye_dist = 0.14;	// default neck->eye distance 14cm
   2.209 -}
   2.210 -
   2.211 -void VRFpsCamera::calc_matrix(Matrix4x4 *mat) const
   2.212 -{
   2.213 -	mat->reset_identity();
   2.214 -	mat->translate(Vector3(pos.x, pos.y, pos.z));
   2.215 -	mat->rotate(Vector3(0, theta, 0));
   2.216 -	mat->rotate(Vector3(phi, 0, 0));
   2.217 -	mat->rotate(Vector3(0, 0, roll));
   2.218 -	mat->translate(Vector3(0, neck_eye_dist, 0));
   2.219 -}
   2.220 -
   2.221 -void VRFpsCamera::calc_inv_matrix(Matrix4x4 *mat) const
   2.222 -{
   2.223 -	mat->reset_identity();
   2.224 -	mat->translate(Vector3(0, -neck_eye_dist, 0));
   2.225 -	mat->rotate(Vector3(0, 0, roll));
   2.226 -	mat->rotate(Vector3(phi, 0, 0));
   2.227 -	mat->rotate(Vector3(0, theta, 0));
   2.228 -	mat->translate(Vector3(-pos.x, -pos.y, -pos.z));
   2.229 -}
   2.230 -
   2.231 -void VRFpsCamera::track_vr()
   2.232 -{
   2.233 -	float euler[3];
   2.234 -	vr_get_rotation_euler(euler);
   2.235 -
   2.236 -	// input_rotate invalidates cache
   2.237 -	input_rotate(prev_angles[0] - euler[0], prev_angles[1] - euler[1], prev_angles[2] - euler[2]);
   2.238 -
   2.239 -	prev_angles[0] = euler[0];
   2.240 -	prev_angles[1] = euler[1];
   2.241 -	prev_angles[2] = euler[2];
   2.242 -}
   2.243 -
     3.1 --- a/src/camera.h	Tue Feb 25 19:53:34 2014 +0200
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,102 +0,0 @@
     3.4 -#ifndef CAMERA_H_
     3.5 -#define CAMERA_H_
     3.6 -
     3.7 -#include <vmath/vmath.h>
     3.8 -
     3.9 -namespace goatgfx {
    3.10 -
    3.11 -class Camera {
    3.12 -protected:
    3.13 -	float roll;
    3.14 -
    3.15 -	mutable struct {
    3.16 -		bool valid;
    3.17 -		Matrix4x4 mat;
    3.18 -	} mcache, mcache_inv;
    3.19 -
    3.20 -	virtual void calc_matrix(Matrix4x4 *mat) const = 0;
    3.21 -	virtual void calc_inv_matrix(Matrix4x4 *mat) const;
    3.22 -
    3.23 -	void inval_cache() { mcache.valid = mcache_inv.valid = false; }
    3.24 -	void set_glmat(const Matrix4x4 &m) const;
    3.25 -
    3.26 -public:
    3.27 -	Camera();
    3.28 -	virtual ~Camera();
    3.29 -
    3.30 -	const Matrix4x4 &matrix() const;
    3.31 -	const Matrix4x4 &inv_matrix() const;
    3.32 -
    3.33 -	void use() const;
    3.34 -	void use_inverse() const;
    3.35 -
    3.36 -	// these do nothing, override to provide input handling
    3.37 -	virtual void input_move(float x, float y, float z);
    3.38 -	virtual void input_rotate(float x, float y, float z);
    3.39 -	virtual void input_zoom(float factor);
    3.40 -};
    3.41 -
    3.42 -class OrbitCamera : public Camera {
    3.43 -protected:
    3.44 -	float theta, phi, rad;
    3.45 -
    3.46 -	void calc_matrix(Matrix4x4 *mat) const;
    3.47 -	void calc_inv_matrix(Matrix4x4 *mat) const;
    3.48 -
    3.49 -public:
    3.50 -	OrbitCamera();
    3.51 -	virtual ~OrbitCamera();
    3.52 -
    3.53 -	void input_rotate(float x, float y, float z);
    3.54 -	void input_zoom(float factor);
    3.55 -};
    3.56 -
    3.57 -class FpsCamera : public OrbitCamera {
    3.58 -protected:
    3.59 -	Vector3 pos;
    3.60 -
    3.61 -	void calc_matrix(Matrix4x4 *mat) const;
    3.62 -	void calc_inv_matrix(Matrix4x4 *mat) const;
    3.63 -
    3.64 -public:
    3.65 -	void input_move(float x, float y, float z);
    3.66 -
    3.67 -	const Vector3 &get_position() const;
    3.68 -};
    3.69 -
    3.70 -class FlyCamera : public Camera {
    3.71 -private:
    3.72 -	Vector3 pos;
    3.73 -	Quaternion rot;
    3.74 -
    3.75 -	void calc_matrix(Matrix4x4 *mat) const;
    3.76 -	//void calc_inv_matrix(Matrix4x4 *mat) const;
    3.77 -
    3.78 -public:
    3.79 -	FlyCamera();
    3.80 -
    3.81 -	const Vector3 &get_position() const;
    3.82 -	const Quaternion &get_rotation() const;
    3.83 -
    3.84 -	void input_move(float x, float y, float z);
    3.85 -	void input_rotate(float x, float y, float z);
    3.86 -};
    3.87 -
    3.88 -
    3.89 -class VRFpsCamera : public FpsCamera {
    3.90 -private:
    3.91 -	float neck_eye_dist;
    3.92 -	float prev_angles[3];
    3.93 -
    3.94 -	void calc_matrix(Matrix4x4 *mat) const;
    3.95 -	void calc_inv_matrix(Matrix4x4 *mat) const;
    3.96 -
    3.97 -public:
    3.98 -	VRFpsCamera();
    3.99 -
   3.100 -	void track_vr();
   3.101 -};
   3.102 -
   3.103 -}	// namespace goatgfx
   3.104 -
   3.105 -#endif	// CAMERA_H_
     4.1 --- a/src/main.cc	Tue Feb 25 19:53:34 2014 +0200
     4.2 +++ b/src/main.cc	Tue Feb 25 23:47:20 2014 +0200
     4.3 @@ -2,13 +2,15 @@
     4.4  #include <stdlib.h>
     4.5  #include <assert.h>
     4.6  #include <vector>
     4.7 -#include "opengl.h"
     4.8 -#include "camera.h"
     4.9 +#include <goat3dgfx/goat3dgfx.h>
    4.10 +
    4.11 +using namespace goatgfx;
    4.12  
    4.13  static bool init();
    4.14  static void cleanup();
    4.15 +static void disp();
    4.16 +static void draw_scene(int which);
    4.17  static void handle_input(float dt);
    4.18 -static void disp();
    4.19  static void idle();
    4.20  static void reshape(int x, int y);
    4.21  static void keypress(unsigned char key, int x, int y);
    4.22 @@ -16,12 +18,14 @@
    4.23  static void mouse(int bn, int st, int x, int y);
    4.24  static void motion(int x, int y);
    4.25  
    4.26 -static goatgfx::VRFpsCamera cam;
    4.27 +static int win_width, win_height;
    4.28 +static float split_pos = 0.5;
    4.29 +static VRFpsCamera cam;
    4.30  static std::vector<bool> keystate(256);
    4.31  
    4.32  int main(int argc, char **argv)
    4.33  {
    4.34 -	glutInitWindowSize(800, 600);
    4.35 +	glutInitWindowSize(1024, 768);
    4.36  	glutInit(&argc, argv);
    4.37  	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    4.38  	glutCreateWindow("symmetry");
    4.39 @@ -68,31 +72,73 @@
    4.40  	unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
    4.41  	static unsigned int prev_msec;
    4.42  	float dt = (float)(msec - prev_msec) / 1000.0f;
    4.43 +	prev_msec = msec;
    4.44  
    4.45  	handle_input(dt);
    4.46  
    4.47  	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    4.48  
    4.49 -	glMatrixMode(GL_MODELVIEW);
    4.50 -	glLoadIdentity();
    4.51  	cam.use_inverse();
    4.52 +	setup_gl_matrices();
    4.53  
    4.54 -	glBegin(GL_QUADS);
    4.55 -	glNormal3f(0, 1, 0);
    4.56 -	glVertex3f(-5, 0, 5);
    4.57 -	glVertex3f(5, 0, 5);
    4.58 -	glVertex3f(5, 0, -5);
    4.59 -	glVertex3f(-5, 0, -5);
    4.60 -	glEnd();
    4.61 +	float left_pixels = split_pos * win_width;
    4.62  
    4.63 -	glFrontFace(GL_CW);
    4.64 -	glutSolidTeapot(1.0);
    4.65 -	glFrontFace(GL_CCW);
    4.66 +	glEnable(GL_SCISSOR_TEST);
    4.67 +
    4.68 +	// draw left viewport
    4.69 +	if(left_pixels > 0) {
    4.70 +		glScissor(0, 0, left_pixels, win_height);
    4.71 +		draw_scene(0);
    4.72 +	}
    4.73 +
    4.74 +	// draw right viewport
    4.75 +	if(left_pixels < win_width) {
    4.76 +		glScissor(left_pixels, 0, win_width - left_pixels, win_height);
    4.77 +		draw_scene(1);
    4.78 +	}
    4.79 +
    4.80 +	glDisable(GL_SCISSOR_TEST);
    4.81  
    4.82  	glutSwapBuffers();
    4.83  	assert(glGetError() == GL_NO_ERROR);
    4.84  }
    4.85  
    4.86 +static void draw_scene(int which)
    4.87 +{
    4.88 +	glMatrixMode(GL_MODELVIEW);
    4.89 +
    4.90 +	float lpos[] = {-5, 20, 5, 1};
    4.91 +	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    4.92 +
    4.93 +	float color[][4] = {
    4.94 +		{1.0, 0.3, 0.2, 1.0},
    4.95 +		{0.2, 0.3, 1.0, 1.0}
    4.96 +	};
    4.97 +
    4.98 +	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color[which]);
    4.99 +
   4.100 +	glBegin(GL_QUADS);
   4.101 +	glNormal3f(0, 1, 0);
   4.102 +	glVertex3f(-20, 0, 20);
   4.103 +	glVertex3f(20, 0, 20);
   4.104 +	glVertex3f(20, 0, -20);
   4.105 +	glVertex3f(-20, 0, -20);
   4.106 +	glEnd();
   4.107 +
   4.108 +	for(int i=0; i<8; i++) {
   4.109 +		float theta = 360.0 * (float)i / 8.0;
   4.110 +		glPushMatrix();
   4.111 +		glRotatef(theta, 0, 1, 0);
   4.112 +		glTranslatef(0, 0, 10);
   4.113 +
   4.114 +		glTranslatef(0, 1, 0);
   4.115 +
   4.116 +		glFrontFace(GL_CW);
   4.117 +		glutSolidTeapot(1.0);
   4.118 +		glFrontFace(GL_CCW);
   4.119 +		glPopMatrix();
   4.120 +	}
   4.121 +}
   4.122  
   4.123  static void handle_input(float dt)
   4.124  {
   4.125 @@ -124,9 +170,12 @@
   4.126  {
   4.127  	glViewport(0, 0, x, y);
   4.128  
   4.129 -	glMatrixMode(GL_PROJECTION);
   4.130 -	glLoadIdentity();
   4.131 -	gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0);
   4.132 +	Matrix4x4 proj;
   4.133 +	proj.set_perspective(DEG_TO_RAD(50), (float)x / (float)y, 0.5, 500.0);
   4.134 +	set_projection_matrix(proj);
   4.135 +
   4.136 +	win_width = x;
   4.137 +	win_height = y;
   4.138  }
   4.139  
   4.140  static void keypress(unsigned char key, int x, int y)
   4.141 @@ -136,6 +185,10 @@
   4.142  	switch(key) {
   4.143  	case 27:
   4.144  		exit(0);
   4.145 +
   4.146 +	case ' ':
   4.147 +		split_pos = 0.5;
   4.148 +		break;
   4.149  	}
   4.150  }
   4.151  
   4.152 @@ -165,6 +218,11 @@
   4.153  		return;
   4.154  	}
   4.155  
   4.156 +	if(keystate[(int)'\b']) {
   4.157 +		split_pos = (float)x / win_width;
   4.158 +		return;
   4.159 +	}
   4.160 +
   4.161  	if(bnstate[0]) {
   4.162  		float dtheta_deg = dy * 0.5;
   4.163  		float dphi_deg = dx * 0.5;
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/terrain.cc	Tue Feb 25 23:47:20 2014 +0200
     5.3 @@ -0,0 +1,349 @@
     5.4 +#include <goat3dgfx/goat3dgfx.h>
     5.5 +#include "terrain.h"
     5.6 +#include "imago2.h"
     5.7 +
     5.8 +using namespace goatgfx;
     5.9 +
    5.10 +Terrain::Terrain()
    5.11 +{
    5.12 +	xsz = ysz = 0;
    5.13 +	dx = dy = 0;
    5.14 +	hmap = 0;
    5.15 +	scale = height_scale = 1;
    5.16 +
    5.17 +	dlist = dlist_norm = 0;
    5.18 +
    5.19 +	dlist_sub[0] = dlist_sub[1] = dlist_norm_sub[0] = dlist_norm_sub[1] = -1;
    5.20 +	dlist_norm_sz = -1.0;
    5.21 +}
    5.22 +
    5.23 +Terrain::~Terrain()
    5.24 +{
    5.25 +	if(hmap) {
    5.26 +		img_free_pixels(hmap);
    5.27 +	}
    5.28 +
    5.29 +	glDeleteLists(dlist, 2);
    5.30 +}
    5.31 +
    5.32 +void Terrain::set_scale(float s)
    5.33 +{
    5.34 +	if(s != scale) {
    5.35 +		scale = s;
    5.36 +		invalidate_mesh();
    5.37 +	}
    5.38 +}
    5.39 +
    5.40 +float Terrain::get_scale() const
    5.41 +{
    5.42 +	return scale;
    5.43 +}
    5.44 +
    5.45 +void Terrain::set_height_scale(float s)
    5.46 +{
    5.47 +	if(s != height_scale) {
    5.48 +		height_scale = s;
    5.49 +		invalidate_mesh();
    5.50 +	}
    5.51 +}
    5.52 +
    5.53 +float Terrain::get_height_scale() const
    5.54 +{
    5.55 +	return height_scale;
    5.56 +}
    5.57 +
    5.58 +bool Terrain::load(const char *fname)
    5.59 +{
    5.60 +	if(!(hmap = (float*)img_load_pixels(fname, &xsz, &ysz, IMG_FMT_GREYF))) {
    5.61 +		fprintf(stderr, "failed to load image: %s\n", fname);
    5.62 +		return false;
    5.63 +	}
    5.64 +
    5.65 +	dx = 1.0 / (float)(xsz - 1);
    5.66 +	dy = 1.0 / (float)(ysz - 1);
    5.67 +	return true;
    5.68 +}
    5.69 +
    5.70 +Vector2 Terrain::world_to_uv(const Vector2 &pt) const
    5.71 +{
    5.72 +	return pt  / scale + 0.5;
    5.73 +}
    5.74 +
    5.75 +Vector2 Terrain::uv_to_world(const Vector2 &pt) const
    5.76 +{
    5.77 +	return (pt - 0.5) * scale;
    5.78 +}
    5.79 +
    5.80 +float Terrain::lookup(int x, int y) const
    5.81 +{
    5.82 +	int px = x < 0 ? 0 : (x >= xsz ? x = xsz - 1 : x);
    5.83 +	int py = y < 0 ? 0 : (y >= ysz ? y = ysz - 1 : y);
    5.84 +	return hmap[py * xsz + px];
    5.85 +}
    5.86 +
    5.87 +float Terrain::get_height(const Vector2 &pt) const
    5.88 +{
    5.89 +	float fxsz = (float)xsz;
    5.90 +	float fysz = (float)ysz;
    5.91 +
    5.92 +	// the floor of x * xsz is the pixel x coordinate (e.g. [0.0, 1.0, 2.0, ... 127.0] for 128x128)
    5.93 +	float floorx = floor(pt.x * fxsz);
    5.94 +	float floory = floor(pt.y * fysz);
    5.95 +
    5.96 +	// (x0, y0) is the lower left pixel in normalized coords of the four pixels surrounding pt
    5.97 +	float x0 = floorx / fxsz;
    5.98 +	float y0 = floory / fysz;
    5.99 +
   5.100 +	// (u, v) is the relative position of pt within the 4pix square
   5.101 +	// so if it's exactly at the lower-right it'll be (0, 0), in the middle it'll be (0.5, 0.5) etc.
   5.102 +	float u = (pt.x - x0) * fxsz;
   5.103 +	float v = (pt.y - y0) * fysz;
   5.104 +
   5.105 +	// we need integer pixel coordinates to use lookup()
   5.106 +	int px = (int)floorx;
   5.107 +	int py = (int)floory;
   5.108 +
   5.109 +	// the heights at the 4 corners
   5.110 +	float h00 = lookup(px, py);
   5.111 +	float h10 = lookup(px + 1, py);
   5.112 +	float h01 = lookup(px, py + 1);
   5.113 +	float h11 = lookup(px + 1, py + 1);
   5.114 +
   5.115 +	// first interpolate along the top and bottom edges
   5.116 +	float top = lerp(h01, h11, u);
   5.117 +	float bot = lerp(h00, h10, u);
   5.118 +	// then vertically between the top/bot values
   5.119 +	return lerp(bot, top, v);
   5.120 +}
   5.121 +
   5.122 +Vector3 Terrain::get_normal(const Vector2 &pt) const
   5.123 +{
   5.124 +	// compute partial derivatives (slopes) in respect to X and Y using central differences
   5.125 +	float dfdx = get_height(Vector2(pt.x + dx, pt.y)) - get_height(Vector2(pt.x - dx, pt.y));
   5.126 +	float dfdy = get_height(Vector2(pt.x, pt.y + dy)) - get_height(Vector2(pt.x, pt.y - dy));
   5.127 +
   5.128 +	/* we need to multiply with the final scale factors while constructing the tangent and
   5.129 +	 * bitangent vectors, otherwise the "aspect" of the normals will be wrong while changing
   5.130 +	 * the two scale factors independently.
   5.131 +	 */
   5.132 +	Vector3 tang = Vector3(2.0 * dx * scale, dfdx * height_scale, 0);
   5.133 +	Vector3 bitan = Vector3(0, dfdy * height_scale, 2.0 * dy * scale);
   5.134 +	return cross_product(bitan, tang).normalized();
   5.135 +}
   5.136 +
   5.137 +float Terrain::get_world_height(const Vector2 &pt) const
   5.138 +{
   5.139 +	return get_height(world_to_uv(pt)) * height_scale;
   5.140 +}
   5.141 +
   5.142 +/* step over pixel distances until we cross the terrain, then determine the
   5.143 + * point of intersection
   5.144 + */
   5.145 +bool Terrain::intersect(const Ray &ray, float *dist) const
   5.146 +{
   5.147 +	// axis-aligned bounding box of the terrain
   5.148 +	AABox aabb;
   5.149 +	aabb.min = Vector3(-0.5 * scale, 0, -0.5 * scale);
   5.150 +	aabb.max = Vector3(0.5 * scale, height_scale, 0.5 * scale);
   5.151 +
   5.152 +	Ray mray;
   5.153 +	mray.origin = ray.origin;
   5.154 +	// find a reasonable step size
   5.155 +	float pixsz = dx > dy ? dx : dy;
   5.156 +	float raysz = ray.dir.length();
   5.157 +	mray.dir = ray.dir / raysz * pixsz;
   5.158 +
   5.159 +	float aabb_dist = 0.0;
   5.160 +
   5.161 +	if(!aabb.contains(mray.origin)) {
   5.162 +		/* if we're not in the aabb, calculate the intersection point of the ray
   5.163 +		 * with the aabb, to start ray-marching from that point.
   5.164 +		 */
   5.165 +		HitPoint hit;
   5.166 +		if(!aabb.intersect(ray, &hit)) {
   5.167 +			return false;	// the ray misses the terrain completely
   5.168 +		}
   5.169 +		aabb_dist = hit.dist;
   5.170 +		mray.origin += ray.dir * aabb_dist;
   5.171 +	}
   5.172 +
   5.173 +
   5.174 +	// ray-march over the terrain until we find an intersection or leave the box
   5.175 +	int num_steps = 0;
   5.176 +	do {
   5.177 +		float mdist;
   5.178 +		if(intersect_micro(mray, &mdist, 0.01)) {
   5.179 +			/* to calculate the distance travelled along the original ray we need to
   5.180 +			 * first add the distance to the aabb where we started ray marching. Then
   5.181 +			 * add the fraction of the last step to the number of micro-steps up to
   5.182 +			 * this point, which have to be converted to the original ray scale by
   5.183 +			 * multiplying by the magnitude of the micro-ray direction, over the
   5.184 +			 * magnitude of the original ray direction.
   5.185 +			 */
   5.186 +			*dist = aabb_dist + (mdist + (float)num_steps) * pixsz / raysz;
   5.187 +			return true;
   5.188 +		}
   5.189 +
   5.190 +		mray.origin += mray.dir;
   5.191 +		num_steps++;
   5.192 +	} while(aabb.contains(mray.origin));
   5.193 +
   5.194 +	return false;
   5.195 +}
   5.196 +
   5.197 +bool Terrain::intersect_micro(const Ray &ray, float *dist, float thres) const
   5.198 +{
   5.199 +	Vector3 start = ray.origin;
   5.200 +	Vector3 end = ray.origin + ray.dir;
   5.201 +
   5.202 +	float hstart = get_world_height(Vector2(start.x, start.z));
   5.203 +	float hend = get_world_height(Vector2(end.x, end.z));
   5.204 +
   5.205 +	/* if both the start and the end of the ray are above or below the heightfield
   5.206 +	 * then there's no possible intersection in micro-scales.
   5.207 +	 */
   5.208 +	if(start.y > hstart && end.y > hend) {
   5.209 +		return false;	// all above
   5.210 +	}
   5.211 +	if(start.y < hstart && end.y < hend) {
   5.212 +		return false;	// all below
   5.213 +	}
   5.214 +
   5.215 +	/* otherwise (one on one side and the other on the other side), we're straddling
   5.216 +	 * the heightfield. So, find the mid-point and binary-search until we find an
   5.217 +	 * estimated intersection point within the limits defined by "thres".
   5.218 +	 */
   5.219 +	Vector3 mid = lerp(start, end, 0.5);
   5.220 +	float hmid = get_world_height(Vector2(mid.x, mid.z));
   5.221 +	float dh = mid.y - hmid;
   5.222 +
   5.223 +	int iter = 0;	// iter is there to avoid infinite loops in marginal cases
   5.224 +	while(fabs(dh) > thres && iter < 100) {
   5.225 +		if(dh > 0) {	// mid is above the surface
   5.226 +			start = mid;
   5.227 +		} else {		// mid is below the surface
   5.228 +			end = mid;
   5.229 +		}
   5.230 +		mid = lerp(start, end, 0.5);
   5.231 +		hmid = get_world_height(Vector2(mid.x, mid.z));
   5.232 +		dh = mid.y - hmid;
   5.233 +
   5.234 +		iter++;
   5.235 +	}
   5.236 +
   5.237 +	// found the intersection point, calculate the parametric distance and return true
   5.238 +	*dist = (mid - ray.origin).length() / ray.dir.length();
   5.239 +	return true;
   5.240 +}
   5.241 +
   5.242 +void Terrain::draw(int usub, int vsub) const
   5.243 +{
   5.244 +	if(usub < 1) usub = xsz - 1;
   5.245 +	if(vsub < 1) vsub = ysz - 1;
   5.246 +
   5.247 +	if(dlist && dlist_sub[0] == usub && dlist_sub[1] == vsub) {
   5.248 +		glCallList(dlist);
   5.249 +		return;
   5.250 +	}
   5.251 +
   5.252 +	if(!dlist) {
   5.253 +		dlist = glGenLists(2);
   5.254 +		dlist_norm = dlist + 1;
   5.255 +	}
   5.256 +	glNewList(dlist, GL_COMPILE_AND_EXECUTE);
   5.257 +	dlist_sub[0] = usub;
   5.258 +	dlist_sub[1] = vsub;
   5.259 +
   5.260 +	float du = 1.0 / (float)usub;
   5.261 +	float dv = 1.0 / (float)vsub;
   5.262 +
   5.263 +	glBegin(GL_QUADS);
   5.264 +
   5.265 +	float v = 0.0;
   5.266 +	for(int i=0; i<vsub; i++) {
   5.267 +		float u = 0.0;
   5.268 +		for(int j=0; j<usub; j++) {
   5.269 +
   5.270 +			Vector2 uv(u, v);
   5.271 +			Vector3 norm = get_normal(uv);
   5.272 +			Vector2 wpt = uv_to_world(Vector2(u, v));
   5.273 +			glNormal3f(norm.x, norm.y, norm.z);
   5.274 +			glVertex3f(wpt.x, get_height(Vector2(u, v)) * height_scale, wpt.y);
   5.275 +
   5.276 +			uv = Vector2(u, v + dv);
   5.277 +			norm = get_normal(uv);
   5.278 +			wpt = uv_to_world(uv);
   5.279 +			glNormal3f(norm.x, norm.y, norm.z);
   5.280 +			glVertex3f(wpt.x, get_height(uv) * height_scale, wpt.y);
   5.281 +
   5.282 +			uv = Vector2(u + du, v + dv);
   5.283 +			norm = get_normal(uv);
   5.284 +			wpt = uv_to_world(uv);
   5.285 +			glNormal3f(norm.x, norm.y, norm.z);
   5.286 +			glVertex3f(wpt.x, get_height(uv) * height_scale, wpt.y);
   5.287 +
   5.288 +			uv = Vector2(u + du, v);
   5.289 +			norm = get_normal(uv);
   5.290 +			wpt = uv_to_world(uv);
   5.291 +			glNormal3f(norm.x, norm.y, norm.z);
   5.292 +			glVertex3f(wpt.x, get_height(uv) * height_scale, wpt.y);
   5.293 +
   5.294 +			u += du;
   5.295 +		}
   5.296 +		v += dv;
   5.297 +	}
   5.298 +	glEnd();
   5.299 +
   5.300 +	glEndList();
   5.301 +}
   5.302 +
   5.303 +void Terrain::draw_normals(float sz, int usub, int vsub) const
   5.304 +{
   5.305 +	if(usub < 1) usub = xsz - 1;
   5.306 +	if(vsub < 1) vsub = ysz - 1;
   5.307 +
   5.308 +	if(dlist_norm && dlist_norm_sub[0] == usub && dlist_norm_sub[1] == vsub && fabs(dlist_norm_sz - sz) < 0.0001) {
   5.309 +		glCallList(dlist_norm);
   5.310 +		return;
   5.311 +	}
   5.312 +
   5.313 +	if(!dlist_norm) {
   5.314 +		dlist = glGenLists(2);
   5.315 +		dlist_norm = dlist + 1;
   5.316 +	}
   5.317 +	glNewList(dlist_norm, GL_COMPILE_AND_EXECUTE);
   5.318 +	dlist_norm_sub[0] = usub;
   5.319 +	dlist_norm_sub[1] = vsub;
   5.320 +	dlist_norm_sz = sz;
   5.321 +
   5.322 +	float du = 1.0 / (float)usub;
   5.323 +	float dv = 1.0 / (float)vsub;
   5.324 +
   5.325 +	glBegin(GL_LINES);
   5.326 +
   5.327 +	float v = 0.0;
   5.328 +	for(int i=0; i<vsub + 1; i++) {
   5.329 +		float u = 0.0;
   5.330 +		for(int j=0; j<usub + 1; j++) {
   5.331 +			Vector2 uv(u, v);
   5.332 +			Vector2 wpt = uv_to_world(uv);
   5.333 +			Vector3 norm = get_normal(uv) * sz * height_scale;
   5.334 +
   5.335 +			Vector3 p(wpt.x, get_height(uv) * height_scale, wpt.y);
   5.336 +			glVertex3f(p.x, p.y, p.z);
   5.337 +			glVertex3f(p.x + norm.x, p.y + norm.y, p.z + norm.z);
   5.338 +
   5.339 +			u += du;
   5.340 +		}
   5.341 +		v += dv;
   5.342 +	}
   5.343 +	glEnd();
   5.344 +
   5.345 +	glEndList();
   5.346 +}
   5.347 +
   5.348 +void Terrain::invalidate_mesh()
   5.349 +{
   5.350 +	// this will force recreation of the display lists on the next draw call
   5.351 +	dlist_sub[0] = dlist_sub[1] = dlist_norm_sub[0] = dlist_norm_sub[1] = -1;
   5.352 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/terrain.h	Tue Feb 25 23:47:20 2014 +0200
     6.3 @@ -0,0 +1,51 @@
     6.4 +#ifndef TERRAIN_H_
     6.5 +#define TERRAIN_H_
     6.6 +
     6.7 +#include "vmath/vmath.h"
     6.8 +
     6.9 +class Terrain {
    6.10 +private:
    6.11 +	float dx, dy;	// inter-pixel distance in uv-space
    6.12 +	int xsz, ysz;
    6.13 +	float *hmap;
    6.14 +
    6.15 +	float scale, height_scale;
    6.16 +
    6.17 +	mutable int dlist, dlist_norm;
    6.18 +	mutable int dlist_sub[2], dlist_norm_sub[2];
    6.19 +	mutable float dlist_norm_sz;
    6.20 +
    6.21 +	void invalidate_mesh();
    6.22 +
    6.23 +public:
    6.24 +	Terrain();
    6.25 +	~Terrain();
    6.26 +
    6.27 +	void set_scale(float s);
    6.28 +	float get_scale() const;
    6.29 +
    6.30 +	void set_height_scale(float s);
    6.31 +	float get_height_scale() const;
    6.32 +
    6.33 +	bool load(const char *fname);
    6.34 +	int get_map_width() const { return xsz; }
    6.35 +	int get_map_height() const { return ysz; }
    6.36 +
    6.37 +	Vector2 world_to_uv(const Vector2 &pt) const;
    6.38 +	Vector2 uv_to_world(const Vector2 &pt) const;
    6.39 +
    6.40 +	float lookup(int x, int y) const;
    6.41 +
    6.42 +	float get_height(const Vector2 &pt) const;
    6.43 +	Vector3 get_normal(const Vector2 &pt) const;
    6.44 +
    6.45 +	float get_world_height(const Vector2 &pt) const;
    6.46 +
    6.47 +	bool intersect(const Ray &ray, float *dist) const;
    6.48 +	bool intersect_micro(const Ray &ray, float *dist, float thres = 0.01) const;
    6.49 +
    6.50 +	void draw(int usub = 0, int vsub = 0) const;
    6.51 +	void draw_normals(float sz = 1.0, int usub = 0, int vsub = 0) const;
    6.52 +};
    6.53 +
    6.54 +#endif	// TERRAIN_H_
     7.1 --- a/src/vr.h	Tue Feb 25 19:53:34 2014 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,63 +0,0 @@
     7.4 -#ifndef GOAT3DGFX_VR_H_
     7.5 -#define GOAT3DGFX_VR_H_
     7.6 -
     7.7 -/* VR mode init options */
     7.8 -enum vr_init_mode {
     7.9 -	VR_INIT_NONE,
    7.10 -	VR_INIT_OCULUS,
    7.11 -	VR_INIT_STEREO
    7.12 -};
    7.13 -
    7.14 -/* possible eye values */
    7.15 -enum {
    7.16 -	VR_EYE_CENTER,
    7.17 -	VR_EYE_LEFT,
    7.18 -	VR_EYE_RIGHT
    7.19 -};
    7.20 -
    7.21 -#ifdef __cplusplus
    7.22 -extern "C" {
    7.23 -#endif
    7.24 -
    7.25 -int vr_init(enum vr_init_mode mode);
    7.26 -void vr_shutdown(void);
    7.27 -
    7.28 -const char *vr_get_display_name(void);
    7.29 -void vr_get_display_pos(int *xptr, int *yptr);
    7.30 -
    7.31 -int vr_get_width(void);
    7.32 -int vr_get_height(void);
    7.33 -
    7.34 -float vr_get_fov(void);
    7.35 -float vr_get_aspect(void);
    7.36 -
    7.37 -void vr_set_eyedist(float ipd);
    7.38 -float vr_get_eyedist(void);
    7.39 -
    7.40 -/* expects an array of 4 barrel distortion coefficients:
    7.41 - * polar scale: k_0 + k_1 r^2 + k_2 r^4 + k_3 r^6
    7.42 - */
    7.43 -void vr_set_distort(const float *coef);
    7.44 -void vr_get_distort(float *coef);
    7.45 -
    7.46 -void vr_set_prediction_sec(float dt);
    7.47 -float vr_get_prediction_sec(void);
    7.48 -
    7.49 -void vr_get_view_matrix(float *res, int eye);
    7.50 -void vr_get_proj_matrix(float *res, int eye);
    7.51 -
    7.52 -/* expects an array of at least 3 floats (x, y, z, offset). */
    7.53 -void vr_get_translation(float *offs);
    7.54 -/* expects an array of at least 4 floats (x, y, z, w, quaternion). */
    7.55 -void vr_get_rotation(float *quat);
    7.56 -/* expects an array of at least 3 floats (pitch, yaw, roll, angles). */
    7.57 -void vr_get_rotation_euler(float *euler);
    7.58 -
    7.59 -/* OpenGL stuff */
    7.60 -void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y);
    7.61 -
    7.62 -#ifdef __cplusplus
    7.63 -}
    7.64 -#endif
    7.65 -
    7.66 -#endif	/* GOAT3DGFX_VR_H_ */
     8.1 --- a/src/vr/vr.cc	Tue Feb 25 19:53:34 2014 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,388 +0,0 @@
     8.4 -#include <stdio.h>
     8.5 -#include <GL/glew.h>
     8.6 -#include "vr.h"
     8.7 -#include "vr_impl.h"
     8.8 -#include "vr_sdr.h"
     8.9 -
    8.10 -#ifndef WIN32
    8.11 -#include <alloca.h>
    8.12 -#else
    8.13 -#include <malloc.h>
    8.14 -#endif
    8.15 -
    8.16 -static void init_ctx();
    8.17 -static bool init_ovr();
    8.18 -static bool init_sdr();
    8.19 -
    8.20 -VRContext vr_ctx;
    8.21 -static unsigned int sdrprog;
    8.22 -
    8.23 -extern "C" int vr_init(enum vr_init_mode mode)
    8.24 -{
    8.25 -	init_ctx();
    8.26 -
    8.27 -	if(!init_ovr()) {
    8.28 -		return -1;
    8.29 -	}
    8.30 -
    8.31 -	if(!init_sdr()) {
    8.32 -		return -1;
    8.33 -	}
    8.34 -
    8.35 -	return 0;
    8.36 -}
    8.37 -
    8.38 -extern "C" void vr_shutdown(void)
    8.39 -{
    8.40 -	delete [] vr_ctx.info.display;
    8.41 -	delete vr_ctx.ovr_sfusion;
    8.42 -	//System::Destroy();
    8.43 -
    8.44 -	memset(&vr_ctx, 0, sizeof vr_ctx);
    8.45 -}
    8.46 -
    8.47 -static void init_ctx()
    8.48 -{
    8.49 -	vr_ctx.info.width = 1280;
    8.50 -	vr_ctx.info.height = 800;
    8.51 -	vr_ctx.info.fov = M_PI / 2.0;
    8.52 -	vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
    8.53 -	vr_ctx.info.ipd = 0.035;
    8.54 -	vr_ctx.info.scale = 1.0;
    8.55 -}
    8.56 -
    8.57 -static bool init_ovr()
    8.58 -{
    8.59 -	LogMaskConstants log_level = LogMask_All;
    8.60 -	// initialize Oculus SDK
    8.61 -	const char *logenv = getenv("VR_LOGLEVEL");
    8.62 -	if(logenv) {
    8.63 -		switch(atoi(logenv)) {
    8.64 -		case 0:
    8.65 -			log_level = LogMask_None;
    8.66 -			break;
    8.67 -		case 1:
    8.68 -			log_level = LogMask_Regular;
    8.69 -			break;
    8.70 -		case 2:
    8.71 -		default:
    8.72 -			log_level = LogMask_All;
    8.73 -			break;
    8.74 -		}
    8.75 -	}
    8.76 -
    8.77 -	System::Init(Log::ConfigureDefaultLog(log_level));
    8.78 -	if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
    8.79 -		fprintf(stderr, "failed to create OVR device manager\n");
    8.80 -		return false;
    8.81 -	}
    8.82 -
    8.83 -	// create the display device
    8.84 -	HMDInfo info;
    8.85 -	if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
    8.86 -		fprintf(stderr, "no oculus rift devices found\n");
    8.87 -	} else {
    8.88 -		if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
    8.89 -			printf("oculus device info:\n");
    8.90 -			printf("  name: %s\n", info.DisplayDeviceName);
    8.91 -			printf("  ipd: %f\n", info.InterpupillaryDistance);
    8.92 -			printf("  distortion: %f %f %f %f\n", info.DistortionK[0],
    8.93 -					info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
    8.94 -		}
    8.95 -
    8.96 -		// calculate and store viewing parameters
    8.97 -		vr_ctx.info.width = info.HResolution;
    8.98 -		vr_ctx.info.height = info.VResolution;
    8.99 -		vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
   8.100 -
   8.101 -		vr_ctx.info.ipd = info.InterpupillaryDistance;
   8.102 -		for(int i=0; i<4; i++) {
   8.103 -			vr_ctx.info.distort[i] = info.DistortionK[i];
   8.104 -		}
   8.105 -
   8.106 -		Util::Render::StereoConfig stereohelp;
   8.107 -		stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
   8.108 -		stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
   8.109 -		stereohelp.SetHMDInfo(info);
   8.110 -		stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
   8.111 -
   8.112 -		vr_ctx.info.scale = stereohelp.GetDistortionScale();
   8.113 -
   8.114 -		float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
   8.115 -		vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
   8.116 -
   8.117 -		vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
   8.118 -
   8.119 -		// calculate center of projection shift to match the lens positions
   8.120 -		float center_dist_meters = info.HScreenSize * 0.25;
   8.121 -		float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
   8.122 -		vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
   8.123 -
   8.124 -		// grab the display info
   8.125 -		vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
   8.126 -		strcpy(vr_ctx.info.display, info.DisplayDeviceName);
   8.127 -
   8.128 -		vr_ctx.info.display_xoffs = info.DesktopX;
   8.129 -		vr_ctx.info.display_yoffs = info.DesktopY;
   8.130 -
   8.131 -		printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
   8.132 -				vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
   8.133 -	}
   8.134 -
   8.135 -	// get the sensor device
   8.136 -	if(vr_ctx.ovr_hmd_dev) {
   8.137 -		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
   8.138 -			fprintf(stderr, "failed to get oculus sensor device\n");
   8.139 -		}
   8.140 -	} else {
   8.141 -		if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
   8.142 -			fprintf(stderr, "failed to get oculus sensor device\n");
   8.143 -		}
   8.144 -	}
   8.145 -
   8.146 -	if(vr_ctx.ovr_sensor_dev) {
   8.147 -		SensorInfo sinfo;
   8.148 -		if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
   8.149 -			printf("oculus sensor device info:\n");
   8.150 -			printf("  name: %s\n", sinfo.ProductName);
   8.151 -		}
   8.152 -
   8.153 -		vr_ctx.ovr_sfusion = new SensorFusion;
   8.154 -		vr_ctx.ovr_sfusion->AttachToSensor(vr_ctx.ovr_sensor_dev);
   8.155 -	}
   8.156 -	return true;
   8.157 -}
   8.158 -
   8.159 -#undef EXTERNAL_SHADER
   8.160 -
   8.161 -static bool init_sdr()
   8.162 -{
   8.163 -	int status;
   8.164 -
   8.165 -#ifdef EXTERNAL_SHADER
   8.166 -	FILE *fp = fopen("sdr/sdr.glsl", "rb");
   8.167 -	if(!fp) {
   8.168 -		perror("failed to load sdr.glsl");
   8.169 -		return false;
   8.170 -	}
   8.171 -	fseek(fp, 0, SEEK_END);
   8.172 -	long sz = ftell(fp);
   8.173 -	rewind(fp);
   8.174 -
   8.175 -	char *buf = (char*)alloca(sz + 1);
   8.176 -	fread(buf, 1, sz, fp);
   8.177 -	buf[sz] = 0;
   8.178 -	sdr_src = buf;
   8.179 -
   8.180 -	fclose(fp);
   8.181 -#endif
   8.182 -
   8.183 -	unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
   8.184 -	glShaderSource(sdr, 1, &sdr_src, 0);
   8.185 -	glCompileShader(sdr);
   8.186 -	glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
   8.187 -	if(!status) {
   8.188 -		fprintf(stderr, "failed to compile distortion shader\n");
   8.189 -
   8.190 -		int loglen;
   8.191 -		glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
   8.192 -
   8.193 -		if(loglen > 0) {
   8.194 -			char *log = (char*)alloca(loglen);
   8.195 -			glGetShaderInfoLog(sdr, loglen, &loglen, log);
   8.196 -			fprintf(stderr, "%s\n", log);
   8.197 -		}
   8.198 -
   8.199 -		return false;
   8.200 -	}
   8.201 -
   8.202 -	sdrprog = glCreateProgram();
   8.203 -	glAttachShader(sdrprog, sdr);
   8.204 -	glLinkProgram(sdrprog);
   8.205 -	if(!status) {
   8.206 -		fprintf(stderr, "failed to link distortion shader program\n");
   8.207 -		glDeleteShader(sdr);
   8.208 -		return false;
   8.209 -	}
   8.210 -
   8.211 -	int loc;
   8.212 -
   8.213 -	glUseProgram(sdrprog);
   8.214 -
   8.215 -	if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
   8.216 -		glUniform1i(loc, 0);
   8.217 -	}
   8.218 -	if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   8.219 -		glUniform1f(loc, 0);
   8.220 -	}
   8.221 -	if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
   8.222 -		glUniform2f(loc, 0, 0);
   8.223 -	}
   8.224 -	if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
   8.225 -		glUniform1f(loc, vr_ctx.info.scale);
   8.226 -	}
   8.227 -	if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
   8.228 -		printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
   8.229 -		glUniform1f(loc, vr_ctx.info.aspect / 2.0);
   8.230 -	}
   8.231 -	if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
   8.232 -		glUniform2f(loc, 1, 1);
   8.233 -	}
   8.234 -	if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
   8.235 -		glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
   8.236 -				vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
   8.237 -	}
   8.238 -
   8.239 -	return true;
   8.240 -}
   8.241 -
   8.242 -extern "C" const char *vr_get_display_name(void)
   8.243 -{
   8.244 -	return vr_ctx.info.display;
   8.245 -}
   8.246 -
   8.247 -extern "C" void vr_get_display_pos(int *xptr, int *yptr)
   8.248 -{
   8.249 -	*xptr = vr_ctx.info.display_xoffs;
   8.250 -	*yptr = vr_ctx.info.display_yoffs;
   8.251 -}
   8.252 -
   8.253 -extern "C" int vr_get_width(void)
   8.254 -{
   8.255 -	return vr_ctx.info.width;
   8.256 -}
   8.257 -
   8.258 -extern "C" int vr_get_height(void)
   8.259 -{
   8.260 -	return vr_ctx.info.height;
   8.261 -}
   8.262 -
   8.263 -extern "C" float vr_get_fov(void)
   8.264 -{
   8.265 -	return vr_ctx.info.fov;
   8.266 -}
   8.267 -
   8.268 -extern "C" float vr_get_aspect(void)
   8.269 -{
   8.270 -	return vr_ctx.info.aspect;
   8.271 -}
   8.272 -
   8.273 -extern "C" void vr_set_eyedist(float ipd)
   8.274 -{
   8.275 -	vr_ctx.info.ipd = ipd;
   8.276 -}
   8.277 -
   8.278 -extern "C" float vr_get_eyedist(void)
   8.279 -{
   8.280 -	return vr_ctx.info.ipd;
   8.281 -}
   8.282 -
   8.283 -extern "C" void vr_set_distort(const float *coef)
   8.284 -{
   8.285 -	memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
   8.286 -}
   8.287 -
   8.288 -extern "C" void vr_get_distort(float *coef)
   8.289 -{
   8.290 -	memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
   8.291 -}
   8.292 -
   8.293 -extern "C" void vr_set_prediction_sec(float dt)
   8.294 -{
   8.295 -	vr_ctx.ovr_sfusion->SetPrediction(dt);
   8.296 -}
   8.297 -
   8.298 -extern "C" float vr_get_prediction_sec(void)
   8.299 -{
   8.300 -	return vr_ctx.ovr_sfusion->GetPredictionDelta();
   8.301 -}
   8.302 -
   8.303 -extern "C" void vr_get_view_matrix(float *res, int eye)
   8.304 -{
   8.305 -	// TODO
   8.306 -}
   8.307 -
   8.308 -extern "C" void vr_get_proj_matrix(float *res, int eye)
   8.309 -{
   8.310 -	static float eye_scale[] = {0.0, 1.0, -1.0};
   8.311 -
   8.312 -	Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
   8.313 -	proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
   8.314 -
   8.315 -	memcpy(res, proj.M[0], 16 * sizeof(float));
   8.316 -}
   8.317 -
   8.318 -extern "C" void vr_get_translation(float *offs)
   8.319 -{
   8.320 -	// current oculus devkit doesn't do translation
   8.321 -	offs[0] = offs[1] = offs[2] = 0.0f;
   8.322 -}
   8.323 -
   8.324 -extern "C" void vr_get_rotation(float *quat)
   8.325 -{
   8.326 -	Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
   8.327 -	quat[0] = oq.x;
   8.328 -	quat[1] = oq.y;
   8.329 -	quat[2] = oq.z;
   8.330 -	quat[3] = oq.w;
   8.331 -}
   8.332 -
   8.333 -extern "C" void vr_get_rotation_euler(float *euler)
   8.334 -{
   8.335 -	Quatf oq = vr_ctx.ovr_sfusion->GetPredictedOrientation();
   8.336 -	oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
   8.337 -}
   8.338 -
   8.339 -extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
   8.340 -{
   8.341 -	static const float rects[3][4] = {
   8.342 -		{-1, -1, 1, 1},
   8.343 -		{-1, -1, 0, 1},
   8.344 -		{0, -1, 1, 1}
   8.345 -	};
   8.346 -	static const float offs_scale[3] = {0.0, -1.0, 1.0};
   8.347 -
   8.348 -	glPushAttrib(GL_ENABLE_BIT);
   8.349 -	glDisable(GL_DEPTH_TEST);
   8.350 -	glDisable(GL_LIGHTING);
   8.351 -	glEnable(GL_TEXTURE_2D);
   8.352 -
   8.353 -	glMatrixMode(GL_MODELVIEW);
   8.354 -	glPushMatrix();
   8.355 -	glLoadIdentity();
   8.356 -
   8.357 -	glMatrixMode(GL_PROJECTION);
   8.358 -	glPushMatrix();
   8.359 -	glLoadIdentity();
   8.360 -
   8.361 -	glUseProgram(sdrprog);
   8.362 -
   8.363 -	if(sdrprog) {
   8.364 -		int loc;
   8.365 -		if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
   8.366 -			float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
   8.367 -			glUniform1f(loc, offset);
   8.368 -		}
   8.369 -
   8.370 -		if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
   8.371 -			glUniform2f(loc, tex_scale_x, tex_scale_y);
   8.372 -		}
   8.373 -	}
   8.374 -
   8.375 -	glBindTexture(GL_TEXTURE_2D, tex);
   8.376 -	glBegin(GL_QUADS);
   8.377 -	glColor4f(1, 1, 1, 1);
   8.378 -	glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
   8.379 -	glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
   8.380 -	glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
   8.381 -	glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
   8.382 -	glEnd();
   8.383 -
   8.384 -	glUseProgram(0);
   8.385 -
   8.386 -	glPopMatrix();
   8.387 -	glMatrixMode(GL_MODELVIEW);
   8.388 -	glPopMatrix();
   8.389 -
   8.390 -	glPopAttrib();
   8.391 -}
     9.1 --- a/src/vr/vr_impl.h	Tue Feb 25 19:53:34 2014 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,36 +0,0 @@
     9.4 -#ifndef VR_IMPL_H_
     9.5 -#define VR_IMPL_H_
     9.6 -
     9.7 -#include <OVR.h>
     9.8 -
     9.9 -using namespace OVR;
    9.10 -
    9.11 -struct VRContext {
    9.12 -	DeviceManager *ovr_devman;
    9.13 -	HMDDevice *ovr_hmd_dev;
    9.14 -	SensorDevice *ovr_sensor_dev;
    9.15 -	SensorFusion *ovr_sfusion;
    9.16 -
    9.17 -	struct {
    9.18 -		char *display;
    9.19 -		int display_xoffs, display_yoffs;
    9.20 -
    9.21 -		// the full width and height of the display (both eyes)
    9.22 -		int width, height;
    9.23 -		float fov;
    9.24 -		// the full aspect ratio of the display (both eyes)
    9.25 -		float aspect;
    9.26 -		float ipd;
    9.27 -		float distort[4];
    9.28 -		// the right lens center offset (negate for left)
    9.29 -		float lens_center_offset;
    9.30 -		float proj_center_offset;
    9.31 -		float scale;	// scaling to be applied to the two views to fill the screen
    9.32 -	} info;
    9.33 -};
    9.34 -
    9.35 -extern VRContext vr_ctx;
    9.36 -
    9.37 -bool vr_gl_init();
    9.38 -
    9.39 -#endif	// VR_IMPL_H_
    10.1 --- a/src/vr/vr_sdr.h	Tue Feb 25 19:53:34 2014 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,45 +0,0 @@
    10.4 -static const char *sdr_src =
    10.5 -	"uniform sampler2D tex;\n"
    10.6 -	"uniform float aspect, scale;\n"
    10.7 -	"uniform float lens_center_offset;\n"
    10.8 -	"uniform vec4 dist_factors;\n"
    10.9 -	"\n"
   10.10 -	"vec2 distort_texcoords(in vec2 tc);\n"
   10.11 -	"float barrel_scale(float x, in vec4 k);\n"
   10.12 -	"\n"
   10.13 -	"void main()\n"
   10.14 -	"{\n"
   10.15 -	"	vec2 tc = distort_texcoords(gl_TexCoord[0].xy);\n"
   10.16 -	"\n"
   10.17 -	"	float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;\n"
   10.18 -	"\n"
   10.19 -	"	gl_FragColor.rgb = texture2D(tex, tc).rgb * vis;\n"
   10.20 -	"	gl_FragColor.a = 1.0;\n"
   10.21 -	"}\n"
   10.22 -	"\n"
   10.23 -	"vec2 distort_texcoords(in vec2 tc)\n"
   10.24 -	"{\n"
   10.25 -	"	// map tc [0, 1] -> [-1, 1]\n"
   10.26 -	"	vec2 pt = tc * 2.0 - 1.0;\n"
   10.27 -	"\n"
   10.28 -	"	pt.x += lens_center_offset * 2.0;\n"
   10.29 -	"	pt.y /= aspect;	// correct for aspect ratio\n"
   10.30 -	"\n"
   10.31 -	"	float rad = barrel_scale(dot(pt, pt), dist_factors);\n"
   10.32 -	"	pt *= rad;	// scale the point by the computer distortion radius\n"
   10.33 -	"\n"
   10.34 -	"	pt /= scale;\n"
   10.35 -	"	pt.y *= aspect;\n"
   10.36 -	"	pt.x -= lens_center_offset * 2.0;\n"
   10.37 -	"\n"
   10.38 -	"	// map back to range [0, 1]\n"
   10.39 -	"	return pt * 0.5 + 0.5;\n"
   10.40 -	"}\n"
   10.41 -	"\n"
   10.42 -	"float barrel_scale(float rad, in vec4 k)\n"
   10.43 -	"{\n"
   10.44 -	"	float radsq = rad * rad;\n"
   10.45 -	"	float radquad = radsq * radsq;\n"
   10.46 -	"	return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq;\n"
   10.47 -	"}\n";
   10.48 -