]> git.tdb.fi Git - libs/vr.git/commitdiff
Convert Oculus code to use SDK 0.4.4
authorMikko Rasa <tdb@tdb.fi>
Mon, 22 Dec 2014 22:13:47 +0000 (00:13 +0200)
committerMikko Rasa <tdb@tdb.fi>
Mon, 22 Dec 2014 22:13:47 +0000 (00:13 +0200)
The resulting aspect ratio might be subtly wrong at this point.  Some
changes are required for proper support.

source/oculusriftcamera.cpp
source/oculusriftcamera.h
source/oculusriftcombiner.cpp
source/oculusriftcombiner.h
source/oculusriftdevice.cpp
source/oculusriftdevice.h
source/oculusriftdevice_private.h

index 2a8af2b020c345a0e8b4f9b172edfc13a457c4b6..8b98adb25fcd520b06450c2cfba3e806f8d3abd2 100644 (file)
@@ -1,5 +1,4 @@
 #include "oculusriftcamera.h"
-#include "oculusriftcamera_private.h"
 #include "oculusriftdevice.h"
 #include "oculusriftdevice_private.h"
 
@@ -8,23 +7,23 @@ namespace VR {
 
 OculusRiftCamera::OculusRiftCamera(const OculusRiftDevice &d, const GL::Camera &c):
        device(d),
-       base_camera(c),
-       priv(new Private)
+       base_camera(c)
 {
        const OculusRiftDevice::Private &dev_priv = device.get_private();
-       priv->ovr_sensor = dev_priv.ovr_hmd->GetSensor();
-       priv->fusion.AttachToSensor(priv->ovr_sensor);
+       unsigned supported = ovrTrackingCap_Orientation|ovrTrackingCap_MagYawCorrection;
+       ovrHmd_ConfigureTracking(dev_priv.ovr_hmd, supported, 0);
 }
 
 OculusRiftCamera::~OculusRiftCamera()
 {
-       delete priv;
 }
 
 void OculusRiftCamera::update()
 {
-       OVR::Matrix4f sensor_matrix = priv->fusion.GetOrientation();
-       const float *m = &sensor_matrix.M[0][0];
+       ovrTrackingState state = ovrHmd_GetTrackingState(device.get_private().ovr_hmd, ovr_GetTimeInSeconds());
+       OVR::Posef head_pose = state.HeadPose.ThePose;
+       OVR::Matrix4f tracking_matrix(head_pose.Rotation);
+       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()));
index bff99676b012efad419f19d09bb609905b5602af..525f7c68be8103df45b48aec78320448e6578fda 100644 (file)
@@ -11,11 +11,8 @@ class OculusRiftDevice;
 class OculusRiftCamera: public HeadTrackingCamera
 {
 private:
-       struct Private;
-
        const OculusRiftDevice &device;
        const GL::Camera &base_camera;
-       Private *priv;
 
 public:
        OculusRiftCamera(const OculusRiftDevice &, const GL::Camera &);
index 67b4729638adf27d9fd36fee7aa2614b91a73429..e6b2908655a9a5d08520124b29e0a7dcbfe3ab21 100644 (file)
 #include <msp/gl/meshbuilder.h>
 #include <msp/gl/texture2d.h>
 #include "oculusriftcombiner.h"
+#include "oculusriftdevice.h"
+#include "oculusriftdevice_private.h"
 
 using namespace std;
 
+
 namespace {
 
 const char vs_source[] =
-       "uniform float offset;\n"
-       "uniform vec2 lens_center;\n"
-       "uniform vec3 scale;\n"
-       "varying vec2 texcoord;\n"
+       "varying vec2 texcoord_r;\n"
+       "varying vec2 texcoord_g;\n"
+       "varying vec2 texcoord_b;\n"
        "void main()\n"
        "{\n"
-       "       gl_Position = vec4(gl_Vertex.x*0.5+offset, gl_Vertex.yzw);\n"
-       "       texcoord = (gl_Vertex.xy*0.5+0.5-lens_center)*scale.xy;\n"
+       "       gl_Position = vec4(gl_Vertex.xy, 0.5, 1.0);\n"
+       "       texcoord_r = gl_MultiTexCoord0.xy;\n"
+       "       texcoord_g = gl_MultiTexCoord1.xy;\n"
+       "       texcoord_b = gl_MultiTexCoord2.xy;\n"
        "}\n";
 
 const char fs_source[] =
        "uniform sampler2D texture;\n"
-       "uniform vec4 distortion;\n"
-       "uniform vec4 chromatic;\n"
-       "uniform vec2 lens_center;\n"
-       "uniform vec2 eye_center;\n"
-       "uniform vec3 scale;\n"
-       "varying vec2 texcoord;\n"
+       "varying vec2 texcoord_r;\n"
+       "varying vec2 texcoord_g;\n"
+       "varying vec2 texcoord_b;\n"
        "void main()\n"
        "{\n"
-       "       float r_sq = dot(texcoord, texcoord);\n"
-       "       float f = dot(distortion, vec4(1.0, r_sq, r_sq*r_sq, r_sq*r_sq*r_sq));\n"
-       "       vec2 dtc = (texcoord*f-eye_center)/(scale.xy*scale.z)+lens_center;\n"
-       "       if(dtc.x<0.0 || dtc.y<0.0 || dtc.x>1.0 || dtc.y>1.0)\n"
-       "               gl_FragColor = vec4(0.0);\n"
-       "       else\n"
-       "       {\n"
-       "               vec2 red_dtc = (texcoord*f*(chromatic[0]+chromatic[1]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
-       "               vec2 blue_dtc = (texcoord*f*(chromatic[2]+chromatic[3]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
-       "               gl_FragColor = vec4(texture2D(texture, red_dtc).r, texture2D(texture, dtc).g, texture2D(texture, blue_dtc).b, 1.0);\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(r, g, b, 1.0);\n"
        "}\n";
 
-}
-
-namespace Msp {
-namespace VR {
-
-OculusRiftCombiner::OculusRiftCombiner():
-       mesh(GL::VERTEX2),
-       shprog(vs_source, fs_source),
-       // Default values copied from the SDK
-       view_distance(0.438f),
-       lens_separation(0.424f),
-       eye_separation(0.42735f),
-       fill_factor(0.95f)
+void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov)
 {
-       width_div = 2;
-
-       left_shdata.uniform("texture", 0);
-       left_shdata.uniform("offset", -0.5f);
-       right_shdata.uniform("texture", 0);
-       right_shdata.uniform("offset", 0.5f);
-
-       chromatic[0] = 1.0f;
-       chromatic[1] = 0.0f;
-       chromatic[2] = 1.0f;
-       chromatic[3] = 0.0f;
-
-       // This will also call update_parameters
-       set_distortion(1.0f, 0.22f, 0.24f);
-
-       GL::MeshBuilder bld(mesh);
-       bld.begin(GL::TRIANGLE_STRIP);
-       bld.vertex(-1, 1);
-       bld.vertex(-1, -1);
-       bld.vertex(1, 1);
-       bld.vertex(1, -1);
-       bld.end();
-}
+       ovrDistortionMesh ovr_mesh;
+       ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Chromatic, &ovr_mesh);
+
+       ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, eye, fov, 1.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(fov, tex_size, view_rect, uv_scale_offset);
+       ovrVector2f &scale = uv_scale_offset[0];
+       ovrVector2f &offset = uv_scale_offset[1];
+
+       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*scale.x+offset.x, 1.0f-(v.TanEyeAnglesR.y*scale.y+offset.y));
+               bld.multitexcoord(1, v.TanEyeAnglesG.x*scale.x+offset.x, 1.0f-(v.TanEyeAnglesG.y*scale.y+offset.y));
+               bld.multitexcoord(2, v.TanEyeAnglesB.x*scale.x+offset.x, 1.0f-(v.TanEyeAnglesB.y*scale.y+offset.y));
+               bld.vertex(v.ScreenPosNDC.x, v.ScreenPosNDC.y);
+       }
 
