Name LibOVR classes after the API, not the device
authorMikko Rasa <tdb@tdb.fi>
Mon, 3 Oct 2016 12:47:59 +0000 (15:47 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 3 Oct 2016 12:48:50 +0000 (15:48 +0300)
16 files changed:
Build
source/libovr/libovrcamera.cpp [new file with mode: 0644]
source/libovr/libovrcamera.h [new file with mode: 0644]
source/libovr/libovrcombiner.cpp [new file with mode: 0644]
source/libovr/libovrcombiner.h [new file with mode: 0644]
source/libovr/libovrsystem.cpp [new file with mode: 0644]
source/libovr/libovrsystem.h [new file with mode: 0644]
source/libovr/libovrsystem_private.h [new file with mode: 0644]
source/ovr/oculusriftcamera.cpp [deleted file]
source/ovr/oculusriftcamera.h [deleted file]
source/ovr/oculusriftcombiner.cpp [deleted file]
source/ovr/oculusriftcombiner.h [deleted file]
source/ovr/oculusriftsystem.cpp [deleted file]
source/ovr/oculusriftsystem.h [deleted file]
source/ovr/oculusriftsystem_private.h [deleted file]
source/system.cpp

diff --git a/Build b/Build
index 98da6b937c45140a0fc45979735f2f7db776e97d..fa837ec0cf19603f5426076b998b388631281009 100644 (file)
--- a/Build
+++ b/Build
@@ -31,7 +31,7 @@ package "mspvr"
                source "source";
                if_feature "libovr"
                {
-                       source "source/ovr";
+                       source "source/libovr";
                };
                if_feature "openvr"
                {
diff --git a/source/libovr/libovrcamera.cpp b/source/libovr/libovrcamera.cpp
new file mode 100644 (file)
index 0000000..7446086
--- /dev/null
@@ -0,0 +1,36 @@
+#include "libovrcamera.h"
+#include "libovrsystem.h"
+#include "libovrsystem_private.h"
+
+namespace Msp {
+namespace VR {
+
+LibOVRCamera::LibOVRCamera(const LibOVRSystem &d, const GL::Camera &c):
+       HeadTrackingCamera(c),
+       device(d)
+{
+       unsigned supported = ovrTrackingCap_Orientation|ovrTrackingCap_MagYawCorrection|ovrTrackingCap_Position;
+       ovrHmd_ConfigureTracking(device.get_private().ovr_hmd, supported, 0);
+}
+
+void LibOVRCamera::reset_tracking()
+{
+       ovrHmd_RecenterPose(device.get_private().ovr_hmd);
+}
+
+void LibOVRCamera::update()
+{
+       double time;
+       if(device.is_timing_active())
+               time = device.get_tracking_time();
+       else
+               time = device.get_current_time();
+
+       ovrTrackingState state = ovrHmd_GetTrackingState(device.get_private().ovr_hmd, time);
+       OVR::Posef head_pose = state.HeadPose.ThePose;
+       OVR::Matrix4f tracking_matrix(head_pose);
+       update_from_matrix(transpose(GL::Matrix(&tracking_matrix.M[0][0])));
+}
+
+} // namespace VR
+} // namespace Msp
diff --git a/source/libovr/libovrcamera.h b/source/libovr/libovrcamera.h
new file mode 100644 (file)
index 0000000..44495b0
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef MSP_VR_LIBOVRCAMERA_H_
+#define MSP_VR_LIBOVRCAMERA_H_
+
+#include <msp/vr/headtrackingcamera.h>
+
+namespace Msp {
+namespace VR {
+
+class LibOVRSystem;
+
+class LibOVRCamera: public HeadTrackingCamera
+{
+private:
+       const LibOVRSystem &device;
+
+public:
+       LibOVRCamera(const LibOVRSystem &, const GL::Camera &);
+
+       virtual void reset_tracking();
+       virtual void update();
+};
+
+} // namespace VR
+} // namespace Msp
+
+#endif
diff --git a/source/libovr/libovrcombiner.cpp b/source/libovr/libovrcombiner.cpp
new file mode 100644 (file)
index 0000000..5eddb4a
--- /dev/null
@@ -0,0 +1,176 @@
+#include <msp/gl/meshbuilder.h>
+#include <msp/gl/texture2d.h>
+#include "libovrcombiner.h"
+#include "libovrsystem.h"
+#include "libovrsystem_private.h"
+
+using namespace std;
+
+
+namespace {
+
+const char vs_source[] =
+       "uniform mat4 timewarp[2];\n"
+       "uniform vec2 uv_scale;\n"
+       "uniform vec2 uv_offset;\n"
+       "varying vec2 texcoord_r;\n"
+       "varying vec2 texcoord_g;\n"
+       "varying vec2 texcoord_b;\n"
+       "varying float vignette;\n"
+       "vec2 apply_timewarp(vec2 coords, float factor)\n"
+       "{\n"
+       "       vec4 coords4 = vec4(coords, 1.0, 1.0);\n"
+       "       vec4 warped = mix(timewarp[0]*coords4, timewarp[1]*coords4, factor);\n"
+       "       return (warped.xy/warped.z)*uv_scale+uv_offset;\n"
+       "}\n"
+       "void main()\n"
+       "{\n"
+       "       gl_Position = vec4(gl_Vertex.xy, 0.5, 1.0);\n"
+       "       float tw_factor = gl_MultiTexCoord3.y;\n"
+       "       texcoord_r = apply_timewarp(gl_MultiTexCoord0.xy, tw_factor);\n"
+       "       texcoord_g = apply_timewarp(gl_MultiTexCoord1.xy, tw_factor);\n"
+       "       texcoord_b = apply_timewarp(gl_MultiTexCoord2.xy, tw_factor);\n"
+       "       vignette = gl_MultiTexCoord3.x;\n"
+       "}\n";
+
+const char fs_source[] =
+       "uniform sampler2D texture;\n"
+       "varying vec2 texcoord_r;\n"
+       "varying vec2 texcoord_g;\n"
+       "varying vec2 texcoord_b;\n"
+       "varying float vignette;\n"
+       "void main()\n"
+       "{\n"
+       "       float r = texture2D(texture, texcoord_r).r;\n"
+       "       float g = texture2D(texture, texcoord_g).g;\n"
+       "       float b = texture2D(texture, texcoord_b).b;\n"
+       "       gl_FragColor = vec4(vec3(r, g, b)*vignette, 1.0);\n"
+       "}\n";
+
+void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov)
+{
+       ovrDistortionMesh ovr_mesh;
+       ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Vignette|ovrDistortionCap_TimeWarp, &ovr_mesh);
+
+       Msp::GL::MeshBuilder bld(mesh);
+       for(unsigned i=0; i<ovr_mesh.VertexCount; ++i)
+       {
+               ovrDistortionVertex &v = ovr_mesh.pVertexData[i];
+               bld.multitexcoord(0, v.TanEyeAnglesR.x, v.TanEyeAnglesR.y);
+               bld.multitexcoord(1, v.TanEyeAnglesG.x, v.TanEyeAnglesG.y);
+               bld.multitexcoord(2, v.TanEyeAnglesB.x, v.TanEyeAnglesB.y);
+               bld.multitexcoord(3, v.VignetteFactor, v.TimeWarpFactor);
+               bld.vertex(v.ScreenPosNDC.x, v.ScreenPosNDC.y);
+       }
+
+       Msp::GL::Batch batch(Msp::GL::TRIANGLES);
+       batch.append(vector<unsigned>(ovr_mesh.pIndexData, ovr_mesh.pIndexData+ovr_mesh.IndexCount));
+       mesh.add_batch(batch);
+
+       ovrHmd_DestroyDistortionMesh(&ovr_mesh);
+}
+
+}
+
+namespace Msp {
+namespace VR {
+
+struct LibOVRCombiner::Frustum: StereoCombiner::Frustum
+{
+       Frustum(const ovrFovPort &);
+};
+
+
+LibOVRCombiner::LibOVRCombiner(LibOVRSystem &d, GL::View &v):
+       device(d),
+       view(v),
+       left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
+       right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
+       shprog(vs_source, fs_source)
+{
+       ovrHmd hmd = device.get_private().ovr_hmd;
+
+       ovrFovPort left_fov = hmd->DefaultEyeFov[ovrEye_Left];
+       ovrFovPort right_fov = hmd->DefaultEyeFov[ovrEye_Right];
+       configure_eye_frustums(Frustum(left_fov), Frustum(right_fov));
+
+       left_fov.UpTan = left_fov.DownTan = tan(fov/2.0f);
+       left_fov.LeftTan = left_fov.UpTan*render_aspect*(1-frustum_skew);
+       left_fov.RightTan = left_fov.UpTan*render_aspect*(1+frustum_skew);
+       right_fov = left_fov;
+       swap(right_fov.LeftTan, right_fov.RightTan);
+
+       create_distortion_mesh(left_mesh, hmd, ovrEye_Left, left_fov);
+       create_distortion_mesh(right_mesh, hmd, ovrEye_Right, right_fov);
+
+       ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0);
+       target_width = tex_size.w;
+       target_height = tex_size.h;
+
+       left_shdata.uniform("texture", 0);
+       right_shdata.uniform("texture", 0);
+
+       ovrRecti view_rect;
+       view_rect.Pos.x = 0;
+       view_rect.Pos.y = 0;
+       view_rect.Size = tex_size;
+       ovrVector2f uv_scale_offset[2];
+       ovrHmd_GetRenderScaleAndOffset(left_fov, tex_size, view_rect, uv_scale_offset);
+       left_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
+       left_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
+       ovrHmd_GetRenderScaleAndOffset(right_fov, tex_size, view_rect, uv_scale_offset);
+       right_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
+       right_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
+
+       device.configure_window(view.get_window());
+}
+
+void LibOVRCombiner::prepare() const
+{
+       device.begin_frame();
+}
+
+void LibOVRCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
+{
+       GL::Bind bind_shprog(shprog);
+
+       ovrHmd hmd = device.get_private().ovr_hmd;
+
+       if(device.is_timing_active())
+       {
+               ovr_WaitTillTime(device.get_timewarp_time());
+               ovrTrackingState state = ovrHmd_GetTrackingState(hmd, device.get_tracking_time());
+
+               ovrMatrix4f matrices[2];
+               ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Left, state.HeadPose.ThePose, matrices);
+               left_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
+
+               ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Right, state.HeadPose.ThePose, matrices);
+               right_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
+       }
+       else
+       {
+               GL::Matrix matrices[2];
+               left_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
+               right_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
+       }
+
+       GL::Bind bind_tex(left);
+       left_shdata.apply();
+       left_mesh.draw();
+
+       right.bind();
+       right_shdata.apply();
+       right_mesh.draw();
+
+       view.get_context().swap_buffers();
+       device.end_frame();
+}
+
+
+LibOVRCombiner::Frustum::Frustum(const ovrFovPort &fov):
+       StereoCombiner::Frustum(-fov.LeftTan, fov.RightTan, -fov.DownTan, fov.UpTan)
+{ }
+
+} // namespace VR
+} // namespace Msp
diff --git a/source/libovr/libovrcombiner.h b/source/libovr/libovrcombiner.h
new file mode 100644 (file)
index 0000000..789de55
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef MSP_VR_LIBOVRCOMBINER_H_
+#define MSP_VR_LIBOVRCOMBINER_H_
+
+#include <msp/gl/mesh.h>
+#include <msp/gl/program.h>
+#include <msp/gl/programdata.h>
+#include <msp/gl/view.h>
+#include <msp/vr/stereocombiner.h>
+
+namespace Msp {
+namespace VR {
+
+class LibOVRSystem;
+
+/**
+Presents a stereo view in a way suitable for an Oculus Rift HMD.  All distances
+are specified in multiples of the screen width.
+*/
+class LibOVRCombiner: public StereoCombiner
+{
+private:
+       struct Frustum;
+
+       LibOVRSystem &device;
+       GL::View &view;
+       GL::Mesh left_mesh;
+       GL::Mesh right_mesh;
+       GL::Program shprog;
+       mutable GL::ProgramData left_shdata;
+       mutable GL::ProgramData right_shdata;
+
+public:
+       LibOVRCombiner(LibOVRSystem &, GL::View &);
+
+       virtual void prepare() const;
+       virtual void render(const GL::Texture2D &, const GL::Texture2D &) const;
+};
+
+} // namespace VR
+} // namespace Msp
+
+#endif
diff --git a/source/libovr/libovrsystem.cpp b/source/libovr/libovrsystem.cpp
new file mode 100644 (file)
index 0000000..c8183b0
--- /dev/null
@@ -0,0 +1,111 @@
+#include <msp/graphics/display.h>
+#include <msp/vr/stereoview.h>
+#include "libovrsystem.h"
+#include "libovrsystem_private.h"
+
+using namespace std;
+
+namespace Msp {
+namespace VR {
+
+unsigned LibOVRSystem::n_instances = 0;
+
+LibOVRSystem::LibOVRSystem():
+       priv(new Private),
+       frame_index(0)
+{
+       if(!n_instances)
+               ovr_Initialize();
+       ++n_instances;
+
+       priv->ovr_hmd = ovrHmd_Create(0);
+       if(!priv->ovr_hmd)
+       {
+               delete priv;
+               // XXX decrement n_instances
+               throw runtime_error("rift hmd not found");
+       }
+}
+
+LibOVRSystem::~LibOVRSystem()
+{
+       ovrHmd_Destroy(priv->ovr_hmd);
+       delete priv;
+
+       --n_instances;
+       if(!n_instances)
+               ovr_Shutdown();
+}
+
+void LibOVRSystem::configure_window(Graphics::Window &window) const
+{
+       Graphics::WindowOptions win_opts = window.get_options();
+       win_opts.width = priv->ovr_hmd->Resolution.w;
+       win_opts.height = priv->ovr_hmd->Resolution.h;
+
+       const list<Graphics::Monitor> &monitors = window.get_display().get_monitors();
+       string hmd_name = priv->ovr_hmd->ProductName;
+       for(list<Graphics::Monitor>::const_iterator i=monitors.begin(); i!=monitors.end(); ++i)
+               if(hmd_name.find(i->name)!=string::npos)
+               {
+                       win_opts.fullscreen = true;
+                       win_opts.fullscreen_monitor = &*i;
+                       win_opts.fullscreen_exclusive = false;
+               }
+
+       window.reconfigure(win_opts);
+}
+
+void LibOVRSystem::configure_view(StereoView &view) const
+{
+       ovrEyeRenderDesc left_desc = ovrHmd_GetRenderDesc(priv->ovr_hmd, ovrEye_Left, priv->ovr_hmd->DefaultEyeFov[ovrEye_Left]);
+       ovrEyeRenderDesc right_desc = ovrHmd_GetRenderDesc(priv->ovr_hmd, ovrEye_Right, priv->ovr_hmd->DefaultEyeFov[ovrEye_Left]);
+       const ovrVector3f &l = left_desc.HmdToEyeViewOffset;
+       const ovrVector3f &r = right_desc.HmdToEyeViewOffset;
+       view.set_eye_matrices(GL::Matrix::translation(GL::Vector3(l.x, l.y, l.z)), GL::Matrix::translation(GL::Vector3(r.x, r.y, r.z)));
+}
+
+LibOVRCamera *LibOVRSystem::create_camera(const GL::Camera &bc)
+{
+       return new LibOVRCamera(*this, bc);
+}
+
+LibOVRCombiner *LibOVRSystem::create_combiner(GL::View &view)
+{
+       return new LibOVRCombiner(*this, view);
+}
+
+void LibOVRSystem::begin_frame()
+{
+       priv->frame_timing = ovrHmd_BeginFrameTiming(priv->ovr_hmd, ++frame_index);
+       timing_active = true;
+}
+
+void LibOVRSystem::end_frame()
+{
+       glFinish();
+       ovrHmd_EndFrameTiming(priv->ovr_hmd);
+       timing_active = false;
+}
+
+double LibOVRSystem::get_tracking_time() const
+{
+       if(!timing_active)
+               throw logic_error("timing not active");
+       return priv->frame_timing.ScanoutMidpointSeconds;
+}
+
+double LibOVRSystem::get_timewarp_time() const
+{
+       if(!timing_active)
+               throw logic_error("timing not active");
+       return priv->frame_timing.TimewarpPointSeconds;
+}
+
+double LibOVRSystem::get_current_time() const
+{
+       return ovr_GetTimeInSeconds();
+}
+
+} // namespace VR
+} // namespace Msp
diff --git a/source/libovr/libovrsystem.h b/source/libovr/libovrsystem.h
new file mode 100644 (file)
index 0000000..d5623a0
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef MSP_VR_LIBOVRSYSTEM_H_
+#define MSP_VR_LIBOVRSYSTEM_H_
+
+#include <msp/vr/system.h>
+#include "libovrcamera.h"
+#include "libovrcombiner.h"
+
+namespace Msp {
+namespace VR {
+
+class LibOVRSystem: public System
+{
+public:
+       struct Private;
+
+private:
+       Private *priv;
+       unsigned frame_index;
+       bool timing_active;
+
+       static unsigned n_instances;
+
+public:
+       LibOVRSystem();
+       virtual ~LibOVRSystem();
+
+       const Private &get_private() const { return *priv; }
+
+       virtual void configure_window(Graphics::Window &) const;
+       virtual void configure_view(StereoView &) const;
+       virtual LibOVRCamera *create_camera(const GL::Camera &);
+       virtual LibOVRCombiner *create_combiner(GL::View &);
+
+       void begin_frame();
+       void end_frame();
+       bool is_timing_active() const { return timing_active; }
+       double get_tracking_time() const;
+       double get_timewarp_time() const;
+       double get_current_time() const;
+};
+
+} // namespace VR
+} // namespace Msp
+
+#endif
diff --git a/source/libovr/libovrsystem_private.h b/source/libovr/libovrsystem_private.h
new file mode 100644 (file)
index 0000000..d75f9f8
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef MSP_VR_LIBOVRSYSTEM_PRIVATE_H_
+#define MSP_VR_LIBOVRSYSTEM_PRIVATE_H_
+
+#include <OVR.h>
+#include "libovrsystem.h"
+
+namespace Msp {
+namespace VR {
+
+struct LibOVRSystem::Private
+{
+       ovrHmd ovr_hmd;
+       ovrFrameTiming frame_timing;
+};
+
+} // namespace VR
+} // namespace Msp
+
+#endif
diff --git a/source/ovr/oculusriftcamera.cpp b/source/ovr/oculusriftcamera.cpp
deleted file mode 100644 (file)
index 4da732b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "oculusriftcamera.h"
-#include "oculusriftsystem.h"
-#include "oculusriftsystem_private.h"
-
-namespace Msp {
-namespace VR {
-
-OculusRiftCamera::OculusRiftCamera(const OculusRiftSystem &d, const GL::Camera &c):
-       HeadTrackingCamera(c),
-       device(d)
-{
-       unsigned supported = ovrTrackingCap_Orientation|ovrTrackingCap_MagYawCorrection|ovrTrackingCap_Position;
-       ovrHmd_ConfigureTracking(device.get_private().ovr_hmd, supported, 0);
-}
-
-void OculusRiftCamera::reset_tracking()
-{
-       ovrHmd_RecenterPose(device.get_private().ovr_hmd);
-}
-
-void OculusRiftCamera::update()
-{
-       double time;
-       if(device.is_timing_active())
-               time = device.get_tracking_time();
-       else
-               time = device.get_current_time();
-
-       ovrTrackingState state = ovrHmd_GetTrackingState(device.get_private().ovr_hmd, time);
-       OVR::Posef head_pose = state.HeadPose.ThePose;
-       OVR::Matrix4f tracking_matrix(head_pose);
-       update_from_matrix(transpose(GL::Matrix(&tracking_matrix.M[0][0])));
-}
-
-} // namespace VR
-} // namespace Msp
diff --git a/source/ovr/oculusriftcamera.h b/source/ovr/oculusriftcamera.h
deleted file mode 100644 (file)
index 6abb116..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef MSP_VR_OCULUSRIFTCAMERA_H_
-#define MSP_VR_OCULUSRIFTCAMERA_H_
-
-#include <msp/vr/headtrackingcamera.h>
-
-namespace Msp {
-namespace VR {
-
-class OculusRiftSystem;
-
-class OculusRiftCamera: public HeadTrackingCamera
-{
-private:
-       const OculusRiftSystem &device;
-
-public:
-       OculusRiftCamera(const OculusRiftSystem &, const GL::Camera &);
-
-       virtual void reset_tracking();
-       virtual void update();
-};
-
-} // namespace VR
-} // namespace Msp
-
-#endif
diff --git a/source/ovr/oculusriftcombiner.cpp b/source/ovr/oculusriftcombiner.cpp
deleted file mode 100644 (file)
index e0c2c4d..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <msp/gl/meshbuilder.h>
-#include <msp/gl/texture2d.h>
-#include "oculusriftcombiner.h"
-#include "oculusriftsystem.h"
-#include "oculusriftsystem_private.h"
-
-using namespace std;
-
-
-namespace {
-
-const char vs_source[] =
-       "uniform mat4 timewarp[2];\n"
-       "uniform vec2 uv_scale;\n"
-       "uniform vec2 uv_offset;\n"
-       "varying vec2 texcoord_r;\n"
-       "varying vec2 texcoord_g;\n"
-       "varying vec2 texcoord_b;\n"
-       "varying float vignette;\n"
-       "vec2 apply_timewarp(vec2 coords, float factor)\n"
-       "{\n"
-       "       vec4 coords4 = vec4(coords, 1.0, 1.0);\n"
-       "       vec4 warped = mix(timewarp[0]*coords4, timewarp[1]*coords4, factor);\n"
-       "       return (warped.xy/warped.z)*uv_scale+uv_offset;\n"
-       "}\n"
-       "void main()\n"
-       "{\n"
-       "       gl_Position = vec4(gl_Vertex.xy, 0.5, 1.0);\n"
-       "       float tw_factor = gl_MultiTexCoord3.y;\n"
-       "       texcoord_r = apply_timewarp(gl_MultiTexCoord0.xy, tw_factor);\n"
-       "       texcoord_g = apply_timewarp(gl_MultiTexCoord1.xy, tw_factor);\n"
-       "       texcoord_b = apply_timewarp(gl_MultiTexCoord2.xy, tw_factor);\n"
-       "       vignette = gl_MultiTexCoord3.x;\n"
-       "}\n";
-
-const char fs_source[] =
-       "uniform sampler2D texture;\n"
-       "varying vec2 texcoord_r;\n"
-       "varying vec2 texcoord_g;\n"
-       "varying vec2 texcoord_b;\n"
-       "varying float vignette;\n"
-       "void main()\n"
-       "{\n"
-       "       float r = texture2D(texture, texcoord_r).r;\n"
-       "       float g = texture2D(texture, texcoord_g).g;\n"
-       "       float b = texture2D(texture, texcoord_b).b;\n"
-       "       gl_FragColor = vec4(vec3(r, g, b)*vignette, 1.0);\n"
-       "}\n";
-
-void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov)
-{
-       ovrDistortionMesh ovr_mesh;
-       ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Vignette|ovrDistortionCap_TimeWarp, &ovr_mesh);
-
-       Msp::GL::MeshBuilder bld(mesh);
-       for(unsigned i=0; i<ovr_mesh.VertexCount; ++i)
-       {
-               ovrDistortionVertex &v = ovr_mesh.pVertexData[i];
-               bld.multitexcoord(0, v.TanEyeAnglesR.x, v.TanEyeAnglesR.y);
-               bld.multitexcoord(1, v.TanEyeAnglesG.x, v.TanEyeAnglesG.y);
-               bld.multitexcoord(2, v.TanEyeAnglesB.x, v.TanEyeAnglesB.y);
-               bld.multitexcoord(3, v.VignetteFactor, v.TimeWarpFactor);
-               bld.vertex(v.ScreenPosNDC.x, v.ScreenPosNDC.y);
-       }
-
-       Msp::GL::Batch batch(Msp::GL::TRIANGLES);
-       batch.append(vector<unsigned>(ovr_mesh.pIndexData, ovr_mesh.pIndexData+ovr_mesh.IndexCount));
-       mesh.add_batch(batch);
-
-       ovrHmd_DestroyDistortionMesh(&ovr_mesh);
-}
-
-}
-
-namespace Msp {
-namespace VR {
-
-struct OculusRiftCombiner::Frustum: StereoCombiner::Frustum
-{
-       Frustum(const ovrFovPort &);
-};
-
-
-OculusRiftCombiner::OculusRiftCombiner(OculusRiftSystem &d, GL::View &v):
-       device(d),
-       view(v),
-       left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
-       right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
-       shprog(vs_source, fs_source)
-{
-       ovrHmd hmd = device.get_private().ovr_hmd;
-
-       ovrFovPort left_fov = hmd->DefaultEyeFov[ovrEye_Left];
-       ovrFovPort right_fov = hmd->DefaultEyeFov[ovrEye_Right];
-       configure_eye_frustums(Frustum(left_fov), Frustum(right_fov));
-
-       left_fov.UpTan = left_fov.DownTan = tan(fov/2.0f);
-       left_fov.LeftTan = left_fov.UpTan*render_aspect*(1-frustum_skew);
-       left_fov.RightTan = left_fov.UpTan*render_aspect*(1+frustum_skew);
-       right_fov = left_fov;
-       swap(right_fov.LeftTan, right_fov.RightTan);
-
-       create_distortion_mesh(left_mesh, hmd, ovrEye_Left, left_fov);
-       create_distortion_mesh(right_mesh, hmd, ovrEye_Right, right_fov);
-
-       ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0);
-       target_width = tex_size.w;
-       target_height = tex_size.h;
-
-       left_shdata.uniform("texture", 0);
-       right_shdata.uniform("texture", 0);
-
-       ovrRecti view_rect;
-       view_rect.Pos.x = 0;
-       view_rect.Pos.y = 0;
-       view_rect.Size = tex_size;
-       ovrVector2f uv_scale_offset[2];
-       ovrHmd_GetRenderScaleAndOffset(left_fov, tex_size, view_rect, uv_scale_offset);
-       left_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
-       left_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
-       ovrHmd_GetRenderScaleAndOffset(right_fov, tex_size, view_rect, uv_scale_offset);
-       right_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
-       right_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
-
-       device.configure_window(view.get_window());
-}
-
-void OculusRiftCombiner::prepare() const
-{
-       device.begin_frame();
-}
-
-void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
-{
-       GL::Bind bind_shprog(shprog);
-
-       ovrHmd hmd = device.get_private().ovr_hmd;
-
-       if(device.is_timing_active())
-       {
-               ovr_WaitTillTime(device.get_timewarp_time());
-               ovrTrackingState state = ovrHmd_GetTrackingState(hmd, device.get_tracking_time());
-
-               ovrMatrix4f matrices[2];
-               ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Left, state.HeadPose.ThePose, matrices);
-               left_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
-
-               ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Right, state.HeadPose.ThePose, matrices);
-               right_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
-       }
-       else
-       {
-               GL::Matrix matrices[2];
-               left_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
-               right_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
-       }
-
-       GL::Bind bind_tex(left);
-       left_shdata.apply();
-       left_mesh.draw();
-
-       right.bind();
-       right_shdata.apply();
-       right_mesh.draw();
-
-       view.get_context().swap_buffers();
-       device.end_frame();
-}
-
-
-OculusRiftCombiner::Frustum::Frustum(const ovrFovPort &fov):
-       StereoCombiner::Frustum(-fov.LeftTan, fov.RightTan, -fov.DownTan, fov.UpTan)
-{ }
-
-} // namespace VR
-} // namespace Msp
diff --git a/source/ovr/oculusriftcombiner.h b/source/ovr/oculusriftcombiner.h
deleted file mode 100644 (file)
index 418c569..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef MSP_VR_OCULUSRIFTCOMBINER_H_
-#define MSP_VR_OCULUSRIFTCOMBINER_H_
-
-#include <msp/gl/mesh.h>
-#include <msp/gl/program.h>
-#include <msp/gl/programdata.h>
-#include <msp/gl/view.h>
-#include <msp/vr/stereocombiner.h>
-
-namespace Msp {
-namespace VR {
-
-class OculusRiftSystem;
-
-/**
-Presents a stereo view in a way suitable for an Oculus Rift HMD.  All distances
-are specified in multiples of the screen width.
-*/
-class OculusRiftCombiner: public StereoCombiner
-{
-private:
-       struct Frustum;
-
-       OculusRiftSystem &device;
-       GL::View &view;
-       GL::Mesh left_mesh;
-       GL::Mesh right_mesh;
-       GL::Program shprog;
-       mutable GL::ProgramData left_shdata;
-       mutable GL::ProgramData right_shdata;
-
-public:
-       OculusRiftCombiner(OculusRiftSystem &, GL::View &);
-
-       virtual void prepare() const;
-       virtual void render(const GL::Texture2D &, const GL::Texture2D &) const;
-};
-
-} // namespace VR
-} // namespace Msp
-
-#endif
diff --git a/source/ovr/oculusriftsystem.cpp b/source/ovr/oculusriftsystem.cpp
deleted file mode 100644 (file)
index 4a85383..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <msp/graphics/display.h>
-#include <msp/vr/stereoview.h>
-#include "oculusriftsystem.h"
-#include "oculusriftsystem_private.h"
-
-using namespace std;
-
-namespace Msp {
-namespace VR {
-
-unsigned OculusRiftSystem::n_instances = 0;
-
-OculusRiftSystem::OculusRiftSystem():
-       priv(new Private),
-       frame_index(0)
-{
-       if(!n_instances)
-               ovr_Initialize();
-       ++n_instances;
-
-       priv->ovr_hmd = ovrHmd_Create(0);
-       if(!priv->ovr_hmd)
-       {
-               delete priv;
-               throw runtime_error("rift hmd not found");
-       }
-}
-
-OculusRiftSystem::~OculusRiftSystem()
-{
-       ovrHmd_Destroy(priv->ovr_hmd);
-       delete priv;
-
-       --n_instances;
-       if(!n_instances)
-               ovr_Shutdown();
-}
-
-void OculusRiftSystem::configure_window(Graphics::Window &window) const
-{
-       Graphics::WindowOptions win_opts = window.get_options();
-       win_opts.width = priv->ovr_hmd->Resolution.w;
-       win_opts.height = priv->ovr_hmd->Resolution.h;
-
-       const list<Graphics::Monitor> &monitors = window.get_display().get_monitors();
-       string hmd_name = priv->ovr_hmd->ProductName;
-       for(list<Graphics::Monitor>::const_iterator i=monitors.begin(); i!=monitors.end(); ++i)
-               if(hmd_name.find(i->name)!=string::npos)
-               {
-                       win_opts.fullscreen = true;
-                       win_opts.fullscreen_monitor = &*i;
-                       win_opts.fullscreen_exclusive = false;
-               }
-
-       window.reconfigure(win_opts);
-}
-
-void OculusRiftSystem::configure_view(StereoView &view) const
-{
-       ovrEyeRenderDesc left_desc = ovrHmd_GetRenderDesc(priv->ovr_hmd, ovrEye_Left, priv->ovr_hmd->DefaultEyeFov[ovrEye_Left]);
-       ovrEyeRenderDesc right_desc = ovrHmd_GetRenderDesc(priv->ovr_hmd, ovrEye_Right, priv->ovr_hmd->DefaultEyeFov[ovrEye_Left]);
-       const ovrVector3f &l = left_desc.HmdToEyeViewOffset;
-       const ovrVector3f &r = right_desc.HmdToEyeViewOffset;
-       view.set_eye_matrices(GL::Matrix::translation(GL::Vector3(l.x, l.y, l.z)), GL::Matrix::translation(GL::Vector3(r.x, r.y, r.z)));
-}
-
-OculusRiftCamera *OculusRiftSystem::create_camera(const GL::Camera &bc)
-{
-       return new OculusRiftCamera(*this, bc);
-}
-
-OculusRiftCombiner *OculusRiftSystem::create_combiner(GL::View &view)
-{
-       return new OculusRiftCombiner(*this, view);
-}
-
-void OculusRiftSystem::begin_frame()
-{
-       priv->frame_timing = ovrHmd_BeginFrameTiming(priv->ovr_hmd, ++frame_index);
-       timing_active = true;
-}
-
-void OculusRiftSystem::end_frame()
-{
-       glFinish();
-       ovrHmd_EndFrameTiming(priv->ovr_hmd);
-       timing_active = false;
-}
-
-double OculusRiftSystem::get_tracking_time() const
-{
-       if(!timing_active)
-               throw logic_error("timing not active");
-       return priv->frame_timing.ScanoutMidpointSeconds;
-}
-
-double OculusRiftSystem::get_timewarp_time() const
-{
-       if(!timing_active)
-               throw logic_error("timing not active");
-       return priv->frame_timing.TimewarpPointSeconds;
-}
-
-double OculusRiftSystem::get_current_time() const
-{
-       return ovr_GetTimeInSeconds();
-}
-
-} // namespace VR
-} // namespace Msp
diff --git a/source/ovr/oculusriftsystem.h b/source/ovr/oculusriftsystem.h
deleted file mode 100644 (file)
index 20a4a5e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef MSP_VR_OCULUSRIFTSYSTEM_H_
-#define MSP_VR_OCULUSRIFTSYSTEM_H_
-
-#include <msp/vr/system.h>
-#include "oculusriftcamera.h"
-#include "oculusriftcombiner.h"
-
-namespace Msp {
-namespace VR {
-
-class OculusRiftSystem: public System
-{
-public:
-       struct Private;
-
-private:
-       Private *priv;
-       unsigned frame_index;
-       bool timing_active;
-
-       static unsigned n_instances;
-
-public:
-       OculusRiftSystem();
-       virtual ~OculusRiftSystem();
-
-       const Private &get_private() const { return *priv; }
-
-       virtual void configure_window(Graphics::Window &) const;
-       virtual void configure_view(StereoView &) const;
-       virtual OculusRiftCamera *create_camera(const GL::Camera &);
-       virtual OculusRiftCombiner *create_combiner(GL::View &);
-
-       void begin_frame();
-       void end_frame();
-       bool is_timing_active() const { return timing_active; }
-       double get_tracking_time() const;
-       double get_timewarp_time() const;
-       double get_current_time() const;
-};
-
-} // namespace VR
-} // namespace Msp
-
-#endif
diff --git a/source/ovr/oculusriftsystem_private.h b/source/ovr/oculusriftsystem_private.h
deleted file mode 100644 (file)
index 2f91fdf..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef MSP_VR_OCULUSRIFTSYSTEM_PRIVATE_H_
-#define MSP_VR_OCULUSRIFTSYSTEM_PRIVATE_H_
-
-#include <OVR.h>
-#include "oculusriftsystem.h"
-
-namespace Msp {
-namespace VR {
-
-struct OculusRiftSystem::Private
-{
-       ovrHmd ovr_hmd;
-       ovrFrameTiming frame_timing;
-};
-
-} // namespace VR
-} // namespace Msp
-
-#endif
index 436862e8fbde8e96dfea3d4588a5b24caf4d62e7..99a6d4871ece2486b7658eb2c1234d9ecbf6f62c 100644 (file)
@@ -4,7 +4,7 @@
 #include "openvr/openvrsystem.h"
 #endif
 #ifdef WITH_LIBOVR
-#include "ovr/oculusriftsystem.h"
+#include "libovr/libovrsystem.h"
 #endif
 
 using namespace std;
@@ -20,7 +20,7 @@ System *System::create(const string &type)
 #endif
 #ifdef WITH_LIBOVR
        if(type=="libovr")
-               return new OculusRiftSystem;
+               return new LibOVRSystem;
 #endif
        throw invalid_argument(format("system '%s' not supported", type));
 }