Merge branch 'master' of https://github.com/worklist/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2013-12-02 12:54:01 -08:00
commit 91aa9918ee
75 changed files with 2394 additions and 775 deletions

View file

@ -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)
endif (LIBOVR_LIBRARIES AND LIBOVR_INCLUDE_DIRS)

View file

@ -117,6 +117,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.
@ -131,7 +139,6 @@ include_directories(
SYSTEM
${FACESHIFT_INCLUDE_DIRS}
${GLM_INCLUDE_DIRS}
${LIBOVR_INCLUDE_DIRS}
${LIBVPX_INCLUDE_DIRS}
${LEAP_INCLUDE_DIRS}
${MOTIONDRIVER_INCLUDE_DIRS}
@ -180,7 +187,6 @@ if (APPLE)
${QTKit}
${QuartzCore}
${UVCCAMERACONTROL_LIBRARIES}
${LIBOVR_LIBRARIES}
)
if (LEAP_FOUND)

View file

@ -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"

View file

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
interface/external/LibOVR/Src/Kernel/OVR_Alg.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_Allocator.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_Array.h vendored Executable file → Normal file
View file

1
interface/external/LibOVR/Src/Kernel/OVR_Atomic.h vendored Executable file → Normal file
View file

@ -824,6 +824,7 @@ public:
Lock (unsigned dummy = 0)
{
OVR_UNUSED(dummy);
if (!RecursiveAttrInit)
{
pthread_mutexattr_init(&RecursiveAttr);

0
interface/external/LibOVR/Src/Kernel/OVR_Color.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_ContainerAllocator.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_File.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_Hash.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_KeyCodes.h vendored Executable file → Normal file
View file

2
interface/external/LibOVR/Src/Kernel/OVR_List.h vendored Executable file → Normal file
View file

@ -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>. B specifies the base class that was directly
// derived from ListNode, and is only necessary if there is an intermediate
// inheritance chain.

0
interface/external/LibOVR/Src/Kernel/OVR_Log.h vendored Executable file → Normal file
View file

596
interface/external/LibOVR/Src/Kernel/OVR_Math.h vendored Executable file → Normal file
View file

@ -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<float> and Math<double> being distinct.
template<class Type>
@ -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<float> Mathf;
typedef Math<double> Mathd;
// Conversion functions between degrees and radians
template<class FT>
FT RadToDegree(FT rads) { return rads * Math<FT>::RadToDegreeFactor; }
template<class FT>
FT DegreeToRad(FT rads) { return rads * Math<FT>::DegreeToRadFactor; }
template<class T>
T RadToDegree(T rads) { return rads * Math<T>::RadToDegreeFactor; }
template<class T>
T DegreeToRad(T rads) { return rads * Math<T>::DegreeToRadFactor; }
// Numerically stable acos function
template<class T>
T Acos(T val) {
if (val > T(1)) return T(0);
else if (val < T(-1)) return Math<T>::Pi;
else return acos(val);
};
// Numerically stable asin function
template<class T>
T Asin(T val) {
if (val > T(1)) return Math<T>::PiOver2;
else if (val < T(-1)) return Math<T>::PiOver2 * T(3);
else return asin(val);
};
#ifdef OVR_CC_MSVC
inline int isnan(double x) { return _isnan(x); };
#endif
template<class T>
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 T>
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<T>::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<float> Vector2f;
typedef Vector2<double> 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<class T>
@ -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<T>::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<double> Vector3d;
//-------------------------------------------------------------------------------------
// ***** Matrix4f
// ***** Size
// Size class represents 2D size with Width, Height components.
// Used to describe distentions of render targets, etc.
template<class T>
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<T> ToVector() const { return Vector2<T>(Width, Height); }
};
typedef Size<int> Sizei;
typedef Size<unsigned> Sizeu;
typedef Size<float> Sizef;
typedef Size<double> 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<float>::PiOver2;
*c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
}
else if (pm > 1.0 - Math<float>::SingularityRadius)
else if (pm > 1.0f - Math<float>::SingularityRadius)
{ // North pole singularity
*a = 0.0f;
*b = S*D*Math<float>::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<float>::SingularityRadius)
if (c2 < -1.0f + Math<float>::SingularityRadius)
{ // South pole singularity
*a = 0.0f;
*b = S*D*Math<float>::Pi;
*c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
}
else if (c2 > 1.0 - Math<float>::SingularityRadius)
else if (c2 > 1.0f - Math<float>::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<T>& axis, T angle)
{
Vector3<T> 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<T>* axis, T* angle) const
// Compute axis and angle from quaternion
void GetAxisAngle(Vector3<T>* axis, T* angle) const
{
if (LengthSq() > Math<T>::Tolerance * Math<T>::Tolerance)
{
*axis = Vector3<T>(x, y, z).Normalized();
*angle = 2 * acos(w);
}
else
{
*axis = Vector3<T>(1, 0, 0);
*angle= 0;
}
if ( x*x + y*y + z*z > Math<T>::Tolerance * Math<T>::Tolerance ) {
*axis = Vector3<T>(x, y, z).Normalized();
*angle = T(2) * Acos(w);
}
else
{
*axis = Vector3<T>(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<T> Imag() const { return Vector3<T>(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<T>::Tolerance; }
void Normalize() { *this /= Length(); }
Quat Normalized() const { return *this / Length(); }
bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::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<T> Rotate(const Vector3<T>& v) const
{
return ((*this * Quat<T>(v.x, v.y, v.z, 0)) * Inverted()).Imag();
return ((*this * Quat<T>(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<T> Matrix4fToQuat(const Matrix4f& m)
{
T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
Quat<T> 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<T>::SingularityRadius)
if (s2 < T(-1) + Math<T>::SingularityRadius)
{ // South pole singularity
*a = T(0.0);
*a = T(0);
*b = -S*D*Math<T>::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<T>::SingularityRadius)
else if (s2 > T(1) - Math<T>::SingularityRadius)
{ // North pole singularity
*a = (T)0.0;
*a = T(0);
*b = S*D*Math<T>::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<T>::SingularityRadius)
if (c2 < T(-1) + Math<T>::SingularityRadius)
{ // South pole singularity
*a = (T)0.0;
*a = T(0);
*b = S*D*Math<T>::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<T>::SingularityRadius)
else if (c2 > T(1) - Math<T>::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<float> Quatf;
typedef Quat<double> 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 T>
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<T>::DegreeToRadFactor) { FixRange(); }
T Get(AngularUnits u = Radians) const { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; }
void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::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<T>::Pi) ? c : Math<T>::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<T>::Pi)
a += Math<T>::TwoPi;
else if (a > Math<T>::Pi)
a -= Math<T>::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<T>::Pi && a <= Math<T>::Pi)
return;
a = fmod(a,Math<T>::TwoPi);
if (a < -Math<T>::Pi)
a += Math<T>::TwoPi;
else if (a > Math<T>::Pi)
a -= Math<T>::TwoPi;
}
};
typedef Angle<float> Anglef;
typedef Angle<double> 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<T>& p) const
{
return (N * p) + D;
return (N.Dot(p)) + D;
}
Plane<T> Flipped() const
@ -1065,6 +1427,6 @@ public:
typedef Plane<float> Planef;
}
} // Namespace OVR
#endif