-void OculusRiftCombiner::set_view_distance(float d)
-{
-       view_distance = d;
-       update_parameters();
-}
+       Msp::GL::Batch batch(Msp::GL::TRIANGLES);
+       batch.append(vector<unsigned>(ovr_mesh.pIndexData, ovr_mesh.pIndexData+ovr_mesh.IndexCount));
+       mesh.add_batch(batch);
 
-void OculusRiftCombiner::set_lens_separation(float s)
-{
-       lens_separation = s;
-       update_parameters();
+       ovrHmd_DestroyDistortionMesh(&ovr_mesh);
 }
 
-void OculusRiftCombiner::set_eye_separation(float s)
-{
-       eye_separation = s;
-       update_parameters();
 }
 
-void OculusRiftCombiner::set_distortion(float d0, float d1, float d2, float d3)
-{
-       distortion[0] = d0;
-       distortion[1] = d1;
-       distortion[2] = d2;
-       distortion[3] = d3;
-
-       update_parameters();
-}
+namespace Msp {
+namespace VR {
 
-void OculusRiftCombiner::set_red_aberration(float c0, float c1)
+OculusRiftCombiner::OculusRiftCombiner(const OculusRiftDevice &d):
+       device(d),
+       left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2)),
+       right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2)),
+       shprog(vs_source, fs_source)
 {
-       chromatic[0] = c0;
-       chromatic[1] = c1;
+       width_div = 2;
 
-       update_parameters();
-}
+       const OculusRiftDevice::Private &dev_priv = device.get_private();
+       ovrHmd hmd = dev_priv.ovr_hmd;
 
