source "source";
if_feature "libovr"
{
- source "source/ovr";
+ source "source/libovr";
};
if_feature "openvr"
{
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
#include "openvr/openvrsystem.h"
#endif
#ifdef WITH_LIBOVR
-#include "ovr/oculusriftsystem.h"
+#include "libovr/libovrsystem.h"
#endif
using namespace std;
#endif
#ifdef WITH_LIBOVR
if(type=="libovr")
- return new OculusRiftSystem;
+ return new LibOVRSystem;
#endif
throw invalid_argument(format("system '%s' not supported", type));
}