0
interface/external/LibOVR/Src/Kernel/OVR_RefCount.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_Std.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_String.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_StringHash.h vendored Executable file → Normal file
View file

2
interface/external/LibOVR/Src/Kernel/OVR_SysFile.h vendored Executable file → Normal file
View file

@ -88,6 +88,6 @@ public:
virtual bool Close();
};
} // Scaleform
} // Namespace OVR
#endif

0
interface/external/LibOVR/Src/Kernel/OVR_System.h vendored Executable file → Normal file
View file

0
interface/external/LibOVR/Src/Kernel/OVR_Threads.h vendored Executable file → Normal file
View file

2
interface/external/LibOVR/Src/Kernel/OVR_Timer.h vendored Executable file → Normal file
View file

@ -95,6 +95,6 @@ private:
};
} // Scaleform::Timer
} // Namespace OVR
#endif

2
interface/external/LibOVR/Src/Kernel/OVR_Types.h vendored Executable file → Normal file
View file

@ -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

0
interface/external/LibOVR/Src/Kernel/OVR_UTF8Util.h vendored Executable file → Normal file
View file

101
interface/external/LibOVR/Src/OVR_Device.h vendored Executable file → Normal file
View file

@ -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<DeviceManager*>(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<DeviceCreateDesc> 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

1
interface/external/LibOVR/Src/OVR_DeviceConstants.h vendored Executable file → Normal file
View file

@ -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.
};

15
interface/external/LibOVR/Src/OVR_DeviceHandle.h vendored Executable file → Normal file
View file

@ -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 <class DeviceT>
DeviceT* CreateDeviceTyped() const
{
return static_cast<DeviceT*>(DeviceHandle(*this).CreateDevice());
}
// Resets the device handle to uninitialized state.
void Clear();

57
interface/external/LibOVR/Src/OVR_DeviceImpl.h vendored Executable file → Normal file
View file

@ -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<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc);
// Finds a device descriptor by path and optional type.
Ptr<DeviceCreateDesc> FindDevice(const String& path, DeviceType = Device_None);
// Finds HID device by HIDDeviceDesc.
Ptr<DeviceCreateDesc> FindHIDDevice(const HIDDeviceDesc&);
void DetectHIDDevice(const HIDDeviceDesc&);
// Manager Lock-protected list of devices.
List<DeviceCreateDesc> Devices;
@ -375,6 +423,7 @@ public:
protected:
Ptr<HIDDeviceManager> HidDeviceManager;
Ptr<ProfileManager> pProfileManager;
};

3
interface/external/LibOVR/Src/OVR_DeviceMessages.h vendored Executable file → Normal file
View file

@ -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:

4
interface/external/LibOVR/Src/OVR_HIDDevice.h vendored Executable file → Normal file
View file

@ -123,8 +123,8 @@ public:
enum HIDDeviceMessageType
{
HIDDeviceMessage_DeviceAdded = 0,
HIDDeviceMessage_DeviceRemoved = 1,
HIDDeviceMessage_DeviceAdded = 0,
HIDDeviceMessage_DeviceRemoved = 1
};
virtual void OnDeviceMessage(HIDDeviceMessageType messageType)

0
interface/external/LibOVR/Src/OVR_HIDDeviceBase.h vendored Executable file → Normal file
View file

50
interface/external/LibOVR/Src/OVR_HIDDeviceImpl.h vendored Executable file → Normal file
View file

@ -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;
}

143
interface/external/LibOVR/Src/OVR_JSON.h vendored Normal file
View file

@ -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<JSON>, public ListNode<JSON>
{
protected:
List<JSON> 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

22
interface/external/LibOVR/Src/OVR_LatencyTestImpl.h vendored Executable file → Normal file
View file

@ -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

View file

@ -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 <unistd.h>
#include <sys/poll.h>
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<DeviceManagerThread> 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<struct pollfd> PollFds;
Array<Notifier*> FdNotifiers;
Event StartupEvent;
// Ticks notifiers - used for time-dependent events such as keep-alive.
Array<Notifier*> TicksNotifiers;
};
}} // namespace Linux::OVR
#endif // OVR_Linux_DeviceManager_h

View file

@ -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 <libudev.h>
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<HIDDevice*> NotificationDevices;
};
}} // namespace OVR::Linux
#endif // OVR_Linux_HIDDevice_h

View file

@ -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<OVR::HMDDevice>
{
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<Profile> pCachedProfile;
};
}} // namespace OVR::Linux
#endif // OVR_Linux_HMDDevice_h

12
interface/external/LibOVR/Src/OVR_OSX_DeviceManager.h vendored Executable file → Normal file
View file

@ -21,6 +21,8 @@ otherwise accompanies this software in either electronic or hard copy form.
#include "Kernel/OVR_Timer.h"
#include <IOKit/hid/IOHIDManager.h>
#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreGraphics/CGDisplayConfiguration.h>
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<DeviceManagerThread> pThread;
};
@ -90,6 +99,7 @@ public:
CFRunLoopRef GetRunLoop()
{ return RunLoop; }
void Shutdown();
private:
CFRunLoopRef RunLoop;

9
interface/external/LibOVR/Src/OVR_OSX_HIDDevice.h vendored Executable file → Normal file
View file

@ -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;

26
interface/external/LibOVR/Src/OVR_OSX_HMDDevice.h vendored Executable file → Normal file
View file

@ -18,6 +18,7 @@ otherwise accompanies this software in either electronic or hard copy form.
#include "OVR_DeviceImpl.h"
#include <Kernel/OVR_String.h>
#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<Profile> pCachedProfile;
};

View file