-void OculusRiftCombiner::set_blue_aberration(float c2, float c3)
-{
-       chromatic[2] = c2;
-       chromatic[3] = c3;
+       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<float>(vertical)*2.0f;
 
-       update_parameters();
-}
+       float inner = max(left_fov.RightTan, right_fov.LeftTan);
+       float outer = max(left_fov.LeftTan, right_fov.RightTan);
+       frustum_skew = (inner-outer)*2/(inner+outer);
 
-void OculusRiftCombiner::set_fill_factor(float f)
-{
-       fill_factor = f;
-       update_parameters();
-}
+       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;
 
-void OculusRiftCombiner::update_parameters()
-{
-       left_shdata.uniform4("distortion", distortion);
-       left_shdata.uniform4("chromatic", chromatic);
-       right_shdata.uniform4("distortion", distortion);
-       right_shdata.uniform4("chromatic", chromatic);
-
-       // Set lens center positions, in output texture coordinates
-       left_shdata.uniform("lens_center", 1.0f-lens_separation, 0.5);
-       right_shdata.uniform("lens_center", lens_separation, 0.5);
-
-       /* Compute distance between eye and lens centers, in sampling texture
-       coordinates. */
-       float eye_offset = distort((eye_separation-lens_separation)*2);
-       left_shdata.uniform("eye_center", -eye_offset, 0.0f);
-       right_shdata.uniform("eye_center", eye_offset, 0.0f);
-
-       /* Determine the necessary scaling factor to avoid quality degradation in
-       the center of the screen. */
-       float horiz_oversize = distort((fill_factor-lens_separation)*2)/((fill_factor-lens_separation)*2)-eye_offset;
-       float vert_oversize = distort(1.25f*fill_factor)/(1.25f*fill_factor);
-       oversize = min(horiz_oversize, vert_oversize);
-
-       left_shdata.uniform("scale", 2.0f, 2.5f, oversize);
-       right_shdata.uniform("scale", 2.0f, 2.5f, oversize);
-
-       fov = Geometry::atan(oversize*0.625f/view_distance/2)*2.0f;
-       frustum_skew = lens_separation*2-1;
-}
+       create_distortion_mesh(left_mesh, hmd, ovrEye_Left, left_fov);
+       create_distortion_mesh(right_mesh, hmd, ovrEye_Right, right_fov);
 
-float OculusRiftCombiner::distort(float r) const
-{
-       float r_sq = r*r;
-       return r*(distortion[0]+(distortion[1]+(distortion[2]+distortion[3]*r_sq)*r_sq)*r_sq);
-}
+       ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0);
+       oversize = max(tex_size.w*2.0f/hmd->Resolution.w, tex_size.h*1.0f/hmd->Resolution.h);
 
-float OculusRiftCombiner::undistort(float r) const
-{
-       float x = r;
-       while(1)
-       {
-               float y = distort(x);
-               if(abs(r-y)<1e-5)
-                       return x;
+       shdata.uniform("texture", 0);
 
-               float x_sq = x*x;
-               float d = distortion[0]+(3*distortion[1]+(5*distortion[2]+7*distortion[3]*x_sq)*x_sq)*x_sq;
-               x -= (y-r)/d;
-       }
 }
 
 void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
 {
        GL::Bind bind_shprog(shprog);
+       shdata.apply();
 
        GL::Bind bind_tex(left);
-       left_shdata.apply();
-       mesh.draw();
+       left_mesh.draw();
 
        right.bind();
-       right_shdata.apply();
-       mesh.draw();
+       right_mesh.draw();
 }
 
 } // namespace VR
