From: Mikko Rasa Date: Mon, 3 Oct 2016 12:47:59 +0000 (+0300) Subject: Name LibOVR classes after the API, not the device X-Git-Url: http://git.tdb.fi/?p=libs%2Fvr.git;a=commitdiff_plain;h=31c28161d36749d040cbab0099b352f53cad232d Name LibOVR classes after the API, not the device --- diff --git a/Build b/Build index 98da6b9..fa837ec 100644 --- 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 index 0000000..7446086 --- /dev/null +++ b/source/libovr/libovrcamera.cpp @@ -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 index 0000000..44495b0 --- /dev/null +++ b/source/libovr/libovrcamera.h @@ -0,0 +1,26 @@ +#ifndef MSP_VR_LIBOVRCAMERA_H_ +#define MSP_VR_LIBOVRCAMERA_H_ + +#include + +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 index 0000000..5eddb4a --- /dev/null +++ b/source/libovr/libovrcombiner.cpp @@ -0,0 +1,176 @@ +#include +#include +#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.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 index 0000000..789de55 --- /dev/null +++ b/source/libovr/libovrcombiner.h @@ -0,0 +1,42 @@ +#ifndef MSP_VR_LIBOVRCOMBINER_H_ +#define MSP_VR_LIBOVRCOMBINER_H_ + +#include +#include +#include +#include +#include + +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 index 0000000..c8183b0 --- /dev/null +++ b/source/libovr/libovrsystem.cpp @@ -0,0 +1,111 @@ +#include +#include +#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 &monitors = window.get_display().get_monitors(); + string hmd_name = priv->ovr_hmd->ProductName; + for(list::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 index 0000000..d5623a0 --- /dev/null +++ b/source/libovr/libovrsystem.h @@ -0,0 +1,45 @@ +#ifndef MSP_VR_LIBOVRSYSTEM_H_ +#define MSP_VR_LIBOVRSYSTEM_H_ + +#include +#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 index 0000000..d75f9f8 --- /dev/null +++ b/source/libovr/libovrsystem_private.h @@ -0,0 +1,19 @@ +#ifndef MSP_VR_LIBOVRSYSTEM_PRIVATE_H_ +#define MSP_VR_LIBOVRSYSTEM_PRIVATE_H_ + +#include +#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 index 4da732b..0000000 --- a/source/ovr/oculusriftcamera.cpp +++ /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 index 6abb116..0000000 --- a/source/ovr/oculusriftcamera.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef MSP_VR_OCULUSRIFTCAMERA_H_ -#define MSP_VR_OCULUSRIFTCAMERA_H_ - -#include - -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 index e0c2c4d..0000000 --- a/source/ovr/oculusriftcombiner.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include -#include -#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.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 index 418c569..0000000 --- a/source/ovr/oculusriftcombiner.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef MSP_VR_OCULUSRIFTCOMBINER_H_ -#define MSP_VR_OCULUSRIFTCOMBINER_H_ - -#include -#include -#include -#include -#include - -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 index 4a85383..0000000 --- a/source/ovr/oculusriftsystem.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#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 &monitors = window.get_display().get_monitors(); - string hmd_name = priv->ovr_hmd->ProductName; - for(list::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 index 20a4a5e..0000000 --- a/source/ovr/oculusriftsystem.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef MSP_VR_OCULUSRIFTSYSTEM_H_ -#define MSP_VR_OCULUSRIFTSYSTEM_H_ - -#include -#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 index 2f91fdf..0000000 --- a/source/ovr/oculusriftsystem_private.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MSP_VR_OCULUSRIFTSYSTEM_PRIVATE_H_ -#define MSP_VR_OCULUSRIFTSYSTEM_PRIVATE_H_ - -#include -#include "oculusriftsystem.h" - -namespace Msp { -namespace VR { - -struct OculusRiftSystem::Private -{ - ovrHmd ovr_hmd; - ovrFrameTiming frame_timing; -}; - -} // namespace VR -} // namespace Msp - -#endif diff --git a/source/system.cpp b/source/system.cpp index 436862e..99a6d48 100644 --- a/source/system.cpp +++ b/source/system.cpp @@ -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)); }