@ -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<ProfileManager> pm = *ProfileManager::Create();
// Ptr<Profile> 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<ProfileManager>
{
protected:
// Synchronize ProfileManager access since it may be accessed from multiple threads,
// as it's shared through DeviceManager.
Lock ProfileLock;
Array<Ptr<Profile> > 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<Profile>
{
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

203
interface/external/LibOVR/Src/OVR_SensorFilter.h vendored Executable file → Normal file
View file

@ -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 <typename T>
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 <typename T>
class SensorFilterBase : public CircularBuffer<T>
{
protected:
T RunningTotal; // Cached sum of the elements
public:
SensorFilterBase(int capacity = CircularBuffer<T>::DefaultFilterCapacity) : CircularBuffer<T>(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<T>::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<Vector3f>
{
public:
SensorFilter(int capacity = DefaultFilterCapacity) : SensorFilterBase<Vector3f>(capacity) { };
// Simple statistics
Vector3f Median() const;
Vector3f Variance() const; // The diagonal of covariance matrix
Matrix4f Covariance() const;
Vector3f PearsonCoefficient() const;
};
} //namespace OVR

267
interface/external/LibOVR/Src/OVR_SensorFusion.h vendored Executable file → Normal file
View file

@ -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 <time.h>
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<class C>
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<float> 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;
};

76
interface/external/LibOVR/Src/OVR_SensorImpl.h vendored Executable file → Normal file
View file

@ -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);

0
interface/external/LibOVR/Src/OVR_ThreadCommandQueue.h vendored Executable file → Normal file
View file

15
interface/external/LibOVR/Src/OVR_Win32_DeviceManager.h vendored Executable file → Normal file
View file

@ -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<DeviceManagerThread> 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<DeviceStatus> pStatusObject;
Lock DevMgrLock;
// pDeviceMgr should be accessed under DevMgrLock
DeviceManager* pDeviceMgr; // back ptr, no addref.
};
}} // namespace Win32::OVR

2
interface/external/LibOVR/Src/OVR_Win32_DeviceStatus.h vendored Executable file → Normal file
View file

@ -92,6 +92,8 @@ private: // data
UINT_PTR LastTimerId;
Array<RecoveryTimerDesc> RecoveryTimers;
GUID HidGuid;
};
}} // namespace OVR::Win32

17
interface/external/LibOVR/Src/OVR_Win32_HIDDevice.h vendored Executable file → Normal file
View file

@ -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

31
interface/external/LibOVR/Src/OVR_Win32_HMDDevice.h vendored Executable file → Normal file
View file

@ -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<OVR::HMDDevice>
{
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<Profile> pCachedProfile;
};

0
interface/external/LibOVR/Src/OVR_Win32_SensorDevice.h vendored Executable file → Normal file
View file

3
interface/external/LibOVR/Src/Util/Util_LatencyTest.h vendored Executable file → Normal file
View file

@ -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; }

View file

@ -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

3
interface/external/LibOVR/Src/Util/Util_Render_Stereo.h vendored Executable file → Normal file
View file

@ -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;

View file

@ -30,6 +30,12 @@ uniform vec2 leftBottom;
// the right and top edges of the view window
uniform vec2 rightTop;
// an offset value to apply to the texture coordinates
uniform vec2 texCoordOffset;
// a scale value to apply to the texture coordinates
uniform vec2 texCoordScale;
// the radius of the effect
uniform float radius;
@ -38,7 +44,7 @@ uniform vec2 noiseScale;
// given a texture coordinate, returns the 3D view space z coordinate
float texCoordToViewSpaceZ(vec2 texCoord) {
return (far * near) / (texture2D(depthTexture, texCoord).r * (far - near) - far);
return (far * near) / (texture2D(depthTexture, texCoord * texCoordScale + texCoordOffset).r * (far - near) - far);
}
// given a texture coordinate, returns the 3D view space coordinate
@ -54,11 +60,15 @@ void main(void) {
vec3 center = texCoordToViewSpace(gl_TexCoord[0].st);
vec2 rdenominator = 1.0 / (rightTop - leftBottom);
vec2 xyFactor = 2.0 * near * rdenominator;
vec2 zFactor = (rightTop + leftBottom) * rdenominator;
float occlusion = 4.0;
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
vec3 offset = center + rotation * (radius * sampleKernel[i]);
vec4 projected = gl_ProjectionMatrix * vec4(offset, 1.0);
float depth = texCoordToViewSpaceZ(projected.xy * 0.5 / projected.w + vec2(0.5, 0.5));
vec2 projected = offset.xy * xyFactor + offset.z * zFactor;
float depth = texCoordToViewSpaceZ(projected * -0.5 / offset.z + vec2(0.5, 0.5));
occlusion += 1.0 - step(offset.z, depth);
}

View file

@ -0,0 +1,36 @@
#version 120
//
// oculus.frag
// fragment shader
//
// Created by Andrzej Kapolka on 11/26/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license
// (http://www.apache.org/licenses/LICENSE-2.0)
//
uniform sampler2D texture;
uniform vec2 lensCenter;
uniform vec2 screenCenter;
uniform vec2 scale;
uniform vec2 scaleIn;
uniform vec4 hmdWarpParam;
vec2 hmdWarp(vec2 in01) {
vec2 theta = (in01 - lensCenter) * scaleIn;
float rSq = theta.x * theta.x + theta.y * theta.y;
vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq +
hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);
return lensCenter + scale * theta1;
}
void main(void) {
vec2 tc = hmdWarp(gl_TexCoord[0].st);
vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);
vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);
gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), above.s * above.t * below.s * below.t);
}

View file

