From dca13ee66628568631f502dfc79847c7368c7bb1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 18 Sep 2016 02:20:01 +0300 Subject: [PATCH] Move some common calculations to base classes --- source/headtrackingcamera.cpp | 24 ++++++++++++++++++++++++ source/headtrackingcamera.h | 5 ++++- source/ovr/oculusriftcamera.cpp | 20 ++++---------------- source/ovr/oculusriftcamera.h | 1 - source/ovr/oculusriftcombiner.cpp | 29 +++++++++++++++++------------ source/ovr/oculusriftcombiner.h | 2 ++ source/stereocombiner.cpp | 30 ++++++++++++++++++++++++++++++ source/stereocombiner.h | 14 ++++++++++++++ 8 files changed, 95 insertions(+), 30 deletions(-) create mode 100644 source/headtrackingcamera.cpp diff --git a/source/headtrackingcamera.cpp b/source/headtrackingcamera.cpp new file mode 100644 index 0000000..95868e2 --- /dev/null +++ b/source/headtrackingcamera.cpp @@ -0,0 +1,24 @@ +#include "headtrackingcamera.h" + +namespace Msp { +namespace VR { + +HeadTrackingCamera::HeadTrackingCamera(const GL::Camera &c): + base_camera(c) +{ } + +void HeadTrackingCamera::update_from_matrix(const GL::Matrix &hmd_matrix) +{ + GL::Matrix matrix = base_camera.get_object_matrix()*hmd_matrix; + + set_position(matrix*GL::Vector3()); + set_look_direction((matrix*GL::Vector4(0, 0, -1, 0)).slice<3>(0)); + set_up_direction((matrix*GL::Vector4(0, 1, 0, 0)).slice<3>(0)); + + set_depth_clip(base_camera.get_near_clip(), base_camera.get_far_clip()); + set_field_of_view(base_camera.get_field_of_view()); + set_aspect(base_camera.get_aspect()); +} + +} // namespace VR +} // namespace Msp diff --git a/source/headtrackingcamera.h b/source/headtrackingcamera.h index 36f0170..5bb911e 100644 --- a/source/headtrackingcamera.h +++ b/source/headtrackingcamera.h @@ -9,13 +9,16 @@ namespace VR { class HeadTrackingCamera: public Msp::GL::Camera { protected: - HeadTrackingCamera() { } + const GL::Camera &base_camera; + HeadTrackingCamera(const GL::Camera &); public: virtual ~HeadTrackingCamera() { } virtual void reset_tracking() { } virtual void update() = 0; +protected: + void update_from_matrix(const GL::Matrix &); }; } // namespace VR diff --git a/source/ovr/oculusriftcamera.cpp b/source/ovr/oculusriftcamera.cpp index 0eede27..713ae3c 100644 --- a/source/ovr/oculusriftcamera.cpp +++ b/source/ovr/oculusriftcamera.cpp @@ -6,8 +6,8 @@ namespace Msp { namespace VR { OculusRiftCamera::OculusRiftCamera(const OculusRiftDevice &d, const GL::Camera &c): - device(d), - base_camera(c) + HeadTrackingCamera(c), + device(d) { unsigned supported = ovrTrackingCap_Orientation|ovrTrackingCap_MagYawCorrection|ovrTrackingCap_Position; ovrHmd_ConfigureTracking(device.get_private().ovr_hmd, supported, 0); @@ -28,20 +28,8 @@ void OculusRiftCamera::update() ovrTrackingState state = ovrHmd_GetTrackingState(device.get_private().ovr_hmd, time); OVR::Posef head_pose = state.HeadPose.ThePose; - OVR::Matrix4f tracking_matrix(head_pose.Rotation); - OVR::Vector3f trans = head_pose.Translation; - const float *m = &tracking_matrix.M[0][0]; - - const GL::Vector3 &base_look = base_camera.get_look_direction(); - GL::Vector3 base_right = normalize(cross(base_look, base_camera.get_up_direction())); - GL::Vector3 base_up = normalize(cross(base_right, base_look)); - - set_position(base_camera.get_position()+trans.x*base_right+trans.y*base_up-trans.z*base_look); - set_up_direction(base_right*m[1]+base_up*m[5]-base_look*m[9]); - set_look_direction(-base_right*m[2]-base_up*m[6]+base_look*m[10]); - set_depth_clip(base_camera.get_near_clip(), base_camera.get_far_clip()); - set_field_of_view(base_camera.get_field_of_view()); - set_aspect(base_camera.get_aspect()); + OVR::Matrix4f tracking_matrix(head_pose); + update_from_matrix(transpose(GL::Matrix(&tracking_matrix.M[0][0]))); } } // namespace VR diff --git a/source/ovr/oculusriftcamera.h b/source/ovr/oculusriftcamera.h index a2b0b28..b6acae1 100644 --- a/source/ovr/oculusriftcamera.h +++ b/source/ovr/oculusriftcamera.h @@ -12,7 +12,6 @@ class OculusRiftCamera: public HeadTrackingCamera { private: const OculusRiftDevice &device; - const GL::Camera &base_camera; public: OculusRiftCamera(const OculusRiftDevice &, const GL::Camera &); diff --git a/source/ovr/oculusriftcombiner.cpp b/source/ovr/oculusriftcombiner.cpp index b9515ed..2d40ea9 100644 --- a/source/ovr/oculusriftcombiner.cpp +++ b/source/ovr/oculusriftcombiner.cpp @@ -1,4 +1,3 @@ -#include #include #include #include "oculusriftcombiner.h" @@ -76,6 +75,12 @@ void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, con namespace Msp { namespace VR { +struct OculusRiftCombiner::Frustum: StereoCombiner::Frustum +{ + Frustum(const ovrFovPort &); +}; + + OculusRiftCombiner::OculusRiftCombiner(OculusRiftDevice &d, GL::View &v): device(d), view(v), @@ -87,17 +92,13 @@ OculusRiftCombiner::OculusRiftCombiner(OculusRiftDevice &d, GL::View &v): ovrFovPort left_fov = hmd->DefaultEyeFov[ovrEye_Left]; ovrFovPort right_fov = hmd->DefaultEyeFov[ovrEye_Right]; - float vertical = max(max(left_fov.UpTan, left_fov.DownTan), max(right_fov.UpTan, right_fov.DownTan)); - fov = Geometry::atan(vertical)*2.0f; + configure_eye_frustums(Frustum(left_fov), Frustum(right_fov)); - float inner = max(left_fov.RightTan, right_fov.LeftTan); - float outer = max(left_fov.LeftTan, right_fov.RightTan); - frustum_skew = (inner-outer)/(inner+outer); - - left_fov.UpTan = right_fov.UpTan = vertical; - left_fov.DownTan = right_fov.DownTan = vertical; - left_fov.RightTan = right_fov.LeftTan = inner; - left_fov.LeftTan = right_fov.RightTan = outer; + 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); @@ -105,7 +106,6 @@ OculusRiftCombiner::OculusRiftCombiner(OculusRiftDevice &d, GL::View &v): ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0); target_width = tex_size.w; target_height = tex_size.h; - render_aspect = (inner+outer)/(vertical*2); left_shdata.uniform("texture", 0); right_shdata.uniform("texture", 0); @@ -167,5 +167,10 @@ void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D & 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 index 27c3c83..14f0e4c 100644 --- a/source/ovr/oculusriftcombiner.h +++ b/source/ovr/oculusriftcombiner.h @@ -19,6 +19,8 @@ are specified in multiples of the screen width. class OculusRiftCombiner: public StereoCombiner { private: + struct Frustum; + OculusRiftDevice &device; GL::View &view; GL::Mesh left_mesh; diff --git a/source/stereocombiner.cpp b/source/stereocombiner.cpp index c24a937..75c7889 100644 --- a/source/stereocombiner.cpp +++ b/source/stereocombiner.cpp @@ -1,5 +1,8 @@ +#include #include "stereocombiner.h" +using namespace std; + namespace Msp { namespace VR { @@ -10,5 +13,32 @@ StereoCombiner::StereoCombiner(): frustum_skew(0.0f) { } +void StereoCombiner::configure_eye_frustums(const Frustum &left_frustum, const Frustum &right_frustum) +{ + float vertical = max(max(left_frustum.top, -left_frustum.bottom), max(right_frustum.top, -right_frustum.bottom)); + fov = Geometry::atan(vertical)*2.0f; + + float inner = max(left_frustum.right, -right_frustum.left); + float outer = max(-left_frustum.left, right_frustum.right); + frustum_skew = (inner-outer)/(inner+outer); + + render_aspect = (inner+outer)/(vertical*2); +} + + +StereoCombiner::Frustum::Frustum(): + left(-1), + right(1), + bottom(-1), + top(1) +{ } + +StereoCombiner::Frustum::Frustum(float l, float r, float b, float t): + left(l), + right(r), + bottom(b), + top(t) +{ } + } // namespace VR } // namespace Msp diff --git a/source/stereocombiner.h b/source/stereocombiner.h index 5439aeb..bef0849 100644 --- a/source/stereocombiner.h +++ b/source/stereocombiner.h @@ -10,6 +10,17 @@ namespace VR { class StereoCombiner { protected: + struct Frustum + { + float left; + float right; + float bottom; + float top; + + Frustum(); + Frustum(float, float, float, float); + }; + unsigned target_width; unsigned target_height; float render_aspect; @@ -20,6 +31,9 @@ protected: public: virtual ~StereoCombiner() { } +protected: + void configure_eye_frustums(const Frustum &, const Frustum &); +public: float get_target_width() const { return target_width; } float get_target_height() const { return target_height; } float get_render_aspect() const { return render_aspect; } -- 2.45.2