index afb5573453b99345edf9900b7c245dc03215122f..435ccb3f18b0bc903a10d462efcd7ebe5188a46c 100644 (file)
@@ -9,6 +9,8 @@
 namespace Msp {
 namespace VR {
 
+class OculusRiftDevice;
+
 /**
 Presents a stereo view in a way suitable for an Oculus Rift HMD.  All distances
 are specified in multiples of the screen width.
@@ -16,34 +18,15 @@ are specified in multiples of the screen width.
 class OculusRiftCombiner: public StereoCombiner
 {
 private:
-       GL::Mesh mesh;
+       const OculusRiftDevice &device;
+       GL::Mesh left_mesh;
+       GL::Mesh right_mesh;
        GL::Program shprog;
-       GL::ProgramData left_shdata;
-       GL::ProgramData right_shdata;
-       float view_distance;
-       float lens_separation;
-       float eye_separation;
-       float distortion[4];
-       float chromatic[4];
-       float fill_factor;
+       GL::ProgramData shdata;
 
 public:
-       OculusRiftCombiner();
-
-       void set_view_distance(float);
-       void set_lens_separation(float);
-       void set_eye_separation(float);
-       void set_distortion(float = 1.0f, float = 0.0f, float = 0.0f, float = 0.0f);
-       void set_red_aberration(float = 1.0f, float = 0.0f);
-       void set_blue_aberration(float = 1.0f, float = 0.0f);
-       void set_fill_factor(float);
-private:
-       void update_parameters();
+       OculusRiftCombiner(const OculusRiftDevice &);
 
-       float distort(float) const;
-       float undistort(float) const;
-
-public:
        virtual void render(const GL::Texture2D &, const GL::Texture2D &) const;
 };
 
index 5f752df1a0d0b279b55a646c239ffbafc3581e8a..9857f78f2f3c7eb933fde613c211a6ba3af268d0 100644 (file)
@@ -6,13 +6,16 @@ using namespace std;
 namespace Msp {
 namespace VR {
 
+unsigned OculusRiftDevice::n_instances = 0;
+
 OculusRiftDevice::OculusRiftDevice():
        priv(new Private)
 {
-       static OVR::System system(OVR::Log::ConfigureDefaultLog(OVR::LogMask_Debug));
+       if(!n_instances)
+               ovr_Initialize();
+       ++n_instances;
 
-       priv->ovr_manager = OVR::DeviceManager::Create();
-       priv->ovr_hmd = priv->ovr_manager->EnumerateDevices<OVR::HMDDevice>().CreateDevice();
+       priv->ovr_hmd = ovrHmd_Create(0);
        if(!priv->ovr_hmd)
        {
                delete priv;
@@ -22,7 +25,12 @@ OculusRiftDevice::OculusRiftDevice():
 
 OculusRiftDevice::~OculusRiftDevice()
 {
+       ovrHmd_Destroy(priv->ovr_hmd);
        delete priv;
+
+       --n_instances;
+       if(!n_instances)
+               ovr_Shutdown();
 }
 
 OculusRiftCamera *OculusRiftDevice::create_camera(const GL::Camera &bc) const
@@ -32,19 +40,7 @@ OculusRiftCamera *OculusRiftDevice::create_camera(const GL::Camera &bc) const
 
 OculusRiftCombiner *OculusRiftDevice::create_combiner() const
 {
-       OculusRiftCombiner *combiner = new OculusRiftCombiner;
-
-       OVR::HMDInfo info;
-       if(priv->ovr_hmd->GetDeviceInfo(&info))
-       {
-               combiner->set_view_distance(info.EyeToScreenDistance/info.HScreenSize);
-               combiner->set_lens_separation(info.LensSeparationDistance/info.HScreenSize);
-               combiner->set_distortion(info.DistortionK[0], info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
-               combiner->set_red_aberration(info.ChromaAbCorrection[0], info.ChromaAbCorrection[1]);
-               combiner->set_blue_aberration(info.ChromaAbCorrection[2], info.ChromaAbCorrection[3]);
-       }
-
-       return combiner;
+       return new OculusRiftCombiner(*this);
 }
 
 } // namespace VR
index 9d9e2ec974454f24ff6696ec7f41b12c3bc68c40..41b721e3e940a771c7148a10b24f86e584a0bbff 100644 (file)
@@ -16,6 +16,8 @@ public:
 private:
        Private *priv;
 
+       static unsigned n_instances;
+
 public:
        OculusRiftDevice();
        virtual ~OculusRiftDevice();
index c2033ee4891d1129cd4cef6509a87380f6c01faa..2b9c695e71c8daee8d9ba05e19d138a2662a4ae1 100644 (file)
@@ -9,8 +9,7 @@ namespace VR {
 
 struct OculusRiftDevice::Private
 {
-       OVR::Ptr<OVR::DeviceManager> ovr_manager;
-       OVR::Ptr<OVR::HMDDevice> ovr_hmd;
+       ovrHmd ovr_hmd;
 };
 
 } // namespace VR