@ -133,8 +133,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_lookatIndicatorScale(1.0f),
_perfStatsOn(false),
_chatEntryOn(false),
_oculusProgram(0),
_oculusDistortionScale(1.25),
#ifndef _WIN32
_audio(&_audioScope, STARTUP_JITTER_SAMPLES),
#endif
@ -252,7 +250,6 @@ Application::~Application() {
VoxelNode::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
delete Menu::getInstance();
delete _oculusProgram;
delete _settings;
delete _followMode;
delete _glWidget;
@ -429,7 +426,7 @@ void Application::paintGL() {
}
if (OculusManager::isConnected()) {
displayOculus(whichCamera);
OculusManager::display(whichCamera);
} else {
_glowEffect.prepare();
@ -520,14 +517,11 @@ void Application::paintGL() {
}
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
float aspectRatio = ((float)width/(float)height); // based on screen resize
if (OculusManager::isConnected()) {
// more magic numbers; see Oculus SDK docs, p. 32
camera.setAspectRatio(aspectRatio *= 0.5);
camera.setFieldOfView(2 * atan((0.0468 * _oculusDistortionScale) / 0.041) * (180 / PIf));
OculusManager::configureCamera(camera, width, height);
} else {
camera.setAspectRatio(aspectRatio);
camera.setAspectRatio((float)width / height);
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
}
}
@ -1473,7 +1467,6 @@ void Application::checkBandwidthMeterClick() {
void Application::setFullscreen(bool fullscreen) {
_window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) :
(_window->windowState() & ~Qt::WindowFullScreen));
updateCursor();
}
void Application::setRenderVoxels(bool voxelRender) {
@ -1487,6 +1480,54 @@ void Application::doKillLocalVoxels() {
_wantToKillLocalVoxels = true;
}
void Application::removeVoxel(glm::vec3 position,
float scale) {
VoxelDetail voxel;
voxel.x = position.x / TREE_SCALE;
voxel.y = position.y / TREE_SCALE;
voxel.z = position.z / TREE_SCALE;
voxel.s = scale / TREE_SCALE;
_voxelEditSender.sendVoxelEditMessage(PACKET_TYPE_ERASE_VOXEL, voxel);
// delete it locally to see the effect immediately (and in case no voxel server is present)
_voxels.deleteVoxelAt(voxel.x, voxel.y, voxel.z, voxel.s);
}
void Application::makeVoxel(glm::vec3 position,
float scale,
unsigned char red,
unsigned char green,
unsigned char blue,
bool isDestructive) {
VoxelDetail voxel;
voxel.x = position.x / TREE_SCALE;
voxel.y = position.y / TREE_SCALE;
voxel.z = position.z / TREE_SCALE;
voxel.s = scale / TREE_SCALE;
voxel.red = red;
voxel.green = green;
voxel.blue = blue;
PACKET_TYPE message = isDestructive ? PACKET_TYPE_SET_VOXEL_DESTRUCTIVE : PACKET_TYPE_SET_VOXEL;
_voxelEditSender.sendVoxelEditMessage(message, voxel);
// create the voxel locally so it appears immediately
_voxels.createVoxel(voxel.x, voxel.y, voxel.z, voxel.s,
voxel.red, voxel.green, voxel.blue,
isDestructive);
// Implement voxel fade effect
VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f);
const float VOXEL_BOUNDS_ADJUST = 0.01f;
float slightlyBigger = voxel.s * VOXEL_BOUNDS_ADJUST;
fade.voxelDetails.x = voxel.x - slightlyBigger;
fade.voxelDetails.y = voxel.y - slightlyBigger;
fade.voxelDetails.z = voxel.z - slightlyBigger;
fade.voxelDetails.s = voxel.s + slightlyBigger + slightlyBigger;
_voxelFades.push_back(fade);
}
const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) {
return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE,
(_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE,
@ -2221,11 +2262,11 @@ void Application::updateLeap(float deltaTime) {
LeapManager::nextFrame();
}
void Application::updateSixense() {
void Application::updateSixense(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateSixense()");
_sixenseManager.update();
_sixenseManager.update(deltaTime);
}
void Application::updateSerialDevices(float deltaTime) {
@ -2435,7 +2476,7 @@ void Application::update(float deltaTime) {
updateMouseVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // UI/UX related to voxels
updateHandAndTouch(deltaTime); // Update state for touch sensors
updateLeap(deltaTime); // Leap finger-sensing device
updateSixense(); // Razer Hydra controllers
updateSixense(deltaTime); // Razer Hydra controllers
updateSerialDevices(deltaTime); // Read serial port interface devices
updateAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
@ -2857,146 +2898,7 @@ void Application::updateShadowMap() {
glViewport(0, 0, _glWidget->width(), _glWidget->height());
}
// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license
// (http://www.apache.org/licenses/LICENSE-2.0)
static const char* DISTORTION_FRAGMENT_SHADER =
"#version 120\n"
"uniform sampler2D texture;"
"uniform vec2 lensCenter;"
"uniform vec2 screenCenter;"
"uniform vec2 scale;"
"uniform vec2 scaleIn;"
"uniform vec4 hmdWarpParam;"
"vec2 hmdWarp(vec2 in01) {"
" vec2 theta = (in01 - lensCenter) * scaleIn;"
" float rSq = theta.x * theta.x + theta.y * theta.y;"
" vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq + "
" hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);"
" return lensCenter + scale * theta1;"
"}"
"void main(void) {"
" vec2 tc = hmdWarp(gl_TexCoord[0].st);"
" vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);"
" vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);"
" gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), "
" above.s * above.t * below.s * below.t);"
"}";
void Application::displayOculus(Camera& whichCamera) {
_glowEffect.prepare();
// magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
// the rendering parameters from the hardware stats, i just folded their calculations into
// constants using the stats for the current-model hardware as contained in the SDK file
// LibOVR/Src/Util/Util_Render_Stereo.cpp
// eye
// render the left eye view to the left side of the screen
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
whichCamera.getNearClip(), whichCamera.getFarClip());
glViewport(0, 0, _glWidget->width() / 2, _glWidget->height());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.032, 0, 0); // dip/2, see p. 27
displaySide(whichCamera);
// and the right eye to the right side
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(-0.151976, 0, 0); // -h
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
whichCamera.getNearClip(), whichCamera.getFarClip());
glViewport(_glWidget->width() / 2, 0, _glWidget->width() / 2, _glWidget->height());
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.032, 0, 0);
displaySide(whichCamera);
glPopMatrix();
// restore our normal viewport
glViewport(0, 0, _glWidget->width(), _glWidget->height());
QOpenGLFramebufferObject* fbo = _glowEffect.render(true);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
if (_oculusProgram == 0) {
_oculusProgram = new ProgramObject();
_oculusProgram->addShaderFromSourceCode(QGLShader::Fragment, DISTORTION_FRAGMENT_SHADER);
_oculusProgram->link();
_textureLocation = _oculusProgram->uniformLocation("texture");
_lensCenterLocation = _oculusProgram->uniformLocation("lensCenter");
_screenCenterLocation = _oculusProgram->uniformLocation("screenCenter");
_scaleLocation = _oculusProgram->uniformLocation("scale");
_scaleInLocation = _oculusProgram->uniformLocation("scaleIn");
_hmdWarpParamLocation = _oculusProgram->uniformLocation("hmdWarpParam");
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, _glWidget->width(), 0, _glWidget->height());
glDisable(GL_DEPTH_TEST);
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
float scaleFactor = 1.0 / _oculusDistortionScale;
float aspectRatio = (_glWidget->width() * 0.5) / _glWidget->height();
glDisable(GL_BLEND);
_oculusProgram->bind();
_oculusProgram->setUniformValue(_textureLocation, 0);
_oculusProgram->setUniformValue(_lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
_oculusProgram->setUniformValue(_screenCenterLocation, 0.25, 0.5);
_oculusProgram->setUniformValue(_scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
_oculusProgram->setUniformValue(_scaleInLocation, 4, 2 / aspectRatio);
_oculusProgram->setUniformValue(_hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(0.5, 0);
glVertex2f(_glWidget->width()/2, 0);
glTexCoord2f(0.5, 1);
glVertex2f(_glWidget->width() / 2, _glWidget->height());
glTexCoord2f(0, 1);
glVertex2f(0, _glWidget->height());
glEnd();
_oculusProgram->setUniformValue(_lensCenterLocation, 0.787994, 0.5);
_oculusProgram->setUniformValue(_screenCenterLocation, 0.75, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0.5, 0);
glVertex2f(_glWidget->width() / 2, 0);
glTexCoord2f(1, 0);
glVertex2f(_glWidget->width(), 0);
glTexCoord2f(1, 1);
glVertex2f(_glWidget->width(), _glWidget->height());
glTexCoord2f(0.5, 1);
glVertex2f(_glWidget->width() / 2, _glWidget->height());
glEnd();
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0);
_oculusProgram->release();
glPopMatrix();
}
const GLfloat WHITE_SPECULAR_COLOR[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat NO_SPECULAR_COLOR[] = { 0.0f, 0.0f, 0.0f, 1.0f };
@ -3019,18 +2921,6 @@ void Application::setupWorldLight() {
glMateriali(GL_FRONT, GL_SHININESS, 96);
}
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix);
glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y,
translation.z + _viewMatrixTranslation.z);
}
void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, near, far, nearClipPlane, farClipPlane);
}
void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
// transform by eye offset
@ -3274,6 +3164,18 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
}
}
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix);
glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y,
translation.z + _viewMatrixTranslation.z);
}
void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
_viewFrustum.computeOffAxisFrustum(left, right, bottom, top, near, far, nearClipPlane, farClipPlane);
}
void Application::displayOverlay() {
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displayOverlay()");
@ -4091,29 +3993,18 @@ bool Application::maybeEditVoxelUnderCursor() {
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode)
|| Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode)) {
if (_mouseVoxel.s != 0) {
PACKET_TYPE message = Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel)
? PACKET_TYPE_SET_VOXEL_DESTRUCTIVE
: PACKET_TYPE_SET_VOXEL;
_voxelEditSender.sendVoxelEditMessage(message, _mouseVoxel);
// create the voxel locally so it appears immediately
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s,
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue,
Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel));
// Implement voxel fade effect
VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f);
const float VOXEL_BOUNDS_ADJUST = 0.01f;
float slightlyBigger = _mouseVoxel.s * VOXEL_BOUNDS_ADJUST;
fade.voxelDetails.x = _mouseVoxel.x - slightlyBigger;
fade.voxelDetails.y = _mouseVoxel.y - slightlyBigger;
fade.voxelDetails.z = _mouseVoxel.z - slightlyBigger;
fade.voxelDetails.s = _mouseVoxel.s + slightlyBigger + slightlyBigger;
_voxelFades.push_back(fade);
makeVoxel(glm::vec3(_mouseVoxel.x * TREE_SCALE,
_mouseVoxel.y * TREE_SCALE,
_mouseVoxel.z * TREE_SCALE),
_mouseVoxel.s * TREE_SCALE,
_mouseVoxel.red,
_mouseVoxel.green,
_mouseVoxel.blue,
Menu::getInstance()->isOptionChecked(MenuOption::DestructiveAddVoxel));
// inject a sound effect
injectVoxelAddedSoundEffect();
// remember the position for drag detection
_justEditedVoxel = true;
@ -4203,6 +4094,7 @@ void Application::resetSensors() {
_webcam.reset();
_faceshift.reset();
LeapManager::reset();
OculusManager::reset();
QCursor::setPos(_headMouseX, _headMouseY);
_myAvatar.reset();
_myTransmitter.resetLevels();
@ -4231,11 +4123,6 @@ void Application::setMenuShortcutsEnabled(bool enabled) {
setShortcutsEnabled(_window->menuBar(), enabled);
}
void Application::updateCursor() {
_glWidget->setCursor(OculusManager::isConnected() && _window->windowState().testFlag(Qt::WindowFullScreen) ?
Qt::BlankCursor : Qt::ArrowCursor);
}
void Application::attachNewHeadToNode(Node* newNode) {
if (newNode->getLinkedData() == NULL) {
newNode->setLinkedData(new Avatar(newNode));

View file

@ -117,6 +117,15 @@ public:
void wheelEvent(QWheelEvent* event);
void makeVoxel(glm::vec3 position,
float scale,
unsigned char red,
unsigned char green,
unsigned char blue,
bool isDestructive);
void removeVoxel(glm::vec3 position, float scale);
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);
QGLWidget* getGLWidget() { return _glWidget; }
@ -155,6 +164,8 @@ public:
void setupWorldLight();
void displaySide(Camera& whichCamera, bool selfAvatarOnly = false);
/// Loads a view matrix that incorporates the specified model translation without the precision issues that can
/// result from matrix multiplication at high translation magnitudes.
void loadTranslatedViewMatrix(const glm::vec3& translation);
@ -247,7 +258,7 @@ private:
glm::vec3& eyePosition);
void updateHandAndTouch(float deltaTime);
void updateLeap(float deltaTime);
void updateSixense();
void updateSixense(float deltaTime);
void updateSerialDevices(float deltaTime);
void updateThreads(float deltaTime);
void updateMyAvatarSimulation(float deltaTime);
@ -272,8 +283,6 @@ private:
glm::vec3 getSunDirection();
void updateShadowMap();
void displayOculus(Camera& whichCamera);
void displaySide(Camera& whichCamera, bool selfAvatarOnly = false);
void displayOverlay();
void displayStats();
void renderAvatars(bool forceRenderHead, bool selfAvatarOnly = false);
@ -288,8 +297,6 @@ private:
void setMenuShortcutsEnabled(bool enabled);
void updateCursor();
static void attachNewHeadToNode(Node *newNode);
static void* networkReceive(void* args); // network receive thread
@ -416,15 +423,6 @@ private:
ChatEntry _chatEntry; // chat entry field
bool _chatEntryOn; // Whether to show the chat entry
ProgramObject* _oculusProgram; // The GLSL program containing the distortion shader
float _oculusDistortionScale; // Controls the Oculus field of view
int _textureLocation;
int _lensCenterLocation;
int _screenCenterLocation;
int _scaleLocation;
int _scaleInLocation;
int _hmdWarpParamLocation;
GeometryCache _geometryCache;
TextureCache _textureCache;

View file

@ -20,7 +20,7 @@
InfoView::InfoView(bool forced) :
_forced(forced) {
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint);
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
switchToResourcesParentIfRequired();
QString absPath = QFileInfo("resources/html/interface-welcome-allsvg.html").absoluteFilePath();

View file

@ -61,6 +61,33 @@ void Hand::simulate(float deltaTime, bool isMine) {
updateRaveGloveParticles(deltaTime);
}
// Create a voxel at fingertip if controller button is pressed
const float FINGERTIP_VOXEL_SIZE = 0.0125;
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
FingerData& finger = palm.getFingers()[0];
glm::vec3 newVoxelPosition = finger.getTipPosition();
if (palm.getControllerButtons() & BUTTON_1) {
if (glm::length(newVoxelPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value<QColor>();
Application::getInstance()->makeVoxel(newVoxelPosition,
FINGERTIP_VOXEL_SIZE,
paintColor.red(),
paintColor.green(),
paintColor.blue(),
true);
_lastFingerAddVoxel = newVoxelPosition;
}
} else if (palm.getControllerButtons() & BUTTON_2) {
if (glm::length(newVoxelPosition - _lastFingerDeleteVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
Application::getInstance()->removeVoxel(newVoxelPosition, FINGERTIP_VOXEL_SIZE);
_lastFingerDeleteVoxel = newVoxelPosition;
}
}
}
}
}
void Hand::calculateGeometry() {
@ -157,6 +184,45 @@ void Hand::render() {
}
}
// If hand controller buttons pressed, render stuff as needed
if (getPalms().size() > 0) {
for (size_t i = 0; i < getPalms().size(); ++i) {
PalmData& palm = getPalms()[i];
// If trigger pulled, thrust in that direction and draw beam
const float MAX_THRUSTER_BEAM_LENGTH = 5.f;
const float THRUSTER_MARKER_SIZE = 0.0125f;
if (palm.getJoystickY() != 0.f) {
FingerData& finger = palm.getFingers()[0];
if (finger.isActive()) {
if (palm.getJoystickY() > 0.f) {
glColor3f(0, 1, 0);
} else {
glColor3f(1, 0, 0);
}
glm::vec3 palmPosition = palm.getPosition();
glm::vec3 pointerPosition = palmPosition +
glm::normalize(finger.getTipPosition() - palmPosition) *
MAX_THRUSTER_BEAM_LENGTH;
glPushMatrix();
glm::vec3 markerPosition = palmPosition +
glm::normalize(finger.getTipPosition() - palmPosition) *
MAX_THRUSTER_BEAM_LENGTH *
(0.5f + palm.getJoystickY() / 2.f);
glTranslatef(markerPosition.x, markerPosition.y, markerPosition.z);
glutSolidSphere(THRUSTER_MARKER_SIZE, 10, 10);
glPopMatrix();
glLineWidth(2.0);
glBegin(GL_LINES);
glVertex3f(palmPosition.x, palmPosition.y, palmPosition.z);
glVertex3f(pointerPosition.x, pointerPosition.y, pointerPosition.z);
glEnd();
}
}
}
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_RESCALE_NORMAL);
@ -227,8 +293,8 @@ void Hand::renderLeapHands() {
//const glm::vec3 handColor = _ballColor;
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glPushMatrix();
// Draw the leap balls
for (size_t i = 0; i < _leapFingerTipBalls.size(); i++) {

View file

@ -30,6 +30,7 @@ enum RaveLightsSetting {
RAVE_LIGHTS_PARTICLES
};
class Avatar;
class ProgramObject;
@ -46,7 +47,7 @@ public:
bool isCollidable; // whether or not the ball responds to collisions
float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball
};
void init();
void reset();
void simulate(float deltaTime, bool isMine);
@ -62,7 +63,7 @@ public:
// getters
const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;}
const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;}
private:
// disallow copies of the Hand, copy of owning Avatar is disallowed too
Hand(const Hand&);
@ -72,6 +73,8 @@ private:
float _raveGloveClock;
bool _raveGloveInitialized;
int _raveGloveEmitter[NUM_FINGERS];
int _controllerButtons; /// Button states read from hand-held controllers
Avatar* _owningAvatar;
float _renderAlpha;
@ -79,6 +82,8 @@ private:
std::vector<HandBall> _leapFingerTipBalls;
std::vector<HandBall> _leapFingerRootBalls;
glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel;
// private methods
void setLeapHands(const std::vector<glm::vec3>& handPositions,
const std::vector<glm::vec3>& handNormals);

