# HG changeset patch # User John Tsiombikas # Date 1385294414 -7200 # Node ID d061fe1a31ec9744df1bd8d044f3a448503a4a8b # Parent b4c9a24c946ee1881d88a04c8973ed2e13ed25b5 compile vr source files or not diff -r b4c9a24c946e -r d061fe1a31ec Makefile.in --- a/Makefile.in Sun Nov 24 13:30:44 2013 +0200 +++ b/Makefile.in Sun Nov 24 14:00:14 2013 +0200 @@ -1,6 +1,9 @@ +ifdef use_vr + vr_ccsrc = $(wildcard src/vr/*.cc) +endif csrc = $(wildcard src/*.c) -ccsrc = $(wildcard src/*.cc) +ccsrc = $(wildcard src/*.cc) $(vr_ccsrc) obj = $(csrc:.c=.o) $(ccsrc:.cc=.o) dep = $(obj:.o=.d) name = goat3dgfx diff -r b4c9a24c946e -r d061fe1a31ec configure --- a/configure Sun Nov 24 13:30:44 2013 +0200 +++ b/configure Sun Nov 24 14:00:14 2013 +0200 @@ -199,6 +199,8 @@ emit "cfg_cflags = $CFLAGS" emit "cfg_ldflags = $LDFLAGS" + if $vr; then emit 'use_vr = true'; fi + cat Makefile.in >>Makefile } diff -r b4c9a24c946e -r d061fe1a31ec src/camera.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/camera.cc Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,235 @@ +#include "opengl.h" +#include "camera.h" +#include "vr.h" + +Camera::Camera() +{ + roll = 0.0; + inval_cache(); +} + +Camera::~Camera() +{ +} + +void Camera::calc_inv_matrix(Matrix4x4 *mat) const +{ + *mat = matrix().inverse(); +} + +const Matrix4x4 &Camera::matrix() const +{ + if(!mcache.valid) { + calc_matrix(&mcache.mat); + mcache.valid = true; + } + return mcache.mat; +} + +const Matrix4x4 &Camera::inv_matrix() const +{ + if(!mcache_inv.valid) { + calc_inv_matrix(&mcache_inv.mat); + mcache_inv.valid = true; + } + return mcache_inv.mat; +} + +void Camera::use() const +{ + mult_matrix(matrix()); +} + +void Camera::use_inverse() const +{ + mult_matrix(inv_matrix()); +} + +void Camera::input_move(float x, float y, float z) +{ +} + +void Camera::input_rotate(float x, float y, float z) +{ +} + +void Camera::input_zoom(float factor) +{ +} + + +// ---- orbit camera ---- + +OrbitCamera::OrbitCamera() +{ + theta = 0.0; + phi = 0.0; + rad = 10.0; +} + +OrbitCamera::~OrbitCamera() +{ +} + +void OrbitCamera::calc_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->translate(Vector3(0, 0, -rad)); + mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, theta, 0)); + mat->rotate(Vector3(0, 0, roll)); +} + +void OrbitCamera::calc_inv_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->rotate(Vector3(0, 0, roll)); + mat->rotate(Vector3(0, theta, 0)); + mat->rotate(Vector3(phi, 0, 0)); + mat->translate(Vector3(0, 0, -rad)); +} + +void OrbitCamera::input_rotate(float x, float y, float z) +{ + theta += y; + phi += x; + roll += z; + + if(phi < -M_PI / 2) + phi = -M_PI / 2; + if(phi > M_PI) + phi = M_PI; + + inval_cache(); +} + +void OrbitCamera::input_zoom(float factor) +{ + rad += factor; + if(rad < 0.0) + rad = 0.0; + + inval_cache(); +} + +void FpsCamera::calc_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->translate(Vector3(pos.x, pos.y, pos.z)); + mat->rotate(Vector3(0, theta, 0)); + mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, 0, roll)); +} + +void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->rotate(Vector3(0, 0, roll)); + mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, theta, 0)); + mat->translate(Vector3(-pos.x, -pos.y, -pos.z)); +} + +void FpsCamera::input_move(float x, float y, float z) +{ + pos.x += x * cos(theta) - z * sin(theta); + pos.z += x * sin(theta) + z * cos(theta); + pos.y += y; + inval_cache(); +} + +const Vector3 &FpsCamera::get_position() const +{ + return pos; +} + + +FlyCamera::FlyCamera() +{ + pos.z = 10.0f; +} + +void FlyCamera::calc_matrix(Matrix4x4 *mat) const +{ + Matrix3x3 rmat = rot.get_rotation_matrix().transposed(); + Matrix4x4 tmat; + tmat.set_translation(pos); + *mat = tmat * Matrix4x4(rmat); +} + +/*void FlyCamera::calc_inv_matrix(Matrix4x4 *mat) const +{ +}*/ + +const Vector3 &FlyCamera::get_position() const +{ + return pos; +} + +const Quaternion &FlyCamera::get_rotation() const +{ + return rot; +} + +void FlyCamera::input_move(float x, float y, float z) +{ + static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0); + + Vector3 k = vfwd.transformed(rot); + Vector3 i = vright.transformed(rot); + Vector3 j = cross_product(k, i); + + pos += i * x + j * y + k * z; + inval_cache(); +} + +void FlyCamera::input_rotate(float x, float y, float z) +{ + Vector3 axis(x, y, z); + float axis_len = axis.length(); + rot.rotate(axis / axis_len, axis_len); + rot.normalize(); + + inval_cache(); +} + + +// --- VR additions --- +VRFpsCamera::VRFpsCamera() +{ + neck_eye_dist = 0.14; // default neck->eye distance 14cm +} + +void VRFpsCamera::calc_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->translate(Vector3(pos.x, pos.y, pos.z)); + mat->rotate(Vector3(0, theta, 0)); + mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, 0, roll)); + mat->translate(Vector3(0, neck_eye_dist, 0)); +} + +void VRFpsCamera::calc_inv_matrix(Matrix4x4 *mat) const +{ + mat->reset_identity(); + mat->translate(Vector3(0, -neck_eye_dist, 0)); + mat->rotate(Vector3(0, 0, roll)); + mat->rotate(Vector3(phi, 0, 0)); + mat->rotate(Vector3(0, theta, 0)); + mat->translate(Vector3(-pos.x, -pos.y, -pos.z)); +} + +void VRFpsCamera::track_vr() +{ + float euler[3]; + vr_get_rotation_euler(euler); + + // input_rotate invalidates cache + input_rotate(prev_angles[0] - euler[0], prev_angles[1] - euler[1], prev_angles[2] - euler[2]); + + prev_angles[0] = euler[0]; + prev_angles[1] = euler[1]; + prev_angles[2] = euler[2]; +} + diff -r b4c9a24c946e -r d061fe1a31ec src/camera.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/camera.h Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,98 @@ +#ifndef CAMERA_H_ +#define CAMERA_H_ + +#include + +class Camera { +protected: + float roll; + + mutable struct { + bool valid; + Matrix4x4 mat; + } mcache, mcache_inv; + + virtual void calc_matrix(Matrix4x4 *mat) const = 0; + virtual void calc_inv_matrix(Matrix4x4 *mat) const; + + void inval_cache() { mcache.valid = mcache_inv.valid = false; } + void set_glmat(const Matrix4x4 &m) const; + +public: + Camera(); + virtual ~Camera(); + + const Matrix4x4 &matrix() const; + const Matrix4x4 &inv_matrix() const; + + void use() const; + void use_inverse() const; + + // these do nothing, override to provide input handling + virtual void input_move(float x, float y, float z); + virtual void input_rotate(float x, float y, float z); + virtual void input_zoom(float factor); +}; + +class OrbitCamera : public Camera { +protected: + float theta, phi, rad; + + void calc_matrix(Matrix4x4 *mat) const; + void calc_inv_matrix(Matrix4x4 *mat) const; + +public: + OrbitCamera(); + virtual ~OrbitCamera(); + + void input_rotate(float x, float y, float z); + void input_zoom(float factor); +}; + +class FpsCamera : public OrbitCamera { +protected: + Vector3 pos; + + void calc_matrix(Matrix4x4 *mat) const; + void calc_inv_matrix(Matrix4x4 *mat) const; + +public: + void input_move(float x, float y, float z); + + const Vector3 &get_position() const; +}; + +class FlyCamera : public Camera { +private: + Vector3 pos; + Quaternion rot; + + void calc_matrix(Matrix4x4 *mat) const; + //void calc_inv_matrix(Matrix4x4 *mat) const; + +public: + FlyCamera(); + + const Vector3 &get_position() const; + const Quaternion &get_rotation() const; + + void input_move(float x, float y, float z); + void input_rotate(float x, float y, float z); +}; + + +class VRFpsCamera : public FpsCamera { +private: + float neck_eye_dist; + float prev_angles[3]; + + void calc_matrix(Matrix4x4 *mat) const; + void calc_inv_matrix(Matrix4x4 *mat) const; + +public: + VRFpsCamera(); + + void track_vr(); +}; + +#endif // CAMERA_H_ diff -r b4c9a24c946e -r d061fe1a31ec src/goat3dgfx.cc --- a/src/goat3dgfx.cc Sun Nov 24 13:30:44 2013 +0200 +++ b/src/goat3dgfx.cc Sun Nov 24 14:00:14 2013 +0200 @@ -1,4 +1,7 @@ +#include "config.h" #include "goat3dgfx.h" +#include "vr.h" +#include "logger.h" bool init_goat_graphics() { @@ -6,6 +9,13 @@ glewInit(); +#ifdef USE_VR + if(vr_init() == -1) { + log_fatal("failed to initialize the VR system\n"); + return false; + } +#endif + return true; } diff -r b4c9a24c946e -r d061fe1a31ec src/vr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vr.h Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,63 @@ +#ifndef GOAT3DGFX_VR_H_ +#define GOAT3DGFX_VR_H_ + +/* VR mode init options */ +enum vr_init_mode { + VR_INIT_NONE, + VR_INIT_OCULUS, + VR_INIT_STEREO +}; + +/* possible eye values */ +enum { + VR_EYE_CENTER, + VR_EYE_LEFT, + VR_EYE_RIGHT +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int vr_init(enum vr_init_mode mode); +void vr_shutdown(void); + +const char *vr_get_display_name(void); +void vr_get_display_pos(int *xptr, int *yptr); + +int vr_get_width(void); +int vr_get_height(void); + +float vr_get_fov(void); +float vr_get_aspect(void); + +void vr_set_eyedist(float ipd); +float vr_get_eyedist(void); + +/* expects an array of 4 barrel distortion coefficients: + * polar scale: k_0 + k_1 r^2 + k_2 r^4 + k_3 r^6 + */ +void vr_set_distort(const float *coef); +void vr_get_distort(float *coef); + +void vr_set_prediction_sec(float dt); +float vr_get_prediction_sec(void); + +void vr_get_view_matrix(float *res, int eye); +void vr_get_proj_matrix(float *res, int eye); + +/* expects an array of at least 3 floats (x, y, z, offset). */ +void vr_get_translation(float *offs); +/* expects an array of at least 4 floats (x, y, z, w, quaternion). */ +void vr_get_rotation(float *quat); +/* expects an array of at least 3 floats (pitch, yaw, roll, angles). */ +void vr_get_rotation_euler(float *euler); + +/* OpenGL stuff */ +void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y); + +#ifdef __cplusplus +} +#endif + +#endif /* GOAT3DGFX_VR_H_ */ diff -r b4c9a24c946e -r d061fe1a31ec src/vr/vr.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vr/vr.cc Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,384 @@ +#include +#include +#include "vr.h" +#include "vr_impl.h" +#include "vr_sdr.h" + +#ifndef WIN32 +#include +#else +#include +#endif + +static void init_ctx(); +static bool init_ovr(); +static bool init_sdr(); + +VRContext vr_ctx; +static unsigned int sdrprog; + +extern "C" int vr_init(enum vr_init_mode mode) +{ + init_ctx(); + + if(!init_ovr()) { + return -1; + } + + if(!init_sdr()) { + return -1; + } + + return 0; +} + +extern "C" void vr_shutdown(void) +{ + delete [] vr_ctx.info.display; + //System::Destroy(); +} + +static void init_ctx() +{ + vr_ctx.info.width = 1280; + vr_ctx.info.height = 800; + vr_ctx.info.fov = M_PI / 2.0; + vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height; + vr_ctx.info.ipd = 0.035; + vr_ctx.info.scale = 1.0; +} + +static bool init_ovr() +{ + LogMaskConstants log_level = LogMask_All; + // initialize Oculus SDK + const char *logenv = getenv("VR_LOGLEVEL"); + if(logenv) { + switch(atoi(logenv)) { + case 0: + log_level = LogMask_None; + break; + case 1: + log_level = LogMask_Regular; + break; + case 2: + default: + log_level = LogMask_All; + break; + } + } + + System::Init(Log::ConfigureDefaultLog(log_level)); + if(!(vr_ctx.ovr_devman = DeviceManager::Create())) { + fprintf(stderr, "failed to create OVR device manager\n"); + return false; + } + + // create the display device + HMDInfo info; + if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices().CreateDevice())) { + fprintf(stderr, "no oculus rift devices found\n"); + } else { + if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) { + printf("oculus device info:\n"); + printf(" name: %s\n", info.DisplayDeviceName); + printf(" ipd: %f\n", info.InterpupillaryDistance); + printf(" distortion: %f %f %f %f\n", info.DistortionK[0], + info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]); + } + + // calculate and store viewing parameters + vr_ctx.info.width = info.HResolution; + vr_ctx.info.height = info.VResolution; + vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height; + + vr_ctx.info.ipd = info.InterpupillaryDistance; + for(int i=0; i<4; i++) { + vr_ctx.info.distort[i] = info.DistortionK[i]; + } + + Util::Render::StereoConfig stereohelp; + stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height)); + stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass); + stereohelp.SetHMDInfo(info); + stereohelp.SetDistortionFitPointVP(-1.0, 0.0); + + vr_ctx.info.scale = stereohelp.GetDistortionScale(); + + float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5; + vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance); + + vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize; + + // calculate center of projection shift to match the lens positions + float center_dist_meters = info.HScreenSize * 0.25; + float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5; + vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize; + + // grab the display info + vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1]; + strcpy(vr_ctx.info.display, info.DisplayDeviceName); + + vr_ctx.info.display_xoffs = info.DesktopX; + vr_ctx.info.display_yoffs = info.DesktopY; + + printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display, + vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs); + } + + // get the sensor device + if(vr_ctx.ovr_hmd_dev) { + if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) { + fprintf(stderr, "failed to get oculus sensor device\n"); + } + } else { + if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices().CreateDevice())) { + fprintf(stderr, "failed to get oculus sensor device\n"); + } + } + + if(vr_ctx.ovr_sensor_dev) { + SensorInfo sinfo; + if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) { + printf("oculus sensor device info:\n"); + printf(" name: %s\n", sinfo.ProductName); + } + + vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev); + } + return true; +} + +#undef EXTERNAL_SHADER + +static bool init_sdr() +{ + int status; + +#ifdef EXTERNAL_SHADER + FILE *fp = fopen("sdr/sdr.glsl", "rb"); + if(!fp) { + perror("failed to load sdr.glsl"); + return false; + } + fseek(fp, 0, SEEK_END); + long sz = ftell(fp); + rewind(fp); + + char *buf = (char*)alloca(sz + 1); + fread(buf, 1, sz, fp); + buf[sz] = 0; + sdr_src = buf; + + fclose(fp); +#endif + + unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(sdr, 1, &sdr_src, 0); + glCompileShader(sdr); + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); + if(!status) { + fprintf(stderr, "failed to compile distortion shader\n"); + + int loglen; + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen); + + if(loglen > 0) { + char *log = (char*)alloca(loglen); + glGetShaderInfoLog(sdr, loglen, &loglen, log); + fprintf(stderr, "%s\n", log); + } + + return false; + } + + sdrprog = glCreateProgram(); + glAttachShader(sdrprog, sdr); + glLinkProgram(sdrprog); + if(!status) { + fprintf(stderr, "failed to link distortion shader program\n"); + glDeleteShader(sdr); + return false; + } + + int loc; + + glUseProgram(sdrprog); + + if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) { + glUniform1i(loc, 0); + } + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { + glUniform1f(loc, 0); + } + if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) { + glUniform2f(loc, 0, 0); + } + if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) { + glUniform1f(loc, vr_ctx.info.scale); + } + if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) { + printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0); + glUniform1f(loc, vr_ctx.info.aspect / 2.0); + } + if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) { + glUniform2f(loc, 1, 1); + } + if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) { + glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1], + vr_ctx.info.distort[2], vr_ctx.info.distort[3]); + } + + return true; +} + +extern "C" const char *vr_get_display_name(void) +{ + return vr_ctx.info.display; +} + +extern "C" void vr_get_display_pos(int *xptr, int *yptr) +{ + *xptr = vr_ctx.info.display_xoffs; + *yptr = vr_ctx.info.display_yoffs; +} + +extern "C" int vr_get_width(void) +{ + return vr_ctx.info.width; +} + +extern "C" int vr_get_height(void) +{ + return vr_ctx.info.height; +} + +extern "C" float vr_get_fov(void) +{ + return vr_ctx.info.fov; +} + +extern "C" float vr_get_aspect(void) +{ + return vr_ctx.info.aspect; +} + +extern "C" void vr_set_eyedist(float ipd) +{ + vr_ctx.info.ipd = ipd; +} + +extern "C" float vr_get_eyedist(void) +{ + return vr_ctx.info.ipd; +} + +extern "C" void vr_set_distort(const float *coef) +{ + memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort); +} + +extern "C" void vr_get_distort(float *coef) +{ + memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort); +} + +extern "C" void vr_set_prediction_sec(float dt) +{ + vr_ctx.ovr_sfusion.SetPrediction(dt); +} + +extern "C" float vr_get_prediction_sec(void) +{ + return vr_ctx.ovr_sfusion.GetPredictionDelta(); +} + +extern "C" void vr_get_view_matrix(float *res, int eye) +{ + // TODO +} + +extern "C" void vr_get_proj_matrix(float *res, int eye) +{ + static float eye_scale[] = {0.0, 1.0, -1.0}; + + Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0); + proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj; + + memcpy(res, proj.M[0], 16 * sizeof(float)); +} + +extern "C" void vr_get_translation(float *offs) +{ + // current oculus devkit doesn't do translation + offs[0] = offs[1] = offs[2] = 0.0f; +} + +extern "C" void vr_get_rotation(float *quat) +{ + Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation(); + quat[0] = oq.x; + quat[1] = oq.y; + quat[2] = oq.z; + quat[3] = oq.w; +} + +extern "C" void vr_get_rotation_euler(float *euler) +{ + Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation(); + oq.GetEulerAngles(euler + 1, euler, euler + 2); +} + +extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y) +{ + static const float rects[3][4] = { + {-1, -1, 1, 1}, + {-1, -1, 0, 1}, + {0, -1, 1, 1} + }; + static const float offs_scale[3] = {0.0, -1.0, 1.0}; + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glUseProgram(sdrprog); + + if(sdrprog) { + int loc; + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; + glUniform1f(loc, offset); + } + + if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { + glUniform2f(loc, tex_scale_x, tex_scale_y); + } + } + + glBindTexture(GL_TEXTURE_2D, tex); + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 1); + glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); + glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); + glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); + glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); + glEnd(); + + glUseProgram(0); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} diff -r b4c9a24c946e -r d061fe1a31ec src/vr/vr_impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vr/vr_impl.h Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,36 @@ +#ifndef VR_IMPL_H_ +#define VR_IMPL_H_ + +#include + +using namespace OVR; + +struct VRContext { + DeviceManager *ovr_devman; + HMDDevice *ovr_hmd_dev; + SensorDevice *ovr_sensor_dev; + SensorFusion ovr_sfusion; + + struct { + char *display; + int display_xoffs, display_yoffs; + + // the full width and height of the display (both eyes) + int width, height; + float fov; + // the full aspect ratio of the display (both eyes) + float aspect; + float ipd; + float distort[4]; + // the right lens center offset (negate for left) + float lens_center_offset; + float proj_center_offset; + float scale; // scaling to be applied to the two views to fill the screen + } info; +}; + +extern VRContext vr_ctx; + +bool vr_gl_init(); + +#endif // VR_IMPL_H_ diff -r b4c9a24c946e -r d061fe1a31ec src/vr/vr_sdr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vr/vr_sdr.h Sun Nov 24 14:00:14 2013 +0200 @@ -0,0 +1,45 @@ +static const char *sdr_src = + "uniform sampler2D tex;\n" + "uniform float aspect, scale;\n" + "uniform float lens_center_offset;\n" + "uniform vec4 dist_factors;\n" + "\n" + "vec2 distort_texcoords(in vec2 tc);\n" + "float barrel_scale(float x, in vec4 k);\n" + "\n" + "void main()\n" + "{\n" + " vec2 tc = distort_texcoords(gl_TexCoord[0].xy);\n" + "\n" + " float vis = any(greaterThan(tc, vec2(1.0)) || lessThan(tc, vec2(0.0))) ? 0.0 : 1.0;\n" + "\n" + " gl_FragColor.rgb = texture2D(tex, tc).rgb * vis;\n" + " gl_FragColor.a = 1.0;\n" + "}\n" + "\n" + "vec2 distort_texcoords(in vec2 tc)\n" + "{\n" + " // map tc [0, 1] -> [-1, 1]\n" + " vec2 pt = tc * 2.0 - 1.0;\n" + "\n" + " pt.x += lens_center_offset * 2.0;\n" + " pt.y /= aspect; // correct for aspect ratio\n" + "\n" + " float rad = barrel_scale(dot(pt, pt), dist_factors);\n" + " pt *= rad; // scale the point by the computer distortion radius\n" + "\n" + " pt /= scale;\n" + " pt.y *= aspect;\n" + " pt.x -= lens_center_offset * 2.0;\n" + "\n" + " // map back to range [0, 1]\n" + " return pt * 0.5 + 0.5;\n" + "}\n" + "\n" + "float barrel_scale(float rad, in vec4 k)\n" + "{\n" + " float radsq = rad * rad;\n" + " float radquad = radsq * radsq;\n" + " return k.x + k.y * radsq + k.z * radquad + k.w * radquad * radsq;\n" + "}\n"; +