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 -