View file

@ -848,7 +848,25 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) {
up;
}
}
// Add thrust and rotation from hand controllers
const float THRUST_MAG_HAND_JETS = THRUST_MAG_FWD;
const float JOYSTICK_YAW_MAG = YAW_MAG;
for (size_t i = 0; i < getHand().getPalms().size(); ++i) {
PalmData& palm = getHand().getPalms()[i];
if (palm.isActive()) {
if (palm.getJoystickY() != 0.f) {
FingerData& finger = palm.getFingers()[0];
if (finger.isActive()) {
}
glm::vec3 thrustDirection = glm::normalize(finger.getTipPosition() - palm.getPosition());
_thrust += thrustDirection * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime;
}
if (palm.getJoystickX() != 0.f) {
_bodyYawDelta -= palm.getJoystickX() * JOYSTICK_YAW_MAG * deltaTime;
}
}
}
// Update speed brake status
const float MIN_SPEED_BRAKE_VELOCITY = _scale * 0.4f;
if ((glm::length(_thrust) == 0.0f) && _isThrustOn && (glm::length(_velocity) > MIN_SPEED_BRAKE_VELOCITY)) {

View file

@ -6,21 +6,37 @@
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include "OculusManager.h"
#include <QOpenGLFramebufferObject>
#include <glm/glm.hpp>
bool OculusManager::_isConnected = false;
#include "Application.h"
#include "InterfaceConfig.h"
#include "OculusManager.h"
ProgramObject OculusManager::_program;
int OculusManager::_textureLocation;
int OculusManager::_lensCenterLocation;
int OculusManager::_screenCenterLocation;
int OculusManager::_scaleLocation;
int OculusManager::_scaleInLocation;
int OculusManager::_hmdWarpParamLocation;
bool OculusManager::_isConnected = false;
float OculusManager::_yawOffset = 0;
#ifdef HAVE_LIBOVR
using namespace OVR;
using namespace OVR::Util::Render;
#ifdef __APPLE__
Ptr<DeviceManager> OculusManager::_deviceManager;
Ptr<HMDDevice> OculusManager::_hmdDevice;
Ptr<SensorDevice> OculusManager::_sensorDevice;
SensorFusion OculusManager::_sensorFusion;
float OculusManager::_yawOffset = 0;
SensorFusion* OculusManager::_sensorFusion;
StereoConfig OculusManager::_stereoConfig;
#endif
void OculusManager::connect() {
#ifdef __APPLE__
#ifdef HAVE_LIBOVR
System::Init();
_deviceManager = *DeviceManager::Create();
_hmdDevice = *_deviceManager->EnumerateDevices<HMDDevice>().CreateDevice();
@ -29,25 +45,152 @@ void OculusManager::connect() {
_isConnected = true;
_sensorDevice = *_hmdDevice->GetSensor();
_sensorFusion.AttachToSensor(_sensorDevice);
_sensorFusion = new SensorFusion;
_sensorFusion->AttachToSensor(_sensorDevice);
// default the yaw to the current orientation
_sensorFusion.SetMagReference();
HMDInfo info;
_hmdDevice->GetDeviceInfo(&info);
_stereoConfig.SetHMDInfo(info);
switchToResourcesParentIfRequired();
_program.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/oculus.frag");
_program.link();
_textureLocation = _program.uniformLocation("texture");
_lensCenterLocation = _program.uniformLocation("lensCenter");
_screenCenterLocation = _program.uniformLocation("screenCenter");
_scaleLocation = _program.uniformLocation("scale");
_scaleInLocation = _program.uniformLocation("scaleIn");
_hmdWarpParamLocation = _program.uniformLocation("hmdWarpParam");
}
#endif
}
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
#ifdef HAVE_LIBOVR
_stereoConfig.SetFullViewport(Viewport(0, 0, screenWidth, screenHeight));
camera.setAspectRatio(_stereoConfig.GetAspect());
camera.setFieldOfView(_stereoConfig.GetYFOVDegrees());
#endif
}
void OculusManager::display(Camera& whichCamera) {
#ifdef HAVE_LIBOVR
Application::getInstance()->getGlowEffect()->prepare();
// render the left eye view to the left side of the screen
const StereoEyeParams& leftEyeParams = _stereoConfig.GetEyeRenderParams(StereoEye_Left);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glTranslatef(_stereoConfig.GetProjectionCenterOffset(), 0, 0);
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
whichCamera.getNearClip(), whichCamera.getFarClip());
glViewport(leftEyeParams.VP.x, leftEyeParams.VP.y, leftEyeParams.VP.w, leftEyeParams.VP.h);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(_stereoConfig.GetIPD() * 0.5f, 0, 0);
Application::getInstance()->displaySide(whichCamera);
// and the right eye to the right side
const StereoEyeParams& rightEyeParams = _stereoConfig.GetEyeRenderParams(StereoEye_Right);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(-_stereoConfig.GetProjectionCenterOffset(), 0, 0);
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
whichCamera.getNearClip(), whichCamera.getFarClip());
glViewport(rightEyeParams.VP.x, rightEyeParams.VP.y, rightEyeParams.VP.w, rightEyeParams.VP.h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(_stereoConfig.GetIPD() * -0.5f, 0, 0);
Application::getInstance()->displaySide(whichCamera);
glPopMatrix();
// restore our normal viewport
const Viewport& fullViewport = _stereoConfig.GetFullViewport();
glViewport(fullViewport.x, fullViewport.y, fullViewport.w, fullViewport.h);
QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(fullViewport.x, fullViewport.x + fullViewport.w, fullViewport.y, fullViewport.y + fullViewport.h);
glDisable(GL_DEPTH_TEST);
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
float scaleFactor = 1.0 / _stereoConfig.GetDistortionScale();
float aspectRatio = _stereoConfig.GetAspect();
glDisable(GL_BLEND);
_program.bind();
_program.setUniformValue(_textureLocation, 0);
const DistortionConfig& distortionConfig = _stereoConfig.GetDistortionConfig();
_program.setUniformValue(_lensCenterLocation, (0.5 + distortionConfig.XCenterOffset * 0.5) * 0.5, 0.5);
_program.setUniformValue(_screenCenterLocation, 0.25, 0.5);
_program.setUniformValue(_scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
_program.setUniformValue(_scaleInLocation, 4, 2 / aspectRatio);
_program.setUniformValue(_hmdWarpParamLocation, distortionConfig.K[0], distortionConfig.K[1],
distortionConfig.K[2], distortionConfig.K[3]);
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(0.5, 0);
glVertex2f(leftEyeParams.VP.w, 0);
glTexCoord2f(0.5, 1);
glVertex2f(leftEyeParams.VP.w, leftEyeParams.VP.h);
glTexCoord2f(0, 1);
glVertex2f(0, leftEyeParams.VP.h);
glEnd();
_program.setUniformValue(_lensCenterLocation, 0.5 + (0.5 - distortionConfig.XCenterOffset * 0.5) * 0.5, 0.5);
_program.setUniformValue(_screenCenterLocation, 0.75, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0.5, 0);
glVertex2f(leftEyeParams.VP.w, 0);
glTexCoord2f(1, 0);
glVertex2f(fullViewport.w, 0);
glTexCoord2f(1, 1);
glVertex2f(fullViewport.w, leftEyeParams.VP.h);
glTexCoord2f(0.5, 1);
glVertex2f(leftEyeParams.VP.w, leftEyeParams.VP.h);
glEnd();
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0);
_program.release();
glPopMatrix();
#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<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
_sensorFusion->GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
_yawOffset = yaw;
#endif
}
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
#ifdef __APPLE__
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
#ifdef HAVE_LIBOVR
_sensorFusion->GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
// convert each angle to degrees
// remove the yaw offset from the returned yaw

