diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index 56f9ece6d8..03334b324c 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -20,6 +20,13 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) if (APPLE) find_library(LIBOVR_LIBRARIES libovr.a ${LIBOVR_ROOT_DIR}/Lib/MacOS/) + elseif (UNIX) + find_library(UDEV_LIBRARY libudev.a /usr/lib/x86_64-linux-gnu/) + find_library(XINERAMA_LIBRARY libXinerama.a /usr/lib/x86_64-linux-gnu/) + find_library(OVR_LIBRARY libovr.a ${LIBOVR_ROOT_DIR}/Lib/UNIX/) + if (UDEV_LIBRARY AND XINERAMA_LIBRARY AND OVR_LIBRARY) + set(LIBOVR_LIBRARIES ${OVR_LIBRARY} ${UDEV_LIBRARY} ${XINERAMA_LIBRARY}) + endif (UDEV_LIBRARY AND XINERAMA_LIBRARY AND OVR_LIBRARY) elseif (WIN32) find_library(LIBOVR_LIBRARIES libovr.lib ${LIBOVR_ROOT_DIR}/Lib/Win32/) endif () @@ -41,4 +48,4 @@ else (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) # show the LIBOVR_INCLUDE_DIRS and LIBOVR_LIBRARIES variables only in the advanced view mark_as_advanced(LIBOVR_INCLUDE_DIRS LIBOVR_LIBRARIES) -endif (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) \ No newline at end of file +endif (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 735989dfbf..fda6862857 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -116,6 +116,14 @@ if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE) +# and with LibOVR for Oculus Rift +if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR) + add_definitions(-DHAVE_LIBOVR) + include_directories(SYSTEM ${LIBOVR_INCLUDE_DIRS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${LIBOVR_INCLUDE_DIRS}") + target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) +endif (LIBOVR_FOUND AND NOT DISABLE_LIBOVR) + qt5_use_modules(${TARGET_NAME} Core Gui Multimedia Network OpenGL Svg WebKit WebKitWidgets) # include headers for interface and InterfaceConfig. @@ -130,7 +138,6 @@ include_directories( SYSTEM ${FACESHIFT_INCLUDE_DIRS} ${GLM_INCLUDE_DIRS} - ${LIBOVR_INCLUDE_DIRS} ${LIBVPX_INCLUDE_DIRS} ${LEAP_INCLUDE_DIRS} ${MOTIONDRIVER_INCLUDE_DIRS} @@ -179,7 +186,6 @@ if (APPLE) ${QTKit} ${QuartzCore} ${UVCCAMERACONTROL_LIBRARIES} - ${LIBOVR_LIBRARIES} ) if (LEAP_FOUND) diff --git a/interface/external/LibOVR/Include/OVR.h b/interface/external/LibOVR/Include/OVR.h index d4dcbb8d86..c8323386ef 100755 --- a/interface/external/LibOVR/Include/OVR.h +++ b/interface/external/LibOVR/Include/OVR.h @@ -25,6 +25,7 @@ otherwise accompanies this software in either electronic or hard copy form. #include "../Src/OVR_DeviceHandle.h" #include "../Src/OVR_DeviceMessages.h" #include "../Src/OVR_SensorFusion.h" +#include "../Src/OVR_Profile.h" #include "../Src/Util/Util_LatencyTest.h" #include "../Src/Util/Util_Render_Stereo.h" diff --git a/interface/external/LibOVR/Include/OVRVersion.h b/interface/external/LibOVR/Include/OVRVersion.h index 7672d3aaf6..a1c7ea6da2 100755 --- a/interface/external/LibOVR/Include/OVRVersion.h +++ b/interface/external/LibOVR/Include/OVRVersion.h @@ -16,7 +16,7 @@ otherwise accompanies this software in either electronic or hard copy form. #define OVR_MAJOR_VERSION 0 #define OVR_MINOR_VERSION 2 -#define OVR_BUILD_VERSION 1 -#define OVR_VERSION_STRING "0.2.1" +#define OVR_BUILD_VERSION 5 +#define OVR_VERSION_STRING "0.2.5" #endif diff --git a/interface/external/LibOVR/Lib/MacOS/libovr.a b/interface/external/LibOVR/Lib/MacOS/libovr.a index c0668c96c6..4b82b91644 100644 Binary files a/interface/external/LibOVR/Lib/MacOS/libovr.a and b/interface/external/LibOVR/Lib/MacOS/libovr.a differ diff --git a/interface/external/LibOVR/Lib/UNIX/libovr.a b/interface/external/LibOVR/Lib/UNIX/libovr.a new file mode 100644 index 0000000000..68d3e72f38 Binary files /dev/null and b/interface/external/LibOVR/Lib/UNIX/libovr.a differ diff --git a/interface/external/LibOVR/Lib/Win32/libovr.lib b/interface/external/LibOVR/Lib/Win32/libovr.lib index 6efaaf4ac6..7d6bd04b5f 100755 Binary files a/interface/external/LibOVR/Lib/Win32/libovr.lib and b/interface/external/LibOVR/Lib/Win32/libovr.lib differ diff --git a/interface/external/LibOVR/Lib/x64/libovr64.lib b/interface/external/LibOVR/Lib/x64/libovr64.lib deleted file mode 100755 index e7b067efbc..0000000000 Binary files a/interface/external/LibOVR/Lib/x64/libovr64.lib and /dev/null differ diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Alg.h b/interface/external/LibOVR/Src/Kernel/OVR_Alg.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Allocator.h b/interface/external/LibOVR/Src/Kernel/OVR_Allocator.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Array.h b/interface/external/LibOVR/Src/Kernel/OVR_Array.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Atomic.h b/interface/external/LibOVR/Src/Kernel/OVR_Atomic.h old mode 100755 new mode 100644 index a8591ff57a..6e04b0f79c --- a/interface/external/LibOVR/Src/Kernel/OVR_Atomic.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_Atomic.h @@ -824,6 +824,7 @@ public: Lock (unsigned dummy = 0) { + OVR_UNUSED(dummy); if (!RecursiveAttrInit) { pthread_mutexattr_init(&RecursiveAttr); diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Color.h b/interface/external/LibOVR/Src/Kernel/OVR_Color.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_ContainerAllocator.h b/interface/external/LibOVR/Src/Kernel/OVR_ContainerAllocator.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_File.h b/interface/external/LibOVR/Src/Kernel/OVR_File.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Hash.h b/interface/external/LibOVR/Src/Kernel/OVR_Hash.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_KeyCodes.h b/interface/external/LibOVR/Src/Kernel/OVR_KeyCodes.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_List.h b/interface/external/LibOVR/Src/Kernel/OVR_List.h old mode 100755 new mode 100644 index 4b32f49a06..6ad471d96a --- a/interface/external/LibOVR/Src/Kernel/OVR_List.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_List.h @@ -115,7 +115,7 @@ struct ListNode // } // -// List<> represents a doubly-linked list if T, where each T must derive +// List<> represents a doubly-linked list of T, where each T must derive // from ListNode. B specifies the base class that was directly // derived from ListNode, and is only necessary if there is an intermediate // inheritance chain. diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Log.h b/interface/external/LibOVR/Src/Kernel/OVR_Log.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Math.h b/interface/external/LibOVR/Src/Kernel/OVR_Math.h old mode 100755 new mode 100644 index ddb411911e..108b9d30e0 --- a/interface/external/LibOVR/Src/Kernel/OVR_Math.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_Math.h @@ -4,7 +4,7 @@ PublicHeader: OVR.h Filename : OVR_Math.h Content : Implementation of 3D primitives such as vectors, matrices. Created : September 4, 2012 -Authors : Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova +Authors : Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova, Max Katsev Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -23,11 +23,12 @@ otherwise accompanies this software in either electronic or hard copy form. #include "OVR_Types.h" #include "OVR_RefCount.h" +#include "OVR_Std.h" namespace OVR { //------------------------------------------------------------------------------------- -// Constants for 3D world/axis definitions. +// ***** Constants for 3D world/axis definitions. // Definitions of axes for coordinate and rotation conversions. enum Axis @@ -48,12 +49,13 @@ enum RotateDirection Rotate_CW = -1 }; +// Constants for right handed and left handed coordinate systems enum HandedSystem { Handed_R = 1, Handed_L = -1 }; -// AxisDirection describes which way the axis points. Used by WorldAxes. +// AxisDirection describes which way the coordinate axis points. Used by WorldAxes. enum AxisDirection { Axis_Up = 2, @@ -74,9 +76,9 @@ struct WorldAxes }; -//------------------------------------------------------------------------------------- -// ***** Math - +//------------------------------------------------------------------------------------// +// ************************************ Math *****************************************// +// // Math class contains constants and functions. This class is a template specialized // per type, with Math and Math being distinct. template @@ -95,14 +97,14 @@ public: static const float PiOver4; static const float E; - static const float MaxValue; // Largest positive float Value - static const float MinPositiveValue; // Smallest possible positive value + static const float MaxValue; // Largest positive float Value + static const float MinPositiveValue; // Smallest possible positive value static const float RadToDegreeFactor; static const float DegreeToRadFactor; - static const float Tolerance; // 0.00001f; - static const float SingularityRadius; //0.00000000001f for Gimbal lock numerical problems + static const float Tolerance; // 0.00001f; + static const float SingularityRadius; // 0.0000001f for Gimbal lock numerical problems }; // Double-precision Math constants class. @@ -116,33 +118,54 @@ public: static const double PiOver4; static const double E; - static const double MaxValue; // Largest positive double Value - static const double MinPositiveValue; // Smallest possible positive value + static const double MaxValue; // Largest positive double Value + static const double MinPositiveValue; // Smallest possible positive value static const double RadToDegreeFactor; static const double DegreeToRadFactor; - static const double Tolerance; // 0.00001f; - static const double SingularityRadius; //0.00000000001 for Gimbal lock numerical problems + static const double Tolerance; // 0.00001; + static const double SingularityRadius; // 0.000000000001 for Gimbal lock numerical problems + }; typedef Math Mathf; typedef Math Mathd; // Conversion functions between degrees and radians -template -FT RadToDegree(FT rads) { return rads * Math::RadToDegreeFactor; } -template -FT DegreeToRad(FT rads) { return rads * Math::DegreeToRadFactor; } +template +T RadToDegree(T rads) { return rads * Math::RadToDegreeFactor; } +template +T DegreeToRad(T rads) { return rads * Math::DegreeToRadFactor; } + +// Numerically stable acos function +template +T Acos(T val) { + if (val > T(1)) return T(0); + else if (val < T(-1)) return Math::Pi; + else return acos(val); +}; + +// Numerically stable asin function +template +T Asin(T val) { + if (val > T(1)) return Math::PiOver2; + else if (val < T(-1)) return Math::PiOver2 * T(3); + else return asin(val); +}; + +#ifdef OVR_CC_MSVC +inline int isnan(double x) { return _isnan(x); }; +#endif template class Quat; //------------------------------------------------------------------------------------- -// ***** Vector2f - 2D Vector2f +// ***** Vector2<> -// Vector2f represents a 2-dimensional vector or point in space, -// consisting of coordinates x and y, +// Vector2f (Vector2d) represents a 2-dimensional vector or point in space, +// consisting of coordinates x and y template class Vector2 @@ -174,33 +197,53 @@ public: return *this; } // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. - bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) + bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance) { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); } - // Dot product overload. + // Entrywise product of two vectors + Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);} + + // Dot product // Used to calculate angle q between two vectors among other things, // as (A dot B) = |a||b|cos(q). - T operator* (const Vector2& b) const { return x*b.x + y*b.y; } + T Dot(const Vector2& b) const { return x*b.x + y*b.y; } // Returns the angle from this vector to b, in radians. - T Angle(const Vector2& b) const { return acos((*this * b)/(Length()*b.Length())); } + T Angle(const Vector2& b) const + { + T div = LengthSq()*b.LengthSq(); + OVR_ASSERT(div != T(0)); + T result = Acos((this->Dot(b))/sqrt(div)); + return result; + } // Return Length of the vector squared. T LengthSq() const { return (x * x + y * y); } // Return vector length. T Length() const { return sqrt(LengthSq()); } - // Returns distance between two points represented by vectors. + // Returns distance between two points represented by vectors. T Distance(Vector2& b) const { return (*this - b).Length(); } - - // Determine if this a unit vector. + + // Determine if this a unit vector. bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance; } + // Normalize, convention vector length to 1. - void Normalize() { *this /= Length(); } + void Normalize() + { + T l = Length(); + OVR_ASSERT(l != T(0)); + *this /= l; + } // Returns normalized (unit) version of the vector without modifying itself. - Vector2 Normalized() const { return *this / Length(); } + Vector2 Normalized() const + { + T l = Length(); + OVR_ASSERT(l != T(0)); + return *this / l; + } // Linearly interpolates from this vector to another. // Factor should be between 0.0 and 1.0, with 0 giving full value to this. @@ -208,17 +251,24 @@ public: // Projects this vector onto the argument; in other words, // A.Project(B) returns projection of vector A onto B. - Vector2 ProjectTo(const Vector2& b) const { return b * ((*this * b) / b.LengthSq()); } + Vector2 ProjectTo(const Vector2& b) const + { + T l2 = b.LengthSq(); + OVR_ASSERT(l2 != T(0)); + return b * ( Dot(b) / l2 ); + } }; typedef Vector2 Vector2f; typedef Vector2 Vector2d; -//------------------------------------------------------------------------------------- -// ***** Vector3f - 3D Vector3f -// Vector3f represents a 3-dimensional vector or point in space, +//------------------------------------------------------------------------------------- +// ***** Vector3<> - 3D vector of {x, y, z} + +// +// Vector3f (Vector3d) represents a 3-dimensional vector or point in space, // consisting of coordinates x, y and z. template @@ -253,13 +303,20 @@ public: // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) { - return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance); + return (fabs(b.x-x) < tolerance) && + (fabs(b.y-y) < tolerance) && + (fabs(b.z-z) < tolerance); } - // Dot product overload. + // Entrywise product of two vectors + Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x, + y * b.y, + z * b.z);} + + // Dot product // Used to calculate angle q between two vectors among other things, // as (A dot B) = |a||b|cos(q). - T operator* (const Vector3& b) const { return x*b.x + y*b.y + z*b.z; } + T Dot(const Vector3& b) const { return x*b.x + y*b.y + z*b.z; } // Compute cross product, which generates a normal vector. // Direction vector can be determined by right-hand rule: Pointing index finder in @@ -269,7 +326,13 @@ public: x*b.y - y*b.x); } // Returns the angle from this vector to b, in radians. - T Angle(const Vector3& b) const { return acos((*this * b)/(Length()*b.Length())); } + T Angle(const Vector3& b) const + { + T div = LengthSq()*b.LengthSq(); + OVR_ASSERT(div != T(0)); + T result = Acos((this->Dot(b))/sqrt(div)); + return result; + } // Return Length of the vector squared. T LengthSq() const { return (x * x + y * y + z * z); } @@ -281,10 +344,22 @@ public: // Determine if this a unit vector. bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance; } + // Normalize, convention vector length to 1. - void Normalize() { *this /= Length(); } + void Normalize() + { + T l = Length(); + OVR_ASSERT(l != T(0)); + *this /= l; + } + // Returns normalized (unit) version of the vector without modifying itself. - Vector3 Normalized() const { return *this / Length(); } + Vector3 Normalized() const + { + T l = Length(); + OVR_ASSERT(l != T(0)); + return *this / l; + } // Linearly interpolates from this vector to another. // Factor should be between 0.0 and 1.0, with 0 giving full value to this. @@ -292,7 +367,15 @@ public: // Projects this vector onto the argument; in other words, // A.Project(B) returns projection of vector A onto B. - Vector3 ProjectTo(const Vector3& b) const { return b * ((*this * b) / b.LengthSq()); } + Vector3 ProjectTo(const Vector3& b) const + { + T l2 = b.LengthSq(); + OVR_ASSERT(l2 != T(0)); + return b * ( Dot(b) / l2 ); + } + + // Projects this vector onto a plane defined by a normal vector + Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); } }; @@ -301,8 +384,55 @@ typedef Vector3 Vector3d; //------------------------------------------------------------------------------------- -// ***** Matrix4f +// ***** Size +// Size class represents 2D size with Width, Height components. +// Used to describe distentions of render targets, etc. + +template +class Size +{ +public: + T Width, Height; + + Size() : Width(0), Height(0) { } + Size(T w_, T h_) : Width(w_), Height(h_) { } + explicit Size(T s) : Width(s), Height(s) { } + + bool operator== (const Size& b) const { return Width == b.Width && Height == b.Height; } + bool operator!= (const Size& b) const { return Width != b.Width || Height != b.Height; } + + Size operator+ (const Size& b) const { return Size(Width + b.Width, Height + b.Height); } + Size& operator+= (const Size& b) { Width += b.Width; Height += b.Height; return *this; } + Size operator- (const Size& b) const { return Size(Width - b.Width, Height - b.Height); } + Size& operator-= (const Size& b) { Width -= b.Width; Height -= b.Height; return *this; } + Size operator- () const { return Size(-Width, -Height); } + Size operator* (const Size& b) const { return Size(Width * b.Width, Height * b.Height); } + Size& operator*= (const Size& b) { Width *= b.Width; Height *= b.Height; return *this; } + Size operator/ (const Size& b) const { return Size(Width / b.Width, Height / b.Height); } + Size& operator/= (const Size& b) { Width /= b.Width; Height /= b.Height; return *this; } + + // Scalar multiplication/division scales both components. + Size operator* (T s) const { return Size(Width*s, Height*s); } + Size& operator*= (T s) { Width *= s; Height *= s; return *this; } + Size operator/ (T s) const { return Size(Width/s, Height/s); } + Size& operator/= (T s) { Width /= s; Height /= s; return *this; } + + T Area() const { return Width * Height; } + + inline Vector2 ToVector() const { return Vector2(Width, Height); } +}; + + +typedef Size Sizei; +typedef Size Sizeu; +typedef Size Sizef; +typedef Size Sized; + + +//------------------------------------------------------------------------------------- +// ***** Matrix4f +// // Matrix4f is a 4x4 matrix used for 3d transformations and projections. // Translation stored in the last column. // The matrix is stored in row-major order in memory, meaning that values @@ -367,6 +497,29 @@ public: M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1; } + void ToString(char* dest, UPInt destsize) + { + UPInt pos = 0; + for (int r=0; r<4; r++) + for (int c=0; c<4; c++) + pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]); + } + + static Matrix4f FromString(const char* src) + { + Matrix4f result; + for (int r=0; r<4; r++) + for (int c=0; c<4; c++) + { + result.M[r][c] = (float)atof(src); + while (src && *src != ' ') + src++; + while (src && *src == ' ') + src++; + } + return result; + } + static const Matrix4f& Identity() { return IdentityValue; } void SetIdentity() @@ -377,6 +530,36 @@ public: M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0; } + Matrix4f operator+ (const Matrix4f& b) const + { + Matrix4f result(*this); + result += b; + return result; + } + + Matrix4f& operator+= (const Matrix4f& b) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] += b.M[i][j]; + return *this; + } + + Matrix4f operator- (const Matrix4f& b) const + { + Matrix4f result(*this); + result -= b; + return result; + } + + Matrix4f& operator-= (const Matrix4f& b) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] -= b.M[i][j]; + return *this; + } + // Multiplies two matrices into destination with minimum copying. static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b) { @@ -406,18 +589,32 @@ public: Matrix4f operator* (float s) const { - return Matrix4f(M[0][0] * s, M[0][1] * s, M[0][2] * s, M[0][3] * s, - M[1][0] * s, M[1][1] * s, M[1][2] * s, M[1][3] * s, - M[2][0] * s, M[2][1] * s, M[2][2] * s, M[2][3] * s, - M[3][0] * s, M[3][1] * s, M[3][2] * s, M[3][3] * s); + Matrix4f result(*this); + result *= s; + return result; } Matrix4f& operator*= (float s) { - M[0][0] *= s; M[0][1] *= s; M[0][2] *= s; M[0][3] *= s; - M[1][0] *= s; M[1][1] *= s; M[1][2] *= s; M[1][3] *= s; - M[2][0] *= s; M[2][1] *= s; M[2][2] *= s; M[2][3] *= s; - M[3][0] *= s; M[3][1] *= s; M[3][2] *= s; M[3][3] *= s; + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] *= s; + return *this; + } + + + Matrix4f operator/ (float s) const + { + Matrix4f result(*this); + result /= s; + return result; + } + + Matrix4f& operator/= (float s) + { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + M[i][j] /= s; return *this; } @@ -442,16 +639,16 @@ public: } - float SubDet (const int* rows, const int* cols) const + float SubDet (const UPInt* rows, const UPInt* cols) const { return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]]) - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]]) + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]); } - float Cofactor(int I, int J) const + float Cofactor(UPInt I, UPInt J) const { - const int indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; + const UPInt indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}}; return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]); } @@ -480,7 +677,27 @@ public: *this = Inverted(); } - //AnnaSteve: + // This is more efficient than general inverse, but ONLY works + // correctly if it is a homogeneous transform matrix (rot + trans) + Matrix4f InvertedHomogeneousTransform() const + { + // Make the inverse rotation matrix + Matrix4f rinv = this->Transposed(); + rinv.M[3][0] = rinv.M[3][1] = rinv.M[3][2] = 0.0f; + // Make the inverse translation matrix + Vector3f tvinv = Vector3f(-M[0][3],-M[1][3],-M[2][3]); + Matrix4f tinv = Matrix4f::Translation(tvinv); + return rinv * tinv; // "untranslate", then "unrotate" + } + + // This is more efficient than general inverse, but ONLY works + // correctly if it is a homogeneous transform matrix (rot + trans) + void InvertHomogeneousTransform() + { + *this = InvertedHomogeneousTransform(); + } + + // Matrix to Euler Angles conversion // a,b,c, are the YawPitchRoll angles to be returned // rotation a around axis A1 // is followed by rotation b around axis A2 @@ -502,7 +719,7 @@ public: *b = -S*D*Math::PiOver2; *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] ); } - else if (pm > 1.0 - Math::SingularityRadius) + else if (pm > 1.0f - Math::SingularityRadius) { // North pole singularity *a = 0.0f; *b = S*D*Math::PiOver2; @@ -518,7 +735,7 @@ public: return; } - //AnnaSteve: + // Matrix to Euler Angles conversion // a,b,c, are the YawPitchRoll angles to be returned // rotation a around axis A1 // is followed by rotation b around axis A2 @@ -537,13 +754,13 @@ public: psign = 1.0f; float c2 = M[A1][A1]; - if (c2 < -1.0 + Math::SingularityRadius) + if (c2 < -1.0f + Math::SingularityRadius) { // South pole singularity *a = 0.0f; *b = S*D*Math::Pi; *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]); } - else if (c2 > 1.0 - Math::SingularityRadius) + else if (c2 > 1.0f - Math::SingularityRadius) { // North pole singularity *a = 0.0f; *b = 0.0f; @@ -560,7 +777,6 @@ public: // Creates a matrix that converts the vertices from one coordinate system // to another. - // static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from) { // Holds axis values from the 'to' structure @@ -584,7 +800,7 @@ public: } - + // Creates a matrix for translation by vector static Matrix4f Translation(const Vector3f& v) { Matrix4f t; @@ -594,6 +810,7 @@ public: return t; } + // Creates a matrix for translation by vector static Matrix4f Translation(float x, float y, float z = 0.0f) { Matrix4f t; @@ -603,6 +820,7 @@ public: return t; } + // Creates a matrix for scaling by vector static Matrix4f Scaling(const Vector3f& v) { Matrix4f t; @@ -612,6 +830,7 @@ public: return t; } + // Creates a matrix for scaling by vector static Matrix4f Scaling(float x, float y, float z) { Matrix4f t; @@ -621,6 +840,7 @@ public: return t; } + // Creates a matrix for scaling by constant static Matrix4f Scaling(float s) { Matrix4f t; @@ -632,7 +852,8 @@ public: - //AnnaSteve : Just for quick testing. Not for final API. Need to remove case. + // Creates a rotation matrix rotating around the X axis by 'angle' radians. + // Just for quick testing. Not for final API. Need to remove case. static Matrix4f RotationAxis(Axis A, float angle, RotateDirection d, HandedSystem s) { float sina = s * d *sin(angle); @@ -658,10 +879,10 @@ public: // Creates a rotation matrix rotating around the X axis by 'angle' radians. // Rotation direction is depends on the coordinate system: - // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), + // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW), // while looking in the negative axis direction. This is the // same as looking down from positive axis values towards origin. - // LHS: Positive angle values rotate clock-wise (CW), while looking in the + // LHS: Positive angle values rotate clock-wise (CW), while looking in the // negative axis direction. static Matrix4f RotationX(float angle) { @@ -743,9 +964,9 @@ public: }; -//------------------------------------------------------------------------------------- -// ***** Quat - +//-------------------------------------------------------------------------------------// +// **************************************** Quat **************************************// +// // Quatf represents a quaternion class used for rotations. // // Quaternion multiplications are done in right-to-left order, to match the @@ -763,7 +984,7 @@ public: Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {} - // Constructs rotation quaternion around the axis. + // Constructs quaternion for rotation around the axis by an angle. Quat(const Vector3& axis, T angle) { Vector3 unitAxis = axis.Normalized(); @@ -775,33 +996,33 @@ public: z = unitAxis.z * sinHalfAngle; } - //AnnaSteve: + // Constructs quaternion for rotation around one of the coordinate axis by an angle. void AxisAngle(Axis A, T angle, RotateDirection d, HandedSystem s) { - T sinHalfAngle = s * d *sin(angle * (T)0.5); + T sinHalfAngle = s * d *sin(angle * T(0.5)); T v[3]; - v[0] = v[1] = v[2] = (T)0; + v[0] = v[1] = v[2] = T(0); v[A] = sinHalfAngle; - //return Quat(v[0], v[1], v[2], cos(angle * (T)0.5)); - w = cos(angle * (T)0.5); + + w = cos(angle * T(0.5)); x = v[0]; y = v[1]; z = v[2]; } - void GetAxisAngle(Vector3* axis, T* angle) const + // Compute axis and angle from quaternion + void GetAxisAngle(Vector3* axis, T* angle) const { - if (LengthSq() > Math::Tolerance * Math::Tolerance) - { - *axis = Vector3(x, y, z).Normalized(); - *angle = 2 * acos(w); - } - else - { - *axis = Vector3(1, 0, 0); - *angle= 0; - } + if ( x*x + y*y + z*z > Math::Tolerance * Math::Tolerance ) { + *axis = Vector3(x, y, z).Normalized(); + *angle = T(2) * Acos(w); + } + else + { + *axis = Vector3(1, 0, 0); + *angle= 0; + } } bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; } @@ -817,6 +1038,7 @@ public: Quat operator/ (T s) const { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); } Quat& operator/= (T s) { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; } + // Get Imaginary part vector Vector3 Imag() const { return Vector3(x,y,z); } @@ -824,29 +1046,42 @@ public: T Length() const { return sqrt(x * x + y * y + z * z + w * w); } // Get quaternion length squared. T LengthSq() const { return (x * x + y * y + z * z + w * w); } + // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure) - T Distance(const Quat& q) const - { + T Distance(const Quat& q) const + { T d1 = (*this - q).Length(); - T d2 = (*this + q).Length(); // Antipoldal point check + T d2 = (*this + q).Length(); // Antipodal point check return (d1 < d2) ? d1 : d2; - } + } + T DistanceSq(const Quat& q) const { T d1 = (*this - q).LengthSq(); - T d2 = (*this + q).LengthSq(); // Antipoldal point check + T d2 = (*this + q).LengthSq(); // Antipodal point check return (d1 < d2) ? d1 : d2; } // Normalize - bool IsNormalized() const { return fabs(LengthSq() - 1) < Math::Tolerance; } - void Normalize() { *this /= Length(); } - Quat Normalized() const { return *this / Length(); } + bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math::Tolerance; } + + void Normalize() + { + T l = Length(); + OVR_ASSERT(l != T(0)); + *this /= l; + } + + Quat Normalized() const + { + T l = Length(); + OVR_ASSERT(l != T(0)); + return *this / l; + } // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized. Quat Conj() const { return Quat(-x, -y, -z, w); } - // AnnaSteve fixed: order of quaternion multiplication // Quaternion multiplication. Combines quaternion rotations, performing the one on the // right hand side first. Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y, @@ -868,7 +1103,7 @@ public: // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. Vector3 Rotate(const Vector3& v) const { - return ((*this * Quat(v.x, v.y, v.z, 0)) * Inverted()).Imag(); + return ((*this * Quat(v.x, v.y, v.z, T(0))) * Inverted()).Imag(); } @@ -879,7 +1114,7 @@ public: } // Sets this quaternion to the one rotates in the opposite direction. - void Invert() const + void Invert() { *this = Quat(-x, -y, -z, w); } @@ -897,6 +1132,52 @@ public: float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) ); } + + // Converting matrix to quaternion + static Quat Matrix4fToQuat(const Matrix4f& m) + { + T trace = m.M[0][0] + m.M[1][1] + m.M[2][2]; + Quat q; + + // In almost all cases, the first part is executed. + // However, if the trace is not positive, the other + // cases arise. + if (trace > T(0)) + { + T s = sqrt(trace + T(1)) * T(2); // s=4*qw + q.w = T(0.25) * s; + q.x = (m.M[2][1] - m.M[1][2]) / s; + q.y = (m.M[0][2] - m.M[2][0]) / s; + q.z = (m.M[1][0] - m.M[0][1]) / s; + } + else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) + { + T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2); + q.w = (m.M[2][1] - m.M[1][2]) / s; + q.x = T(0.25) * s; + q.y = (m.M[0][1] + m.M[1][0]) / s; + q.z = (m.M[2][0] + m.M[0][2]) / s; + } + else if (m.M[1][1] > m.M[2][2]) + { + T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy + q.w = (m.M[0][2] - m.M[2][0]) / s; + q.x = (m.M[0][1] + m.M[1][0]) / s; + q.y = T(0.25) * s; + q.z = (m.M[1][2] + m.M[2][1]) / s; + } + else + { + T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz + q.w = (m.M[1][0] - m.M[0][1]) / s; + q.x = (m.M[0][2] + m.M[2][0]) / s; + q.y = (m.M[1][2] + m.M[2][1]) / s; + q.z = T(0.25) * s; + } + return q; + } + + // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of // axis rotations and the specified coordinate system. Right-handed coordinate system @@ -918,33 +1199,33 @@ public: T Q22 = Q[A2]*Q[A2]; T Q33 = Q[A3]*Q[A3]; - T psign = T(-1.0); + T psign = T(-1); // Determine whether even permutation if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) - psign = T(1.0); + psign = T(1); - T s2 = psign * T(2.0) * (psign*w*Q[A2] + Q[A1]*Q[A3]); + T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]); - if (s2 < (T)-1.0 + Math::SingularityRadius) + if (s2 < T(-1) + Math::SingularityRadius) { // South pole singularity - *a = T(0.0); + *a = T(0); *b = -S*D*Math::PiOver2; - *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), + *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33 ); } - else if (s2 > (T)1.0 - Math::SingularityRadius) + else if (s2 > T(1) - Math::SingularityRadius) { // North pole singularity - *a = (T)0.0; + *a = T(0); *b = S*D*Math::PiOver2; - *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]), + *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]), ww + Q22 - Q11 - Q33); } else { - *a = -S*D*atan2((T)-2.0*(w*Q[A1] - psign*Q[A2]*Q[A3]), + *a = -S*D*atan2(T(-2)*(w*Q[A1] - psign*Q[A2]*Q[A3]), ww + Q33 - Q11 - Q22); *b = S*D*asin(s2); - *c = S*D*atan2((T)2.0*(w*Q[A3] - psign*Q[A1]*Q[A2]), + *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]), ww + Q11 - Q22 - Q33); } return; @@ -982,25 +1263,25 @@ public: T Q22 = Q[A2]*Q[A2]; T Qmm = Q[m]*Q[m]; - T psign = T(-1.0); + T psign = T(-1); if ((A1 + 1) % 3 == A2) // Determine whether even permutation { - psign = (T)1.0; + psign = T(1); } T c2 = ww + Q11 - Q22 - Qmm; - if (c2 < (T)-1.0 + Math::SingularityRadius) + if (c2 < T(-1) + Math::SingularityRadius) { // South pole singularity - *a = (T)0.0; + *a = T(0); *b = S*D*Math::Pi; - *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), + *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]), ww + Q22 - Q11 - Qmm); } - else if (c2 > (T)1.0 - Math::SingularityRadius) + else if (c2 > T(1) - Math::SingularityRadius) { // North pole singularity - *a = (T)0.0; - *b = (T)0.0; - *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]), + *a = T(0); + *b = T(0); + *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]), ww + Q22 - Q11 - Qmm); } else @@ -1013,12 +1294,93 @@ public: } return; } -}; +}; typedef Quat Quatf; typedef Quat Quatd; + + +//------------------------------------------------------------------------------------- +// ***** Angle + +// Cleanly representing the algebra of 2D rotations. +// The operations maintain the angle between -Pi and Pi, the same range as atan2. + +template +class Angle +{ +public: + enum AngularUnits + { + Radians = 0, + Degrees = 1 + }; + + Angle() : a(0) {} + + // Fix the range to be between -Pi and Pi + Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math::DegreeToRadFactor) { FixRange(); } + + T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math::RadToDegreeFactor; } + void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math::DegreeToRadFactor; FixRange(); } + int Sign() const { if (a == 0) return 0; else return (a > 0) ? 1 : -1; } + T Abs() const { return (a > 0) ? a : -a; } + + bool operator== (const Angle& b) const { return a == b.a; } + bool operator!= (const Angle& b) const { return a != b.a; } +// bool operator< (const Angle& b) const { return a < a.b; } +// bool operator> (const Angle& b) const { return a > a.b; } +// bool operator<= (const Angle& b) const { return a <= a.b; } +// bool operator>= (const Angle& b) const { return a >= a.b; } +// bool operator= (const T& x) { a = x; FixRange(); } + + // These operations assume a is already between -Pi and Pi. + Angle& operator+= (const Angle& b) { a = a + b.a; FastFixRange(); return *this; } + Angle& operator+= (const T& x) { a = a + x; FixRange(); return *this; } + Angle operator+ (const Angle& b) const { Angle res = *this; res += b; return res; } + Angle operator+ (const T& x) const { Angle res = *this; res += x; return res; } + Angle& operator-= (const Angle& b) { a = a - b.a; FastFixRange(); return *this; } + Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; } + Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; } + Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; } + + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math::Pi) ? c : Math::TwoPi - c; } + +private: + + // The stored angle, which should be maintained between -Pi and Pi + T a; + + // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side + inline void FastFixRange() + { + if (a < -Math::Pi) + a += Math::TwoPi; + else if (a > Math::Pi) + a -= Math::TwoPi; + } + + // Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method + inline void FixRange() + { + // do nothing if the value is already in the correct range, since fmod call is expensive + if (a >= -Math::Pi && a <= Math::Pi) + return; + a = fmod(a,Math::TwoPi); + if (a < -Math::Pi) + a += Math::TwoPi; + else if (a > Math::Pi) + a -= Math::TwoPi; + } +}; + + +typedef Angle Anglef; +typedef Angle Angled; + + //------------------------------------------------------------------------------------- // ***** Plane @@ -1043,7 +1405,7 @@ public: // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane). T TestSide(const Vector3& p) const { - return (N * p) + D; + return (N.Dot(p)) + D; } Plane Flipped() const @@ -1065,6 +1427,6 @@ public: typedef Plane Planef; -} +} // Namespace OVR #endif diff --git a/interface/external/LibOVR/Src/Kernel/OVR_RefCount.h b/interface/external/LibOVR/Src/Kernel/OVR_RefCount.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Std.h b/interface/external/LibOVR/Src/Kernel/OVR_Std.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_String.h b/interface/external/LibOVR/Src/Kernel/OVR_String.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_StringHash.h b/interface/external/LibOVR/Src/Kernel/OVR_StringHash.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_SysFile.h b/interface/external/LibOVR/Src/Kernel/OVR_SysFile.h old mode 100755 new mode 100644 index d078df15db..892d16b344 --- a/interface/external/LibOVR/Src/Kernel/OVR_SysFile.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_SysFile.h @@ -88,6 +88,6 @@ public: virtual bool Close(); }; -} // Scaleform +} // Namespace OVR #endif diff --git a/interface/external/LibOVR/Src/Kernel/OVR_System.h b/interface/external/LibOVR/Src/Kernel/OVR_System.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Threads.h b/interface/external/LibOVR/Src/Kernel/OVR_Threads.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Timer.h b/interface/external/LibOVR/Src/Kernel/OVR_Timer.h old mode 100755 new mode 100644 index 778dce812b..34f72c4d26 --- a/interface/external/LibOVR/Src/Kernel/OVR_Timer.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_Timer.h @@ -95,6 +95,6 @@ private: }; -} // Scaleform::Timer +} // Namespace OVR #endif diff --git a/interface/external/LibOVR/Src/Kernel/OVR_Types.h b/interface/external/LibOVR/Src/Kernel/OVR_Types.h old mode 100755 new mode 100644 index 75493aab2b..db024f1fd1 --- a/interface/external/LibOVR/Src/Kernel/OVR_Types.h +++ b/interface/external/LibOVR/Src/Kernel/OVR_Types.h @@ -291,7 +291,7 @@ namespace BaseTypes #if defined(OVR_CC_MSVC) # define OVR_FORCE_INLINE __forceinline #elif defined(OVR_CC_GNU) -# define OVR_FORCE_INLINE __attribute__((always_inline)) +# define OVR_FORCE_INLINE __attribute__((always_inline)) inline #else # define OVR_FORCE_INLINE inline #endif // OVR_CC_MSVC diff --git a/interface/external/LibOVR/Src/Kernel/OVR_UTF8Util.h b/interface/external/LibOVR/Src/Kernel/OVR_UTF8Util.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/OVR_Device.h b/interface/external/LibOVR/Src/OVR_Device.h old mode 100755 new mode 100644 index ef33ed4579..72a8c5ec70 --- a/interface/external/LibOVR/Src/OVR_Device.h +++ b/interface/external/LibOVR/Src/OVR_Device.h @@ -24,14 +24,19 @@ otherwise accompanies this software in either electronic or hard copy form. #include "Kernel/OVR_Atomic.h" #include "Kernel/OVR_RefCount.h" +#include "Kernel/OVR_String.h" namespace OVR { +// Declared externally +class Profile; +class ProfileManager; // << Should be renamed for consistency + +// Forward declarations class SensorDevice; class DeviceCommon; class DeviceManager; - // MessageHandler is a base class from which users derive to receive messages, // its OnMessage handler will be called for messages once it is installed on // a device. Same message handler can be installed on multiple devices. @@ -102,6 +107,8 @@ public: virtual DeviceType GetType() const; virtual bool GetDeviceInfo(DeviceInfo* info) const; + // returns the MessageHandler's lock + Lock* GetHandlerLock() const; protected: // Internal virtual DeviceCommon* getDeviceCommon() const = 0; @@ -228,6 +235,10 @@ public: virtual DeviceType GetType() const { return Device_Manager; } virtual DeviceManager* GetManager() const { return const_cast(this); } + // Every DeviceManager has an associated profile manager, which us used to store + // user settings that may affect device behavior. + virtual ProfileManager* GetProfileManager() const = 0; + // EnumerateDevices enumerates all of the available devices of the specified class, // returning an enumerator that references the first device. An empty enumerator is @@ -251,14 +262,18 @@ public: // End users should call DeumerateDevices<>() instead. virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0; - // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time. static DeviceManager* Create(); - // Static constant for this device type, used in template cast type checks. enum { EnumDeviceType = Device_Manager }; + + + // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL, + // if unsuccessful or device is already in the list. + virtual Ptr AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0; + protected: DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args) { return DeviceEnumerator<>(h, args); } @@ -368,6 +383,14 @@ public: memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName)); DisplayId = src.DisplayId; } + + bool IsSameDisplay(const HMDInfo& o) const + { + return DisplayId == o.DisplayId && + String::CompareNoCase(DisplayDeviceName, + o.DisplayDeviceName) == 0; + } + }; @@ -389,10 +412,29 @@ public: // Static constant for this device type, used in template cast type checks. enum { EnumDeviceType = Device_HMD }; - virtual DeviceType GetType() const { return Device_HMD; } + virtual DeviceType GetType() const { return Device_HMD; } // Creates a sensor associated with this HMD. virtual SensorDevice* GetSensor() = 0; + + + // Requests the currently used profile. This profile affects the + // settings reported by HMDInfo. + virtual Profile* GetProfile() const = 0; + // Obtains the currently used profile name. This is initialized to the default + // profile name, if any; it can then be changed per-device by SetProfileName. + virtual const char* GetProfileName() const = 0; + // Sets the profile user name, changing the data returned by GetProfileInfo. + virtual bool SetProfileName(const char* name) = 0; + + + // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD. + // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL). + HMDDevice* Disconnect(SensorDevice*); + + // Returns 'true' if HMD device is a 'fake' HMD (was created this way or + // 'Disconnect' method was called). + bool IsDisconnected() const; }; @@ -479,6 +521,17 @@ public: virtual void SetCoordinateFrame(CoordinateFrame coordframe) = 0; virtual CoordinateFrame GetCoordinateFrame() const = 0; + // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). + // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be + // called twice or thrice at the same 'tick'. + // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three + // times for each 'tick': the first call will contain averaged values, the second + // and third calls will provide with most recent two recorded samples. + virtual void SetReportRate(unsigned rateHz) = 0; + // Returns currently set report rate, in Hz. If 0 - error occurred. + // Note, this value may be different from the one provided for SetReportRate. The return + // value will contain the actual rate. + virtual unsigned GetReportRate() const = 0; // Sets maximum range settings for the sensor described by SensorRange. // The function will fail if you try to pass values outside Maximum supported @@ -509,34 +562,6 @@ struct LatencyTestConfiguration bool SendSamples; }; -//------------------------------------------------------------------------------------- -// ***** LatencyTestCalibrate -// LatencyTestCalibrate specifies colors used for Latency Tester calibration. -struct LatencyTestCalibrate -{ - LatencyTestCalibrate(const Color& value) - : Value(value) - { - } - - // The color being calibrated to. - Color Value; -}; - -//------------------------------------------------------------------------------------- -// ***** LatencyTestStartTest -// LatencyTestStartTest specifies values used when starting the Latency Tester test. -struct LatencyTestStartTest -{ - LatencyTestStartTest(const Color& targetValue) - : TargetValue(targetValue) - { - } - - // The color value that the display is being set to. - Color TargetValue; -}; - //------------------------------------------------------------------------------------- // ***** LatencyTestDisplay // LatencyTestDisplay sets the mode and contents of the Latency Tester LED display. @@ -574,19 +599,19 @@ public: // Get configuration information from device. virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0; - // Used to calibrate the latency tester at the start of a test. Calibration information is lost + // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen + // beneath the latency tester and then call this method. Calibration information is lost // when power is removed from the device. - virtual bool SetCalibrate(const LatencyTestCalibrate& calibrate, bool waitFlag = false) = 0; - - // Get calibration information from device. - virtual bool GetCalibrate(LatencyTestCalibrate* calibrate) = 0; + virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0; // Triggers the start of a measurement. This starts the millisecond timer on the device and // causes it to respond with the 'MessageLatencyTestStarted' message. - virtual bool SetStartTest(const LatencyTestStartTest& start, bool waitFlag = false) = 0; + virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0; // Used to set the value displayed on the LED display panel. virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0; + + virtual DeviceBase* GetDevice() { return this; } }; } // namespace OVR diff --git a/interface/external/LibOVR/Src/OVR_DeviceConstants.h b/interface/external/LibOVR/Src/OVR_DeviceConstants.h old mode 100755 new mode 100644 index 41342ce670..37b95cf43c --- a/interface/external/LibOVR/Src/OVR_DeviceConstants.h +++ b/interface/external/LibOVR/Src/OVR_DeviceConstants.h @@ -30,6 +30,7 @@ enum DeviceType Device_HMD = 2, Device_Sensor = 3, Device_LatencyTester = 4, + Device_BootLoader = 5, Device_All = 0xFF // Set for enumeration only, to enumerate all device types. }; diff --git a/interface/external/LibOVR/Src/OVR_DeviceHandle.h b/interface/external/LibOVR/Src/OVR_DeviceHandle.h old mode 100755 new mode 100644 index b626188204..dc8b26716e --- a/interface/external/LibOVR/Src/OVR_DeviceHandle.h +++ b/interface/external/LibOVR/Src/OVR_DeviceHandle.h @@ -59,15 +59,30 @@ public: // operator bool() returns true if Handle/Enumerator points to a valid device. operator bool () const { return GetType() != Device_None; } + // Returns existing device, or NULL if !IsCreated. The returned ptr is + // addref-ed. + DeviceBase* GetDevice_AddRef() const; DeviceType GetType() const; bool GetDeviceInfo(DeviceInfo* info) const; bool IsAvailable() const; bool IsCreated() const; + // Returns true, if the handle contains the same device ptr + // as specified in the parameter. + bool IsDevice(DeviceBase*) const; // Creates a device, or returns AddRefed pointer if one is already created. // New devices start out with RefCount of 1. DeviceBase* CreateDevice(); + // Creates a device, or returns AddRefed pointer if one is already created. + // New devices start out with RefCount of 1. DeviceT is used to cast the + // DeviceBase* to a concreete type. + template + DeviceT* CreateDeviceTyped() const + { + return static_cast(DeviceHandle(*this).CreateDevice()); + } + // Resets the device handle to uninitialized state. void Clear(); diff --git a/interface/external/LibOVR/Src/OVR_DeviceImpl.h b/interface/external/LibOVR/Src/OVR_DeviceImpl.h old mode 100755 new mode 100644 index 3cccb0643d..e61e37b7d8 --- a/interface/external/LibOVR/Src/OVR_DeviceImpl.h +++ b/interface/external/LibOVR/Src/OVR_DeviceImpl.h @@ -30,12 +30,18 @@ namespace OVR { class DeviceManagerImpl; class DeviceFactory; +enum +{ + Oculus_VendorId = 0x2833 +}; + //------------------------------------------------------------------------------------- // Globally shared Lock implementation used for MessageHandlers. class SharedLock { public: + SharedLock() : UseCount(0) {} Lock* GetLockAddRef(); void ReleaseLock(Lock* plock); @@ -127,8 +133,8 @@ public: RemoveNode(); } - DeviceManagerImpl* GetManagerImpl() { return pLock->pManager; } - Lock* GetLock() const { return &pLock->CreateLock; } + DeviceManagerImpl* GetManagerImpl() const { return pLock->pManager; } + Lock* GetLock() const { return &pLock->CreateLock; } // DeviceCreateDesc reference counting is tied to Devices list management, // see comments for HandleCount. @@ -160,12 +166,21 @@ public: // but more searching is necessary. If this is the case UpdateMatchedCandidate will be called. virtual MatchResult MatchDevice(const DeviceCreateDesc& other, DeviceCreateDesc** pcandidate) const = 0; + // Called for matched candidate after all potential matches are iterated. // Used to update HMDevice creation arguments from Sensor. + // Optional return param 'newDeviceFlag' will be set to true if the + // 'desc' refers to a new device; false, otherwise. // Return 'false' to create new object, 'true' if done with this argument. - virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&) { return false; } + virtual bool UpdateMatchedCandidate( + const DeviceCreateDesc& desc, bool* newDeviceFlag = NULL) + { OVR_UNUSED2(desc, newDeviceFlag); return false; } + // Matches HID device to the descriptor. + virtual bool MatchHIDDevice(const HIDDeviceDesc&) const { return false; } + // Matches device by path. + virtual bool MatchDevice(const String& /*path*/) { return false; } //protected: DeviceFactory* const pFactory; const DeviceType Type; @@ -292,6 +307,22 @@ public: // Enumerates factory devices by notifying EnumerateVisitor about every // device that is present. virtual void EnumerateDevices(EnumerateVisitor& visitor) = 0; + + // Matches vendorId/productId pair with the factory; returns 'true' + // if the factory can handle the device. + virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const + { + OVR_UNUSED2(vendorId, productId); + return false; + } + + // Detects the HID device and adds the DeviceCreateDesc into Devices list, if + // the device belongs to this factory. Returns 'false', if not. + virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc) + { + OVR_UNUSED2(pdevMgr, desc); + return false; + } protected: DeviceManagerImpl* pManager; @@ -318,10 +349,17 @@ public: virtual bool Initialize(DeviceBase* parent); virtual void Shutdown(); + + // Every DeviceManager has an associated profile manager, which is used to store + // user settings that may affect device behavior. + virtual ProfileManager* GetProfileManager() const { return pProfileManager.GetPtr(); } + // Override to return ThreadCommandQueue implementation used to post commands // to the background device manager thread (that must be created by Initialize). virtual ThreadCommandQueue* GetThreadQueue() = 0; + // Returns the thread id of the DeviceManager. + virtual ThreadId GetThreadId() const = 0; virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); @@ -361,11 +399,21 @@ public: // Enumerates devices for a particular factory. virtual Void EnumerateFactoryDevices(DeviceFactory* factory); - virtual HIDDeviceManager* GetHIDDeviceManager() + virtual HIDDeviceManager* GetHIDDeviceManager() const { return HidDeviceManager; } + // Adds device (DeviceCreateDesc*) into Devices. Returns NULL, + // if unsuccessful or device is already in the list. + virtual Ptr AddDevice_NeedsLock(const DeviceCreateDesc& createDesc); + + // Finds a device descriptor by path and optional type. + Ptr FindDevice(const String& path, DeviceType = Device_None); + + // Finds HID device by HIDDeviceDesc. + Ptr FindHIDDevice(const HIDDeviceDesc&); + void DetectHIDDevice(const HIDDeviceDesc&); // Manager Lock-protected list of devices. List Devices; @@ -375,6 +423,7 @@ public: protected: Ptr HidDeviceManager; + Ptr pProfileManager; }; diff --git a/interface/external/LibOVR/Src/OVR_DeviceMessages.h b/interface/external/LibOVR/Src/OVR_DeviceMessages.h old mode 100755 new mode 100644 index 8042468313..43f9496533 --- a/interface/external/LibOVR/Src/OVR_DeviceMessages.h +++ b/interface/external/LibOVR/Src/OVR_DeviceMessages.h @@ -93,7 +93,8 @@ public: float TimeDelta; // Time passed since last Body Frame, in seconds. }; -// Sent when we receive a device status changes. +// Sent when we receive a device status changes (e.g.: +// Message_DeviceAdded, Message_DeviceRemoved). class MessageDeviceStatus : public Message { public: diff --git a/interface/external/LibOVR/Src/OVR_HIDDevice.h b/interface/external/LibOVR/Src/OVR_HIDDevice.h old mode 100755 new mode 100644 index 7765f52991..512b96ac8b --- a/interface/external/LibOVR/Src/OVR_HIDDevice.h +++ b/interface/external/LibOVR/Src/OVR_HIDDevice.h @@ -123,8 +123,8 @@ public: enum HIDDeviceMessageType { - HIDDeviceMessage_DeviceAdded = 0, - HIDDeviceMessage_DeviceRemoved = 1, + HIDDeviceMessage_DeviceAdded = 0, + HIDDeviceMessage_DeviceRemoved = 1 }; virtual void OnDeviceMessage(HIDDeviceMessageType messageType) diff --git a/interface/external/LibOVR/Src/OVR_HIDDeviceBase.h b/interface/external/LibOVR/Src/OVR_HIDDeviceBase.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/OVR_HIDDeviceImpl.h b/interface/external/LibOVR/Src/OVR_HIDDeviceImpl.h old mode 100755 new mode 100644 index 6a77659897..f9d0922225 --- a/interface/external/LibOVR/Src/OVR_HIDDeviceImpl.h +++ b/interface/external/LibOVR/Src/OVR_HIDDeviceImpl.h @@ -30,6 +30,12 @@ public: HIDDeviceCreateDesc(const HIDDeviceCreateDesc& other) : DeviceCreateDesc(other.pFactory, other.Type), HIDDesc(other.HIDDesc) { } + virtual bool MatchDevice(const String& path) + { + // should it be case insensitive? + return HIDDesc.Path.CompareNoCase(path) == 0; + } + HIDDeviceDesc HIDDesc; }; @@ -46,19 +52,18 @@ public: // HIDDevice::Handler interface. virtual void OnDeviceMessage(HIDDeviceMessageType messageType) { - MessageType handlerMessageType = handlerMessageType = Message_DeviceAdded; - if (messageType == HIDDeviceMessage_DeviceAdded) - { - } - else if (messageType == HIDDeviceMessage_DeviceRemoved) - { - handlerMessageType = Message_DeviceRemoved; - } - else - { - OVR_ASSERT(0); - } + MessageType handlerMessageType; + switch (messageType) { + case HIDDeviceMessage_DeviceAdded: + handlerMessageType = Message_DeviceAdded; + break; + case HIDDeviceMessage_DeviceRemoved: + handlerMessageType = Message_DeviceRemoved; + break; + + default: OVR_ASSERT(0); return; + } // Do device notification. { @@ -71,17 +76,18 @@ public: } } - // Do device manager notification. DeviceManagerImpl* manager = this->GetManagerImpl(); - - if (handlerMessageType == Message_DeviceAdded) - { - manager->CallOnDeviceAdded(this->pCreateDesc); - } - else if (handlerMessageType == Message_DeviceRemoved) - { - manager->CallOnDeviceRemoved(this->pCreateDesc); + switch (handlerMessageType) { + case Message_DeviceAdded: + manager->CallOnDeviceAdded(this->pCreateDesc); + break; + + case Message_DeviceRemoved: + manager->CallOnDeviceRemoved(this->pCreateDesc); + break; + + default:; } } @@ -177,7 +183,7 @@ public: } protected: - HIDDevice* GetInternalDevice() + HIDDevice* GetInternalDevice() const { return InternalDevice; } diff --git a/interface/external/LibOVR/Src/OVR_JSON.h b/interface/external/LibOVR/Src/OVR_JSON.h new file mode 100644 index 0000000000..5e5996fcd8 --- /dev/null +++ b/interface/external/LibOVR/Src/OVR_JSON.h @@ -0,0 +1,143 @@ +/************************************************************************************ + +PublicHeader: None +Filename : OVR_JSON.h +Content : JSON format reader and writer +Created : April 9, 2013 +Author : Brant Lewis +Notes : + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#ifndef OVR_JSON_H +#define OVR_JSON_H + +#include "Kernel/OVR_RefCount.h" +#include "Kernel/OVR_String.h" +#include "Kernel/OVR_List.h" + +namespace OVR { + +// JSONItemType describes the type of JSON item, specifying the type of +// data that can be obtained from it. +enum JSONItemType +{ + JSON_None = 0, + JSON_Null = 1, + JSON_Bool = 2, + JSON_Number = 3, + JSON_String = 4, + JSON_Array = 5, + JSON_Object = 6 +}; + + +//----------------------------------------------------------------------------- +// ***** JSON + +// JSON object represents a JSON node that can be either a root of the JSON tree +// or a child item. Every node has a type that describes what is is. +// New JSON trees are typically loaded JSON::Load or created with JSON::Parse. + +class JSON : public RefCountBase, public ListNode +{ +protected: + List Children; + +public: + JSONItemType Type; // Type of this JSON node. + String Name; // Name part of the {Name, Value} pair in a parent object. + String Value; + double dValue; + +public: + ~JSON(); + + // *** Creation of NEW JSON objects + + static JSON* CreateObject() { return new JSON(JSON_Object);} + static JSON* CreateNull() { return new JSON(JSON_Null); } + static JSON* CreateArray() { return new JSON(JSON_Array); } + static JSON* CreateBool(bool b) { return createHelper(JSON_Bool, b ? 1.0 : 0.0); } + static JSON* CreateNumber(double num) { return createHelper(JSON_Number, num); } + static JSON* CreateString(const char *s) { return createHelper(JSON_String, 0.0, s); } + + // Creates a new JSON object from parsing string. + // Returns null pointer and fills in *perror in case of parse error. + static JSON* Parse(const char* buff, const char** perror = 0); + + // Loads and parses a JSON object from a file. + // Returns 0 and assigns perror with error message on fail. + static JSON* Load(const char* path, const char** perror = 0); + + // Saves a JSON object to a file. + bool Save(const char* path); + + + // *** Object Member Access + + // These provide access to child items of the list. + bool HasItems() const { return Children.IsEmpty(); } + // Returns first/last child item, or null if child list is empty + JSON* GetFirstItem() { return (!Children.IsEmpty()) ? Children.GetFirst() : 0; } + JSON* GetLastItem() { return (!Children.IsEmpty()) ? Children.GetLast() : 0; } + + // Counts the number of items in the object; these methods are inefficient. + unsigned GetItemCount() const; + JSON* GetItemByIndex(unsigned i); + JSON* GetItemByName(const char* name); + + // Returns next item in a list of children; 0 if no more items exist. + JSON* GetNextItem(JSON* item) { return Children.IsNull(item->pNext) ? 0 : item->pNext; } + JSON* GetPrevItem(JSON* item) { return Children.IsNull(item->pPrev) ? 0 : item->pPrev; } + + + // Child item access functions + void AddItem(const char *string, JSON* item); + void AddNullItem(const char* name) { AddItem(name, CreateNull()); } + void AddBoolItem(const char* name, bool b) { AddItem(name, CreateBool(b)); } + void AddNumberItem(const char* name, double n) { AddItem(name, CreateNumber(n)); } + void AddStringItem(const char* name, const char* s) { AddItem(name, CreateString(s)); } +// void ReplaceItem(unsigned index, JSON* new_item); +// void DeleteItem(unsigned index); + + // *** Array Element Access + + // Add new elements to the end of array. + void AddArrayElement(JSON *item); + void AddArrayNumber(double n) { AddArrayElement(CreateNumber(n)); } + void AddArrayString(const char* s) { AddArrayElement(CreateString(s)); } + + // Accessed array elements; currently inefficient. + int GetArraySize(); + double GetArrayNumber(int index); + const char* GetArrayString(int index); + + +protected: + JSON(JSONItemType itemType = JSON_Object); + + static JSON* createHelper(JSONItemType itemType, double dval, const char* strVal = 0); + + // JSON Parsing helper functions. + const char* parseValue(const char *buff, const char** perror); + const char* parseNumber(const char *num); + const char* parseArray(const char* value, const char** perror); + const char* parseObject(const char* value, const char** perror); + const char* parseString(const char* str, const char** perror); + + char* PrintValue(int depth, bool fmt); + char* PrintObject(int depth, bool fmt); + char* PrintArray(int depth, bool fmt); +}; + + +} + +#endif diff --git a/interface/external/LibOVR/Src/OVR_LatencyTestImpl.h b/interface/external/LibOVR/Src/OVR_LatencyTestImpl.h old mode 100755 new mode 100644 index 5201186c4b..727e36e51c --- a/interface/external/LibOVR/Src/OVR_LatencyTestImpl.h +++ b/interface/external/LibOVR/Src/OVR_LatencyTestImpl.h @@ -35,6 +35,9 @@ public: // Enumerates devices, creating and destroying relevant objects in manager. virtual void EnumerateDevices(EnumerateVisitor& visitor); + virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const; + virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc); + protected: DeviceManager* getManager() const { return (DeviceManager*) pManager; } }; @@ -60,13 +63,18 @@ public: if ((other.Type == Device_LatencyTester) && (pFactory == other.pFactory)) { const LatencyTestDeviceCreateDesc& s2 = (const LatencyTestDeviceCreateDesc&) other; - if ((HIDDesc.Path == s2.HIDDesc.Path) && - (HIDDesc.SerialNumber == s2.HIDDesc.SerialNumber)) + if (MatchHIDDevice(s2.HIDDesc)) return Match_Found; } return Match_None; } + virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const + { + // should paths comparison be case insensitive? + return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) && + (HIDDesc.SerialNumber == hidDesc.SerialNumber)); + } virtual bool GetDeviceInfo(DeviceInfo* info) const; }; @@ -93,10 +101,9 @@ public: virtual bool SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag = false); virtual bool GetConfiguration(OVR::LatencyTestConfiguration* configuration); - virtual bool SetCalibrate(const OVR::LatencyTestCalibrate& calibrate, bool waitFlag = false); - virtual bool GetCalibrate(OVR::LatencyTestCalibrate* calibrate); + virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false); - virtual bool SetStartTest(const OVR::LatencyTestStartTest& start, bool waitFlag = false); + virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false); virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false); protected: @@ -109,9 +116,8 @@ protected: bool setConfiguration(const OVR::LatencyTestConfiguration& configuration); bool getConfiguration(OVR::LatencyTestConfiguration* configuration); - bool setCalibrate(const OVR::LatencyTestCalibrate& calibrate); - bool getCalibrate(OVR::LatencyTestCalibrate* calibrate); - bool setStartTest(const OVR::LatencyTestStartTest& start); + bool setCalibrate(const Color& calibrationColor); + bool setStartTest(const Color& targetColor); bool setDisplay(const OVR::LatencyTestDisplay& display); // Called for decoded messages diff --git a/interface/external/LibOVR/Src/OVR_Linux_DeviceManager.h b/interface/external/LibOVR/Src/OVR_Linux_DeviceManager.h new file mode 100644 index 0000000000..69dabc013a --- /dev/null +++ b/interface/external/LibOVR/Src/OVR_Linux_DeviceManager.h @@ -0,0 +1,111 @@ +/************************************************************************************ + +Filename : OVR_Linux_DeviceManager.h +Content : Linux-specific DeviceManager header. +Created : +Authors : + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +*************************************************************************************/ + +#ifndef OVR_Linux_DeviceManager_h +#define OVR_Linux_DeviceManager_h + +#include "OVR_DeviceImpl.h" + +#include +#include + + +namespace OVR { namespace Linux { + +class DeviceManagerThread; + +//------------------------------------------------------------------------------------- +// ***** Linux DeviceManager + +class DeviceManager : public DeviceManagerImpl +{ +public: + DeviceManager(); + ~DeviceManager(); + + // Initialize/Shutdowncreate and shutdown manger thread. + virtual bool Initialize(DeviceBase* parent); + virtual void Shutdown(); + + virtual ThreadCommandQueue* GetThreadQueue(); + virtual ThreadId GetThreadId() const; + + virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); + + virtual bool GetDeviceInfo(DeviceInfo* info) const; + + Ptr pThread; +}; + +//------------------------------------------------------------------------------------- +// ***** Device Manager Background Thread + +class DeviceManagerThread : public Thread, public ThreadCommandQueue +{ + friend class DeviceManager; + enum { ThreadStackSize = 64 * 1024 }; +public: + DeviceManagerThread(); + ~DeviceManagerThread(); + + virtual int Run(); + + // ThreadCommandQueue notifications for CommandEvent handling. + virtual void OnPushNonEmpty_Locked() { write(CommandFd[1], this, 1); } + virtual void OnPopEmpty_Locked() { } + + class Notifier + { + public: + // Called when I/O is received + virtual void OnEvent(int i, int fd) = 0; + + // Called when timing ticks are updated. + // Returns the largest number of microseconds this function can + // wait till next call. + virtual UInt64 OnTicks(UInt64 ticksMks) + { + OVR_UNUSED1(ticksMks); + return Timer::MksPerSecond * 1000; + } + }; + + // Add I/O notifier + bool AddSelectFd(Notifier* notify, int fd); + bool RemoveSelectFd(Notifier* notify, int fd); + + // Add notifier that will be called at regular intervals. + bool AddTicksNotifier(Notifier* notify); + bool RemoveTicksNotifier(Notifier* notify); + +private: + + bool threadInitialized() { return CommandFd[0] != 0; } + + // pipe used to signal commands + int CommandFd[2]; + + Array PollFds; + Array FdNotifiers; + + Event StartupEvent; + + // Ticks notifiers - used for time-dependent events such as keep-alive. + Array TicksNotifiers; +}; + +}} // namespace Linux::OVR + +#endif // OVR_Linux_DeviceManager_h diff --git a/interface/external/LibOVR/Src/OVR_Linux_HIDDevice.h b/interface/external/LibOVR/Src/OVR_Linux_HIDDevice.h new file mode 100644 index 0000000000..eae352e896 --- /dev/null +++ b/interface/external/LibOVR/Src/OVR_Linux_HIDDevice.h @@ -0,0 +1,124 @@ +/************************************************************************************ +Filename : OVR_Linux_HIDDevice.h +Content : Linux HID device implementation. +Created : June 13, 2013 +Authors : Brant Lewis + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +*************************************************************************************/ + +#ifndef OVR_LINUX_HIDDevice_h +#define OVR_LINUX_HIDDevice_h + +#include "OVR_HIDDevice.h" +#include "OVR_Linux_DeviceManager.h" +#include + +namespace OVR { namespace Linux { + +class HIDDeviceManager; + +//------------------------------------------------------------------------------------- +// ***** Linux HIDDevice + +class HIDDevice : public OVR::HIDDevice, public DeviceManagerThread::Notifier +{ +private: + friend class HIDDeviceManager; + +public: + HIDDevice(HIDDeviceManager* manager); + + // This is a minimal constructor used during enumeration for us to pass + // a HIDDevice to the visit function (so that it can query feature reports). + HIDDevice(HIDDeviceManager* manager, int device_handle); + + virtual ~HIDDevice(); + + bool HIDInitialize(const String& path); + void HIDShutdown(); + + virtual bool SetFeatureReport(UByte* data, UInt32 length); + virtual bool GetFeatureReport(UByte* data, UInt32 length); + + // DeviceManagerThread::Notifier + void OnEvent(int i, int fd); + UInt64 OnTicks(UInt64 ticksMks); + + bool OnDeviceNotification(MessageType messageType, + HIDDeviceDesc* device_info, + bool* error); + +private: + bool initInfo(); + bool openDevice(const char* dev_path); + void closeDevice(bool wasUnplugged); + void closeDeviceOnIOError(); + bool setupDevicePluggedInNotification(); + + bool InMinimalMode; + HIDDeviceManager* HIDManager; + int DeviceHandle; // file handle to the device + HIDDeviceDesc DevDesc; + + enum { ReadBufferSize = 96 }; + UByte ReadBuffer[ReadBufferSize]; + + UInt16 InputReportBufferLength; + UInt16 OutputReportBufferLength; + UInt16 FeatureReportBufferLength; +}; + + +//------------------------------------------------------------------------------------- +// ***** Linux HIDDeviceManager + +class HIDDeviceManager : public OVR::HIDDeviceManager, public DeviceManagerThread::Notifier +{ + friend class HIDDevice; + +public: + HIDDeviceManager(Linux::DeviceManager* Manager); + virtual ~HIDDeviceManager(); + + virtual bool Initialize(); + virtual void Shutdown(); + + virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor); + virtual OVR::HIDDevice* Open(const String& path); + + static HIDDeviceManager* CreateInternal(DeviceManager* manager); + + void OnEvent(int i, int fd); + +private: + bool initializeManager(); + bool initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc); + bool getPath(udev_device* device, String* pPath); + bool getIntProperty(udev_device* device, const char* key, int32_t* pResult); + bool getStringProperty(udev_device* device, + const char* propertyName, + OVR::String* pResult); + bool getFullDesc(udev_device* device, HIDDeviceDesc* desc); + bool GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc); + + bool AddNotificationDevice(HIDDevice* device); + bool RemoveNotificationDevice(HIDDevice* device); + + DeviceManager* DevManager; + + udev* UdevInstance; // a handle to the udev library instance + udev_monitor* HIDMonitor; + int HIDMonHandle; // the udev_monitor file handle + + Array NotificationDevices; +}; + +}} // namespace OVR::Linux + +#endif // OVR_Linux_HIDDevice_h diff --git a/interface/external/LibOVR/Src/OVR_Linux_HMDDevice.h b/interface/external/LibOVR/Src/OVR_Linux_HMDDevice.h new file mode 100644 index 0000000000..d0585d1a43 --- /dev/null +++ b/interface/external/LibOVR/Src/OVR_Linux_HMDDevice.h @@ -0,0 +1,156 @@ +/************************************************************************************ + +Filename : OVR_Linux_HMDDevice.h +Content : Linux HMDDevice implementation +Created : June 17, 2013 +Authors : Brant Lewis + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +*************************************************************************************/ + +#ifndef OVR_Linux_HMDDevice_h +#define OVR_Linux_HMDDevice_h + +#include "OVR_Linux_DeviceManager.h" +#include "OVR_Profile.h" + +namespace OVR { namespace Linux { + +class HMDDevice; + +//------------------------------------------------------------------------------------- + +// HMDDeviceFactory enumerates attached Oculus HMD devices. +// +// This is currently done by matching monitor device strings. + +class HMDDeviceFactory : public DeviceFactory +{ +public: + static HMDDeviceFactory Instance; + + // Enumerates devices, creating and destroying relevant objects in manager. + virtual void EnumerateDevices(EnumerateVisitor& visitor); + +protected: + DeviceManager* getManager() const { return (DeviceManager*) pManager; } +}; + + +class HMDDeviceCreateDesc : public DeviceCreateDesc +{ + friend class HMDDevice; + +protected: + enum + { + Contents_Screen = 1, + Contents_Distortion = 2, + Contents_7Inch = 4, + }; + String DeviceId; + String DisplayDeviceName; + int DesktopX, DesktopY; + unsigned Contents; + unsigned HResolution, VResolution; + float HScreenSize, VScreenSize; + long DisplayId; + float DistortionK[4]; + +public: + HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId); + HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other); + + virtual DeviceCreateDesc* Clone() const + { + return new HMDDeviceCreateDesc(*this); + } + + virtual DeviceBase* NewDeviceInstance(); + + virtual MatchResult MatchDevice(const DeviceCreateDesc& other, + DeviceCreateDesc**) const; + + // Matches device by path. + virtual bool MatchDevice(const String& path); + + virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL); + + virtual bool GetDeviceInfo(DeviceInfo* info) const; + + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + Profile* GetProfileAddRef() const; + + ProfileType GetProfileType() const + { + return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1; + } + + + void SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize) + { + DesktopX = x; + DesktopY = y; + HResolution = hres; + VResolution = vres; + HScreenSize = hsize; + VScreenSize = vsize; + Contents |= Contents_Screen; + } + void SetDistortion(const float* dks) + { + for (int i = 0; i < 4; i++) + DistortionK[i] = dks[i]; + Contents |= Contents_Distortion; + } + + void Set7Inch() { Contents |= Contents_7Inch; } + + bool Is7Inch() const; +}; + + +//------------------------------------------------------------------------------------- + +// HMDDevice represents an Oculus HMD device unit. An instance of this class +// is typically created from the DeviceManager. +// After HMD device is created, we its sensor data can be obtained by +// first creating a Sensor object and then wrappig it in SensorFusion. + +class HMDDevice : public DeviceImpl +{ +public: + HMDDevice(HMDDeviceCreateDesc* createDesc); + ~HMDDevice(); + + virtual bool Initialize(DeviceBase* parent); + virtual void Shutdown(); + + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + virtual Profile* GetProfile() const; + virtual const char* GetProfileName() const; + virtual bool SetProfileName(const char* name); + + // Query associated sensor. + virtual OVR::SensorDevice* GetSensor(); + +protected: + HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); } + + // User name for the profile used with this device. + String ProfileName; + mutable Ptr pCachedProfile; +}; + + +}} // namespace OVR::Linux + +#endif // OVR_Linux_HMDDevice_h + diff --git a/interface/external/LibOVR/Src/OVR_OSX_DeviceManager.h b/interface/external/LibOVR/Src/OVR_OSX_DeviceManager.h old mode 100755 new mode 100644 index 1729bf9618..f272a352d3 --- a/interface/external/LibOVR/Src/OVR_OSX_DeviceManager.h +++ b/interface/external/LibOVR/Src/OVR_OSX_DeviceManager.h @@ -21,6 +21,8 @@ otherwise accompanies this software in either electronic or hard copy form. #include "Kernel/OVR_Timer.h" #include +#include +#include namespace OVR { namespace OSX { @@ -41,11 +43,18 @@ public: virtual void Shutdown(); virtual ThreadCommandQueue* GetThreadQueue(); - + virtual ThreadId GetThreadId() const; + virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); virtual bool GetDeviceInfo(DeviceInfo* info) const; +protected: + static void displayReconfigurationCallBack (CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags, + void *userInfo); + +public: // data Ptr pThread; }; @@ -90,6 +99,7 @@ public: CFRunLoopRef GetRunLoop() { return RunLoop; } + void Shutdown(); private: CFRunLoopRef RunLoop; diff --git a/interface/external/LibOVR/Src/OVR_OSX_HIDDevice.h b/interface/external/LibOVR/Src/OVR_OSX_HIDDevice.h old mode 100755 new mode 100644 index cb5ef8f955..564bb6014f --- a/interface/external/LibOVR/Src/OVR_OSX_HIDDevice.h +++ b/interface/external/LibOVR/Src/OVR_OSX_HIDDevice.h @@ -45,8 +45,8 @@ public: bool HIDInitialize(const String& path); void HIDShutdown(); - bool SetFeatureReport(UByte* data, UInt32 length); - bool GetFeatureReport(UByte* data, UInt32 length); + virtual bool SetFeatureReport(UByte* data, UInt32 length); + virtual bool GetFeatureReport(UByte* data, UInt32 length); bool Write(UByte* data, UInt32 length); @@ -134,6 +134,11 @@ private: bool getStringProperty(IOHIDDeviceRef device, CFStringRef propertyName, String* pResult); bool getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc); + static void staticDeviceMatchingCallback(void *inContext, + IOReturn inResult, + void *inSender, + IOHIDDeviceRef inIOHIDDeviceRef); + DeviceManager* DevManager; IOHIDManagerRef HIDManager; diff --git a/interface/external/LibOVR/Src/OVR_OSX_HMDDevice.h b/interface/external/LibOVR/Src/OVR_OSX_HMDDevice.h old mode 100755 new mode 100644 index b2b9e0da2e..52b8471faa --- a/interface/external/LibOVR/Src/OVR_OSX_HMDDevice.h +++ b/interface/external/LibOVR/Src/OVR_OSX_HMDDevice.h @@ -18,6 +18,7 @@ otherwise accompanies this software in either electronic or hard copy form. #include "OVR_DeviceImpl.h" #include +#include "OVR_Profile.h" namespace OVR { namespace OSX { @@ -71,10 +72,19 @@ public: virtual MatchResult MatchDevice(const DeviceCreateDesc& other, DeviceCreateDesc**) const; - virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&); + virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL); virtual bool GetDeviceInfo(DeviceInfo* info) const; + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + Profile* GetProfileAddRef() const; + + ProfileType GetProfileType() const + { + return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1; + } + void SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize) { DesktopX = x; @@ -125,8 +135,22 @@ public: virtual bool Initialize(DeviceBase* parent); virtual void Shutdown(); + + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + virtual Profile* GetProfile() const; + virtual const char* GetProfileName() const; + virtual bool SetProfileName(const char* name); + // Query associated sensor. virtual OVR::SensorDevice* GetSensor(); + +protected: + HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); } + + // User name for the profile used with this device. + String ProfileName; + mutable Ptr pCachedProfile; }; diff --git a/interface/external/LibOVR/Src/OVR_Profile.h b/interface/external/LibOVR/Src/OVR_Profile.h new file mode 100644 index 0000000000..df25fead95 --- /dev/null +++ b/interface/external/LibOVR/Src/OVR_Profile.h @@ -0,0 +1,243 @@ +/************************************************************************************ + +PublicHeader: OVR.h +Filename : OVR_Profile.h +Content : Structs and functions for loading and storing device profile settings +Created : February 14, 2013 +Notes : + Profiles are used to store per-user settings that can be transferred and used + across multiple applications. For example, player IPD can be configured once + and reused for a unified experience across games. Configuration and saving of profiles + can be accomplished in game via the Profile API or by the official Oculus Configuration + Utility. + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#ifndef OVR_Profile_h +#define OVR_Profile_h + +#include "Kernel/OVR_String.h" +#include "Kernel/OVR_RefCount.h" +#include "Kernel/OVR_Array.h" + +namespace OVR { + +// Defines the profile object for each device type +enum ProfileType +{ + Profile_Unknown = 0, + Profile_GenericHMD = 10, + Profile_RiftDK1 = 11, + Profile_RiftDKHD = 12, +}; + +class Profile; + +// ----------------------------------------------------------------------------- +// ***** ProfileManager + +// Profiles are interfaced through a ProfileManager object. Applications should +// create a ProfileManager each time they intend to read or write user profile data. +// The scope of the ProfileManager object defines when disk I/O is performed. Disk +// reads are performed on the first profile access and disk writes are performed when +// the ProfileManager goes out of scope. All profile interactions between these times +// are performed in local memory and are fast. A typical profile interaction might +// look like this: +// +// { +// Ptr pm = *ProfileManager::Create(); +// Ptr profile = pm->LoadProfile(Profile_RiftDK1, +// pm->GetDefaultProfileName(Profile_RiftDK1)); +// if (profile) +// { // Retrieve the current profile settings +// } +// } // Profile will be destroyed and any disk I/O completed when going out of scope + +class ProfileManager : public RefCountBase +{ +protected: + // Synchronize ProfileManager access since it may be accessed from multiple threads, + // as it's shared through DeviceManager. + Lock ProfileLock; + Array > ProfileCache; + ProfileType CacheDevice; + String DefaultProfile; + bool Changed; + char NameBuff[32]; + +public: + static ProfileManager* Create(); + + // Static interface functions + int GetProfileCount(ProfileType device); + const char* GetProfileName(ProfileType device, unsigned int index); + bool HasProfile(ProfileType device, const char* name); + Profile* LoadProfile(ProfileType device, unsigned int index); + Profile* LoadProfile(ProfileType device, const char* name); + Profile* GetDeviceDefaultProfile(ProfileType device); + const char* GetDefaultProfileName(ProfileType device); + bool SetDefaultProfileName(ProfileType device, const char* name); + bool Save(const Profile* profile); + bool Delete(const Profile* profile); + +protected: + ProfileManager(); + ~ProfileManager(); + void LoadCache(ProfileType device); + void SaveCache(); + void ClearCache(); + Profile* CreateProfileObject(const char* user, + ProfileType device, + const char** device_name); +}; + +//------------------------------------------------------------------- +// ***** Profile + +// The base profile for all users. This object is not created directly. +// Instead derived device objects provide add specific device members to +// the base profile + +class Profile : public RefCountBase +{ +public: + enum { MaxNameLen = 32 }; + + enum GenderType + { + Gender_Unspecified = 0, + Gender_Male = 1, + Gender_Female = 2 + }; + + ProfileType Type; // The type of device profile + char Name[MaxNameLen]; // The name given to this profile + +protected: + GenderType Gender; // The gender of the user + float PlayerHeight; // The height of the user in meters + float IPD; // Distance between eyes in meters + +public: + virtual Profile* Clone() const = 0; + + // These are properties which are intrinsic to the user and affect scene setup + GenderType GetGender() { return Gender; }; + float GetPlayerHeight() { return PlayerHeight; }; + float GetIPD() { return IPD; }; + float GetEyeHeight(); + + void SetGender(GenderType gender) { Gender = gender; }; + void SetPlayerHeight(float height) { PlayerHeight = height; }; + void SetIPD(float ipd) { IPD = ipd; }; + +protected: + Profile(ProfileType type, const char* name); + + virtual bool ParseProperty(const char* prop, const char* sval); + + friend class ProfileManager; +}; + +//----------------------------------------------------------------------------- +// ***** HMDProfile + +// The generic HMD profile is used for properties that are common to all headsets +class HMDProfile : public Profile +{ +protected: + // FOV extents in pixels measured by a user + int LL; // left eye outer extent + int LR; // left eye inner extent + int RL; // right eye inner extent + int RR; // right eye outer extent + +public: + virtual Profile* Clone() const; + + void SetLL(int val) { LL = val; }; + void SetLR(int val) { LR = val; }; + void SetRL(int val) { RL = val; }; + void SetRR(int val) { RR = val; }; + + int GetLL() { return LL; }; + int GetLR() { return LR; }; + int GetRL() { return RL; }; + int GetRR() { return RR; }; + +protected: + HMDProfile(ProfileType type, const char* name); + + virtual bool ParseProperty(const char* prop, const char* sval); + + friend class ProfileManager; +}; + +// For headsets that use eye cups +enum EyeCupType +{ + EyeCup_A = 0, + EyeCup_B = 1, + EyeCup_C = 2 +}; + +//----------------------------------------------------------------------------- +// ***** RiftDK1Profile + +// This profile is specific to the Rift Dev Kit 1 and contains overrides specific +// to that device and lens cup settings. +class RiftDK1Profile : public HMDProfile +{ +protected: + EyeCupType EyeCups; // Which eye cup does the player use + +public: + virtual Profile* Clone() const; + + EyeCupType GetEyeCup() { return EyeCups; }; + void SetEyeCup(EyeCupType cup) { EyeCups = cup; }; + +protected: + RiftDK1Profile(const char* name); + + virtual bool ParseProperty(const char* prop, const char* sval); + + friend class ProfileManager; +}; + +//----------------------------------------------------------------------------- +// ***** RiftDKHDProfile + +// This profile is specific to the Rift HD Dev Kit and contains overrides specific +// to that device and lens cup settings. +class RiftDKHDProfile : public HMDProfile +{ +protected: + EyeCupType EyeCups; // Which eye cup does the player use + +public: + virtual Profile* Clone() const; + + EyeCupType GetEyeCup() { return EyeCups; }; + void SetEyeCup(EyeCupType cup) { EyeCups = cup; }; + +protected: + RiftDKHDProfile(const char* name); + + virtual bool ParseProperty(const char* prop, const char* sval); + + friend class ProfileManager; +}; + + +String GetBaseOVRPath(bool create_dir); + +} + +#endif // OVR_Profile_h \ No newline at end of file diff --git a/interface/external/LibOVR/Src/OVR_SensorFilter.h b/interface/external/LibOVR/Src/OVR_SensorFilter.h old mode 100755 new mode 100644 index de35cabc0a..e6ff01a03b --- a/interface/external/LibOVR/Src/OVR_SensorFilter.h +++ b/interface/external/LibOVR/Src/OVR_SensorFilter.h @@ -4,7 +4,7 @@ PublicHeader: OVR.h Filename : OVR_SensorFilter.h Content : Basic filtering of sensor data Created : March 7, 2013 -Authors : Steve LaValle, Anna Yershova +Authors : Steve LaValle, Anna Yershova, Max Katsev Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -22,74 +22,179 @@ otherwise accompanies this software in either electronic or hard copy form. namespace OVR { -// This class maintains a sliding window of sensor data taken over time and implements -// various simple filters, most of which are linear functions of the data history. -class SensorFilter +// A simple circular buffer data structure that stores last N elements in an array +template +class CircularBuffer { +protected: enum { - MaxFilterSize = 100, - DefaultFilterSize = 20 + DefaultFilterCapacity = 20 }; -private: - int LastIdx; // The index of the last element that was added to the array - int Size; // The window size (number of elements) - Vector3f Elements[MaxFilterSize]; + int LastIdx; // The index of the last element that was added to the buffer + int Capacity; // The buffer size (maximum number of elements) + int Count; // Number of elements in the filter + T* Elements; public: - // Create a new filter with default size - SensorFilter() + CircularBuffer(int capacity = DefaultFilterCapacity) + : LastIdx(-1), Capacity(capacity), Count(0) { - LastIdx = -1; - Size = DefaultFilterSize; - }; + Elements = (T*)OVR_ALLOC(capacity * sizeof(T)); + for (int i = 0; i < Capacity; i++) + Elements[i] = T(); + } - // Create a new filter with size i - SensorFilter(const int &i) + ~CircularBuffer() { + OVR_FREE(Elements); + } + +private: + // Make the class non-copyable + CircularBuffer(const CircularBuffer& other); + CircularBuffer& operator=(const CircularBuffer& other); + +public: + // Add a new element to the filter + void AddElement (const T &e) { - OVR_ASSERT(i <= MaxFilterSize); - LastIdx = -1; - Size = i; - }; - - - // Create a new element to the filter - void AddElement (const Vector3f &e) - { - if (LastIdx == Size - 1) - LastIdx = 0; - else - LastIdx++; - + LastIdx = (LastIdx + 1) % Capacity; Elements[LastIdx] = e; - }; + if (Count < Capacity) + Count++; + } // Get element i. 0 is the most recent, 1 is one step ago, 2 is two steps ago, ... - Vector3f GetPrev(const int &i) + T GetPrev(int i = 0) const { - int idx = (LastIdx - i) % Size; - if (idx < 0) // Fix the negative mod problem - idx += Size; + OVR_ASSERT(i >= 0); + if (i >= Count) // return 0 if the filter doesn't have enough elements + return T(); + int idx = (LastIdx - i); + if (idx < 0) // Fix the wraparound case + idx += Capacity; + OVR_ASSERT(idx >= 0); // Multiple wraparounds not allowed return Elements[idx]; - }; + } +}; + +// A base class for filters that maintains a buffer of sensor data taken over time and implements +// various simple filters, most of which are linear functions of the data history. +// Maintains the running sum of its elements for better performance on large capacity values +template +class SensorFilterBase : public CircularBuffer +{ +protected: + T RunningTotal; // Cached sum of the elements + +public: + SensorFilterBase(int capacity = CircularBuffer::DefaultFilterCapacity) : CircularBuffer(capacity), RunningTotal() { }; + + // Add a new element to the filter + // Updates the running sum value + void AddElement (const T &e) + { + int NextIdx = (this->LastIdx + 1) % this->Capacity; + RunningTotal += (e - this->Elements[NextIdx]); + CircularBuffer::AddElement(e); + if (this->LastIdx == 0) + { + // update the cached total to avoid error accumulation + RunningTotal = T(); + for (int i = 0; i < this->Count; i++) + RunningTotal += this->Elements[i]; + } + } // Simple statistics - Vector3f Total(); - Vector3f Mean(); - Vector3f Median(); - Vector3f Variance(); // The diagonal of covariance matrix - Matrix4f Covariance(); - Vector3f PearsonCoefficient(); + T Total() const + { + return RunningTotal; + } + + T Mean() const + { + return (this->Count == 0) ? T() : (Total() / (float) this->Count); + } // A popular family of smoothing filters and smoothed derivatives - Vector3f SavitzkyGolaySmooth8(); - Vector3f SavitzkyGolayDerivative4(); - Vector3f SavitzkyGolayDerivative5(); - Vector3f SavitzkyGolayDerivative12(); - Vector3f SavitzkyGolayDerivativeN(const int &n); + T SavitzkyGolaySmooth8() const + { + OVR_ASSERT(this->Capacity >= 8); + return this->GetPrev(0)*0.41667f + + this->GetPrev(1)*0.33333f + + this->GetPrev(2)*0.25f + + this->GetPrev(3)*0.16667f + + this->GetPrev(4)*0.08333f - + this->GetPrev(6)*0.08333f - + this->GetPrev(7)*0.16667f; + } - ~SensorFilter() {}; + T SavitzkyGolayDerivative4() const + { + OVR_ASSERT(this->Capacity >= 4); + return this->GetPrev(0)*0.3f + + this->GetPrev(1)*0.1f - + this->GetPrev(2)*0.1f - + this->GetPrev(3)*0.3f; + } + + T SavitzkyGolayDerivative5() const + { + OVR_ASSERT(this->Capacity >= 5); + return this->GetPrev(0)*0.2f + + this->GetPrev(1)*0.1f - + this->GetPrev(3)*0.1f - + this->GetPrev(4)*0.2f; + } + + T SavitzkyGolayDerivative12() const + { + OVR_ASSERT(this->Capacity >= 12); + return this->GetPrev(0)*0.03846f + + this->GetPrev(1)*0.03147f + + this->GetPrev(2)*0.02448f + + this->GetPrev(3)*0.01748f + + this->GetPrev(4)*0.01049f + + this->GetPrev(5)*0.0035f - + this->GetPrev(6)*0.0035f - + this->GetPrev(7)*0.01049f - + this->GetPrev(8)*0.01748f - + this->GetPrev(9)*0.02448f - + this->GetPrev(10)*0.03147f - + this->GetPrev(11)*0.03846f; + } + + T SavitzkyGolayDerivativeN(int n) const + { + OVR_ASSERT(this->Capacity >= n); + int m = (n-1)/2; + T result = T(); + for (int k = 1; k <= m; k++) + { + int ind1 = m - k; + int ind2 = n - m + k - 1; + result += (this->GetPrev(ind1) - this->GetPrev(ind2)) * (float) k; + } + float coef = 3.0f/(m*(m+1.0f)*(2.0f*m+1.0f)); + result = result*coef; + return result; + } +}; + +// This class maintains a buffer of sensor data taken over time and implements +// various simple filters, most of which are linear functions of the data history. +class SensorFilter : public SensorFilterBase +{ +public: + SensorFilter(int capacity = DefaultFilterCapacity) : SensorFilterBase(capacity) { }; + + // Simple statistics + Vector3f Median() const; + Vector3f Variance() const; // The diagonal of covariance matrix + Matrix4f Covariance() const; + Vector3f PearsonCoefficient() const; }; } //namespace OVR diff --git a/interface/external/LibOVR/Src/OVR_SensorFusion.h b/interface/external/LibOVR/Src/OVR_SensorFusion.h old mode 100755 new mode 100644 index d638da2225..5847f54cbd --- a/interface/external/LibOVR/Src/OVR_SensorFusion.h +++ b/interface/external/LibOVR/Src/OVR_SensorFusion.h @@ -4,7 +4,7 @@ PublicHeader: OVR.h Filename : OVR_SensorFusion.h Content : Methods that determine head orientation from sensor data over time Created : October 9, 2012 -Authors : Michael Antonov, Steve LaValle +Authors : Michael Antonov, Steve LaValle, Max Katsev Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. @@ -19,6 +19,7 @@ otherwise accompanies this software in either electronic or hard copy form. #include "OVR_Device.h" #include "OVR_SensorFilter.h" +#include namespace OVR { @@ -27,6 +28,8 @@ namespace OVR { // SensorFusion class accumulates Sensor notification messages to keep track of // orientation, which involves integrating the gyro and doing correction with gravity. +// Magnetometer based yaw drift correction is also supported; it is usually enabled +// automatically based on loaded magnetometer configuration. // Orientation is reported as a quaternion, from which users can obtain either the // rotation matrix or Euler angles. // @@ -35,11 +38,20 @@ namespace OVR { // - By attaching SensorFusion to a SensorDevice, in which case it will // automatically handle notifications from that device. + class SensorFusion : public NewOverrideBase { + enum + { + MagMaxReferences = 1000 + }; + public: SensorFusion(SensorDevice* sensor = 0); ~SensorFusion(); + + + // *** Setup // Attaches this SensorFusion to a sensor device, from which it will receive // notification messages. If a sensor is attached, manual message notification @@ -47,53 +59,108 @@ public: bool AttachToSensor(SensorDevice* sensor); // Returns true if this Sensor fusion object is attached to a sensor. - bool IsAttachedToSensor() const { return Handler.IsHandlerInstalled(); } + bool IsAttachedToSensor() const { return Handler.IsHandlerInstalled(); } - void SetGravityEnabled(bool enableGravity) { EnableGravity = enableGravity; } - - bool IsGravityEnabled() const { return EnableGravity;} - void SetYawCorrectionEnabled(bool enableYawCorrection) { EnableYawCorrection = enableYawCorrection; } - - // Yaw correction is set up to work - bool IsYawCorrectionEnabled() const { return EnableYawCorrection;} - // Yaw correction is currently working (forcing a corrective yaw rotation) - bool IsYawCorrectionInProgress() const { return YawCorrectionInProgress;} + // *** State Query + + // Obtain the current accumulated orientation. Many apps will want to use GetPredictedOrientation + // instead to reduce latency. + Quatf GetOrientation() const { return lockedGet(&Q); } + + // Get predicted orientaion in the near future; predictDt is lookahead amount in seconds. + Quatf GetPredictedOrientation(float predictDt); + Quatf GetPredictedOrientation() { return GetPredictedOrientation(PredictionDT); } + + // Obtain the last absolute acceleration reading, in m/s^2. + Vector3f GetAcceleration() const { return lockedGet(&A); } + // Obtain the last angular velocity reading, in rad/s. + Vector3f GetAngularVelocity() const { return lockedGet(&AngV); } + + // Obtain the last raw magnetometer reading, in Gauss + Vector3f GetMagnetometer() const { return lockedGet(&RawMag); } + // Obtain the calibrated magnetometer reading (direction and field strength) + Vector3f GetCalibratedMagnetometer() const { OVR_ASSERT(MagCalibrated); return lockedGet(&CalMag); } + + + // Resets the current orientation. + void Reset(); + + + + // *** Configuration + + void EnableMotionTracking(bool enable = true) { MotionTrackingEnabled = enable; } + bool IsMotionTrackingEnabled() const { return MotionTrackingEnabled; } + + + + // *** Prediction Control + + // Prediction functions. + // Prediction delta specifes how much prediction should be applied in seconds; it should in + // general be under the average rendering latency. Call GetPredictedOrientation() to get + // predicted orientation. + float GetPredictionDelta() const { return PredictionDT; } + void SetPrediction(float dt, bool enable = true) { PredictionDT = dt; EnablePrediction = enable; } + void SetPredictionEnabled(bool enable = true) { EnablePrediction = enable; } + bool IsPredictionEnabled() { return EnablePrediction; } + + + // *** Accelerometer/Gravity Correction Control + + // Enables/disables gravity correction (on by default). + void SetGravityEnabled(bool enableGravity) { EnableGravity = enableGravity; } + bool IsGravityEnabled() const { return EnableGravity;} + + // Gain used to correct gyro with accel. Default value is appropriate for typical use. + float GetAccelGain() const { return Gain; } + void SetAccelGain(float ag) { Gain = ag; } + + + // *** Magnetometer and Yaw Drift Correction Control + + // Methods to load and save a mag calibration. Calibrations can optionally + // be specified by name to differentiate multiple calibrations under different conditions + // If LoadMagCalibration succeeds, it will override YawCorrectionEnabled based on + // saved calibration setting. + bool SaveMagCalibration(const char* calibrationName = NULL) const; + bool LoadMagCalibration(const char* calibrationName = NULL); + + // Enables/disables magnetometer based yaw drift correction. Must also have mag calibration + // data for this correction to work. + void SetYawCorrectionEnabled(bool enable) { EnableYawCorrection = enable; } + // Determines if yaw correction is enabled. + bool IsYawCorrectionEnabled() const { return EnableYawCorrection;} // Store the calibration matrix for the magnetometer void SetMagCalibration(const Matrix4f& m) { MagCalibrationMatrix = m; + time(&MagCalibrationTime); // time stamp the calibration MagCalibrated = true; } + // Retrieves the magnetometer calibration matrix + Matrix4f GetMagCalibration() const { return MagCalibrationMatrix; } + // Retrieve the time of the calibration + time_t GetMagCalibrationTime() const { return MagCalibrationTime; } + // True only if the mag has calibration values stored - bool HasMagCalibration() const { return MagCalibrated;} - + bool HasMagCalibration() const { return MagCalibrated;} // Force the mag into the uncalibrated state - void ClearMagCalibration() - { - MagCalibrated = false; - MagReady = false; - } + void ClearMagCalibration() { MagCalibrated = false; } - // Set the magnetometer's reference orientation for use in yaw correction - void SetMagReference(const Quatf& q); - // Default to current HMD orientation - void SetMagReference() { SetMagReference(Q); } + // These refer to reference points that associate mag readings with orientations + void ClearMagReferences() { MagNumReferences = 0; } - bool HasMagReference() const { return MagReferenced; } - void ClearMagReference() - { - MagReferenced = false; - MagReady = false; - } + Vector3f GetCalibratedMagValue(const Vector3f& rawMag) const; - bool IsMagReady() const { return MagReady; } - void SetMagRefDistance(const float d) { MagRefDistance = d; } + + // *** Message Handler Logic // Notifies SensorFusion object about a new BodyFrame message from a sensor. // Should be called by user if not attaching to a sensor. @@ -103,99 +170,33 @@ public: handleMessage(msg); } - // Obtain the current accumulated orientation. - Quatf GetOrientation() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return Q; - } - Quatf GetPredictedOrientation() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return QP; - } - // Obtain the last absolute acceleration reading, in m/s^2. - Vector3f GetAcceleration() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return A; - } - - // Obtain the last angular velocity reading, in rad/s. - Vector3f GetAngularVelocity() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return AngV; - } - // Obtain the last magnetometer reading, in Gauss - Vector3f GetMagnetometer() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return Mag; - } - // Obtain the raw magnetometer reading, in Gauss (uncalibrated!) - Vector3f GetRawMagnetometer() const - { - Lock::Locker lockScope(Handler.GetHandlerLock()); - return RawMag; - } - - float GetMagRefYaw() const - { - return MagRefYaw; - } - // For later - //Vector3f GetGravity() const; - - // Resets the current orientation - void Reset() - { - MagReferenced = false; - - Lock::Locker lockScope(Handler.GetHandlerLock()); - Q = Quatf(); - QP = Quatf(); - - Stage = 0; - } - - // Configuration - - // Gain used to correct gyro with accel. Default value is appropriate for typical use. - float GetAccelGain() const { return Gain; } - void SetAccelGain(float ag) { Gain = ag; } - - // Multiplier for yaw rotation (turning); setting this higher than 1 (the default) can allow the game - // to be played without auxillary rotation controls, possibly making it more immersive. Whether this is more - // or less likely to cause motion sickness is unknown. - float GetYawMultiplier() const { return YawMult; } - void SetYawMultiplier(float y) { YawMult = y; } - void SetDelegateMessageHandler(MessageHandler* handler) { pDelegate = handler; } - // Prediction functions. - // Prediction delta specifes how much prediction should be applied in seconds; it should in - // general be under the average rendering latency. Call GetPredictedOrientation() to get - // predicted orientation. - float GetPredictionDelta() const { return PredictionDT; } - void SetPrediction(float dt, bool enable = true) { PredictionDT = dt; EnablePrediction = enable; } - void SetPredictionEnabled(bool enable = true) { EnablePrediction = enable; } - bool IsPredictionEnabled() { return EnablePrediction; } - - // Methods for magnetometer calibration - float AngleDifference(float theta1, float theta2); - Vector3f CalculateSphereCenter(Vector3f p1, Vector3f p2, - Vector3f p3, Vector3f p4); private: + SensorFusion* getThis() { return this; } - // Internal handler for messages; bypasses error checking. - void handleMessage(const MessageBodyFrame& msg); + // Helper used to read and return value within a Lock. + template + C lockedGet(const C* p) const + { + Lock::Locker lockScope(Handler.GetHandlerLock()); + return *p; + } - class BodyFrameHandler : public MessageHandler + // Internal handler for messages; bypasses error checking. + void handleMessage(const MessageBodyFrame& msg); + + // Set the magnetometer's reference orientation for use in yaw correction + // The supplied mag is an uncalibrated value + void setMagReference(const Quatf& q, const Vector3f& rawMag); + // Default to current HMD orientation + void setMagReference() { setMagReference(Q, RawMag); } + + class BodyFrameHandler : public MessageHandler { SensorFusion* pFusion; public: @@ -206,44 +207,44 @@ private: virtual bool SupportsMessageType(MessageType type) const; }; + SensorInfo CachedSensorInfo; + Quatf Q; + Quatf QUncorrected; Vector3f A; Vector3f AngV; - Vector3f Mag; + Vector3f CalMag; Vector3f RawMag; unsigned int Stage; + float RunningTime; + float DeltaT; BodyFrameHandler Handler; MessageHandler* pDelegate; float Gain; - float YawMult; volatile bool EnableGravity; bool EnablePrediction; float PredictionDT; - Quatf QP; + float PredictionTimeIncrement; - SensorFilter FMag; - SensorFilter FAccW; + SensorFilter FRawMag; SensorFilter FAngV; - int TiltCondCount; - float TiltErrorAngle; - Vector3f TiltErrorAxis; + Vector3f GyroOffset; + SensorFilterBase TiltAngleFilter; + bool EnableYawCorrection; - Matrix4f MagCalibrationMatrix; bool MagCalibrated; - int MagCondCount; - bool MagReferenced; - float MagRefDistance; - bool MagReady; - Quatf MagRefQ; - Vector3f MagRefM; - float MagRefYaw; - float YawErrorAngle; - int YawErrorCount; - bool YawCorrectionInProgress; + Matrix4f MagCalibrationMatrix; + time_t MagCalibrationTime; + int MagNumReferences; + Vector3f MagRefsInBodyFrame[MagMaxReferences]; + Vector3f MagRefsInWorldFrame[MagMaxReferences]; + int MagRefIdx; + int MagRefScore; + bool MotionTrackingEnabled; }; diff --git a/interface/external/LibOVR/Src/OVR_SensorImpl.h b/interface/external/LibOVR/Src/OVR_SensorImpl.h old mode 100755 new mode 100644 index 4b47833900..4bdcc4f044 --- a/interface/external/LibOVR/Src/OVR_SensorImpl.h +++ b/interface/external/LibOVR/Src/OVR_SensorImpl.h @@ -33,6 +33,8 @@ public: // Enumerates devices, creating and destroying relevant objects in manager. virtual void EnumerateDevices(EnumerateVisitor& visitor); + virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const; + virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc); protected: DeviceManager* getManager() const { return (DeviceManager*) pManager; } }; @@ -58,16 +60,68 @@ public: if ((other.Type == Device_Sensor) && (pFactory == other.pFactory)) { const SensorDeviceCreateDesc& s2 = (const SensorDeviceCreateDesc&) other; - if ((HIDDesc.Path == s2.HIDDesc.Path) && - (HIDDesc.SerialNumber == s2.HIDDesc.SerialNumber)) + if (MatchHIDDevice(s2.HIDDesc)) return Match_Found; } return Match_None; } + virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const + { + // should paths comparison be case insensitive? + return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) && + (HIDDesc.SerialNumber == hidDesc.SerialNumber) && + (HIDDesc.VersionNumber == hidDesc.VersionNumber)); + } + virtual bool GetDeviceInfo(DeviceInfo* info) const; }; +// A simple stub for notification of a sensor in Boot Loader mode +// This descriptor does not support the creation of a device, only the detection +// of its existence to warn apps that the sensor device needs firmware. +// The Boot Loader descriptor reuses and is created by the Sensor device factory +// but in the future may use a dedicated factory +class BootLoaderDeviceCreateDesc : public HIDDeviceCreateDesc +{ +public: + BootLoaderDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc) + : HIDDeviceCreateDesc(factory, Device_BootLoader, hidDesc) { } + + virtual DeviceCreateDesc* Clone() const + { + return new BootLoaderDeviceCreateDesc(*this); + } + + // Boot Loader device creation is not allowed + virtual DeviceBase* NewDeviceInstance() { return NULL; }; + + virtual MatchResult MatchDevice(const DeviceCreateDesc& other, + DeviceCreateDesc**) const + { + if ((other.Type == Device_BootLoader) && (pFactory == other.pFactory)) + { + const BootLoaderDeviceCreateDesc& s2 = (const BootLoaderDeviceCreateDesc&) other; + if (MatchHIDDevice(s2.HIDDesc)) + return Match_Found; + } + return Match_None; + } + + virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const + { + // should paths comparison be case insensitive? + return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) && + (HIDDesc.SerialNumber == hidDesc.SerialNumber)); + } + + virtual bool GetDeviceInfo(DeviceInfo* info) const + { + OVR_UNUSED(info); + return false; + } +}; + //------------------------------------------------------------------------------------- // ***** OVR::SensorDisplayInfoImpl @@ -135,9 +189,21 @@ public: virtual bool SetRange(const SensorRange& range, bool waitFlag); virtual void GetRange(SensorRange* range) const; + // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). + // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be + // called twice or thrice at the same 'tick'. + // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three + // times for each 'tick': the first call will contain averaged values, the second + // and third calls will provide with most recent two recorded samples. + virtual void SetReportRate(unsigned rateHz); + // Returns currently set report rate, in Hz. If 0 - error occurred. + // Note, this value may be different from the one provided for SetReportRate. The return + // value will contain the actual rate. + virtual unsigned GetReportRate() const; + // Hack to create HMD device from sensor display info. - static void EnumerateHMDFromSensorDisplayInfo( const SensorDisplayInfoImpl& displayInfo, - DeviceFactory::EnumerateVisitor& visitor); + static void EnumerateHMDFromSensorDisplayInfo(const SensorDisplayInfoImpl& displayInfo, + DeviceFactory::EnumerateVisitor& visitor); protected: void openDevice(); @@ -146,6 +212,8 @@ protected: Void setCoordinateFrame(CoordinateFrame coordframe); bool setRange(const SensorRange& range); + Void setReportRate(unsigned rateHz); + // Called for decoded messages void onTrackerMessage(TrackerMessage* message); diff --git a/interface/external/LibOVR/Src/OVR_ThreadCommandQueue.h b/interface/external/LibOVR/Src/OVR_ThreadCommandQueue.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/OVR_Win32_DeviceManager.h b/interface/external/LibOVR/Src/OVR_Win32_DeviceManager.h old mode 100755 new mode 100644 index e1fd03ccbc..1b88657fa1 --- a/interface/external/LibOVR/Src/OVR_Win32_DeviceManager.h +++ b/interface/external/LibOVR/Src/OVR_Win32_DeviceManager.h @@ -40,11 +40,16 @@ public: virtual void Shutdown(); virtual ThreadCommandQueue* GetThreadQueue(); + virtual ThreadId GetThreadId() const; virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args); virtual bool GetDeviceInfo(DeviceInfo* info) const; + // Fills HIDDeviceDesc by using the path. + // Returns 'true' if successful, 'false' otherwise. + bool GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const; + Ptr pThread; }; @@ -56,7 +61,7 @@ class DeviceManagerThread : public Thread, public ThreadCommandQueue, public Dev friend class DeviceManager; enum { ThreadStackSize = 32 * 1024 }; public: - DeviceManagerThread(); + DeviceManagerThread(DeviceManager* pdevMgr); ~DeviceManagerThread(); virtual int Run(); @@ -67,7 +72,7 @@ public: // Notifier used for different updates (EVENT or regular timing or messages). - class Notifier + class Notifier { public: // Called when overlapped I/O handle is signaled. @@ -108,6 +113,8 @@ public: // DeviceStatus::Notifier interface. bool OnMessage(MessageType type, const String& devicePath); + void DetachDeviceManager(); + private: bool threadInitialized() { return hCommandEvent != 0; } @@ -128,6 +135,10 @@ private: // Object that manages notifications originating from Windows messages. Ptr pStatusObject; + + Lock DevMgrLock; + // pDeviceMgr should be accessed under DevMgrLock + DeviceManager* pDeviceMgr; // back ptr, no addref. }; }} // namespace Win32::OVR diff --git a/interface/external/LibOVR/Src/OVR_Win32_DeviceStatus.h b/interface/external/LibOVR/Src/OVR_Win32_DeviceStatus.h old mode 100755 new mode 100644 index afbb5aab49..669a12e0bd --- a/interface/external/LibOVR/Src/OVR_Win32_DeviceStatus.h +++ b/interface/external/LibOVR/Src/OVR_Win32_DeviceStatus.h @@ -92,6 +92,8 @@ private: // data UINT_PTR LastTimerId; Array RecoveryTimers; + + GUID HidGuid; }; }} // namespace OVR::Win32 diff --git a/interface/external/LibOVR/Src/OVR_Win32_HIDDevice.h b/interface/external/LibOVR/Src/OVR_Win32_HIDDevice.h old mode 100755 new mode 100644 index 9078f29c46..85a72e8cdd --- a/interface/external/LibOVR/Src/OVR_Win32_HIDDevice.h +++ b/interface/external/LibOVR/Src/OVR_Win32_HIDDevice.h @@ -140,9 +140,12 @@ public: virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor); virtual OVR::HIDDevice* Open(const String& path); - GUID GetHIDGuid() - { return HidGuid; } + // Fills HIDDeviceDesc by using the path. + // Returns 'true' if successful, 'false' otherwise. + bool GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const; + GUID GetHIDGuid() { return HidGuid; } + static HIDDeviceManager* CreateInternal(DeviceManager* manager); private: @@ -171,7 +174,7 @@ func = (PFn_##func)::GetProcAddress(hHidLib, #func) OVR_DECLARE_HIDFUNC(HidD_FreePreparsedData, BOOLEAN, (HIDP_PREPARSED_DATA *preparsedData)); OVR_DECLARE_HIDFUNC(HidP_GetCaps, NTSTATUS,(HIDP_PREPARSED_DATA *preparsedData, HIDP_CAPS* caps)); - HANDLE CreateHIDFile(const char* path, bool exclusiveAccess = true) + HANDLE CreateHIDFile(const char* path, bool exclusiveAccess = true) const { return ::CreateFileA(path, GENERIC_WRITE|GENERIC_READ, (!exclusiveAccess) ? (FILE_SHARE_READ|FILE_SHARE_WRITE) : 0x0, @@ -179,11 +182,11 @@ func = (PFn_##func)::GetProcAddress(hHidLib, #func) } // Helper functions to fill in HIDDeviceDesc from open device handle. - bool initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc); - bool initUsage(HANDLE hidDev, HIDDeviceDesc* desc); - void initStrings(HANDLE hidDev, HIDDeviceDesc* desc); + bool initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc) const; + bool initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const; + void initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const; - bool getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc); + bool getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc) const; }; }} // namespace OVR::Win32 diff --git a/interface/external/LibOVR/Src/OVR_Win32_HMDDevice.h b/interface/external/LibOVR/Src/OVR_Win32_HMDDevice.h old mode 100755 new mode 100644 index 19778f5bb5..e4b6657da3 --- a/interface/external/LibOVR/Src/OVR_Win32_HMDDevice.h +++ b/interface/external/LibOVR/Src/OVR_Win32_HMDDevice.h @@ -17,6 +17,7 @@ otherwise accompanies this software in either electronic or hard copy form. #define OVR_Win32_HMDDevice_h #include "OVR_Win32_DeviceManager.h" +#include "OVR_Profile.h" namespace OVR { namespace Win32 { @@ -76,10 +77,23 @@ public: virtual MatchResult MatchDevice(const DeviceCreateDesc& other, DeviceCreateDesc**) const; - virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&); + // Matches device by path. + virtual bool MatchDevice(const String& path); + + virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL); virtual bool GetDeviceInfo(DeviceInfo* info) const; + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + Profile* GetProfileAddRef() const; + + ProfileType GetProfileType() const + { + return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1; + } + + void SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize) { DesktopX = x; @@ -114,13 +128,26 @@ class HMDDevice : public DeviceImpl { public: HMDDevice(HMDDeviceCreateDesc* createDesc); - ~HMDDevice(); + ~HMDDevice(); virtual bool Initialize(DeviceBase* parent); virtual void Shutdown(); + // Requests the currently used default profile. This profile affects the + // settings reported by HMDInfo. + virtual Profile* GetProfile() const; + virtual const char* GetProfileName() const; + virtual bool SetProfileName(const char* name); + // Query associated sensor. virtual OVR::SensorDevice* GetSensor(); + +protected: + HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); } + + // User name for the profile used with this device. + String ProfileName; + mutable Ptr pCachedProfile; }; diff --git a/interface/external/LibOVR/Src/OVR_Win32_SensorDevice.h b/interface/external/LibOVR/Src/OVR_Win32_SensorDevice.h old mode 100755 new mode 100644 diff --git a/interface/external/LibOVR/Src/Util/Util_LatencyTest.h b/interface/external/LibOVR/Src/Util/Util_LatencyTest.h old mode 100755 new mode 100644 index bac13ccdcf..a01864e1a5 --- a/interface/external/LibOVR/Src/Util/Util_LatencyTest.h +++ b/interface/external/LibOVR/Src/Util/Util_LatencyTest.h @@ -69,6 +69,9 @@ public: bool DisplayScreenColor(Color& colorToDisplay); const char* GetResultsString(); + // Begin test. Equivalent to pressing the button on the latency tester. + void BeginTest(); + private: LatencyTest* getThis() { return this; } diff --git a/interface/external/LibOVR/Src/Util/Util_MagCalibration.h b/interface/external/LibOVR/Src/Util/Util_MagCalibration.h deleted file mode 100755 index 77e6b21f35..0000000000 --- a/interface/external/LibOVR/Src/Util/Util_MagCalibration.h +++ /dev/null @@ -1,109 +0,0 @@ -/************************************************************************************ - -PublicHeader: OVR.h -Filename : Util_MagCalibration.h -Content : Procedures for calibrating the magnetometer -Created : April 16, 2013 -Authors : Steve LaValle, Andrew Reisse - -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. - -Use of this software is subject to the terms of the Oculus license -agreement provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -*************************************************************************************/ - -#ifndef OVR_Util_MagCalibration_h -#define OVR_Util_MagCalibration_h - -#include "../OVR_SensorFusion.h" -#include "../Kernel/OVR_String.h" -#include "../Kernel/OVR_Log.h" - -namespace OVR { namespace Util { - -class MagCalibration -{ -public: - enum MagStatus - { - Mag_Uninitialized = 0, - Mag_AutoCalibrating = 1, - Mag_ManuallyCalibrating = 2, - Mag_Calibrated = 3, - }; - - MagCalibration() : - Status(Mag_Uninitialized), - MinMagDistance(0.3f), MinQuatDistance(0.5f), - SampleCount(0) - { - MinMagDistanceSq = MinMagDistance * MinMagDistance; - MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; - } - - // Methods that are useful for either auto or manual calibration - bool IsUnitialized() const { return Status == Mag_Uninitialized; } - bool IsCalibrated() const { return Status == Mag_Calibrated; } - int NumberOfSamples() const { return SampleCount; } - void ClearCalibration(SensorFusion& sf); - - // Methods for automatic magnetometer calibration - void BeginAutoCalibration(SensorFusion& sf); - unsigned UpdateAutoCalibration(SensorFusion& sf); - bool IsAutoCalibrating() const { return Status == Mag_AutoCalibrating; } - - // Methods for building a manual (user-guided) calibraton procedure - void BeginManualCalibration(SensorFusion& sf); - bool IsAcceptableSample(const Quatf& q, const Vector3f& m); - bool InsertIfAcceptable(const Quatf& q, const Vector3f& m); - // Returns true if successful, requiring that SampleCount = 4 - bool SetCalibration(SensorFusion& sf); - bool IsManuallyCalibrating() const { return Status == Mag_ManuallyCalibrating; } - - // This is the minimum acceptable distance (Euclidean) between raw - // magnetometer values to be acceptable for usage in calibration. - void SetMinMagDistance(float dist) - { - MinMagDistance = dist; - MinMagDistanceSq = MinMagDistance * MinMagDistance; - } - - // The minimum acceptable distance (4D Euclidean) between orientations - // to be acceptable for calibration usage. - void SetMinQuatDistance(float dist) - { - MinQuatDistance = dist; - MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; - } - - // A result of the calibration, which is the center of a sphere that - // roughly approximates the magnetometer data. - Vector3f GetMagCenter() const { return MagCenter; } - -private: - // Determine the unique sphere through 4 non-coplanar points - Vector3f CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4); - - // Distance from p4 to the nearest point on a plane through p1, p2, p3 - float PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4); - - Vector3f MagCenter; - unsigned Status; - float MinMagDistance; - float MinQuatDistance; - float MinMagDistanceSq; - float MinQuatDistanceSq; - - unsigned SampleCount; - Vector3f MagSamples[4]; - Quatf QuatSamples[4]; - -}; - -}} - -#endif diff --git a/interface/external/LibOVR/Src/Util/Util_Render_Stereo.h b/interface/external/LibOVR/Src/Util/Util_Render_Stereo.h old mode 100755 new mode 100644 index 285a4fd99f..9ac40025f8 --- a/interface/external/LibOVR/Src/Util/Util_Render_Stereo.h +++ b/interface/external/LibOVR/Src/Util/Util_Render_Stereo.h @@ -189,7 +189,7 @@ public: void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; } // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm). - void SetIPD(float ipd) { InterpupillaryDistance = ipd; DirtyFlag = true; } + void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; } float GetIPD() const { return InterpupillaryDistance; } // Set full render target viewport; for HMD this includes both eyes. @@ -279,6 +279,7 @@ private: // *** Computed State bool DirtyFlag; // Set when any if the modifiable state changed. + bool IPDOverride; // True after SetIPD was called. float YFov; // Vertical FOV. float Aspect; // Aspect ratio: (w/h)*AspectMultiplier. float ProjectionCenterOffset; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58629df41e..c1fc39de41 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4206,6 +4206,7 @@ void Application::resetSensors() { _webcam.reset(); _faceshift.reset(); LeapManager::reset(); + OculusManager::reset(); QCursor::setPos(_headMouseX, _headMouseY); _myAvatar.reset(); _myTransmitter.resetLevels(); diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 17775b9f9c..d878c92c0a 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -9,9 +9,11 @@ #include "OculusManager.h" #include +using namespace OVR; + bool OculusManager::_isConnected = false; -#ifdef __APPLE__ +#ifdef HAVE_LIBOVR Ptr OculusManager::_deviceManager; Ptr OculusManager::_hmdDevice; Ptr OculusManager::_sensorDevice; @@ -20,7 +22,7 @@ float OculusManager::_yawOffset = 0; #endif void OculusManager::connect() { -#ifdef __APPLE__ +#ifdef HAVE_LIBOVR System::Init(); _deviceManager = *DeviceManager::Create(); _hmdDevice = *_deviceManager->EnumerateDevices().CreateDevice(); @@ -30,15 +32,18 @@ void OculusManager::connect() { _sensorDevice = *_hmdDevice->GetSensor(); _sensorFusion.AttachToSensor(_sensorDevice); - - // default the yaw to the current orientation - _sensorFusion.SetMagReference(); } #endif } +void OculusManager::reset() { +#ifdef HAVE_LIBOVR + _sensorFusion.Reset(); +#endif +} + void OculusManager::updateYawOffset() { -#ifdef __APPLE__ +#ifdef HAVE_LIBOVR float yaw, pitch, roll; _sensorFusion.GetOrientation().GetEulerAngles(&yaw, &pitch, &roll); _yawOffset = yaw; @@ -46,7 +51,7 @@ void OculusManager::updateYawOffset() { } void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { -#ifdef __APPLE__ +#ifdef HAVE_LIBOVR _sensorFusion.GetOrientation().GetEulerAngles(&yaw, &pitch, &roll); // convert each angle to degrees diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 7bfea8b419..d15b9fcd52 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -12,23 +12,23 @@ #include #include -using namespace OVR; - class OculusManager { public: static void connect(); static bool isConnected() { return _isConnected; } + static void reset(); + static void getEulerAngles(float& yaw, float& pitch, float& roll); static void updateYawOffset(); private: static bool _isConnected; - static Ptr _deviceManager; - static Ptr _hmdDevice; - static Ptr _sensorDevice; - static SensorFusion _sensorFusion; + static OVR::Ptr _deviceManager; + static OVR::Ptr _hmdDevice; + static OVR::Ptr _sensorDevice; + static OVR::SensorFusion _sensorFusion; static float _yawOffset; };