View file

@ -10,26 +10,50 @@
#define __hifi__OculusManager__
#include <iostream>
#ifdef HAVE_LIBOVR
#include <OVR.h>
#endif
using namespace OVR;
#include "renderer/ProgramObject.h"
class Camera;
/// Handles interaction with the Oculus Rift.
class OculusManager {
public:
static void connect();
static bool isConnected() { return _isConnected; }
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
static void display(Camera& whichCamera);
static void reset();
static void getEulerAngles(float& yaw, float& pitch, float& roll);
static void updateYawOffset();
private:
private:
static ProgramObject _program;
static int _textureLocation;
static int _lensCenterLocation;
static int _screenCenterLocation;
static int _scaleLocation;
static int _scaleInLocation;
static int _hmdWarpParamLocation;
static bool _isConnected;
static Ptr<DeviceManager> _deviceManager;
static Ptr<HMDDevice> _hmdDevice;
static Ptr<SensorDevice> _sensorDevice;
static SensorFusion _sensorFusion;
static float _yawOffset;
#ifdef HAVE_LIBOVR
static OVR::Ptr<OVR::DeviceManager> _deviceManager;
static OVR::Ptr<OVR::HMDDevice> _hmdDevice;
static OVR::Ptr<OVR::SensorDevice> _sensorDevice;
static OVR::SensorFusion* _sensorFusion;
static OVR::Util::Render::StereoConfig _stereoConfig;
#endif
};
#endif /* defined(__hifi__OculusManager__) */

View file

@ -25,7 +25,7 @@ SixenseManager::~SixenseManager() {
#endif
}
void SixenseManager::update() {
void SixenseManager::update(float deltaTime) {
#ifdef HAVE_SIXENSE
if (sixenseGetNumActiveControllers() == 0) {
return;
@ -42,27 +42,19 @@ void SixenseManager::update() {
sixenseControllerData data;
sixenseGetNewestData(i, &data);
// drive avatar with joystick and triggers
if (data.controller_index) {
avatar->setDriveKeys(ROT_LEFT, qMax(0.0f, -data.joystick_x));
avatar->setDriveKeys(ROT_RIGHT, qMax(0.0f, data.joystick_x));
avatar->setDriveKeys(ROT_UP, qMax(0.0f, data.joystick_y));
avatar->setDriveKeys(ROT_DOWN, qMax(0.0f, -data.joystick_y));
avatar->setDriveKeys(UP, data.trigger);
} else {
avatar->setDriveKeys(FWD, qMax(0.0f, data.joystick_y));
avatar->setDriveKeys(BACK, qMax(0.0f, -data.joystick_y));
avatar->setDriveKeys(LEFT, qMax(0.0f, -data.joystick_x));
avatar->setDriveKeys(RIGHT, qMax(0.0f, data.joystick_x));
avatar->setDriveKeys(DOWN, data.trigger);
}
// Set palm position and normal based on Hydra position/orientation
PalmData palm(&hand);
palm.setActive(true);
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
// Compute current velocity from position change
palm.setVelocity((position - palm.getPosition()) / deltaTime);
// Read controller buttons and joystick into the hand
palm.setControllerButtons(data.buttons);
palm.setTrigger(data.trigger);
palm.setJoystick(data.joystick_x, data.joystick_y);
// Adjust for distance between acquisition 'orb' and the user's torso
// (distance to the right of body center, distance below torso, distance behind torso)
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);

View file

@ -16,7 +16,7 @@ public:
SixenseManager();
~SixenseManager();
void update();
void update(float deltaTime);
};
#endif /* defined(__interface__SixenseManager__) */

View file

@ -57,6 +57,8 @@ void AmbientOcclusionEffect::init() {
_leftBottomLocation = _occlusionProgram->uniformLocation("leftBottom");
_rightTopLocation = _occlusionProgram->uniformLocation("rightTop");
_noiseScaleLocation = _occlusionProgram->uniformLocation("noiseScale");
_texCoordOffsetLocation = _occlusionProgram->uniformLocation("texCoordOffset");
_texCoordScaleLocation = _occlusionProgram->uniformLocation("texCoordScale");
// generate the random rotation texture
glGenTextures(1, &_rotationTextureID);
@ -106,22 +108,25 @@ void AmbientOcclusionEffect::render() {
Application::getInstance()->computeOffAxisFrustum(
left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_WIDTH_INDEX = 2;
QSize widgetSize = Application::getInstance()->getGLWidget()->size();
float sMin = viewport[VIEWPORT_X_INDEX] / (float)widgetSize.width();
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)widgetSize.width();
_occlusionProgram->bind();
_occlusionProgram->setUniformValue(_nearLocation, nearVal);
_occlusionProgram->setUniformValue(_farLocation, farVal);
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
QSize widgetSize = Application::getInstance()->getGLWidget()->size();
_occlusionProgram->setUniformValue(_noiseScaleLocation, widgetSize.width() / (float)ROTATION_WIDTH,
_occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH,
widgetSize.height() / (float)ROTATION_HEIGHT);
_occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f);
_occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f);
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
const int VIEWPORT_X_INDEX = 0;
const int VIEWPORT_WIDTH_INDEX = 2;
float sMin = viewport[VIEWPORT_X_INDEX] / (float)widgetSize.width();
float sMax = (viewport[VIEWPORT_X_INDEX] + viewport[VIEWPORT_WIDTH_INDEX]) / (float)widgetSize.width();
renderFullscreenQuad(sMin, sMax);
renderFullscreenQuad();
_occlusionProgram->release();
@ -141,7 +146,7 @@ void AmbientOcclusionEffect::render() {
_blurProgram->bind();
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / widgetSize.width(), 1.0f / widgetSize.height());
renderFullscreenQuad(sMin, sMax);
renderFullscreenQuad(sMin, sMin + sWidth);
_blurProgram->release();

View file

@ -30,6 +30,8 @@ private:
int _leftBottomLocation;
int _rightTopLocation;
int _noiseScaleLocation;
int _texCoordOffsetLocation;
int _texCoordScaleLocation;
ProgramObject* _blurProgram;
int _blurScaleLocation;

View file

@ -37,6 +37,8 @@ PalmData& HandData::addNewPalm() {
PalmData::PalmData(HandData* owningHandData) :
_rawPosition(0, 0, 0),
_rawNormal(0, 1, 0),
_velocity(0, 0, 0),
_controllerButtons(0),
_isActive(false),
_leapID(LEAPID_INVALID),
_numFramesWithoutData(0),

View file

@ -41,6 +41,12 @@ enum RaveGloveEffectsMode
NUM_RAVE_GLOVE_EFFECTS_MODES
};
const int BUTTON_1 = 32;
const int BUTTON_2 = 64;
const int BUTTON_3 = 8;
const int BUTTON_4 = 16;
const int BUTTON_FWD = 128;
class HandData {
public:
HandData(AvatarData* owningAvatar);
@ -144,17 +150,34 @@ public:
void setLeapID(int id) { _leapID = id; }
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
void setVelocity(const glm::vec3& velocity) { _velocity = velocity; }
const glm::vec3& getVelocity() const { return _velocity; }
void incrementFramesWithoutData() { _numFramesWithoutData++; }
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
int getFramesWithoutData() const { return _numFramesWithoutData; }
// Controller buttons
void setControllerButtons(int controllerButtons) { _controllerButtons = controllerButtons; }
int getControllerButtons() { return _controllerButtons; }
void setTrigger(float trigger) { _trigger = trigger; }
float getTrigger() { return _trigger; }
void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; }
float getJoystickX() { return _joystickX; }
float getJoystickY() { return _joystickY; }
private:
std::vector<FingerData> _fingers;
glm::vec3 _rawPosition;
glm::vec3 _rawNormal;
bool _isActive; // This has current valid data
int _leapID; // the Leap's serial id for this tracked object
glm::vec3 _velocity;
int _controllerButtons;
float _trigger;
float _joystickX, _joystickY;
bool _isActive; // This has current valid data
int _leapID; // the Leap's serial id for this tracked object
int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost.
HandData* _owningHandData;
};