aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/Kernel')
-rw-r--r--LibOVR/Src/Kernel/OVR_Alg.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_Alg.h122
-rw-r--r--LibOVR/Src/Kernel/OVR_Allocator.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_Allocator.h10
-rw-r--r--LibOVR/Src/Kernel/OVR_Array.h53
-rw-r--r--LibOVR/Src/Kernel/OVR_Atomic.cpp77
-rw-r--r--LibOVR/Src/Kernel/OVR_Atomic.h27
-rw-r--r--LibOVR/Src/Kernel/OVR_Color.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_ContainerAllocator.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_Deque.h310
-rw-r--r--LibOVR/Src/Kernel/OVR_File.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_File.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_FileFILE.cpp13
-rw-r--r--LibOVR/Src/Kernel/OVR_Hash.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_KeyCodes.h10
-rw-r--r--LibOVR/Src/Kernel/OVR_List.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_Lockless.cpp231
-rw-r--r--LibOVR/Src/Kernel/OVR_Lockless.h107
-rw-r--r--LibOVR/Src/Kernel/OVR_Log.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_Log.h10
-rw-r--r--LibOVR/Src/Kernel/OVR_Math.cpp99
-rw-r--r--LibOVR/Src/Kernel/OVR_Math.h1918
-rw-r--r--LibOVR/Src/Kernel/OVR_RefCount.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_RefCount.h47
-rw-r--r--LibOVR/Src/Kernel/OVR_Std.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_Std.h14
-rw-r--r--LibOVR/Src/Kernel/OVR_String.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_String.h16
-rw-r--r--LibOVR/Src/Kernel/OVR_StringHash.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_String_PathUtil.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_SysFile.cpp12
-rw-r--r--LibOVR/Src/Kernel/OVR_SysFile.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_System.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_System.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_Threads.h8
-rw-r--r--LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp821
-rw-r--r--LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_Timer.cpp256
-rw-r--r--LibOVR/Src/Kernel/OVR_Timer.h85
-rw-r--r--LibOVR/Src/Kernel/OVR_Types.h19
-rw-r--r--LibOVR/Src/Kernel/OVR_UTF8Util.cpp8
-rw-r--r--LibOVR/Src/Kernel/OVR_UTF8Util.h9
43 files changed, 2763 insertions, 1671 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Alg.cpp b/LibOVR/Src/Kernel/OVR_Alg.cpp
index 0c564ab..2e52bc3 100644
--- a/LibOVR/Src/Kernel/OVR_Alg.cpp
+++ b/LibOVR/Src/Kernel/OVR_Alg.cpp
@@ -5,16 +5,16 @@ Content : Static lookup tables for Alg functions
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Alg.h b/LibOVR/Src/Kernel/OVR_Alg.h
index 51261d3..783af21 100644
--- a/LibOVR/Src/Kernel/OVR_Alg.h
+++ b/LibOVR/Src/Kernel/OVR_Alg.h
@@ -6,16 +6,16 @@ Content : Simple general purpose algorithms: Sort, Binary Search, etc.
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -433,7 +433,29 @@ void InsertionSort(Array& arr)
InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
}
+//-----------------------------------------------------------------------------------
+// ***** Median
+// Returns a median value of the input array.
+// Caveats: partially sorts the array, returns a reference to the array element
+// TBD: This needs to be optimized and generalized
+//
+template<class Array>
+typename Array::ValueType& Median(Array& arr)
+{
+ UPInt count = arr.GetSize();
+ UPInt mid = (count - 1) / 2;
+ OVR_ASSERT(count > 0);
+ for (int j = 0; j <= mid; j++)
+ {
+ int min = j;
+ for (int k = j + 1; k < count; k++)
+ if (arr[k] < arr[min])
+ min = k;
+ Swap(arr[j], arr[min]);
+ }
+ return arr[mid];
+}
//-----------------------------------------------------------------------------------
// ***** LowerBoundSliced
@@ -651,13 +673,13 @@ inline UByte UpperBit(UPInt val)
if (val & 0xFFFF0000)
{
- return static_cast<UByte>((val & 0xFF000000) ?
+ return (val & 0xFF000000) ?
UpperBitTable[(val >> 24) ] + 24:
- UpperBitTable[(val >> 16) & 0xFF] + 16);
+ UpperBitTable[(val >> 16) & 0xFF] + 16;
}
- return static_cast<UByte>((val & 0xFF00) ?
+ return (val & 0xFF00) ?
UpperBitTable[(val >> 8) & 0xFF] + 8:
- UpperBitTable[(val ) & 0xFF]);
+ UpperBitTable[(val ) & 0xFF];
#else
@@ -696,13 +718,13 @@ inline UByte LowerBit(UPInt val)
if (val & 0xFFFF)
{
- return static_cast<UByte>( (val & 0xFF) ?
+ return (val & 0xFF) ?
LowerBitTable[ val & 0xFF]:
- LowerBitTable[(val >> 8) & 0xFF] + 8 );
+ LowerBitTable[(val >> 8) & 0xFF] + 8;
}
- return static_cast<UByte>( (val & 0xFF0000) ?
+ return (val & 0xFF0000) ?
LowerBitTable[(val >> 16) & 0xFF] + 16:
- LowerBitTable[(val >> 24) & 0xFF] + 24 );
+ LowerBitTable[(val >> 24) & 0xFF] + 24;
#else
@@ -813,7 +835,7 @@ namespace ByteUtil {
// Swap the byte order of primitive types
inline UByte SwapOrder(UByte v) { return v; }
inline SByte SwapOrder(SByte v) { return v; }
- inline UInt16 SwapOrder(UInt16 v) { return static_cast<UInt16>( UInt16(v>>8)|UInt16(v<<8) ); }
+ inline UInt16 SwapOrder(UInt16 v) { return UInt16(v>>8)|UInt16(v<<8); }
inline SInt16 SwapOrder(SInt16 v) { return SInt16((UInt16(v)>>8)|(v<<8)); }
inline UInt32 SwapOrder(UInt32 v) { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); }
inline SInt32 SwapOrder(SInt32 p) { return (SInt32)SwapOrder(UInt32(p)); }
@@ -959,6 +981,80 @@ namespace ByteUtil {
+// Used primarily for hardware interfacing such as sensor reports, firmware, etc.
+// Reported data is all little-endian.
+inline UInt16 DecodeUInt16(const UByte* buffer)
+{
+ return ByteUtil::LEToSystem ( *(const UInt16*)buffer );
+}
+
+inline SInt16 DecodeSInt16(const UByte* buffer)
+{
+ return ByteUtil::LEToSystem ( *(const SInt16*)buffer );
+}
+
+inline UInt32 DecodeUInt32(const UByte* buffer)
+{
+ return ByteUtil::LEToSystem ( *(const UInt32*)buffer );
+}
+
+inline SInt32 DecodeSInt32(const UByte* buffer)
+{
+ return ByteUtil::LEToSystem ( *(const SInt32*)buffer );
+}
+
+inline float DecodeFloat(const UByte* buffer)
+{
+ union {
+ UInt32 U;
+ float F;
+ };
+
+ U = DecodeUInt32(buffer);
+ return F;
+}
+
+inline void EncodeUInt16(UByte* buffer, UInt16 val)
+{
+ *(UInt16*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeSInt16(UByte* buffer, SInt16 val)
+{
+ *(SInt16*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeUInt32(UByte* buffer, UInt32 val)
+{
+ *(UInt32*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeSInt32(UByte* buffer, SInt32 val)
+{
+ *(SInt32*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeFloat(UByte* buffer, float val)
+{
+ union {
+ UInt32 U;
+ float F;
+ };
+
+ F = val;
+ EncodeUInt32(buffer, U);
+}
+
+// Converts an 8-bit binary-coded decimal
+inline SByte DecodeBCD(UByte byte)
+{
+ UByte digit1 = (byte >> 4) & 0x0f;
+ UByte digit2 = byte & 0x0f;
+ int decimal = digit1 * 10 + digit2; // maximum value = 99
+ return (SByte)decimal;
+}
+
+
}} // OVR::Alg
#endif
diff --git a/LibOVR/Src/Kernel/OVR_Allocator.cpp b/LibOVR/Src/Kernel/OVR_Allocator.cpp
index 51eebba..0f82561 100644
--- a/LibOVR/Src/Kernel/OVR_Allocator.cpp
+++ b/LibOVR/Src/Kernel/OVR_Allocator.cpp
@@ -5,16 +5,16 @@ Content : Installable memory allocator implementation
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Allocator.h b/LibOVR/Src/Kernel/OVR_Allocator.h
index b2e0472..b862557 100644
--- a/LibOVR/Src/Kernel/OVR_Allocator.h
+++ b/LibOVR/Src/Kernel/OVR_Allocator.h
@@ -6,16 +6,16 @@ Content : Installable memory allocator
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -104,7 +104,7 @@ namespace OVR {
template <class T>
OVR_FORCE_INLINE T* Construct(void *p)
{
- return ::new(p) T;
+ return ::new(p) T();
}
template <class T>
diff --git a/LibOVR/Src/Kernel/OVR_Array.h b/LibOVR/Src/Kernel/OVR_Array.h
index 552ddcc..7a715ba 100644
--- a/LibOVR/Src/Kernel/OVR_Array.h
+++ b/LibOVR/Src/Kernel/OVR_Array.h
@@ -6,16 +6,16 @@ Content : Template implementation for Array
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -222,7 +222,7 @@ struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy>
ArrayData()
: BaseType() { }
- ArrayData(int size)
+ ArrayData(UPInt size)
: BaseType() { Resize(size); }
ArrayData(const SelfType& a)
@@ -281,7 +281,7 @@ struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy>
ArrayDataCC(const ValueType& defval)
: BaseType(), DefaultValue(defval) { }
- ArrayDataCC(const ValueType& defval, int size)
+ ArrayDataCC(const ValueType& defval, UPInt size)
: BaseType(), DefaultValue(defval) { Resize(size); }
ArrayDataCC(const SelfType& a)
@@ -359,14 +359,14 @@ public:
ArrayBase()
: Data() {}
- ArrayBase(int size)
+ ArrayBase(UPInt size)
: Data(size) {}
ArrayBase(const SelfType& a)
: Data(a.Data) {}
ArrayBase(const ValueType& defval)
: Data(defval) {}
- ArrayBase(const ValueType& defval, int size)
+ ArrayBase(const ValueType& defval, UPInt size)
: Data(defval, size) {}
SizePolicyType* GetSizePolicy() const { return Data.Policy; }
@@ -499,6 +499,9 @@ public:
// Removing an element from the array is an expensive operation!
// It compacts only after removing the last element.
+ // If order of elements in the array is not important then use
+ // RemoveAtUnordered, that could be much faster than the regular
+ // RemoveAt.
void RemoveAt(UPInt index)
{
OVR_ASSERT(index < Data.Size);
@@ -517,6 +520,32 @@ public:
}
}
+ // Removes an element from the array without respecting of original order of
+ // elements for better performance. Do not use on array where order of elements
+ // is important, otherwise use it instead of regular RemoveAt().
+ void RemoveAtUnordered(UPInt index)
+ {
+ OVR_ASSERT(index < Data.Size);
+ if (Data.Size == 1)
+ {
+ Clear();
+ }
+ else
+ {
+ // copy the last element into the 'index' position
+ // and decrement the size (instead of moving all elements
+ // in [index + 1 .. size - 1] range).
+ const UPInt lastElemIndex = Data.Size - 1;
+ if (index < lastElemIndex)
+ {
+ AllocatorType::Destruct(Data.Data + index);
+ AllocatorType::Construct(Data.Data + index, Data.Data[lastElemIndex]);
+ }
+ AllocatorType::Destruct(Data.Data + lastElemIndex);
+ --Data.Size;
+ }
+ }
+
// Insert the given object at the given index shifting all the elements up.
void InsertAt(UPInt index, const ValueType& val = ValueType())
{
@@ -725,7 +754,7 @@ public:
typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType;
Array() : BaseType() {}
- Array(int size) : BaseType(size) {}
+ Array(UPInt size) : BaseType(size) {}
Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
Array(const SelfType& a) : BaseType(a) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
@@ -747,7 +776,7 @@ public:
typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType;
ArrayPOD() : BaseType() {}
- ArrayPOD(int size) : BaseType(size) {}
+ ArrayPOD(UPInt size) : BaseType(size) {}
ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
ArrayPOD(const SelfType& a) : BaseType(a) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
@@ -769,7 +798,7 @@ public:
typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType;
ArrayCPP() : BaseType() {}
- ArrayCPP(int size) : BaseType(size) {}
+ ArrayCPP(UPInt size) : BaseType(size) {}
ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
ArrayCPP(const SelfType& a) : BaseType(a) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
@@ -793,7 +822,7 @@ public:
typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> > BaseType;
ArrayCC(const ValueType& defval) : BaseType(defval) {}
- ArrayCC(const ValueType& defval, int size) : BaseType(defval, size) {}
+ ArrayCC(const ValueType& defval, UPInt size) : BaseType(defval, size) {}
ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); }
ArrayCC(const SelfType& a) : BaseType(a) {}
const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
diff --git a/LibOVR/Src/Kernel/OVR_Atomic.cpp b/LibOVR/Src/Kernel/OVR_Atomic.cpp
index 1c0efc2..9ea6e76 100644
--- a/LibOVR/Src/Kernel/OVR_Atomic.cpp
+++ b/LibOVR/Src/Kernel/OVR_Atomic.cpp
@@ -7,16 +7,16 @@ Content : Contains atomic operations and inline fastest locking
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,6 +27,7 @@ limitations under the License.
************************************************************************************/
#include "OVR_Atomic.h"
+#include "OVR_Allocator.h"
#ifdef OVR_ENABLE_THREADS
@@ -88,6 +89,74 @@ Lock::~Lock()
#endif
+
+//-------------------------------------------------------------------------------------
+// ***** SharedLock
+
+// This is a general purpose globally shared Lock implementation that should probably be
+// moved to Kernel.
+// May in theory busy spin-wait if we hit contention on first lock creation,
+// but this shouldn't matter in practice since Lock* should be cached.
+
+
+enum { LockInitMarker = 0xFFFFFFFF };
+
+Lock* SharedLock::GetLockAddRef()
+{
+ int oldUseCount;
+
+ do {
+ oldUseCount = UseCount;
+ if (oldUseCount == LockInitMarker)
+ continue;
+
+ if (oldUseCount == 0)
+ {
+ // Initialize marker
+ if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
+ {
+ Construct<Lock>(Buffer);
+ do { }
+ while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
+ return toLock();
+ }
+ continue;
+ }
+
+ } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
+
+ return toLock();
+}
+
+void SharedLock::ReleaseLock(Lock* plock)
+{
+ OVR_UNUSED(plock);
+ OVR_ASSERT(plock == toLock());
+
+ int oldUseCount;
+
+ do {
+ oldUseCount = UseCount;
+ OVR_ASSERT(oldUseCount != LockInitMarker);
+
+ if (oldUseCount == 1)
+ {
+ // Initialize marker
+ if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
+ {
+ Destruct<Lock>(toLock());
+
+ do { }
+ while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
+
+ return;
+ }
+ continue;
+ }
+
+ } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
+}
+
} // OVR
#endif // OVR_ENABLE_THREADS
diff --git a/LibOVR/Src/Kernel/OVR_Atomic.h b/LibOVR/Src/Kernel/OVR_Atomic.h
index b539ccd..b826251 100644
--- a/LibOVR/Src/Kernel/OVR_Atomic.h
+++ b/LibOVR/Src/Kernel/OVR_Atomic.h
@@ -8,16 +8,16 @@ Content : Contains atomic operations and inline fastest locking
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -865,6 +865,25 @@ public:
};
+//-------------------------------------------------------------------------------------
+// Globally shared Lock implementation used for MessageHandlers, etc.
+
+class SharedLock
+{
+public:
+ SharedLock() : UseCount(0) {}
+
+ Lock* GetLockAddRef();
+ void ReleaseLock(Lock* plock);
+
+private:
+ Lock* toLock() { return (Lock*)Buffer; }
+
+ // UseCount and max alignment.
+ volatile int UseCount;
+ UInt64 Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)];
+};
+
} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_Color.h b/LibOVR/Src/Kernel/OVR_Color.h
index 0881997..cf536da 100644
--- a/LibOVR/Src/Kernel/OVR_Color.h
+++ b/LibOVR/Src/Kernel/OVR_Color.h
@@ -6,16 +6,16 @@ Content : Contains color struct.
Created : February 7, 2013
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h
index 36c22d1..afc0e6a 100644
--- a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h
+++ b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h
@@ -6,16 +6,16 @@ Content : Template allocators and constructors for containers.
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Deque.h b/LibOVR/Src/Kernel/OVR_Deque.h
new file mode 100644
index 0000000..747810e
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Deque.h
@@ -0,0 +1,310 @@
+/************************************************************************************
+
+Filename : OVR_Deque.h
+Content : Deque container
+Created : Nov. 15, 2013
+Authors : Dov Katz
+
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Deque_h
+#define OVR_Deque_h
+
+namespace OVR{
+
+template <class Elem>
+class Deque
+{
+public:
+ enum
+ {
+ DefaultCapacity = 500
+ };
+
+ Deque(int capacity = DefaultCapacity);
+ Deque(const Deque<Elem> &OtherDeque);
+ virtual ~Deque(void);
+
+ virtual void PushBack (const Elem &Item); // Adds Item to the end
+ virtual void PushFront (const Elem &Item); // Adds Item to the beginning
+ virtual Elem PopBack (void); // Removes Item from the end
+ virtual Elem PopFront (void); // Removes Item from the beginning
+ virtual const Elem& PeekBack (int count = 0) const; // Returns count-th Item from the end
+ virtual const Elem& PeekFront (int count = 0) const; // Returns count-th Item from the beginning
+
+ virtual inline UPInt GetSize (void) const; // Returns Number of Elements
+ virtual inline UPInt GetCapacity(void) const; // Returns the maximum possible number of elements
+ virtual void Clear (void); // Remove all elements
+ virtual inline bool IsEmpty () const;
+ virtual inline bool IsFull () const;
+
+protected:
+ Elem *Data; // The actual Data array
+ const int Capacity; // Deque capacity
+ int Beginning; // Index of the first element
+ int End; // Index of the next after last element
+
+ // Instead of calculating the number of elements, using this variable
+ // is much more convenient.
+ int ElemCount;
+
+private:
+ Deque& operator= (const Deque& q) { }; // forbidden
+};
+
+template <class Elem>
+class InPlaceMutableDeque : public Deque<Elem>
+{
+public:
+ InPlaceMutableDeque( int capacity = Deque<Elem>::DefaultCapacity ) : Deque<Elem>( capacity ) {}
+ virtual ~InPlaceMutableDeque() {};
+
+ virtual Elem& PeekBack (int count = 0); // Returns count-th Item from the end
+ virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning
+private:
+ InPlaceMutableDeque& operator=(const InPlaceMutableDeque& q) {};
+};
+
+// Same as Deque, but allows to write more elements than maximum capacity
+// Old elements are lost as they are overwritten with the new ones
+template <class Elem>
+class CircularBuffer : public Deque<Elem>
+{
+public:
+ CircularBuffer(int MaxSize = Deque<Elem>::DefaultCapacity) : Deque<Elem>(MaxSize) { };
+
+ // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings
+ // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class
+ inline virtual void PushBack (const Elem &Item); // Adds Item to the end, overwriting the oldest element at the beginning if necessary
+ inline virtual void PushFront (const Elem &Item); // Adds Item to the beginning, overwriting the oldest element at the end if necessary
+};
+
+//----------------------------------------------------------------------------------
+
+// Deque Constructor function
+template <class Elem>
+Deque<Elem>::Deque(int capacity) :
+Capacity( capacity ), Beginning(0), End(0), ElemCount(0)
+{
+ Data = (Elem*) OVR_ALLOC(Capacity * sizeof(Elem));
+ ConstructArray<Elem>(Data, Capacity);
+}
+
+// Deque Copy Constructor function
+template <class Elem>
+Deque<Elem>::Deque(const Deque &OtherDeque) :
+Capacity( OtherDeque.Capacity ) // Initialize the constant
+{
+ Beginning = OtherDeque.Beginning;
+ End = OtherDeque.End;
+ ElemCount = OtherDeque.ElemCount;
+
+ Data = (Elem*) OVR_ALLOC(Capacity * sizeof(Elem));
+ for (int i = 0; i < Capacity; i++)
+ Data[i] = OtherDeque.Data[i];
+}
+
+// Deque Destructor function
+template <class Elem>
+Deque<Elem>::~Deque(void)
+{
+ DestructArray<Elem>(Data, Capacity);
+ OVR_FREE(Data);
+}
+
+template <class Elem>
+void Deque<Elem>::Clear()
+{
+ Beginning = 0;
+ End = 0;
+ ElemCount = 0;
+
+ DestructArray<Elem>(Data, Capacity);
+ ConstructArray<Elem>(Data, Capacity);
+}
+
+// Push functions
+template <class Elem>
+void Deque<Elem>::PushBack(const Elem &Item)
+{
+ // Error Check: Make sure we aren't
+ // exceeding our maximum storage space
+ OVR_ASSERT( ElemCount < Capacity );
+
+ Data[ End++ ] = Item;
+ ++ElemCount;
+
+ // Check for wrap-around
+ if (End >= Capacity)
+ End -= Capacity;
+}
+
+template <class Elem>
+void Deque<Elem>::PushFront(const Elem &Item)
+{
+ // Error Check: Make sure we aren't
+ // exceeding our maximum storage space
+ OVR_ASSERT( ElemCount < Capacity );
+
+ Beginning--;
+ // Check for wrap-around
+ if (Beginning < 0)
+ Beginning += Capacity;
+
+ Data[ Beginning ] = Item;
+ ++ElemCount;
+}
+
+// Pop functions
+template <class Elem>
+Elem Deque<Elem>::PopFront(void)
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( ElemCount > 0 );
+
+ Elem ReturnValue = Data[ Beginning ];
+ Destruct<Elem>(&Data[ Beginning ]);
+ Construct<Elem>(&Data[ Beginning ]);
+
+ ++Beginning;
+ --ElemCount;
+
+ // Check for wrap-around
+ if (Beginning >= Capacity)
+ Beginning -= Capacity;
+
+ return ReturnValue;
+}
+
+template <class Elem>
+Elem Deque<Elem>::PopBack(void)
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( ElemCount > 0 );
+
+ End--;
+ --ElemCount;
+
+ // Check for wrap-around
+ if (End < 0)
+ End += Capacity;
+
+ Elem ReturnValue = Data[ End ];
+ Destruct<Elem>(&Data[ End ]);
+ Construct<Elem>(&Data[ End ]);
+
+ return ReturnValue;
+}
+
+// Peek functions
+template <class Elem>
+const Elem& Deque<Elem>::PeekFront(int count) const
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( ElemCount > count );
+
+ int idx = Beginning + count;
+ if (idx >= Capacity)
+ idx -= Capacity;
+ return Data[ idx ];
+}
+
+template <class Elem>
+const Elem& Deque<Elem>::PeekBack(int count) const
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( ElemCount > count );
+
+ int idx = End - count - 1;
+ if (idx < 0)
+ idx += Capacity;
+ return Data[ idx ];
+}
+
+// Mutable Peek functions
+template <class Elem>
+Elem& InPlaceMutableDeque<Elem>::PeekFront(int count)
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( Deque<Elem>::ElemCount > count );
+
+ int idx = Deque<Elem>::Beginning + count;
+ if (idx >= Deque<Elem>::Capacity)
+ idx -= Deque<Elem>::Capacity;
+ return Deque<Elem>::Data[ idx ];
+}
+
+template <class Elem>
+Elem& InPlaceMutableDeque<Elem>::PeekBack(int count)
+{
+ // Error Check: Make sure we aren't reading from an empty Deque
+ OVR_ASSERT( Deque<Elem>::ElemCount > count );
+
+ int idx = Deque<Elem>::End - count - 1;
+ if (idx < 0)
+ idx += Deque<Elem>::Capacity;
+ return Deque<Elem>::Data[ idx ];
+}
+
+template <class Elem>
+inline UPInt Deque<Elem>::GetCapacity(void) const
+{
+ return Deque<Elem>::Capacity;
+}
+
+template <class Elem>
+inline UPInt Deque<Elem>::GetSize(void) const
+{
+ return Deque<Elem>::ElemCount;
+}
+
+template <class Elem>
+inline bool Deque<Elem>::IsEmpty(void) const
+{
+ return Deque<Elem>::ElemCount==0;
+}
+
+template <class Elem>
+inline bool Deque<Elem>::IsFull(void) const
+{
+ return Deque<Elem>::ElemCount==Deque<Elem>::Capacity;
+}
+
+// ******* CircularBuffer<Elem> *******
+// Push functions
+template <class Elem>
+void CircularBuffer<Elem>::PushBack(const Elem &Item)
+{
+ if (this->IsFull())
+ this->PopFront();
+ Deque<Elem>::PushBack(Item);
+}
+
+template <class Elem>
+void CircularBuffer<Elem>::PushFront(const Elem &Item)
+{
+ if (this->IsFull())
+ this->PopBack();
+ Deque<Elem>::PushFront(Item);
+}
+
+};
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_File.cpp b/LibOVR/Src/Kernel/OVR_File.cpp
index 3f52488..31ab516 100644
--- a/LibOVR/Src/Kernel/OVR_File.cpp
+++ b/LibOVR/Src/Kernel/OVR_File.cpp
@@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32)
Created : April 5, 1999
Authors : Michael Antonov
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_File.h b/LibOVR/Src/Kernel/OVR_File.h
index 92c53ab..a8dc615 100644
--- a/LibOVR/Src/Kernel/OVR_File.h
+++ b/LibOVR/Src/Kernel/OVR_File.h
@@ -11,16 +11,16 @@ Notes : errno may not be preserved across use of BaseFile member functio
: Directories cannot be deleted while files opened from them are in use
(For the GetFullName function)
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_FileFILE.cpp b/LibOVR/Src/Kernel/OVR_FileFILE.cpp
index fd01118..4fe4cbe 100644
--- a/LibOVR/Src/Kernel/OVR_FileFILE.cpp
+++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp
@@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32)
Created : April 5, 1999
Authors : Michael Antonov
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -561,9 +561,10 @@ bool FILEFile::CloseCancel()
}
*/
-File *FileFILEOpen(const String& path, int flags, int mode)
+Ptr<File> FileFILEOpen(const String& path, int flags, int mode)
{
- return new FILEFile(path, flags, mode);
+ Ptr<File> result = *new FILEFile(path, flags, mode);
+ return result;
}
// Helper function: obtain file information time.
diff --git a/LibOVR/Src/Kernel/OVR_Hash.h b/LibOVR/Src/Kernel/OVR_Hash.h
index 98c206b..04c4db8 100644
--- a/LibOVR/Src/Kernel/OVR_Hash.h
+++ b/LibOVR/Src/Kernel/OVR_Hash.h
@@ -6,16 +6,16 @@ Content : Template hash-table/set implementation
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_KeyCodes.h b/LibOVR/Src/Kernel/OVR_KeyCodes.h
index 42d98ee..b5c5930 100644
--- a/LibOVR/Src/Kernel/OVR_KeyCodes.h
+++ b/LibOVR/Src/Kernel/OVR_KeyCodes.h
@@ -5,16 +5,16 @@ Filename : OVR_KeyCodes.h
Content : Common keyboard constants
Created : September 19, 2012
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -147,7 +147,7 @@ enum KeyCode
Key_Semicolon = 59,
Key_Equal = 61,
- Key_Bar = 192,
+ Key_Backtick = 96, // ` and tilda~ when shifted (US keyboard)
Key_BracketLeft = 91,
Key_Backslash,
Key_BracketRight,
diff --git a/LibOVR/Src/Kernel/OVR_List.h b/LibOVR/Src/Kernel/OVR_List.h
index d5e79a3..6b49f37 100644
--- a/LibOVR/Src/Kernel/OVR_List.h
+++ b/LibOVR/Src/Kernel/OVR_List.h
@@ -6,16 +6,16 @@ Content : Template implementation for doubly-connected linked List
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Lockless.cpp b/LibOVR/Src/Kernel/OVR_Lockless.cpp
new file mode 100644
index 0000000..0f25805
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp
@@ -0,0 +1,231 @@
+/************************************************************************************
+
+PublicHeader: OVR.h
+Filename : OVR_Lockless.cpp
+Content : Test logic for lock-less classes
+Created : December 27, 2013
+Authors : Michael Antonov
+
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Lockless.h"
+
+#ifdef OVR_LOCKLESS_TEST
+
+#include "OVR_Threads.h"
+#include "OVR_Timer.h"
+#include "OVR_Log.h"
+
+
+namespace OVR { namespace LocklessTest {
+
+
+const int TestIterations = 10000000;
+
+// Use volatile dummys to force compiler to do spinning.
+volatile int Dummy1;
+int Unused1[32];
+volatile int Dummy2;
+int Unused2[32];
+volatile int Dummy3;
+int Unused3[32];
+
+
+// Data block out of 20 consecutive integers, should be internally consistent.
+struct TestData
+{
+ enum { ItemCount = 20 };
+
+ int Data[ItemCount];
+
+
+ void Set(int val)
+ {
+ for (int i=0; i<ItemCount; i++)
+ {
+ Data[i] = val*100 + i;
+ }
+ }
+
+ int ReadAndCheckConsistency(int prevValue) const
+ {
+ int val = Data[0];
+
+ for (int i=1; i<ItemCount; i++)
+ {
+
+ if (Data[i] != (val + i))
+ {
+ // Only complain once per same-value entry
+ if (prevValue != val / 100)
+ {
+ LogText("LocklessTest Fail - corruption at %d inside block %d\n",
+ i, val/100);
+ // OVR_ASSERT(Data[i] == val + i);
+ }
+ break;
+ }
+ }
+
+ return val / 100;
+ }
+};
+
+
+
+volatile bool FirstItemWritten = false;
+LocklessUpdater<TestData> TestDataUpdater;
+
+// Use this lock to verify that testing algorithm is otherwise correct...
+Lock TestLock;
+
+
+//-------------------------------------------------------------------------------------
+
+// Consumer thread reads values from TestDataUpdater and
+// ensures that each one is internally consistent.
+
+class Consumer : public Thread
+{
+ virtual int Run()
+ {
+ LogText("LocklessTest::Consumer::Run started.\n");
+
+
+ while (!FirstItemWritten)
+ {
+ // spin until producer wrote first value...
+ }
+
+ TestData d;
+ int oldValue = 0;
+ int newValue;
+
+ do
+ {
+ {
+ //Lock::Locker scope(&TestLock);
+ d = TestDataUpdater.GetState();
+ }
+
+ newValue = d.ReadAndCheckConsistency(oldValue);
+
+ // Values should increase or stay the same!
+ if (newValue < oldValue)
+ {
+ LogText("LocklessTest Fail - %d after %d; delta = %d\n",
+ newValue, oldValue, newValue - oldValue);
+ // OVR_ASSERT(0);
+ }
+
+
+ if (oldValue != newValue)
+ {
+ oldValue = newValue;
+
+ if (oldValue % (TestIterations/30) == 0)
+ {
+ LogText("LocklessTest::Consumer - %5.2f%% done\n",
+ 100.0f * (float)oldValue/(float)TestIterations);
+ }
+ }
+
+ // Spin a while
+ for (int j = 0; j< 300; j++)
+ {
+ Dummy3 = j;
+ }
+
+
+ } while (oldValue < (TestIterations * 99 / 100));
+
+ LogText("LocklessTest::Consumer::Run exiting.\n");
+ return 0;
+ }
+
+};
+
+
+//-------------------------------------------------------------------------------------
+
+class Producer : public Thread
+{
+
+ virtual int Run()
+ {
+ LogText("LocklessTest::Producer::Run started.\n");
+
+ for (int testVal = 0; testVal < TestIterations; testVal++)
+ {
+ TestData d;
+ d.Set(testVal);
+
+ {
+ //Lock::Locker scope(&TestLock);
+ TestDataUpdater.SetState(d);
+ }
+
+ FirstItemWritten = true;
+
+ // Spin a bit
+ for(int j = 0; j < 1000; j++)
+ {
+ Dummy2 = j;
+ }
+
+ if (testVal % (TestIterations/30) == 0)
+ {
+ LogText("LocklessTest::Producer - %5.2f%% done\n",
+ 100.0f * (float)testVal/(float)TestIterations);
+ }
+ }
+
+ LogText("LocklessTest::Producer::Run exiting.\n");
+ return 0;
+ }
+};
+
+
+} // namespace LocklessTest
+
+
+
+void StartLocklessTest()
+{
+ // These threads will release themselves once done
+ Ptr<LocklessTest::Producer> producerThread = *new LocklessTest::Producer;
+ Ptr<LocklessTest::Consumer> consumerThread = *new LocklessTest::Consumer;
+
+ producerThread->Start();
+ consumerThread->Start();
+
+ /*
+ while (!producerThread->IsFinished() && consumerThread->IsFinished())
+ {
+ Thread::MSleep(500);
+ } */
+
+ // TBD: Cleanup
+}
+
+
+} // namespace OVR
+
+#endif // OVR_LOCKLESS_TEST
diff --git a/LibOVR/Src/Kernel/OVR_Lockless.h b/LibOVR/Src/Kernel/OVR_Lockless.h
new file mode 100644
index 0000000..a12f824
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Lockless.h
@@ -0,0 +1,107 @@
+/************************************************************************************
+
+PublicHeader: OVR.h
+Filename : OVR_Lockless.h
+Content : Lock-less classes for producer/consumer communication
+Created : November 9, 2013
+Authors : John Carmack
+
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
+which is provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Lockless_h
+#define OVR_Lockless_h
+
+#include "OVR_Atomic.h"
+
+// Define this to compile-in Lockless test logic
+//#define OVR_LOCKLESS_TEST
+
+namespace OVR {
+
+
+// ***** LocklessUpdater
+
+// For single producer cases where you only care about the most recent update, not
+// necessarily getting every one that happens (vsync timing, SensorFusion updates).
+//
+// This is multiple consumer safe, but is currently only used with a single consumer.
+
+template<class T>
+class LocklessUpdater
+{
+public:
+ LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) {}
+
+ T GetState() const
+ {
+ // Copy the state out, then retry with the alternate slot
+ // if we determine that our copy may have been partially
+ // stepped on by a new update.
+ T state;
+ int begin, end, final;
+
+ for(;;)
+ {
+ // We are adding 0, only using these as atomic memory barriers, so it
+ // is ok to cast off the const, allowing GetState() to remain const.
+ end = UpdateEnd.ExchangeAdd_Sync(0);
+ state = Slots[ end & 1 ];
+ begin = UpdateBegin.ExchangeAdd_Sync(0);
+ if ( begin == end ) {
+ break;
+ }
+
+ // The producer is potentially blocked while only having partially
+ // written the update, so copy out the other slot.
+ state = Slots[ (begin & 1) ^ 1 ];
+ final = UpdateBegin.ExchangeAdd_NoSync(0);
+ if ( final == begin ) {
+ break;
+ }
+
+ // The producer completed the last update and started a new one before
+ // we got it copied out, so try fetching the current buffer again.
+ }
+ return state;
+ }
+
+ void SetState( T state )
+ {
+ const int slot = UpdateBegin.ExchangeAdd_Sync(1) & 1;
+ // Write to (slot ^ 1) because ExchangeAdd returns 'previous' value before add.
+ Slots[slot ^ 1] = state;
+ UpdateEnd.ExchangeAdd_Sync(1);
+ }
+
+ mutable AtomicInt<int> UpdateBegin;
+ mutable AtomicInt<int> UpdateEnd;
+ T Slots[2];
+};
+
+
+#ifdef OVR_LOCKLESS_TEST
+void StartLocklessTest();
+#endif
+
+
+} // namespace OVR
+
+#endif // OVR_Lockless_h
+
diff --git a/LibOVR/Src/Kernel/OVR_Log.cpp b/LibOVR/Src/Kernel/OVR_Log.cpp
index 76b09ad..d5f8a68 100644
--- a/LibOVR/Src/Kernel/OVR_Log.cpp
+++ b/LibOVR/Src/Kernel/OVR_Log.cpp
@@ -5,16 +5,16 @@ Content : Logging support
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Log.h b/LibOVR/Src/Kernel/OVR_Log.h
index 9c6feb6..4d9acc1 100644
--- a/LibOVR/Src/Kernel/OVR_Log.h
+++ b/LibOVR/Src/Kernel/OVR_Log.h
@@ -6,16 +6,16 @@ Content : Logging support
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -108,7 +108,7 @@ public:
virtual ~Log();
// Log formating buffer size used by default LogMessageVarg. Longer strings are truncated.
- enum { MaxLogBufferMessageSize = 2048 };
+ enum { MaxLogBufferMessageSize = 4096 };
unsigned GetLoggingMask() const { return LoggingMask; }
void SetLoggingMask(unsigned logMask) { LoggingMask = logMask; }
diff --git a/LibOVR/Src/Kernel/OVR_Math.cpp b/LibOVR/Src/Kernel/OVR_Math.cpp
index e5a1f0e..396d3ff 100644
--- a/LibOVR/Src/Kernel/OVR_Math.cpp
+++ b/LibOVR/Src/Kernel/OVR_Math.cpp
@@ -5,16 +5,16 @@ Content : Implementation of 3D primitives such as vectors, matrices.
Created : September 4, 2012
Authors : Andrew Reisse, Michael Antonov, Anna Yershova
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -72,83 +72,20 @@ const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal
//-------------------------------------------------------------------------------------
-// ***** Matrix4f
-
-
-Matrix4f Matrix4f::LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up)
-{
- Vector3f z = (eye - at).Normalized(); // Forward
- Vector3f x = up.Cross(z).Normalized(); // Right
- Vector3f y = z.Cross(x);
-
- Matrix4f m(x.x, x.y, x.z, -(x.Dot(eye)),
- y.x, y.y, y.z, -(y.Dot(eye)),
- z.x, z.y, z.z, -(z.Dot(eye)),
- 0, 0, 0, 1 );
- return m;
-}
-
-Matrix4f Matrix4f::LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up)
-{
- Vector3f z = (at - eye).Normalized(); // Forward
- Vector3f x = up.Cross(z).Normalized(); // Right
- Vector3f y = z.Cross(x);
-
- Matrix4f m(x.x, x.y, x.z, -(x.Dot(eye)),
- y.x, y.y, y.z, -(y.Dot(eye)),
- z.x, z.y, z.z, -(z.Dot(eye)),
- 0, 0, 0, 1 );
- return m;
-}
-
-
-Matrix4f Matrix4f::PerspectiveLH(float yfov, float aspect, float znear, float zfar)
-{
- Matrix4f m;
- float tanHalfFov = tan(yfov * 0.5f);
-
- m.M[0][0] = 1.0f / (aspect * tanHalfFov);
- m.M[1][1] = 1.0f / tanHalfFov;
- m.M[2][2] = zfar / (zfar - znear);
- m.M[3][2] = 1.0f;
- m.M[2][3] = (zfar * znear) / (znear - zfar);
- m.M[3][3] = 0.0f;
-
- // Note: Post-projection matrix result assumes Left-Handed coordinate system,
- // with Y up, X right and Z forward. This supports positive z-buffer values.
- return m;
-}
-
-
-Matrix4f Matrix4f::PerspectiveRH(float yfov, float aspect, float znear, float zfar)
-{
- Matrix4f m;
- float tanHalfFov = tan(yfov * 0.5f);
-
- m.M[0][0] = 1.0f / (aspect * tanHalfFov);
- m.M[1][1] = 1.0f / tanHalfFov;
- m.M[2][2] = zfar / (znear - zfar);
- // m.M[2][2] = zfar / (zfar - znear);
- m.M[3][2] = -1.0f;
- m.M[2][3] = (zfar * znear) / (znear - zfar);
- m.M[3][3] = 0.0f;
-
- // Note: Post-projection matrix result assumes Left-Handed coordinate system,
- // with Y up, X right and Z forward. This supports positive z-buffer values.
- // This is the case even for RHS cooridnate input.
- return m;
-}
-
-Matrix4f Matrix4f::Ortho2D(float w, float h)
-{
- Matrix4f m;
- m.M[0][0] = 2.0f/w;
- m.M[1][1] = -2.0f/h;
- m.M[0][3] = -1.0;
- m.M[1][3] = 1.0;
- m.M[2][2] = 0;
- return m;
-}
+// ***** Matrix4
+
+template<>
+const Matrix4<float> Matrix4<float>::IdentityValue = Matrix4<float>(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+
+template<>
+const Matrix4<double> Matrix4<double>::IdentityValue = Matrix4<double>(1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+
} // Namespace OVR
diff --git a/LibOVR/Src/Kernel/OVR_Math.h b/LibOVR/Src/Kernel/OVR_Math.h
index cdcce81..9bd5bad 100644
--- a/LibOVR/Src/Kernel/OVR_Math.h
+++ b/LibOVR/Src/Kernel/OVR_Math.h
@@ -4,18 +4,19 @@ 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, Max Katsev
+Authors : Andrew Reisse, Michael Antonov, Steve LaValle,
+ Anna Yershova, Max Katsev, Dov Katz
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -35,6 +36,8 @@ limitations under the License.
#include "OVR_Types.h"
#include "OVR_RefCount.h"
#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
namespace OVR {
@@ -86,15 +89,85 @@ struct WorldAxes
{ OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
};
+} // namespace OVR
+
+
+//------------------------------------------------------------------------------------//
+// ***** C Compatibility Types
+
+// These declarations are used to support conversion between C types used in
+// LibOVR C interfaces and their C++ versions. As an example, they allow passing
+// Vector3f into a function that expects ovrVector3f.
+
+typedef struct ovrQuatf_ ovrQuatf;
+typedef struct ovrQuatd_ ovrQuatd;
+typedef struct ovrSizei_ ovrSizei;
+typedef struct ovrSizef_ ovrSizef;
+typedef struct ovrRecti_ ovrRecti;
+typedef struct ovrVector2i_ ovrVector2i;
+typedef struct ovrVector2f_ ovrVector2f;
+typedef struct ovrVector3f_ ovrVector3f;
+typedef struct ovrVector3d_ ovrVector3d;
+typedef struct ovrMatrix3d_ ovrMatrix3d;
+typedef struct ovrMatrix4f_ ovrMatrix4f;
+typedef struct ovrPosef_ ovrPosef;
+typedef struct ovrPosed_ ovrPosed;
+typedef struct ovrPoseStatef_ ovrPoseStatef;
+typedef struct ovrPoseStated_ ovrPoseStated;
+
+namespace OVR {
+
+// Forward-declare our templates.
+template<class T> class Quat;
+template<class T> class Size;
+template<class T> class Rect;
+template<class T> class Vector2;
+template<class T> class Vector3;
+template<class T> class Matrix3;
+template<class T> class Matrix4;
+template<class T> class Pose;
+template<class T> class PoseState;
+
+// CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class.
+template<class C>
+struct CompatibleTypes
+{
+ // Declaration here seems necessary for MSVC; specializations are
+ // used instead.
+ typedef float Type;
+};
+
+// Specializations providing CompatibleTypes::Type value.
+template<> struct CompatibleTypes<Quat<float> > { typedef ovrQuatf Type; };
+template<> struct CompatibleTypes<Quat<double> > { typedef ovrQuatd Type; };
+template<> struct CompatibleTypes<Matrix3<double> > { typedef ovrMatrix3d Type; };
+template<> struct CompatibleTypes<Matrix4<float> > { typedef ovrMatrix4f Type; };
+template<> struct CompatibleTypes<Size<int> > { typedef ovrSizei Type; };
+template<> struct CompatibleTypes<Size<float> > { typedef ovrSizef Type; };
+template<> struct CompatibleTypes<Rect<int> > { typedef ovrRecti Type; };
+template<> struct CompatibleTypes<Vector2<int> > { typedef ovrVector2i Type; };
+template<> struct CompatibleTypes<Vector2<float> > { typedef ovrVector2f Type; };
+template<> struct CompatibleTypes<Vector3<float> > { typedef ovrVector3f Type; };
+template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; };
+
+template<> struct CompatibleTypes<Pose<float> > { typedef ovrPosef Type; };
+template<> struct CompatibleTypes<PoseState<float> >{ typedef ovrPoseStatef Type; };
+
+template<> struct CompatibleTypes<Pose<double> > { typedef ovrPosed Type; };
+template<> struct CompatibleTypes<PoseState<double> >{ typedef ovrPoseStated Type; };
//------------------------------------------------------------------------------------//
-// ************************************ 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>
class Math
{
+public:
+ // By default, support explicit conversion to float. This allows Vector2<int> to
+ // compile, for example.
+ typedef float OtherFloatType;
};
// Single-precision Math constants class.
@@ -116,6 +189,9 @@ public:
static const float Tolerance; // 0.00001f;
static const float SingularityRadius; // 0.0000001f for Gimbal lock numerical problems
+
+ // Used to support direct conversions in template classes.
+ typedef double OtherFloatType;
};
// Double-precision Math constants class.
@@ -136,10 +212,12 @@ public:
static const double DegreeToRadFactor;
static const double Tolerance; // 0.00001;
- static const double SingularityRadius; // 0.000000000001 for Gimbal lock numerical problems
+ static const double SingularityRadius; // 0.000000000001 for Gimbal lock numerical problems
+ typedef float OtherFloatType;
};
+
typedef Math<float> Mathf;
typedef Math<double> Mathd;
@@ -172,6 +250,7 @@ inline int isnan(double x) { return _isnan(x); };
template<class T>
class Quat;
+
//-------------------------------------------------------------------------------------
// ***** Vector2<>
@@ -187,7 +266,22 @@ public:
Vector2() : x(0), y(0) { }
Vector2(T x_, T y_) : x(x_), y(y_) { }
explicit Vector2(T s) : x(s), y(s) { }
+ explicit Vector2(const Vector2<typename Math<T>::OtherFloatType> &src)
+ : x((T)src.x), y((T)src.y) { }
+
+ // C-interop support.
+ typedef typename CompatibleTypes<Vector2<T> >::Type CompatibleType;
+
+ Vector2(const CompatibleType& s) : x(s.x), y(s.y) { }
+
+ operator const CompatibleType& () const
+ {
+ OVR_COMPILER_ASSERT(sizeof(Vector2<T>) == sizeof(CompatibleType));
+ return reinterpret_cast<const CompatibleType&>(*this);
+ }
+
+
bool operator== (const Vector2& b) const { return x == b.x && y == b.y; }
bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; }
@@ -207,6 +301,11 @@ public:
x *= rcp; y *= rcp;
return *this; }
+ static Vector2 Min(const Vector2& a, const Vector2& b) { return Vector2((a.x < b.x) ? a.x : b.x,
+ (a.y < b.y) ? a.y : b.y); }
+ static Vector2 Max(const Vector2& a, const Vector2& b) { return Vector2((a.x > b.x) ? a.x : b.x,
+ (a.y > b.y) ? a.y : b.y); }
+
// Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
bool Compare(const Vector2&b, T tolerance = Mathf::Tolerance)
{
@@ -216,10 +315,15 @@ public:
// Entrywise product of two vectors
Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);}
+
+ // Multiply and divide operators do entry-wise math. Used Dot() for dot product.
+ Vector2 operator* (const Vector2& b) const { return Vector2(x * b.x, y * b.y); }
+ Vector2 operator/ (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 Dot(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
@@ -232,9 +336,13 @@ public:
// Return Length of the vector squared.
T LengthSq() const { return (x * x + y * y); }
+
// Return vector length.
T Length() const { return sqrt(LengthSq()); }
+ // Returns squared distance between two points represented by vectors.
+ T DistanceSq(Vector2& b) const { return (*this - b).LengthSq(); }
+
// Returns distance between two points represented by vectors.
T Distance(Vector2& b) const { return (*this - b).Length(); }
@@ -273,7 +381,7 @@ public:
typedef Vector2<float> Vector2f;
typedef Vector2<double> Vector2d;
-
+typedef Vector2<int> Vector2i;
//-------------------------------------------------------------------------------------
// ***** Vector3<> - 3D vector of {x, y, z}
@@ -291,6 +399,20 @@ public:
Vector3() : x(0), y(0), z(0) { }
Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
explicit Vector3(T s) : x(s), y(s), z(s) { }
+ explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src)
+ : x((T)src.x), y((T)src.y), z((T)src.z) { }
+
+
+ // C-interop support.
+ typedef typename CompatibleTypes<Vector3<T> >::Type CompatibleType;
+
+ Vector3(const CompatibleType& s) : x(s.x), y(s.y), z(s.z) { }
+
+ operator const CompatibleType& () const
+ {
+ OVR_COMPILER_ASSERT(sizeof(Vector3<T>) == sizeof(CompatibleType));
+ return reinterpret_cast<const CompatibleType&>(*this);
+ }
bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; }
bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; }
@@ -311,6 +433,19 @@ public:
x *= rcp; y *= rcp; z *= rcp;
return *this; }
+ static Vector3 Min(const Vector3& a, const Vector3& b)
+ {
+ return Vector3((a.x < b.x) ? a.x : b.x,
+ (a.y < b.y) ? a.y : b.y,
+ (a.z < b.z) ? a.z : b.z);
+ }
+ static Vector3 Max(const Vector3& a, const Vector3& b)
+ {
+ return Vector3((a.x > b.x) ? a.x : b.x,
+ (a.y > b.y) ? a.y : b.y,
+ (a.z > b.z) ? a.z : b.z);
+ }
+
// Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance)
{
@@ -319,11 +454,33 @@ public:
(fabs(b.z-z) < tolerance);
}
+ T& operator[] (int idx)
+ {
+ OVR_ASSERT(0 <= idx && idx < 3);
+ return *(&x + idx);
+ }
+
+ const T& operator[] (int idx) const
+ {
+ OVR_ASSERT(0 <= idx && idx < 3);
+ return *(&x + idx);
+ }
+
// Entrywise product of two vectors
Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x,
y * b.y,
z * b.z);}
+ // Multiply and divide operators do entry-wise math
+ Vector3 operator* (const Vector3& b) const { return Vector3(x * b.x,
+ y * b.y,
+ z * b.z); }
+
+ Vector3 operator/ (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).
@@ -347,11 +504,15 @@ public:
// Return Length of the vector squared.
T LengthSq() const { return (x * x + y * y + z * z); }
+
// Return vector length.
T Length() const { return sqrt(LengthSq()); }
+ // Returns squared distance between two points represented by vectors.
+ T DistanceSq(Vector3& b) const { return (*this - b).LengthSq(); }
+
// Returns distance between two points represented by vectors.
- T Distance(Vector3& b) const { return (*this - b).Length(); }
+ T Distance(Vector3 const& b) const { return (*this - b).Length(); }
// Determine if this a unit vector.
bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
@@ -392,6 +553,24 @@ public:
typedef Vector3<float> Vector3f;
typedef Vector3<double> Vector3d;
+typedef Vector3<SInt32> Vector3i;
+
+
+// JDC: this was defined in Render_Device.h, I moved it here, but it
+// needs to be fleshed out like the other Vector types.
+//
+// A vector with a dummy w component for alignment in uniform buffers (and for float colors).
+// The w component is not used in any calculations.
+
+struct Vector4f : public Vector3f
+{
+ float w;
+
+ Vector4f() : w(1) {}
+ Vector4f(const Vector3f& v) : Vector3f(v), w(1) {}
+ Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {}
+};
+
//-------------------------------------------------------------------------------------
@@ -404,34 +583,53 @@ template<class T>
class Size
{
public:
- T Width, Height;
+ T w, h;
+
+ Size() : w(0), h(0) { }
+ Size(T w_, T h_) : w(w_), h(h_) { }
+ explicit Size(T s) : w(s), h(s) { }
+ explicit Size(const Size<typename Math<T>::OtherFloatType> &src)
+ : w((T)src.w), h((T)src.h) { }
+
+ // C-interop support.
+ typedef typename CompatibleTypes<Size<T> >::Type CompatibleType;
- Size() : Width(0), Height(0) { }
- Size(T w_, T h_) : Width(w_), Height(h_) { }
- explicit Size(T s) : Width(s), Height(s) { }
+ Size(const CompatibleType& s) : w(s.w), h(s.h) { }
+
+ operator const CompatibleType& () const
+ {
+ OVR_COMPILER_ASSERT(sizeof(Size<T>) == sizeof(CompatibleType));
+ return reinterpret_cast<const CompatibleType&>(*this);
+ }
- 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; }
+ bool operator== (const Size& b) const { return w == b.w && h == b.h; }
+ bool operator!= (const Size& b) const { return w != b.w || h != b.h; }
- 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; }
+ Size operator+ (const Size& b) const { return Size(w + b.w, h + b.h); }
+ Size& operator+= (const Size& b) { w += b.w; h += b.h; return *this; }
+ Size operator- (const Size& b) const { return Size(w - b.w, h - b.h); }
+ Size& operator-= (const Size& b) { w -= b.w; h -= b.h; return *this; }
+ Size operator- () const { return Size(-w, -h); }
+ Size operator* (const Size& b) const { return Size(w * b.w, h * b.h); }
+ Size& operator*= (const Size& b) { w *= b.w; h *= b.h; return *this; }
+ Size operator/ (const Size& b) const { return Size(w / b.w, h / b.h); }
+ Size& operator/= (const Size& b) { w /= b.w; h /= b.h; 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; }
+ Size operator* (T s) const { return Size(w*s, h*s); }
+ Size& operator*= (T s) { w *= s; h *= s; return *this; }
+ Size operator/ (T s) const { return Size(w/s, h/s); }
+ Size& operator/= (T s) { w /= s; h /= s; return *this; }
+
+ static Size Min(const Size& a, const Size& b) { return Size((a.w < b.w) ? a.w : b.w,
+ (a.h < b.h) ? a.h : b.h); }
+ static Size Max(const Size& a, const Size& b) { return Size((a.w > b.w) ? a.w : b.w,
+ (a.h > b.h) ? a.h : b.h); }
+
- T Area() const { return Width * Height; }
+ T Area() const { return w * h; }
- inline Vector2<T> ToVector() const { return Vector2<T>(Width, Height); }
+ inline Vector2<T> ToVector() const { return Vector2<T>(w, h); }
};
@@ -441,10 +639,494 @@ typedef Size<float> Sizef;
typedef Size<double> Sized;
+
+//-----------------------------------------------------------------------------------
+// ***** Rect
+
+// Rect describes a rectangular area for rendering, that includes position and size.
+template<class T>
+class Rect
+{
+public:
+ T x, y;
+ T w, h;
+
+ Rect() { }
+ Rect(T x1, T y1, T w1, T h1) : x(x1), y(y1), w(w1), h(h1) { }
+ Rect(const Vector2<T>& pos, const Size<T>& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { }
+ Rect(const Size<T>& sz) : x(0), y(0), w(sz.w), h(sz.h) { }
+
+ // C-interop support.
+ typedef typename CompatibleTypes<Rect<T> >::Type CompatibleType;
+
+ Rect(const CompatibleType& s) : x(s.Pos.x), y(s.Pos.y), w(s.Size.w), h(s.Size.h) { }
+
+ operator const CompatibleType& () const
+ {
+ OVR_COMPILER_ASSERT(sizeof(Rect<T>) == sizeof(CompatibleType));
+ return reinterpret_cast<const CompatibleType&>(*this);
+ }
+
+ Vector2<T> GetPos() const { return Vector2<T>(x, y); }
+ Size<T> GetSize() const { return Size<T>(w, h); }
+ void SetPos(const Vector2<T>& pos) { x = pos.x; y = pos.y; }
+ void SetSize(const Size<T>& sz) { w = sz.w; h = sz.h; }
+
+ bool operator == (const Rect& vp) const
+ { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
+ bool operator != (const Rect& vp) const
+ { return !operator == (vp); }
+};
+
+typedef Rect<int> Recti;
+
+
+//-------------------------------------------------------------------------------------//
+// ***** Quat
+//
+// Quatf represents a quaternion class used for rotations.
+//
+// Quaternion multiplications are done in right-to-left order, to match the
+// behavior of matrices.
+
+
+template<class T>
+class Quat
+{
+public:
+ // w + Xi + Yj + Zk
+ T x, y, z, w;
+
+ Quat() : x(0), y(0), z(0), w(1) { }
+ Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
+ explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src)
+ : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
+
+ // C-interop support.
+ Quat(const typename CompatibleTypes<Quat<T> >::Type& s) : x(s.x), y(s.y), z(s.z), w(s.w) { }
+
+ operator const typename CompatibleTypes<Quat<T> >::Type () const
+ {
+ typename CompatibleTypes<Quat<T> >::Type result;
+ result.x = x;
+ result.y = y;
+ result.z = z;
+ result.w = w;
+ return result;
+ }
+
+ // Constructs quaternion for rotation around the axis by an angle.
+ Quat(const Vector3<T>& axis, T angle)
+ {
+ // Make sure we don't divide by zero.
+ if (axis.LengthSq() == 0)
+ {
+ // Assert if the axis is zero, but the angle isn't
+ OVR_ASSERT(angle == 0);
+ x = 0; y = 0; z = 0; w = 1;
+ return;
+ }
+
+ Vector3<T> unitAxis = axis.Normalized();
+ T sinHalfAngle = sin(angle * T(0.5));
+
+ w = cos(angle * T(0.5));
+ x = unitAxis.x * sinHalfAngle;
+ y = unitAxis.y * sinHalfAngle;
+ z = unitAxis.z * sinHalfAngle;
+ }
+
+ // Constructs quaternion for rotation around one of the coordinate axis by an angle.
+ Quat(Axis A, T angle, RotateDirection d = Rotate_CCW, HandedSystem s = Handed_R)
+ {
+ T sinHalfAngle = s * d *sin(angle * T(0.5));
+ T v[3];
+ v[0] = v[1] = v[2] = T(0);
+ v[A] = sinHalfAngle;
+
+ w = cos(angle * T(0.5));
+ x = v[0];
+ y = v[1];
+ z = v[2];
+ }
+
+ // Compute axis and angle from quaternion
+ void GetAxisAngle(Vector3<T>* axis, T* angle) const
+ {
+ if ( x*x + y*y + z*z > Math<T>::Tolerance * Math<T>::Tolerance ) {
+ *axis = Vector3<T>(x, y, z).Normalized();
+ *angle = 2 * Acos(w);
+ if (*angle > Math<T>::Pi) // Reduce the magnitude of the angle, if necessary
+ {
+ *angle = Math<T>::TwoPi - *angle;
+ *axis = *axis * (-1);
+ }
+ }
+ else
+ {
+ *axis = Vector3<T>(1, 0, 0);
+ *angle= 0;
+ }
+ }
+
+ // Constructs the quaternion from a rotation matrix
+ explicit Quat(const Matrix4<T>& m)
+ {
+ T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
+
+ // 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
+ w = T(0.25) * s;
+ x = (m.M[2][1] - m.M[1][2]) / s;
+ y = (m.M[0][2] - m.M[2][0]) / s;
+ 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);
+ w = (m.M[2][1] - m.M[1][2]) / s;
+ x = T(0.25) * s;
+ y = (m.M[0][1] + m.M[1][0]) / s;
+ 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
+ w = (m.M[0][2] - m.M[2][0]) / s;
+ x = (m.M[0][1] + m.M[1][0]) / s;
+ y = T(0.25) * s;
+ 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
+ w = (m.M[1][0] - m.M[0][1]) / s;
+ x = (m.M[0][2] + m.M[2][0]) / s;
+ y = (m.M[1][2] + m.M[2][1]) / s;
+ z = T(0.25) * s;
+ }
+ }
+
+ // Constructs the quaternion from a rotation matrix
+ explicit Quat(const Matrix3<T>& m)
+ {
+ T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
+
+ // 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
+ w = T(0.25) * s;
+ x = (m.M[2][1] - m.M[1][2]) / s;
+ y = (m.M[0][2] - m.M[2][0]) / s;
+ 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);
+ w = (m.M[2][1] - m.M[1][2]) / s;
+ x = T(0.25) * s;
+ y = (m.M[0][1] + m.M[1][0]) / s;
+ 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
+ w = (m.M[0][2] - m.M[2][0]) / s;
+ x = (m.M[0][1] + m.M[1][0]) / s;
+ y = T(0.25) * s;
+ 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
+ w = (m.M[1][0] - m.M[0][1]) / s;
+ x = (m.M[0][2] + m.M[2][0]) / s;
+ y = (m.M[1][2] + m.M[2][1]) / s;
+ z = T(0.25) * s;
+ }
+ }
+
+ bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; }
+ bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; }
+
+ Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
+ Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
+ Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
+ Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
+
+ Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); }
+ Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; }
+ 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); }
+
+ // Get quaternion length.
+ T Length() const { return sqrt(LengthSq()); }
+
+ // Get quaternion length squared.
+ T LengthSq() const { return (x * x + y * y + z * z + w * w); }
+
+ // Simple Euclidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
+ T Distance(const Quat& q) const
+ {
+ T d1 = (*this - q).Length();
+ 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(); // Antipodal point check
+ return (d1 < d2) ? d1 : d2;
+ }
+
+ T Dot(const Quat& q) const
+ {
+ return x * q.x + y * q.y + z * q.z + w * q.w;
+ }
+
+ // Angle between two quaternions in radians
+ T Angle(const Quat& q) const
+ {
+ return 2 * Acos(Alg::Abs(Dot(q)));
+ }
+
+ // Normalize
+ 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); }
+
+ // 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,
+ w * b.y - x * b.z + y * b.w + z * b.x,
+ w * b.z + x * b.y - y * b.x + z * b.w,
+ w * b.w - x * b.x - y * b.y - z * b.z); }
+
+ //
+ // this^p normalized; same as rotating by this p times.
+ Quat PowNormalized(T p) const
+ {
+ Vector3<T> v;
+ T a;
+ GetAxisAngle(&v, &a);
+ return Quat(v, a * p);
+ }
+
+ // Normalized linear interpolation of quaternions
+ Quat Nlerp(const Quat& other, T a)
+ {
+ T sign = (Dot(other) >= 0) ? 1 : -1;
+ return (*this * sign * a + other * (1-a)).Normalized();
+ }
+
+ // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
+ // 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, T(0))) * Inverted()).Imag();
+ }
+
+ // Inversed quaternion rotates in the opposite direction.
+ Quat Inverted() const
+ {
+ return Quat(-x, -y, -z, w);
+ }
+
+ // Sets this quaternion to the one rotates in the opposite direction.
+ void Invert()
+ {
+ *this = Quat(-x, -y, -z, w);
+ }
+
+ // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
+ // axis rotations and the specified coordinate system. Right-handed coordinate system
+ // is the default, with CCW rotations while looking in the negative axis direction.
+ // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
+ // rotation a around axis A1
+ // is followed by rotation b around axis A2
+ // is followed by rotation c around axis A3
+ // rotations are CCW or CW (D) in LH or RH coordinate system (S)
+ template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
+ void GetEulerAngles(T *a, T *b, T *c) const
+ {
+ OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
+
+ T Q[3] = { x, y, z }; //Quaternion components x,y,z
+
+ T ww = w*w;
+ T Q11 = Q[A1]*Q[A1];
+ T Q22 = Q[A2]*Q[A2];
+ T Q33 = Q[A3]*Q[A3];
+
+ T psign = T(-1);
+ // Determine whether even permutation
+ if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
+ psign = T(1);
+
+ T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
+
+ if (s2 < T(-1) + Math<T>::SingularityRadius)
+ { // South pole singularity
+ *a = T(0);
+ *b = -S*D*Math<T>::PiOver2;
+ *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
+ ww + Q22 - Q11 - Q33 );
+ }
+ else if (s2 > T(1) - Math<T>::SingularityRadius)
+ { // North pole singularity
+ *a = T(0);
+ *b = S*D*Math<T>::PiOver2;
+ *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)*(w*Q[A1] - psign*Q[A2]*Q[A3]),
+ ww + Q33 - Q11 - Q22);
+ *b = S*D*asin(s2);
+ *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]),
+ ww + Q11 - Q22 - Q33);
+ }
+ return;
+ }
+
+ template <Axis A1, Axis A2, Axis A3, RotateDirection D>
+ void GetEulerAngles(T *a, T *b, T *c) const
+ { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
+
+ template <Axis A1, Axis A2, Axis A3>
+ void GetEulerAngles(T *a, T *b, T *c) const
+ { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
+
+
+ // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
+ // axis rotations and the specified coordinate system. Right-handed coordinate system
+ // is the default, with CCW rotations while looking in the negative axis direction.
+ // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
+ // rotation a around axis A1
+ // is followed by rotation b around axis A2
+ // is followed by rotation c around axis A1
+ // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
+ template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
+ void GetEulerAnglesABA(T *a, T *b, T *c) const
+ {
+ OVR_COMPILER_ASSERT(A1 != A2);
+
+ T Q[3] = {x, y, z}; // Quaternion components
+
+ // Determine the missing axis that was not supplied
+ int m = 3 - A1 - A2;
+
+ T ww = w*w;
+ T Q11 = Q[A1]*Q[A1];
+ T Q22 = Q[A2]*Q[A2];
+ T Qmm = Q[m]*Q[m];
+
+ T psign = T(-1);
+ if ((A1 + 1) % 3 == A2) // Determine whether even permutation
+ {
+ psign = T(1);
+ }
+
+ T c2 = ww + Q11 - Q22 - Qmm;
+ if (c2 < T(-1) + Math<T>::SingularityRadius)
+ { // South pole singularity
+ *a = T(0);
+ *b = S*D*Math<T>::Pi;
+ *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
+ ww + Q22 - Q11 - Qmm);
+ }
+ else if (c2 > T(1) - Math<T>::SingularityRadius)
+ { // North pole singularity
+ *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
+ {
+ *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
+ w*Q[A2] -psign*Q[A1]*Q[m]);
+ *b = S*D*acos(c2);
+ *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
+ w*Q[A2] + psign*Q[A1]*Q[m]);
+ }
+ return;
+ }
+};
+
+typedef Quat<float> Quatf;
+typedef Quat<double> Quatd;
+
//-------------------------------------------------------------------------------------
-// ***** Matrix4f
+// ***** Pose
+
+// Position and orientation combined.
+
+template<class T>
+class Pose
+{
+public:
+
+ typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType;
+
+ Pose() { }
+ Pose(const Quat<T>& orientation, const Vector3<T>& pos)
+ : Orientation(orientation), Position(pos) { }
+ Pose(const Pose& s)
+ : Orientation(s.Orientation), Position(s.Position) { }
+ Pose(const CompatibleType& s)
+ : Orientation(s.Orientation), Position(s.Position) { }
+ explicit Pose(const Pose<typename Math<T>::OtherFloatType> &s)
+ : Orientation(s.Orientation), Position(s.Position) { }
+
+ operator const typename CompatibleTypes<Pose<T> >::Type () const
+ {
+ typename CompatibleTypes<Pose<T> >::Type result;
+ result.Orientation = Orientation;
+ result.Position = Position;
+ return result;
+ }
+
+ Quat<T> Orientation;
+ Vector3<T> Position;
+};
+
+typedef Pose<float> Posef;
+typedef Pose<double> Posed;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Matrix4
//
-// Matrix4f is a 4x4 matrix used for 3d transformations and projections.
+// Matrix4 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
// of the first row are stored before the next one.
@@ -469,28 +1151,29 @@ typedef Size<double> Sized;
//
// The basis vectors are first three columns.
-class Matrix4f
+template<class T>
+class Matrix4
{
- static Matrix4f IdentityValue;
+ static const Matrix4 IdentityValue;
public:
- float M[4][4];
+ T M[4][4];
enum NoInitType { NoInit };
// Construct with no memory initialization.
- Matrix4f(NoInitType) { }
+ Matrix4(NoInitType) { }
// By default, we construct identity matrix.
- Matrix4f()
+ Matrix4()
{
SetIdentity();
}
- Matrix4f(float m11, float m12, float m13, float m14,
- float m21, float m22, float m23, float m24,
- float m31, float m32, float m33, float m34,
- float m41, float m42, float m43, float m44)
+ Matrix4(T m11, T m12, T m13, T m14,
+ T m21, T m22, T m23, T m24,
+ T m31, T m32, T m33, T m34,
+ T m41, T m42, T m43, T m44)
{
M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
@@ -498,9 +1181,9 @@ public:
M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
}
- Matrix4f(float m11, float m12, float m13,
- float m21, float m22, float m23,
- float m31, float m32, float m33)
+ Matrix4(T m11, T m12, T m13,
+ T m21, T m22, T m23,
+ T m31, T m32, T m33)
{
M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
@@ -508,7 +1191,50 @@ public:
M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
}
- void ToString(char* dest, UPInt destsize)
+ explicit Matrix4(const Quat<T>& q)
+ {
+ T ww = q.w*q.w;
+ T xx = q.x*q.x;
+ T yy = q.y*q.y;
+ T zz = q.z*q.z;
+
+ M[0][0] = ww + xx - yy - zz; M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y); M[0][3] = 0;
+ M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz; M[1][2] = 2 * (q.y*q.z - q.w*q.x); M[1][3] = 0;
+ M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz; M[2][3] = 0;
+ M[3][0] = 0; M[3][1] = 0; M[3][2] = 0; M[3][3] = 1;
+ }
+
+ explicit Matrix4(const Pose<T>& p)
+ {
+ Matrix4 result(p.Orientation);
+ result.SetTranslation(p.Position);
+ *this = result;
+ }
+
+ // C-interop support
+ explicit Matrix4(const Matrix4<typename Math<T>::OtherFloatType> &src)
+ {
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ M[i][j] = (T)src.M[i][j];
+ }
+
+ // C-interop support.
+ Matrix4(const typename CompatibleTypes<Matrix4<T> >::Type& s)
+ {
+ OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix4));
+ memcpy(M, s.M, sizeof(M));
+ }
+
+ operator const typename CompatibleTypes<Matrix4<T> >::Type () const
+ {
+ typename CompatibleTypes<Matrix4<T> >::Type result;
+ OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix4));
+ memcpy(result.M, M, sizeof(M));
+ return result;
+ }
+
+ void ToString(char* dest, UPInt destsize) const
{
UPInt pos = 0;
for (int r=0; r<4; r++)
@@ -516,13 +1242,13 @@ public:
pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
}
- static Matrix4f FromString(const char* src)
+ static Matrix4 FromString(const char* src)
{
- Matrix4f result;
+ Matrix4 result;
for (int r=0; r<4; r++)
for (int c=0; c<4; c++)
{
- result.M[r][c] = (float)atof(src);
+ result.M[r][c] = (T)atof(src);
while (src && *src != ' ')
src++;
while (src && *src == ' ')
@@ -531,7 +1257,7 @@ public:
return result;
}
- static const Matrix4f& Identity() { return IdentityValue; }
+ static const Matrix4& Identity() { return IdentityValue; }
void SetIdentity()
{
@@ -541,14 +1267,24 @@ public:
M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
}
- Matrix4f operator+ (const Matrix4f& b) const
+ bool operator== (const Matrix4& b) const
+ {
+ bool isEqual = true;
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ isEqual &= (M[i][j] == b.M[i][j]);
+
+ return isEqual;
+ }
+
+ Matrix4 operator+ (const Matrix4& b) const
{
- Matrix4f result(*this);
+ Matrix4 result(*this);
result += b;
return result;
}
- Matrix4f& operator+= (const Matrix4f& b)
+ Matrix4& operator+= (const Matrix4& b)
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
@@ -556,14 +1292,14 @@ public:
return *this;
}
- Matrix4f operator- (const Matrix4f& b) const
+ Matrix4 operator- (const Matrix4& b) const
{
- Matrix4f result(*this);
+ Matrix4 result(*this);
result -= b;
return result;
}
- Matrix4f& operator-= (const Matrix4f& b)
+ Matrix4& operator-= (const Matrix4& b)
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
@@ -572,7 +1308,7 @@ public:
}
// Multiplies two matrices into destination with minimum copying.
- static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b)
+ static Matrix4& Multiply(Matrix4* d, const Matrix4& a, const Matrix4& b)
{
OVR_ASSERT((d != &a) && (d != &b));
int i = 0;
@@ -586,26 +1322,26 @@ public:
return *d;
}
- Matrix4f operator* (const Matrix4f& b) const
+ Matrix4 operator* (const Matrix4& b) const
{
- Matrix4f result(Matrix4f::NoInit);
+ Matrix4 result(Matrix4::NoInit);
Multiply(&result, *this, b);
return result;
}
- Matrix4f& operator*= (const Matrix4f& b)
+ Matrix4& operator*= (const Matrix4& b)
{
- return Multiply(this, Matrix4f(*this), b);
+ return Multiply(this, Matrix4(*this), b);
}
- Matrix4f operator* (float s) const
+ Matrix4 operator* (T s) const
{
- Matrix4f result(*this);
+ Matrix4 result(*this);
result *= s;
return result;
}
- Matrix4f& operator*= (float s)
+ Matrix4& operator*= (T s)
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
@@ -614,14 +1350,14 @@ public:
}
- Matrix4f operator/ (float s) const
+ Matrix4 operator/ (T s) const
{
- Matrix4f result(*this);
+ Matrix4 result(*this);
result /= s;
return result;
}
- Matrix4f& operator/= (float s)
+ Matrix4& operator/= (T s)
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
@@ -629,16 +1365,16 @@ public:
return *this;
}
- Vector3f Transform(const Vector3f& v) const
+ Vector3<T> Transform(const Vector3<T>& v) const
{
- return Vector3f(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3],
- M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3],
- M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]);
+ return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3],
+ M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3],
+ M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]);
}
- Matrix4f Transposed() const
+ Matrix4 Transposed() const
{
- return Matrix4f(M[0][0], M[1][0], M[2][0], M[3][0],
+ return Matrix4(M[0][0], M[1][0], M[2][0], M[3][0],
M[0][1], M[1][1], M[2][1], M[3][1],
M[0][2], M[1][2], M[2][2], M[3][2],
M[0][3], M[1][3], M[2][3], M[3][3]);
@@ -650,35 +1386,35 @@ public:
}
- float SubDet (const UPInt* rows, const UPInt* cols) const
+ T 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(UPInt I, UPInt J) const
+ T Cofactor(UPInt I, UPInt J) const
{
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]);
}
- float Determinant() const
+ T Determinant() const
{
return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3);
}
- Matrix4f Adjugated() const
+ Matrix4 Adjugated() const
{
- return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0),
+ return Matrix4(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0),
Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1),
Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
}
- Matrix4f Inverted() const
+ Matrix4 Inverted() const
{
- float det = Determinant();
+ T det = Determinant();
assert(det != 0);
return Adjugated() * (1.0f/det);
}
@@ -690,14 +1426,14 @@ public:
// This is more efficient than general inverse, but ONLY works
// correctly if it is a homogeneous transform matrix (rot + trans)
- Matrix4f InvertedHomogeneousTransform() const
+ Matrix4 InvertedHomogeneousTransform() const
{
// Make the inverse rotation matrix
- Matrix4f rinv = this->Transposed();
+ Matrix4 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);
+ Vector3<T> tvinv(-M[0][3],-M[1][3],-M[2][3]);
+ Matrix4 tinv = Matrix4::Translation(tvinv);
return rinv * tinv; // "untranslate", then "unrotate"
}
@@ -715,25 +1451,25 @@ public:
// is followed by rotation c around axis A3
// rotations are CCW or CW (D) in LH or RH coordinate system (S)
template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
- void ToEulerAngles(float *a, float *b, float *c)
+ void ToEulerAngles(T *a, T *b, T *c)
{
OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
- float psign = -1.0f;
+ T psign = -1;
if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
- psign = 1.0f;
+ psign = 1;
- float pm = psign*M[A1][A3];
- if (pm < -1.0f + Math<float>::SingularityRadius)
+ T pm = psign*M[A1][A3];
+ if (pm < -1.0f + Math<T>::SingularityRadius)
{ // South pole singularity
- *a = 0.0f;
- *b = -S*D*Math<float>::PiOver2;
+ *a = 0;
+ *b = -S*D*Math<T>::PiOver2;
*c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
}
- else if (pm > 1.0f - Math<float>::SingularityRadius)
+ else if (pm > 1.0f - Math<T>::SingularityRadius)
{ // North pole singularity
- *a = 0.0f;
- *b = S*D*Math<float>::PiOver2;
+ *a = 0;
+ *b = S*D*Math<T>::PiOver2;
*c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
}
else
@@ -753,28 +1489,28 @@ public:
// is followed by rotation c around axis A1
// rotations are CCW or CW (D) in LH or RH coordinate system (S)
template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
- void ToEulerAnglesABA(float *a, float *b, float *c)
+ void ToEulerAnglesABA(T *a, T *b, T *c)
{
OVR_COMPILER_ASSERT(A1 != A2);
// Determine the axis that was not supplied
int m = 3 - A1 - A2;
- float psign = -1.0f;
+ T psign = -1;
if ((A1 + 1) % 3 == A2) // Determine whether even permutation
psign = 1.0f;
- float c2 = M[A1][A1];
- if (c2 < -1.0f + Math<float>::SingularityRadius)
+ T c2 = M[A1][A1];
+ if (c2 < -1 + Math<T>::SingularityRadius)
{ // South pole singularity
- *a = 0.0f;
- *b = S*D*Math<float>::Pi;
+ *a = 0;
+ *b = S*D*Math<T>::Pi;
*c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
}
- else if (c2 > 1.0f - Math<float>::SingularityRadius)
+ else if (c2 > 1.0f - Math<T>::SingularityRadius)
{ // North pole singularity
- *a = 0.0f;
- *b = 0.0f;
+ *a = 0;
+ *b = 0;
*c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
}
else
@@ -788,7 +1524,7 @@ public:
// Creates a matrix that converts the vertices from one coordinate system
// to another.
- static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from)
+ static Matrix4 AxisConversion(const WorldAxes& to, const WorldAxes& from)
{
// Holds axis values from the 'to' structure
int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
@@ -799,22 +1535,22 @@ public:
inv[abs(to.YAxis)] = 1;
inv[abs(to.ZAxis)] = 2;
- Matrix4f m(0, 0, 0,
- 0, 0, 0,
- 0, 0, 0);
+ Matrix4 m(0, 0, 0,
+ 0, 0, 0,
+ 0, 0, 0);
// Only three values in the matrix need to be changed to 1 or -1.
- m.M[inv[abs(from.XAxis)]][0] = float(from.XAxis/toArray[inv[abs(from.XAxis)]]);
- m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]);
- m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
+ m.M[inv[abs(from.XAxis)]][0] = T(from.XAxis/toArray[inv[abs(from.XAxis)]]);
+ m.M[inv[abs(from.YAxis)]][1] = T(from.YAxis/toArray[inv[abs(from.YAxis)]]);
+ m.M[inv[abs(from.ZAxis)]][2] = T(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
return m;
}
// Creates a matrix for translation by vector
- static Matrix4f Translation(const Vector3f& v)
+ static Matrix4 Translation(const Vector3<T>& v)
{
- Matrix4f t;
+ Matrix4 t;
t.M[0][3] = v.x;
t.M[1][3] = v.y;
t.M[2][3] = v.z;
@@ -822,19 +1558,32 @@ public:
}
// Creates a matrix for translation by vector
- static Matrix4f Translation(float x, float y, float z = 0.0f)
+ static Matrix4 Translation(T x, T y, T z = 0.0f)
{
- Matrix4f t;
+ Matrix4 t;
t.M[0][3] = x;
t.M[1][3] = y;
t.M[2][3] = z;
return t;
}
+ // Sets the translation part
+ void SetTranslation(const Vector3<T>& v)
+ {
+ M[0][3] = v.x;
+ M[1][3] = v.y;
+ M[2][3] = v.z;
+ }
+
+ Vector3<T> GetTranslation() const
+ {
+ return Vector3<T>( M[0][3], M[1][3], M[2][3] );
+ }
+
// Creates a matrix for scaling by vector
- static Matrix4f Scaling(const Vector3f& v)
+ static Matrix4 Scaling(const Vector3<T>& v)
{
- Matrix4f t;
+ Matrix4 t;
t.M[0][0] = v.x;
t.M[1][1] = v.y;
t.M[2][2] = v.z;
@@ -842,9 +1591,9 @@ public:
}
// Creates a matrix for scaling by vector
- static Matrix4f Scaling(float x, float y, float z)
+ static Matrix4 Scaling(T x, T y, T z)
{
- Matrix4f t;
+ Matrix4 t;
t.M[0][0] = x;
t.M[1][1] = y;
t.M[2][2] = z;
@@ -852,38 +1601,50 @@ public:
}
// Creates a matrix for scaling by constant
- static Matrix4f Scaling(float s)
+ static Matrix4 Scaling(T s)
{
- Matrix4f t;
+ Matrix4 t;
t.M[0][0] = s;
t.M[1][1] = s;
t.M[2][2] = s;
return t;
}
-
+ // Simple L1 distance in R^12
+ T Distance(const Matrix4& m2) const
+ {
+ T d = fabs(M[0][0] - m2.M[0][0]) + fabs(M[0][1] - m2.M[0][1]);
+ d += fabs(M[0][2] - m2.M[0][2]) + fabs(M[0][3] - m2.M[0][3]);
+ d += fabs(M[1][0] - m2.M[1][0]) + fabs(M[1][1] - m2.M[1][1]);
+ d += fabs(M[1][2] - m2.M[1][2]) + fabs(M[1][3] - m2.M[1][3]);
+ d += fabs(M[2][0] - m2.M[2][0]) + fabs(M[2][1] - m2.M[2][1]);
+ d += fabs(M[2][2] - m2.M[2][2]) + fabs(M[2][3] - m2.M[2][3]);
+ d += fabs(M[3][0] - m2.M[3][0]) + fabs(M[3][1] - m2.M[3][1]);
+ d += fabs(M[3][2] - m2.M[3][2]) + fabs(M[3][3] - m2.M[3][3]);
+ return d;
+ }
// 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)
+ static Matrix4 RotationAxis(Axis A, T angle, RotateDirection d, HandedSystem s)
{
- float sina = s * d *sin(angle);
- float cosa = cos(angle);
+ T sina = s * d *sin(angle);
+ T cosa = cos(angle);
switch(A)
{
case Axis_X:
- return Matrix4f(1, 0, 0,
- 0, cosa, -sina,
- 0, sina, cosa);
+ return Matrix4(1, 0, 0,
+ 0, cosa, -sina,
+ 0, sina, cosa);
case Axis_Y:
- return Matrix4f(cosa, 0, sina,
- 0, 1, 0,
- -sina, 0, cosa);
+ return Matrix4(cosa, 0, sina,
+ 0, 1, 0,
+ -sina, 0, cosa);
case Axis_Z:
- return Matrix4f(cosa, -sina, 0,
- sina, cosa, 0,
- 0, 0, 1);
+ return Matrix4(cosa, -sina, 0,
+ sina, cosa, 0,
+ 0, 0, 1);
}
}
@@ -895,13 +1656,13 @@ public:
// same as looking down from positive axis values towards origin.
// LHS: Positive angle values rotate clock-wise (CW), while looking in the
// negative axis direction.
- static Matrix4f RotationX(float angle)
+ static Matrix4 RotationX(T angle)
{
- float sina = sin(angle);
- float cosa = cos(angle);
- return Matrix4f(1, 0, 0,
- 0, cosa, -sina,
- 0, sina, cosa);
+ T sina = sin(angle);
+ T cosa = cos(angle);
+ return Matrix4(1, 0, 0,
+ 0, cosa, -sina,
+ 0, sina, cosa);
}
// Creates a rotation matrix rotating around the Y axis by 'angle' radians.
@@ -911,13 +1672,13 @@ public:
// same as looking down from positive axis values towards origin.
// LHS: Positive angle values rotate clock-wise (CW), while looking in the
// negative axis direction.
- static Matrix4f RotationY(float angle)
+ static Matrix4 RotationY(T angle)
{
- float sina = sin(angle);
- float cosa = cos(angle);
- return Matrix4f(cosa, 0, sina,
- 0, 1, 0,
- -sina, 0, cosa);
+ T sina = sin(angle);
+ T cosa = cos(angle);
+ return Matrix4(cosa, 0, sina,
+ 0, 1, 0,
+ -sina, 0, cosa);
}
// Creates a rotation matrix rotating around the Z axis by 'angle' radians.
@@ -927,27 +1688,47 @@ public:
// same as looking down from positive axis values towards origin.
// LHS: Positive angle values rotate clock-wise (CW), while looking in the
// negative axis direction.
- static Matrix4f RotationZ(float angle)
+ static Matrix4 RotationZ(T angle)
{
- float sina = sin(angle);
- float cosa = cos(angle);
- return Matrix4f(cosa, -sina, 0,
- sina, cosa, 0,
- 0, 0, 1);
+ T sina = sin(angle);
+ T cosa = cos(angle);
+ return Matrix4(cosa, -sina, 0,
+ sina, cosa, 0,
+ 0, 0, 1);
}
-
// LookAtRH creates a View transformation matrix for right-handed coordinate system.
// The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
// specifying the up vector. The resulting matrix should be used with PerspectiveRH
// projection.
- static Matrix4f LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
-
+ static Matrix4 LookAtRH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
+ {
+ Vector3<T> z = (eye - at).Normalized(); // Forward
+ Vector3<T> x = up.Cross(z).Normalized(); // Right
+ Vector3<T> y = z.Cross(x);
+
+ Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)),
+ y.x, y.y, y.z, -(y.Dot(eye)),
+ z.x, z.y, z.z, -(z.Dot(eye)),
+ 0, 0, 0, 1 );
+ return m;
+ }
+
// LookAtLH creates a View transformation matrix for left-handed coordinate system.
// The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
// specifying the up vector.
- static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
-
+ static Matrix4 LookAtLH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
+ {
+ Vector3<T> z = (at - eye).Normalized(); // Forward
+ Vector3<T> x = up.Cross(z).Normalized(); // Right
+ Vector3<T> y = z.Cross(x);
+
+ Matrix4 m(x.x, x.y, x.z, -(x.Dot(eye)),
+ y.x, y.y, y.z, -(y.Dot(eye)),
+ z.x, z.y, z.z, -(z.Dot(eye)),
+ 0, 0, 0, 1 );
+ return m;
+ }
// PerspectiveRH creates a right-handed perspective projection matrix that can be
// used with the Oculus sample renderer.
@@ -958,8 +1739,22 @@ public:
// zfar - Absolute value of far Z clipping clipping range (larger then near).
// Even though RHS usually looks in the direction of negative Z, positive values
// are expected for znear and zfar.
- static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar);
-
+ static Matrix4 PerspectiveRH(T yfov, T aspect, T znear, T zfar)
+ {
+ Matrix4 m;
+ T tanHalfFov = tan(yfov * 0.5f);
+
+ m.M[0][0] = 1 / (aspect * tanHalfFov);
+ m.M[1][1] = 1 / tanHalfFov;
+ m.M[2][2] = zfar / (zfar - znear);
+ m.M[3][2] = 1;
+ m.M[2][3] = (zfar * znear) / (znear - zfar);
+ m.M[3][3] = 0;
+
+ // Note: Post-projection matrix result assumes Left-Handed coordinate system,
+ // with Y up, X right and Z forward. This supports positive z-buffer values.
+ return m;
+ }
// PerspectiveRH creates a left-handed perspective projection matrix that can be
// used with the Oculus sample renderer.
@@ -968,350 +1763,601 @@ public:
// Note that xfov = yfov * aspect.
// znear - Absolute value of near Z clipping clipping range.
// zfar - Absolute value of far Z clipping clipping range (larger then near).
- static Matrix4f PerspectiveLH(float yfov, float aspect, float znear, float zfar);
-
+ static Matrix4 PerspectiveLH(T yfov, T aspect, T znear, T zfar)
+ {
+ Matrix4 m;
+ T tanHalfFov = tan(yfov * 0.5f);
+
+ m.M[0][0] = 1.0 / (aspect * tanHalfFov);
+ m.M[1][1] = 1.0 / tanHalfFov;
+ m.M[2][2] = zfar / (znear - zfar);
+ // m.M[2][2] = zfar / (zfar - znear);
+ m.M[3][2] = -1.0;
+ m.M[2][3] = (zfar * znear) / (znear - zfar);
+ m.M[3][3] = 0.0;
+
+ // Note: Post-projection matrix result assumes Left-Handed coordinate system,
+ // with Y up, X right and Z forward. This supports positive z-buffer values.
+ // This is the case even for RHS cooridnate input.
+ return m;
+ }
- static Matrix4f Ortho2D(float w, float h);
+ static Matrix4 Ortho2D(T w, T h)
+ {
+ Matrix4 m;
+ m.M[0][0] = 2.0/w;
+ m.M[1][1] = -2.0/h;
+ m.M[0][3] = -1.0;
+ m.M[1][3] = 1.0;
+ m.M[2][2] = 0;
+ return m;
+ }
};
+typedef Matrix4<float> Matrix4f;
+typedef Matrix4<double> Matrix4d;
-//-------------------------------------------------------------------------------------//
-// **************************************** Quat **************************************//
+//-------------------------------------------------------------------------------------
+// ***** Matrix3
//
-// Quatf represents a quaternion class used for rotations.
-//
-// Quaternion multiplications are done in right-to-left order, to match the
-// behavior of matrices.
+// Matrix3 is a 3x3 matrix used for representing a rotation matrix.
+// The matrix is stored in row-major order in memory, meaning that values
+// of the first row are stored before the next one.
+//
+// The arrangement of the matrix is chosen to be in Right-Handed
+// coordinate system and counterclockwise rotations when looking down
+// the axis
+//
+// Transformation Order:
+// - Transformations are applied from right to left, so the expression
+// M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
+// followed by M2 and M1.
+//
+// Coordinate system: Right Handed
+//
+// Rotations: Counterclockwise when looking down the axis. All angles are in radians.
+template<typename T>
+class SymMat3;
template<class T>
-class Quat
+class Matrix3
{
+ static const Matrix3 IdentityValue;
+
public:
- // w + Xi + Yj + Zk
- T x, y, z, w;
+ T M[3][3];
- Quat() : x(0), y(0), z(0), w(1) {}
- Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {}
+ enum NoInitType { NoInit };
+ // Construct with no memory initialization.
+ Matrix3(NoInitType) { }
- // Constructs quaternion for rotation around the axis by an angle.
- Quat(const Vector3<T>& axis, T angle)
- {
- Vector3<T> unitAxis = axis.Normalized();
- T sinHalfAngle = sin(angle * T(0.5));
+ // By default, we construct identity matrix.
+ Matrix3()
+ {
+ SetIdentity();
+ }
- w = cos(angle * T(0.5));
- x = unitAxis.x * sinHalfAngle;
- y = unitAxis.y * sinHalfAngle;
- z = unitAxis.z * sinHalfAngle;
+ Matrix3(T m11, T m12, T m13,
+ T m21, T m22, T m23,
+ T m31, T m32, T m33)
+ {
+ M[0][0] = m11; M[0][1] = m12; M[0][2] = m13;
+ M[1][0] = m21; M[1][1] = m22; M[1][2] = m23;
+ M[2][0] = m31; M[2][1] = m32; M[2][2] = m33;
+ }
+
+ /*
+ explicit Matrix3(const Quat<T>& q)
+ {
+ T ww = q.w*q.w;
+ T xx = q.x*q.x;
+ T yy = q.y*q.y;
+ T zz = q.z*q.z;
+
+ M[0][0] = ww + xx - yy - zz; M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y);
+ M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz; M[1][2] = 2 * (q.y*q.z - q.w*q.x);
+ M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;
+ }
+ */
+
+ explicit Matrix3(const Quat<T>& q)
+ {
+ const T tx = q.x+q.x, ty = q.y+q.y, tz = q.z+q.z;
+ const T twx = q.w*tx, twy = q.w*ty, twz = q.w*tz;
+ const T txx = q.x*tx, txy = q.x*ty, txz = q.x*tz;
+ const T tyy = q.y*ty, tyz = q.y*tz, tzz = q.z*tz;
+ M[0][0] = T(1) - (tyy + tzz); M[0][1] = txy - twz; M[0][2] = txz + twy;
+ M[1][0] = txy + twz; M[1][1] = T(1) - (txx + tzz); M[1][2] = tyz - twx;
+ M[2][0] = txz - twy; M[2][1] = tyz + twx; M[2][2] = T(1) - (txx + tyy);
+ }
+
+ inline explicit Matrix3(T s)
+ {
+ M[0][0] = M[1][1] = M[2][2] = s;
+ M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0;
}
- // 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 v[3];
- v[0] = v[1] = v[2] = T(0);
- v[A] = sinHalfAngle;
+ explicit Matrix3(const Pose<T>& p)
+ {
+ Matrix3 result(p.Orientation);
+ result.SetTranslation(p.Position);
+ *this = result;
+ }
- w = cos(angle * T(0.5));
- x = v[0];
- y = v[1];
- z = v[2];
- }
+ // C-interop support
+ explicit Matrix3(const Matrix4<typename Math<T>::OtherFloatType> &src)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] = (T)src.M[i][j];
+ }
+ // C-interop support.
+ Matrix3(const typename CompatibleTypes<Matrix3<T> >::Type& s)
+ {
+ OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix3));
+ memcpy(M, s.M, sizeof(M));
+ }
- // Compute axis and angle from quaternion
- void GetAxisAngle(Vector3<T>* axis, T* angle) const
- {
- 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;
- }
- }
+ operator const typename CompatibleTypes<Matrix3<T> >::Type () const
+ {
+ typename CompatibleTypes<Matrix3<T> >::Type result;
+ OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix3));
+ memcpy(result.M, M, sizeof(M));
+ return result;
+ }
- bool operator== (const Quat& b) const { return x == b.x && y == b.y && z == b.z && w == b.w; }
- bool operator!= (const Quat& b) const { return x != b.x || y != b.y || z != b.z || w != b.w; }
+ void ToString(char* dest, UPInt destsize) const
+ {
+ UPInt pos = 0;
+ for (int r=0; r<3; r++)
+ for (int c=0; c<3; c++)
+ pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
+ }
- Quat operator+ (const Quat& b) const { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
- Quat& operator+= (const Quat& b) { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
- Quat operator- (const Quat& b) const { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
- Quat& operator-= (const Quat& b) { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
+ static Matrix3 FromString(const char* src)
+ {
+ Matrix3 result;
+ for (int r=0; r<3; r++)
+ for (int c=0; c<3; c++)
+ {
+ result.M[r][c] = (T)atof(src);
+ while (src && *src != ' ')
+ src++;
+ while (src && *src == ' ')
+ src++;
+ }
+ return result;
+ }
- Quat operator* (T s) const { return Quat(x * s, y * s, z * s, w * s); }
- Quat& operator*= (T s) { w *= s; x *= s; y *= s; z *= s; return *this; }
- 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; }
+ static const Matrix3& Identity() { return IdentityValue; }
+ void SetIdentity()
+ {
+ M[0][0] = M[1][1] = M[2][2] = 1;
+ M[0][1] = M[1][0] = M[2][0] = 0;
+ M[0][2] = M[1][2] = M[2][1] = 0;
+ }
- // Get Imaginary part vector
- Vector3<T> Imag() const { return Vector3<T>(x,y,z); }
+ bool operator== (const Matrix3& b) const
+ {
+ bool isEqual = true;
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ isEqual &= (M[i][j] == b.M[i][j]);
- // Get quaternion length.
- 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); }
+ return isEqual;
+ }
- // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
- T Distance(const Quat& q) const
- {
- T d1 = (*this - q).Length();
- T d2 = (*this + q).Length(); // Antipodal point check
- return (d1 < d2) ? d1 : d2;
+ Matrix3 operator+ (const Matrix3& b) const
+ {
+ Matrix4<T> result(*this);
+ result += b;
+ return result;
}
- T DistanceSq(const Quat& q) const
- {
- T d1 = (*this - q).LengthSq();
- T d2 = (*this + q).LengthSq(); // Antipodal point check
- return (d1 < d2) ? d1 : d2;
- }
+ Matrix3& operator+= (const Matrix3& b)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] += b.M[i][j];
+ return *this;
+ }
- // Normalize
- bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
+ void operator= (const Matrix3& b)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] = b.M[i][j];
+ return;
+ }
- void Normalize()
+ void operator= (const SymMat3<T>& b)
{
- T l = Length();
- OVR_ASSERT(l != T(0));
- *this /= l;
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] = 0;
+
+ M[0][0] = b.v[0];
+ M[0][1] = b.v[1];
+ M[0][2] = b.v[2];
+ M[1][1] = b.v[3];
+ M[1][2] = b.v[4];
+ M[2][2] = b.v[5];
+
+ return;
}
- Quat Normalized() const
- {
- T l = Length();
- OVR_ASSERT(l != T(0));
- return *this / l;
+ Matrix3 operator- (const Matrix3& b) const
+ {
+ Matrix3 result(*this);
+ result -= b;
+ return result;
}
- // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
- Quat Conj() const { return Quat(-x, -y, -z, w); }
+ Matrix3& operator-= (const Matrix3& b)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] -= b.M[i][j];
+ return *this;
+ }
- // 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,
- w * b.y - x * b.z + y * b.w + z * b.x,
- w * b.z + x * b.y - y * b.x + z * b.w,
- w * b.w - x * b.x - y * b.y - z * b.z); }
+ // Multiplies two matrices into destination with minimum copying.
+ static Matrix3& Multiply(Matrix3* d, const Matrix3& a, const Matrix3& b)
+ {
+ OVR_ASSERT((d != &a) && (d != &b));
+ int i = 0;
+ do {
+ d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0];
+ d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1];
+ d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2];
+ } while((++i) < 3);
+
+ return *d;
+ }
- //
- // this^p normalized; same as rotating by this p times.
- Quat PowNormalized(T p) const
- {
- Vector3<T> v;
- T a;
- GetAxisAngle(&v, &a);
- return Quat(v, a * p);
- }
-
- // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
- // 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, T(0))) * Inverted()).Imag();
- }
+ Matrix3 operator* (const Matrix3& b) const
+ {
+ Matrix3 result(Matrix3::NoInit);
+ Multiply(&result, *this, b);
+ return result;
+ }
-
- // Inversed quaternion rotates in the opposite direction.
- Quat Inverted() const
- {
- return Quat(-x, -y, -z, w);
- }
+ Matrix3& operator*= (const Matrix3& b)
+ {
+ return Multiply(this, Matrix3(*this), b);
+ }
- // Sets this quaternion to the one rotates in the opposite direction.
- void Invert()
- {
- *this = Quat(-x, -y, -z, w);
- }
-
- // Converting quaternion to matrix.
- operator Matrix4f() const
- {
- T ww = w*w;
- T xx = x*x;
- T yy = y*y;
- T zz = z*z;
+ Matrix3 operator* (T s) const
+ {
+ Matrix3 result(*this);
+ result *= s;
+ return result;
+ }
- return Matrix4f(float(ww + xx - yy - zz), float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)),
- float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz), float(T(2) * (y*z - w*x)),
- float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) );
- }
+ Matrix3& operator*= (T s)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] *= s;
+ return *this;
+ }
+ Vector3<T> operator* (const Vector3<T> &b) const
+ {
+ Vector3<T> result;
+ result.x = M[0][0]*b.x + M[0][1]*b.y + M[0][2]*b.z;
+ result.y = M[1][0]*b.x + M[1][1]*b.y + M[1][2]*b.z;
+ result.z = M[2][0]*b.x + M[2][1]*b.y + M[2][2]*b.z;
+
+ return result;
+ }
- // Converting matrix to quaternion
- static Quat<T> Matrix4fToQuat(const Matrix4f& m)
+ Matrix3 operator/ (T s) const
{
- T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
- Quat<T> q;
+ Matrix3 result(*this);
+ result /= s;
+ return result;
+ }
- // 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;
+ Matrix3& operator/= (T s)
+ {
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ M[i][j] /= s;
+ return *this;
}
+ Vector3<T> Transform(const Vector3<T>& v) const
+ {
+ return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z,
+ M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z,
+ M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z);
+ }
-
- // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
- // axis rotations and the specified coordinate system. Right-handed coordinate system
- // is the default, with CCW rotations while looking in the negative axis direction.
- // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
- // rotation a around axis A1
- // is followed by rotation b around axis A2
- // is followed by rotation c around axis A3
- // rotations are CCW or CW (D) in LH or RH coordinate system (S)
- template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
- void GetEulerAngles(T *a, T *b, T *c)
+ Matrix3 Transposed() const
+ {
+ return Matrix3(M[0][0], M[1][0], M[2][0],
+ M[0][1], M[1][1], M[2][1],
+ M[0][2], M[1][2], M[2][2]);
+ }
+
+ void Transpose()
+ {
+ *this = Transposed();
+ }
+
+
+ T 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]]);
+ }
+
+ // M += a*b.t()
+ inline void Rank1Add(const Vector3<T> &a, const Vector3<T> &b)
+ {
+ M[0][0] += a.x*b.x; M[0][1] += a.x*b.y; M[0][2] += a.x*b.z;
+ M[1][0] += a.y*b.x; M[1][1] += a.y*b.y; M[1][2] += a.y*b.z;
+ M[2][0] += a.z*b.x; M[2][1] += a.z*b.y; M[2][2] += a.z*b.z;
+ }
+
+ // M -= a*b.t()
+ inline void Rank1Sub(const Vector3<T> &a, const Vector3<T> &b)
+ {
+ M[0][0] -= a.x*b.x; M[0][1] -= a.x*b.y; M[0][2] -= a.x*b.z;
+ M[1][0] -= a.y*b.x; M[1][1] -= a.y*b.y; M[1][2] -= a.y*b.z;
+ M[2][0] -= a.z*b.x; M[2][1] -= a.z*b.y; M[2][2] -= a.z*b.z;
+ }
+
+ inline Vector3<T> Col(int c) const
+ {
+ return Vector3<T>(M[0][c], M[1][c], M[2][c]);
+ }
+
+ inline Vector3<T> Row(int r) const
+ {
+ return Vector3<T>(M[r][0], M[r][1], M[r][2]);
+ }
+
+ inline T Determinant() const
+ {
+ const Matrix3<T>& m = *this;
+ T d;
+
+ d = m.M[0][0] * (m.M[1][1]*m.M[2][2] - m.M[1][2] * m.M[2][1]);
+ d -= m.M[0][1] * (m.M[1][0]*m.M[2][2] - m.M[1][2] * m.M[2][0]);
+ d += m.M[0][2] * (m.M[1][0]*m.M[2][1] - m.M[1][1] * m.M[2][0]);
+
+ return d;
+ }
+
+ inline Matrix3<T> Inverse() const
{
- OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
+ Matrix3<T> a;
+ const Matrix3<T>& m = *this;
+ T d = Determinant();
- T Q[3] = { x, y, z }; //Quaternion components x,y,z
+ assert(d != 0);
+ T s = T(1)/d;
- T ww = w*w;
- T Q11 = Q[A1]*Q[A1];
- T Q22 = Q[A2]*Q[A2];
- T Q33 = Q[A3]*Q[A3];
+ a.M[0][0] = s * (m.M[1][1] * m.M[2][2] - m.M[1][2] * m.M[2][1]);
+ a.M[1][0] = s * (m.M[1][2] * m.M[2][0] - m.M[1][0] * m.M[2][2]);
+ a.M[2][0] = s * (m.M[1][0] * m.M[2][1] - m.M[1][1] * m.M[2][0]);
- T psign = T(-1);
- // Determine whether even permutation
- if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
- psign = T(1);
+ a.M[0][1] = s * (m.M[0][2] * m.M[2][1] - m.M[0][1] * m.M[2][2]);
+ a.M[1][1] = s * (m.M[0][0] * m.M[2][2] - m.M[0][2] * m.M[2][0]);
+ a.M[2][1] = s * (m.M[0][1] * m.M[2][0] - m.M[0][0] * m.M[2][1]);
- T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
-
- if (s2 < T(-1) + Math<T>::SingularityRadius)
- { // South pole singularity
- *a = T(0);
- *b = -S*D*Math<T>::PiOver2;
- *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
- ww + Q22 - Q11 - Q33 );
- }
- else if (s2 > T(1) - Math<T>::SingularityRadius)
- { // North pole singularity
- *a = T(0);
- *b = S*D*Math<T>::PiOver2;
- *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)*(w*Q[A1] - psign*Q[A2]*Q[A3]),
- ww + Q33 - Q11 - Q22);
- *b = S*D*asin(s2);
- *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]),
- ww + Q11 - Q22 - Q33);
- }
- return;
+ a.M[0][2] = s * (m.M[0][1] * m.M[1][2] - m.M[0][2] * m.M[1][1]);
+ a.M[1][2] = s * (m.M[0][2] * m.M[1][0] - m.M[0][0] * m.M[1][2]);
+ a.M[2][2] = s * (m.M[0][0] * m.M[1][1] - m.M[0][1] * m.M[1][0]);
+
+ return a;
}
+
+};
- template <Axis A1, Axis A2, Axis A3, RotateDirection D>
- void GetEulerAngles(T *a, T *b, T *c)
- { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
+typedef Matrix3<float> Matrix3f;
+typedef Matrix3<double> Matrix3d;
- template <Axis A1, Axis A2, Axis A3>
- void GetEulerAngles(T *a, T *b, T *c)
- { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
+//-------------------------------------------------------------------------------------
+template<typename T>
+class SymMat3
+{
+private:
+ typedef SymMat3<T> this_type;
- // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
- // axis rotations and the specified coordinate system. Right-handed coordinate system
- // is the default, with CCW rotations while looking in the negative axis direction.
- // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
- // rotation a around axis A1
- // is followed by rotation b around axis A2
- // is followed by rotation c around axis A1
- // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
- template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
- void GetEulerAnglesABA(T *a, T *b, T *c)
- {
- OVR_COMPILER_ASSERT(A1 != A2);
+public:
+ typedef T Value_t;
+ // Upper symmetric
+ T v[6]; // _00 _01 _02 _11 _12 _22
- T Q[3] = {x, y, z}; // Quaternion components
+ inline SymMat3() {}
- // Determine the missing axis that was not supplied
- int m = 3 - A1 - A2;
+ inline explicit SymMat3(T s)
+ {
+ v[0] = v[3] = v[5] = s;
+ v[1] = v[2] = v[4] = 0;
+ }
- T ww = w*w;
- T Q11 = Q[A1]*Q[A1];
- T Q22 = Q[A2]*Q[A2];
- T Qmm = Q[m]*Q[m];
+ inline explicit SymMat3(T a00, T a01, T a02, T a11, T a12, T a22)
+ {
+ v[0] = a00; v[1] = a01; v[2] = a02;
+ v[3] = a11; v[4] = a12;
+ v[5] = a22;
+ }
- T psign = T(-1);
- if ((A1 + 1) % 3 == A2) // Determine whether even permutation
- {
- psign = T(1);
- }
+ static inline int Index(unsigned int i, unsigned int j)
+ {
+ return (i <= j) ? (3*i - i*(i+1)/2 + j) : (3*j - j*(j+1)/2 + i);
+ }
- T c2 = ww + Q11 - Q22 - Qmm;
- if (c2 < T(-1) + Math<T>::SingularityRadius)
- { // South pole singularity
- *a = T(0);
- *b = S*D*Math<T>::Pi;
- *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
- ww + Q22 - Q11 - Qmm);
- }
- else if (c2 > T(1) - Math<T>::SingularityRadius)
- { // North pole singularity
- *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
- {
- *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
- w*Q[A2] -psign*Q[A1]*Q[m]);
- *b = S*D*acos(c2);
- *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
- w*Q[A2] + psign*Q[A1]*Q[m]);
- }
- return;
- }
+ inline T operator()(int i, int j) const { return v[Index(i,j)]; }
+
+ inline T &operator()(int i, int j) { return v[Index(i,j)]; }
-};
+ template<typename U>
+ inline SymMat3<U> CastTo() const
+ {
+ return SymMat3<U>(static_cast<U>(v[0]), static_cast<U>(v[1]), static_cast<U>(v[2]),
+ static_cast<U>(v[3]), static_cast<U>(v[4]), static_cast<U>(v[5]));
+ }
-typedef Quat<float> Quatf;
-typedef Quat<double> Quatd;
+ inline this_type& operator+=(const this_type& b)
+ {
+ v[0]+=b.v[0];
+ v[1]+=b.v[1];
+ v[2]+=b.v[2];
+ v[3]+=b.v[3];
+ v[4]+=b.v[4];
+ v[5]+=b.v[5];
+ return *this;
+ }
+
+ inline this_type& operator-=(const this_type& b)
+ {
+ v[0]-=b.v[0];
+ v[1]-=b.v[1];
+ v[2]-=b.v[2];
+ v[3]-=b.v[3];
+ v[4]-=b.v[4];
+ v[5]-=b.v[5];
+
+ return *this;
+ }
+
+ inline this_type& operator*=(T s)
+ {
+ v[0]*=s;
+ v[1]*=s;
+ v[2]*=s;
+ v[3]*=s;
+ v[4]*=s;
+ v[5]*=s;
+
+ return *this;
+ }
+
+ inline SymMat3 operator*(T s) const
+ {
+ SymMat3 d;
+ d.v[0] = v[0]*s;
+ d.v[1] = v[1]*s;
+ d.v[2] = v[2]*s;
+ d.v[3] = v[3]*s;
+ d.v[4] = v[4]*s;
+ d.v[5] = v[5]*s;
+
+ return d;
+ }
+
+ // Multiplies two matrices into destination with minimum copying.
+ static SymMat3& Multiply(SymMat3* d, const SymMat3& a, const SymMat3& b)
+ {
+ // _00 _01 _02 _11 _12 _22
+
+ d->v[0] = a.v[0] * b.v[0];
+ d->v[1] = a.v[0] * b.v[1] + a.v[1] * b.v[3];
+ d->v[2] = a.v[0] * b.v[2] + a.v[1] * b.v[4];
+
+ d->v[3] = a.v[3] * b.v[3];
+ d->v[4] = a.v[3] * b.v[4] + a.v[4] * b.v[5];
+
+ d->v[5] = a.v[5] * b.v[5];
+
+ return *d;
+ }
+
+ inline T Determinant() const
+ {
+ const this_type& m = *this;
+ T d;
+
+ d = m(0,0) * (m(1,1)*m(2,2) - m(1,2) * m(2,1));
+ d -= m(0,1) * (m(1,0)*m(2,2) - m(1,2) * m(2,0));
+ d += m(0,2) * (m(1,0)*m(2,1) - m(1,1) * m(2,0));
+
+ return d;
+ }
+
+ inline this_type Inverse() const
+ {
+ this_type a;
+ const this_type& m = *this;
+ T d = Determinant();
+
+ assert(d != 0);
+ T s = T(1)/d;
+
+ a(0,0) = s * (m(1,1) * m(2,2) - m(1,2) * m(2,1));
+
+ a(0,1) = s * (m(0,2) * m(2,1) - m(0,1) * m(2,2));
+ a(1,1) = s * (m(0,0) * m(2,2) - m(0,2) * m(2,0));
+
+ a(0,2) = s * (m(0,1) * m(1,2) - m(0,2) * m(1,1));
+ a(1,2) = s * (m(0,2) * m(1,0) - m(0,0) * m(1,2));
+ a(2,2) = s * (m(0,0) * m(1,1) - m(0,1) * m(1,0));
+
+ return a;
+ }
+ inline T Trace() const { return v[0] + v[3] + v[5]; }
+ // M = a*a.t()
+ inline void Rank1(const Vector3<T> &a)
+ {
+ v[0] = a.x*a.x; v[1] = a.x*a.y; v[2] = a.x*a.z;
+ v[3] = a.y*a.y; v[4] = a.y*a.z;
+ v[5] = a.z*a.z;
+ }
+
+ // M += a*a.t()
+ inline void Rank1Add(const Vector3<T> &a)
+ {
+ v[0] += a.x*a.x; v[1] += a.x*a.y; v[2] += a.x*a.z;
+ v[3] += a.y*a.y; v[4] += a.y*a.z;
+ v[5] += a.z*a.z;
+ }
+
+ // M -= a*a.t()
+ inline void Rank1Sub(const Vector3<T> &a)
+ {
+ v[0] -= a.x*a.x; v[1] -= a.x*a.y; v[2] -= a.x*a.z;
+ v[3] -= a.y*a.y; v[4] -= a.y*a.z;
+ v[5] -= a.z*a.z;
+ }
+};
+
+typedef SymMat3<float> SymMat3f;
+typedef SymMat3<double> SymMat3d;
+
+template<typename T>
+inline Matrix3<T> operator*(const SymMat3<T>& a, const SymMat3<T>& b)
+{
+ #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
+ return Matrix3<T>(
+ AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
+ AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
+ AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
+ #undef AJB_ARBC
+}
+
+template<typename T>
+inline Matrix3<T> operator*(const Matrix3<T>& a, const SymMat3<T>& b)
+{
+ #define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
+ return Matrix3<T>(
+ AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
+ AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
+ AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
+ #undef AJB_ARBC
+}
//-------------------------------------------------------------------------------------
// ***** Angle
diff --git a/LibOVR/Src/Kernel/OVR_RefCount.cpp b/LibOVR/Src/Kernel/OVR_RefCount.cpp
index 8bb80ef..c6301ed 100644
--- a/LibOVR/Src/Kernel/OVR_RefCount.cpp
+++ b/LibOVR/Src/Kernel/OVR_RefCount.cpp
@@ -5,16 +5,16 @@ Content : Reference counting implementation
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_RefCount.h b/LibOVR/Src/Kernel/OVR_RefCount.h
index 8f2e3ad..775e24c 100644
--- a/LibOVR/Src/Kernel/OVR_RefCount.h
+++ b/LibOVR/Src/Kernel/OVR_RefCount.h
@@ -6,16 +6,16 @@ Content : Reference counting implementation headers
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -62,7 +62,7 @@ class RefCountNTSImpl;
class RefCountImplCore
{
protected:
- volatile int RefCount;
+ volatile int RefCount;
public:
// RefCountImpl constructor always initializes RefCount to 1 by default.
@@ -145,7 +145,7 @@ public:
// RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
// virtual AddRef and Release.
-class RefCountVImpl : public RefCountImplCore
+class RefCountVImpl : virtual public RefCountImplCore
{
public:
// Thread-Safe Ref-Count Implementation.
@@ -194,6 +194,8 @@ public:
// Redefine all new & delete operators.
OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
#ifdef OVR_DEFINE_NEW
#define new OVR_DEFINE_NEW
#endif
@@ -202,6 +204,35 @@ public:
};
+template<class Base>
+class RefCountBaseStatVImpl : virtual public Base
+{
+public:
+ RefCountBaseStatVImpl() { }
+
+ // *** Override New and Delete
+
+ // DOM-IGNORE-BEGIN
+ // Undef new temporarily if it is being redefined
+#ifdef OVR_DEFINE_NEW
+#undef new
+#endif
+
+#define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
+
+ // Redefine all new & delete operators.
+ OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+ // OVR_BUILD_DEFINE_NEW
+ // DOM-IGNORE-END
+};
+
+
//-----------------------------------------------------------------------------------
// *** End user RefCountBase<> classes
@@ -225,11 +256,11 @@ public:
// RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
template<class C>
-class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl>
+class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
{
public:
// Constructor.
- OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { }
+ OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatVImpl<RefCountVImpl>() { }
};
diff --git a/LibOVR/Src/Kernel/OVR_Std.cpp b/LibOVR/Src/Kernel/OVR_Std.cpp
index 4159652..6b5be18 100644
--- a/LibOVR/Src/Kernel/OVR_Std.cpp
+++ b/LibOVR/Src/Kernel/OVR_Std.cpp
@@ -5,16 +5,16 @@ Content : Standard C function implementation
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Std.h b/LibOVR/Src/Kernel/OVR_Std.h
index 4ec8d65..c11f853 100644
--- a/LibOVR/Src/Kernel/OVR_Std.h
+++ b/LibOVR/Src/Kernel/OVR_Std.h
@@ -6,16 +6,16 @@ Content : Standard C function interface
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -229,7 +229,7 @@ inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix)
return strtol(string, tailptr, radix);
}
-inline unsigned long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
+inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
{
return strtoul(string, tailptr, radix);
}
@@ -281,7 +281,7 @@ inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* forma
{
va_list argList;
va_start(argList,format);
- SInt32 ret;
+ UPInt ret;
#if defined(OVR_CC_MSVC)
#if defined(OVR_MSVC_SAFESTRING)
ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
@@ -298,7 +298,7 @@ inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* forma
OVR_ASSERT(ret < destsize);
#endif
va_end(argList);
- return (UPInt)ret;
+ return ret;
}
inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList)
diff --git a/LibOVR/Src/Kernel/OVR_String.cpp b/LibOVR/Src/Kernel/OVR_String.cpp
index 8c72c6d..86aa126 100644
--- a/LibOVR/Src/Kernel/OVR_String.cpp
+++ b/LibOVR/Src/Kernel/OVR_String.cpp
@@ -6,16 +6,16 @@ Content : String UTF8 string implementation with copy-on-write semantics
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h
index 6c09178..f7151c7 100644
--- a/LibOVR/Src/Kernel/OVR_String.h
+++ b/LibOVR/Src/Kernel/OVR_String.h
@@ -7,16 +7,16 @@ Content : String UTF8 string implementation with copy-on-write semantics
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -236,7 +236,7 @@ public:
// String& Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
// Get Byte index of the character at position = index
- UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(static_cast<SPInt>(index), GetData()->Data); }
+ UPInt GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
// Utility: case-insensitive string compare. stricmp() & strnicmp() are not
// ANSI or POSIX, do not seem to appear in Linux.
@@ -286,7 +286,7 @@ public:
void operator += (const String& src);
void operator += (const char* psrc) { AppendString(psrc); }
void operator += (const wchar_t* psrc) { AppendString(psrc); }
- void operator += (char ch) { AppendChar( static_cast<UInt32>(ch) ); }
+ void operator += (char ch) { AppendChar(ch); }
String operator + (const char* str) const;
String operator + (const String& src) const;
@@ -476,10 +476,10 @@ public:
void operator = (const String& src);
// Addition
- void operator += (const String& src) { AppendString(src.ToCStr(),static_cast<SPInt>(src.GetSize())); }
+ void operator += (const String& src) { AppendString(src.ToCStr(),src.GetSize()); }
void operator += (const char* psrc) { AppendString(psrc); }
void operator += (const wchar_t* psrc) { AppendString(psrc); }
- void operator += (char ch) { AppendChar( static_cast<SPInt>(ch) ); }
+ void operator += (char ch) { AppendChar(ch); }
//String operator + (const char* str) const ;
//String operator + (const String& src) const ;
diff --git a/LibOVR/Src/Kernel/OVR_StringHash.h b/LibOVR/Src/Kernel/OVR_StringHash.h
index 90679e0..baa80a7 100644
--- a/LibOVR/Src/Kernel/OVR_StringHash.h
+++ b/LibOVR/Src/Kernel/OVR_StringHash.h
@@ -7,16 +7,16 @@ Content : String hash table used when optional case-insensitive
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
index e0db5d4..e196dd7 100644
--- a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
+++ b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
@@ -5,16 +5,16 @@ Content : String format functions.
Created : February 27, 2013
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
index 4a7e87a..02abe15 100644
--- a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
+++ b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
@@ -5,16 +5,16 @@ Content : String filename/url helper function
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_SysFile.cpp b/LibOVR/Src/Kernel/OVR_SysFile.cpp
index cdbc843..f487492 100644
--- a/LibOVR/Src/Kernel/OVR_SysFile.cpp
+++ b/LibOVR/Src/Kernel/OVR_SysFile.cpp
@@ -6,16 +6,16 @@ Content : File wrapper class implementation (Win32)
Created : April 5, 1999
Authors : Michael Antonov
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -83,7 +83,7 @@ SysFile::SysFile() : DelegatedFile(0)
pFile = *new UnopenedFile;
}
-File* FileFILEOpen(const String& path, int flags, int mode);
+Ptr<File> FileFILEOpen(const String& path, int flags, int mode);
// Opens a file
SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0)
@@ -96,7 +96,7 @@ SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0)
// Will fail if file's already open
bool SysFile::Open(const String& path, int flags, int mode)
{
- pFile = *FileFILEOpen(path, flags, mode);
+ pFile = FileFILEOpen(path, flags, mode);
if ((!pFile) || (!pFile->IsValid()))
{
pFile = *new UnopenedFile;
diff --git a/LibOVR/Src/Kernel/OVR_SysFile.h b/LibOVR/Src/Kernel/OVR_SysFile.h
index 3241e67..d492377 100644
--- a/LibOVR/Src/Kernel/OVR_SysFile.h
+++ b/LibOVR/Src/Kernel/OVR_SysFile.h
@@ -11,16 +11,16 @@ Notes : errno may not be preserved across use of GBaseFile member functi
: Directories cannot be deleted while files opened from them are in use
(For the GetFullName function)
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_System.cpp b/LibOVR/Src/Kernel/OVR_System.cpp
index e57a663..3144ade 100644
--- a/LibOVR/Src/Kernel/OVR_System.cpp
+++ b/LibOVR/Src/Kernel/OVR_System.cpp
@@ -6,16 +6,16 @@ Content : General kernel initialization/cleanup, including that
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h
index 1e4065f..253fe19 100644
--- a/LibOVR/Src/Kernel/OVR_System.h
+++ b/LibOVR/Src/Kernel/OVR_System.h
@@ -7,16 +7,16 @@ Content : General kernel initialization/cleanup, including that
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h
index 0585972..e1f5abe 100644
--- a/LibOVR/Src/Kernel/OVR_Threads.h
+++ b/LibOVR/Src/Kernel/OVR_Threads.h
@@ -6,16 +6,16 @@ Content : Contains thread-related (safe) functionality
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp
deleted file mode 100644
index bf87f8c..0000000
--- a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp
+++ /dev/null
@@ -1,821 +0,0 @@
-/************************************************************************************
-
-PublicHeader: OVR
-Filename : OVR_Threads.h
-Content :
-Created :
-Notes :
-
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
-
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
-which is provided at the time of installation or download, or which
-otherwise accompanies this software in either electronic or hard copy form.
-
-You may obtain a copy of the License at
-
-http://www.oculusvr.com/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, the Oculus VR SDK
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-************************************************************************************/
-
-#include "OVR_Threads.h"
-#include "OVR_Hash.h"
-
-#ifdef OVR_ENABLE_THREADS
-
-#include "OVR_Timer.h"
-#include "OVR_Log.h"
-
-#include <pthread.h>
-#include <time.h>
-
-#ifdef OVR_OS_PS3
-#include <sys/sys_time.h>
-#include <sys/timer.h>
-#include <sys/synchronization.h>
-#define sleep(x) sys_timer_sleep(x)
-#define usleep(x) sys_timer_usleep(x)
-using std::timespec;
-#else
-#include <unistd.h>
-#include <sys/time.h>
-#include <errno.h>
-#endif
-
-namespace OVR {
-
-// ***** Mutex implementation
-
-
-// *** Internal Mutex implementation structure
-
-class MutexImpl : public NewOverrideBase
-{
- // System mutex or semaphore
- pthread_mutex_t SMutex;
- bool Recursive;
- unsigned LockCount;
- pthread_t LockedBy;
-
- friend class WaitConditionImpl;
-
-public:
- // Constructor/destructor
- MutexImpl(Mutex* pmutex, bool recursive = 1);
- ~MutexImpl();
-
- // Locking functions
- void DoLock();
- bool TryLock();
- void Unlock(Mutex* pmutex);
- // Returns 1 if the mutes is currently locked
- bool IsLockedByAnotherThread(Mutex* pmutex);
- bool IsSignaled() const;
-};
-
-pthread_mutexattr_t Lock::RecursiveAttr;
-bool Lock::RecursiveAttrInit = 0;
-
-// *** Constructor/destructor
-MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
-{
- Recursive = recursive;
- LockCount = 0;
-
- if (Recursive)
- {
- if (!Lock::RecursiveAttrInit)
- {
- pthread_mutexattr_init(&Lock::RecursiveAttr);
- pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
- Lock::RecursiveAttrInit = 1;
- }
-
- pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
- }
- else
- pthread_mutex_init(&SMutex, 0);
-}
-
-MutexImpl::~MutexImpl()
-{
- pthread_mutex_destroy(&SMutex);
-}
-
-
-// Lock and try lock
-void MutexImpl::DoLock()
-{
- while (pthread_mutex_lock(&SMutex));
- LockCount++;
- LockedBy = pthread_self();
-}
-
-bool MutexImpl::TryLock()
-{
- if (!pthread_mutex_trylock(&SMutex))
- {
- LockCount++;
- LockedBy = pthread_self();
- return 1;
- }
-
- return 0;
-}
-
-void MutexImpl::Unlock(Mutex* pmutex)
-{
- OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
-
- unsigned lockCount;
- LockCount--;
- lockCount = LockCount;
-
- pthread_mutex_unlock(&SMutex);
-}
-
-bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
-{
- // There could be multiple interpretations of IsLocked with respect to current thread
- if (LockCount == 0)
- return 0;
- if (pthread_self() != LockedBy)
- return 1;
- return 0;
-}
-
-bool MutexImpl::IsSignaled() const
-{
- // An mutex is signaled if it is not locked ANYWHERE
- // Note that this is different from IsLockedByAnotherThread function,
- // that takes current thread into account
- return LockCount == 0;
-}
-
-
-// *** Actual Mutex class implementation
-
-Mutex::Mutex(bool recursive)
-{
- // NOTE: RefCount mode already thread-safe for all waitables.
- pImpl = new MutexImpl(this, recursive);
-}
-
-Mutex::~Mutex()
-{
- delete pImpl;
-}
-
-// Lock and try lock
-void Mutex::DoLock()
-{
- pImpl->DoLock();
-}
-bool Mutex::TryLock()
-{
- return pImpl->TryLock();
-}
-void Mutex::Unlock()
-{
- pImpl->Unlock(this);
-}
-bool Mutex::IsLockedByAnotherThread()
-{
- return pImpl->IsLockedByAnotherThread(this);
-}
-
-
-
-//-----------------------------------------------------------------------------------
-// ***** Event
-
-bool Event::Wait(unsigned delay)
-{
- Mutex::Locker lock(&StateMutex);
-
- // Do the correct amount of waiting
- if (delay == OVR_WAIT_INFINITE)
- {
- while(!State)
- StateWaitCondition.Wait(&StateMutex);
- }
- else if (delay)
- {
- if (!State)
- StateWaitCondition.Wait(&StateMutex, delay);
- }
-
- bool state = State;
- // Take care of temporary 'pulsing' of a state
- if (Temporary)
- {
- Temporary = false;
- State = false;
- }
- return state;
-}
-
-void Event::updateState(bool newState, bool newTemp, bool mustNotify)
-{
- Mutex::Locker lock(&StateMutex);
- State = newState;
- Temporary = newTemp;
- if (mustNotify)
- StateWaitCondition.NotifyAll();
-}
-
-
-
-// ***** Wait Condition Implementation
-
-// Internal implementation class
-class WaitConditionImpl : public NewOverrideBase
-{
- pthread_mutex_t SMutex;
- pthread_cond_t Condv;
-
-public:
-
- // Constructor/destructor
- WaitConditionImpl();
- ~WaitConditionImpl();
-
- // Release mutex and wait for condition. The mutex is re-aqured after the wait.
- bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
-
- // Notify a condition, releasing at one object waiting
- void Notify();
- // Notify a condition, releasing all objects waiting
- void NotifyAll();
-};
-
-
-WaitConditionImpl::WaitConditionImpl()
-{
- pthread_mutex_init(&SMutex, 0);
- pthread_cond_init(&Condv, 0);
-}
-
-WaitConditionImpl::~WaitConditionImpl()
-{
- pthread_mutex_destroy(&SMutex);
- pthread_cond_destroy(&Condv);
-}
-
-bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
-{
- bool result = 1;
- unsigned lockCount = pmutex->pImpl->LockCount;
-
- // Mutex must have been locked
- if (lockCount == 0)
- return 0;
-
- pthread_mutex_lock(&SMutex);
-
- // Finally, release a mutex or semaphore
- if (pmutex->pImpl->Recursive)
- {
- // Release the recursive mutex N times
- pmutex->pImpl->LockCount = 0;
- for(unsigned i=0; i<lockCount; i++)
- pthread_mutex_unlock(&pmutex->pImpl->SMutex);
- }
- else
- {
- pmutex->pImpl->LockCount = 0;
- pthread_mutex_unlock(&pmutex->pImpl->SMutex);
- }
-
- // Note that there is a gap here between mutex.Unlock() and Wait().
- // The other mutex protects this gap.
-
- if (delay == OVR_WAIT_INFINITE)
- pthread_cond_wait(&Condv,&SMutex);
- else
- {
- timespec ts;
-#ifdef OVR_OS_PS3
- sys_time_sec_t s;
- sys_time_nsec_t ns;
- sys_time_get_current_time(&s, &ns);
-
- ts.tv_sec = s + (delay / 1000);
- ts.tv_nsec = ns + (delay % 1000) * 1000000;
-
-#else
- struct timeval tv;
- gettimeofday(&tv, 0);
-
- ts.tv_sec = tv.tv_sec + (delay / 1000);
- ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
-#endif
- if (ts.tv_nsec > 999999999)
- {
- ts.tv_sec++;
- ts.tv_nsec -= 1000000000;
- }
- int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
- OVR_ASSERT(r == 0 || r == ETIMEDOUT);
- if (r)
- result = 0;
- }
-
- pthread_mutex_unlock(&SMutex);
-
- // Re-aquire the mutex
- for(unsigned i=0; i<lockCount; i++)
- pmutex->DoLock();
-
- // Return the result
- return result;
-}
-
-// Notify a condition, releasing the least object in a queue
-void WaitConditionImpl::Notify()
-{
- pthread_mutex_lock(&SMutex);
- pthread_cond_signal(&Condv);
- pthread_mutex_unlock(&SMutex);
-}
-
-// Notify a condition, releasing all objects waiting
-void WaitConditionImpl::NotifyAll()
-{
- pthread_mutex_lock(&SMutex);
- pthread_cond_broadcast(&Condv);
- pthread_mutex_unlock(&SMutex);
-}
-
-
-
-// *** Actual implementation of WaitCondition
-
-WaitCondition::WaitCondition()
-{
- pImpl = new WaitConditionImpl;
-}
-WaitCondition::~WaitCondition()
-{
- delete pImpl;
-}
-
-bool WaitCondition::Wait(Mutex *pmutex, unsigned delay)
-{
- return pImpl->Wait(pmutex, delay);
-}
-// Notification
-void WaitCondition::Notify()
-{
- pImpl->Notify();
-}
-void WaitCondition::NotifyAll()
-{
- pImpl->NotifyAll();
-}
-
-
-// ***** Current thread
-
-// Per-thread variable
-/*
-static __thread Thread* pCurrentThread = 0;
-
-// Static function to return a pointer to the current thread
-void Thread::InitCurrentThread(Thread *pthread)
-{
- pCurrentThread = pthread;
-}
-
-// Static function to return a pointer to the current thread
-Thread* Thread::GetThread()
-{
- return pCurrentThread;
-}
-*/
-
-
-// *** Thread constructors.
-
-Thread::Thread(UPInt stackSize, int processor)
-{
- // NOTE: RefCount mode already thread-safe for all Waitable objects.
- CreateParams params;
- params.stackSize = stackSize;
- params.processor = processor;
- Init(params);
-}
-
-Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
- int processor, Thread::ThreadState initialState)
-{
- CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
- Init(params);
-}
-
-Thread::Thread(const CreateParams& params)
-{
- Init(params);
-}
-
-void Thread::Init(const CreateParams& params)
-{
- // Clear the variables
- ThreadFlags = 0;
- ThreadHandle = 0;
- ExitCode = 0;
- SuspendCount = 0;
- StackSize = params.stackSize;
- Processor = params.processor;
- Priority = params.priority;
-
- // Clear Function pointers
- ThreadFunction = params.threadFunction;
- UserHandle = params.userHandle;
- if (params.initialState != NotRunning)
- Start(params.initialState);
-}
-
-Thread::~Thread()
-{
- // Thread should not running while object is being destroyed,
- // this would indicate ref-counting issue.
- //OVR_ASSERT(IsRunning() == 0);
-
- // Clean up thread.
- ThreadHandle = 0;
-}
-
-
-
-// *** Overridable User functions.
-
-// Default Run implementation
-int Thread::Run()
-{
- // Call pointer to function, if available.
- return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
-}
-void Thread::OnExit()
-{
-}
-
-
-// Finishes the thread and releases internal reference to it.
-void Thread::FinishAndRelease()
-{
- // Note: thread must be US.
- ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
- ThreadFlags |= OVR_THREAD_FINISHED;
-
- // Release our reference; this is equivalent to 'delete this'
- // from the point of view of our thread.
- Release();
-}
-
-
-
-// *** ThreadList - used to track all created threads
-
-class ThreadList : public NewOverrideBase
-{
- //------------------------------------------------------------------------
- struct ThreadHashOp
- {
- size_t operator()(const Thread* ptr)
- {
- return (((size_t)ptr) >> 6) ^ (size_t)ptr;
- }
- };
-
- HashSet<Thread*, ThreadHashOp> ThreadSet;
- Mutex ThreadMutex;
- WaitCondition ThreadsEmpty;
- // Track the root thread that created us.
- pthread_t RootThreadId;
-
- static ThreadList* volatile pRunningThreads;
-
- void addThread(Thread *pthread)
- {
- Mutex::Locker lock(&ThreadMutex);
- ThreadSet.Add(pthread);
- }
-
- void removeThread(Thread *pthread)
- {
- Mutex::Locker lock(&ThreadMutex);
- ThreadSet.Remove(pthread);
- if (ThreadSet.GetSize() == 0)
- ThreadsEmpty.Notify();
- }
-
- void finishAllThreads()
- {
- // Only original root thread can call this.
- OVR_ASSERT(pthread_self() == RootThreadId);
-
- Mutex::Locker lock(&ThreadMutex);
- while (ThreadSet.GetSize() != 0)
- ThreadsEmpty.Wait(&ThreadMutex);
- }
-
-public:
-
- ThreadList()
- {
- RootThreadId = pthread_self();
- }
- ~ThreadList() { }
-
-
- static void AddRunningThread(Thread *pthread)
- {
- // Non-atomic creation ok since only the root thread
- if (!pRunningThreads)
- {
- pRunningThreads = new ThreadList;
- OVR_ASSERT(pRunningThreads);
- }
- pRunningThreads->addThread(pthread);
- }
-
- // NOTE: 'pthread' might be a dead pointer when this is
- // called so it should not be accessed; it is only used
- // for removal.
- static void RemoveRunningThread(Thread *pthread)
- {
- OVR_ASSERT(pRunningThreads);
- pRunningThreads->removeThread(pthread);
- }
-
- static void FinishAllThreads()
- {
- // This is ok because only root thread can wait for other thread finish.
- if (pRunningThreads)
- {
- pRunningThreads->finishAllThreads();
- delete pRunningThreads;
- pRunningThreads = 0;
- }
- }
-};
-
-// By default, we have no thread list.
-ThreadList* volatile ThreadList::pRunningThreads = 0;
-
-
-// FinishAllThreads - exposed publicly in Thread.
-void Thread::FinishAllThreads()
-{
- ThreadList::FinishAllThreads();
-}
-
-// *** Run override
-
-int Thread::PRun()
-{
- // Suspend us on start, if requested
- if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
- {
- Suspend();
- ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
- }
-
- // Call the virtual run function
- ExitCode = Run();
- return ExitCode;
-}
-
-
-
-
-// *** User overridables
-
-bool Thread::GetExitFlag() const
-{
- return (ThreadFlags & OVR_THREAD_EXIT) != 0;
-}
-
-void Thread::SetExitFlag(bool exitFlag)
-{
- // The below is atomic since ThreadFlags is AtomicInt.
- if (exitFlag)
- ThreadFlags |= OVR_THREAD_EXIT;
- else
- ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
-}
-
-
-// Determines whether the thread was running and is now finished
-bool Thread::IsFinished() const
-{
- return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
-}
-// Determines whether the thread is suspended
-bool Thread::IsSuspended() const
-{
- return SuspendCount > 0;
-}
-// Returns current thread state
-Thread::ThreadState Thread::GetThreadState() const
-{
- if (IsSuspended())
- return Suspended;
- if (ThreadFlags & OVR_THREAD_STARTED)
- return Running;
- return NotRunning;
-}
-/*
-static const char* mapsched_policy(int policy)
-{
- switch(policy)
- {
- case SCHED_OTHER:
- return "SCHED_OTHER";
- case SCHED_RR:
- return "SCHED_RR";
- case SCHED_FIFO:
- return "SCHED_FIFO";
-
- }
- return "UNKNOWN";
-}
- int policy;
- sched_param sparam;
- pthread_getschedparam(pthread_self(), &policy, &sparam);
- int max_prior = sched_get_priority_max(policy);
- int min_prior = sched_get_priority_min(policy);
- printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
-#include <stdio.h>
-*/
-// ***** Thread management
-
-// The actual first function called on thread start
-void* Thread_PthreadStartFn(void* phandle)
-{
- Thread* pthread = (Thread*)phandle;
- int result = pthread->PRun();
- // Signal the thread as done and release it atomically.
- pthread->FinishAndRelease();
- // At this point Thread object might be dead; however we can still pass
- // it to RemoveRunningThread since it is only used as a key there.
- ThreadList::RemoveRunningThread(pthread);
- return (void*) result;
-}
-
-int Thread::InitAttr = 0;
-pthread_attr_t Thread::Attr;
-
-/* static */
-int Thread::GetOSPriority(ThreadPriority p)
-//static inline int MapToSystemPrority(Thread::ThreadPriority p)
-{
-#ifdef OVR_OS_PS3
- switch(p)
- {
- case Thread::CriticalPriority: return 0;
- case Thread::HighestPriority: return 300;
- case Thread::AboveNormalPriority: return 600;
- case Thread::NormalPriority: return 1000;
- case Thread::BelowNormalPriority: return 1500;
- case Thread::LowestPriority: return 2500;
- case Thread::IdlePriority: return 3071;
- } return 1000;
-#else
- OVR_UNUSED(p);
- return -1;
-#endif
-}
-
-bool Thread::Start(ThreadState initialState)
-{
- if (initialState == NotRunning)
- return 0;
- if (GetThreadState() != NotRunning)
- {
- OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
- return 0;
- }
-
- if (!InitAttr)
- {
- pthread_attr_init(&Attr);
- pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&Attr, 128 * 1024);
- sched_param sparam;
- sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
- pthread_attr_setschedparam(&Attr, &sparam);
- InitAttr = 1;
- }
-
- ExitCode = 0;
- SuspendCount = 0;
- ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
-
- // AddRef to us until the thread is finished
- AddRef();
- ThreadList::AddRunningThread(this);
-
- int result;
- if (StackSize != 128 * 1024 || Priority != NormalPriority)
- {
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&attr, StackSize);
- sched_param sparam;
- sparam.sched_priority = Thread::GetOSPriority(Priority);
- pthread_attr_setschedparam(&attr, &sparam);
- result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
- pthread_attr_destroy(&attr);
- }
- else
- result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
-
- if (result)
- {
- ThreadFlags = 0;
- Release();
- ThreadList::RemoveRunningThread(this);
- return 0;
- }
- return 1;
-}
-
-
-// Suspend the thread until resumed
-bool Thread::Suspend()
-{
- OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
- return 0;
-}
-
-// Resumes currently suspended thread
-bool Thread::Resume()
-{
- return 0;
-}
-
-
-// Quits with an exit code
-void Thread::Exit(int exitCode)
-{
- // Can only exist the current thread
- // if (GetThread() != this)
- // return;
-
- // Call the virtual OnExit function
- OnExit();
-
- // Signal this thread object as done and release it's references.
- FinishAndRelease();
- ThreadList::RemoveRunningThread(this);
-
- pthread_exit((void *) exitCode);
-}
-
-ThreadId GetCurrentThreadId()
-{
- return (void*)pthread_self();
-}
-
-// *** Sleep functions
-
-/* static */
-bool Thread::Sleep(unsigned secs)
-{
- sleep(secs);
- return 1;
-}
-/* static */
-bool Thread::MSleep(unsigned msecs)
-{
- usleep(msecs*1000);
- return 1;
-}
-
-/* static */
-int Thread::GetCPUCount()
-{
- return 1;
-}
-
-
-#ifdef OVR_OS_PS3
-
-sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
-
-#endif
-
-}
-
-#endif // OVR_ENABLE_THREADS
diff --git a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp
index 8880082..663d859 100644
--- a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp
+++ b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp
@@ -6,16 +6,16 @@ Content : Windows specific thread-related (safe) functionality
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp
index 84ff4a1..a8de47d 100644
--- a/LibOVR/Src/Kernel/OVR_Timer.cpp
+++ b/LibOVR/Src/Kernel/OVR_Timer.cpp
@@ -5,16 +5,16 @@ Content : Provides static functions for precise timing
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -39,49 +39,48 @@ limitations under the License.
namespace OVR {
+// For recorded data playback
+bool Timer::useFakeSeconds = false;
+double Timer::FakeSeconds = 0;
+
//------------------------------------------------------------------------
// *** Timer - Platform Independent functions
-double ovr_GetTimeInSeconds()
+// Returns global high-resolution application timer in seconds.
+double Timer::GetSeconds()
{
- return Timer::GetSeconds();
+ if(useFakeSeconds)
+ return FakeSeconds;
+
+ return double(Timer::GetTicksNanos()) * 0.000000001;
}
-UInt64 Timer::GetProfileTicks()
+#ifndef OVR_OS_WIN32
+
+// Unused on OSs other then Win32.
+void Timer::initializeTimerSystem()
{
- return (GetRawTicks() * MksPerSecond) / GetRawFrequency();
}
-double Timer::GetProfileSeconds()
+void Timer::shutdownTimerSystem()
{
- static UInt64 StartTime = GetProfileTicks();
- return TicksToSeconds(GetProfileTicks()-StartTime);
}
-#ifndef OVR_OS_ANDROID
-
-double Timer::GetSeconds()
-{
- return (double)Timer::GetRawTicks() / (double) GetRawFrequency();
-}
#endif
+
//------------------------------------------------------------------------
// *** Android Specific Timer
-
#if defined(OVR_OS_ANDROID)
-// Returns global high-resolution application timer in seconds.
-double Timer::GetSeconds()
+UInt64 Timer::GetTicksNanos()
{
- return double(Timer::GetRawTicks()) * 0.000000001;
-}
+ if (useFakeSeconds)
+ return (UInt64) (FakeSeconds * NanosPerSecond);
-UInt64 Timer::GetRawTicks()
-{
// Choreographer vsync timestamp is based on.
struct timespec tp;
const int status = clock_gettime(CLOCK_MONOTONIC, &tp);
@@ -94,108 +93,178 @@ UInt64 Timer::GetRawTicks()
return result;
}
-UInt64 Timer::GetRawFrequency()
-{
- return MksPerSecond * 1000;
-}
-
-#endif
-
//------------------------------------------------------------------------
// *** Win32 Specific Timer
-#if defined (OVR_OS_WIN32)
+#elif defined (OVR_OS_WIN32)
-CRITICAL_SECTION WinAPI_GetTimeCS;
-volatile UInt32 WinAPI_OldTime = 0;
-volatile UInt32 WinAPI_WrapCounter = 0;
+// This helper class implements high-resolution wrapper that combines timeGetTime() output
+// with QueryPerformanceCounter. timeGetTime() is lower precision but drives the high bits,
+// as it's tied to the system clock.
+struct PerformanceTimer
+{
+ PerformanceTimer()
+ : OldMMTimeMs(0), MMTimeWrapCounter(0), PrefFrequency(0),
+ LastResultNanos(0), PerfMinusTicksDeltaNanos(0)
+ { }
+
+ enum {
+ MMTimerResolutionNanos = 1000000
+ };
+
+ void Initialize();
+ void Shutdown();
+
+ UInt64 GetTimeNanos();
+
+
+ UINT64 getFrequency()
+ {
+ if (PrefFrequency == 0)
+ {
+ LARGE_INTEGER freq;
+ QueryPerformanceFrequency(&freq);
+ PrefFrequency = freq.QuadPart;
+ }
+ return PrefFrequency;
+ }
+
+
+ CRITICAL_SECTION TimeCS;
+ // timeGetTime() support with wrap.
+ UInt32 OldMMTimeMs;
+ UInt32 MMTimeWrapCounter;
+ // Cached performance frequency result.
+ UInt64 PrefFrequency;
+
+ // Computed as (perfCounterNanos - ticksCounterNanos) initially,
+ // and used to adjust timing.
+ UInt64 PerfMinusTicksDeltaNanos;
+ // Last returned value in nanoseconds, to ensure we don't back-step in time.
+ UInt64 LastResultNanos;
+};
+
+PerformanceTimer Win32_PerfTimer;
+
+
+void PerformanceTimer::Initialize()
+{
+ timeBeginPeriod(1);
+ InitializeCriticalSection(&TimeCS);
+ MMTimeWrapCounter = 0;
+ getFrequency();
+}
-UInt32 Timer::GetTicksMs()
+void PerformanceTimer::Shutdown()
{
- return timeGetTime();
+ DeleteCriticalSection(&TimeCS);
+ timeEndPeriod(1);
}
-UInt64 Timer::GetTicks()
+UInt64 PerformanceTimer::GetTimeNanos()
{
- DWORD ticks = timeGetTime();
- UInt64 result;
+ UInt64 resultNanos;
+ LARGE_INTEGER li;
+ DWORD mmTimeMs;
// On Win32 QueryPerformanceFrequency is unreliable due to SMP and
// performance levels, so use this logic to detect wrapping and track
// high bits.
- ::EnterCriticalSection(&WinAPI_GetTimeCS);
-
- if (WinAPI_OldTime > ticks)
- WinAPI_WrapCounter++;
- WinAPI_OldTime = ticks;
+ ::EnterCriticalSection(&TimeCS);
- result = (UInt64(WinAPI_WrapCounter) << 32) | ticks;
- ::LeaveCriticalSection(&WinAPI_GetTimeCS);
-
- return result * MksPerMs;
-}
-
-UInt64 Timer::GetRawTicks()
-{
- LARGE_INTEGER li;
+ // Get raw value and perf counter "At the same time".
+ mmTimeMs = timeGetTime();
QueryPerformanceCounter(&li);
- return li.QuadPart;
-}
-UInt64 Timer::GetRawFrequency()
-{
- static UInt64 perfFreq = 0;
- if (perfFreq == 0)
+ if (OldMMTimeMs > mmTimeMs)
+ MMTimeWrapCounter++;
+ OldMMTimeMs = mmTimeMs;
+
+ // Normalize to nanoseconds.
+ UInt64 mmCounterNanos = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
+ UInt64 frequency = getFrequency();
+ UInt64 perfCounterSeconds = UInt64(li.QuadPart) / frequency;
+ UInt64 perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) *
+ Timer::NanosPerSecond ) / frequency;
+ UInt64 perfCounterNanos = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
+
+ if (PerfMinusTicksDeltaNanos == 0)
+ PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos;
+
+
+ // Compute result before snapping.
+ //
+ // On first call, this evaluates to:
+ // resultNanos = mmCounterNanos.
+ // Next call, assuming no wrap:
+ // resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos).
+ // After wrap, this would be:
+ // resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos).
+ //
+ resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos;
+
+ // Snap the range so that resultNanos never moves further apart then its target resolution.
+ // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically
+ // larger then 1 ms intervals even when 1 ms resolution is requested.
+ if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2))
{
- LARGE_INTEGER freq;
- QueryPerformanceFrequency(&freq);
- perfFreq = freq.QuadPart;
+ resultNanos = mmCounterNanos + MMTimerResolutionNanos*2;
+ if (resultNanos < LastResultNanos)
+ resultNanos = LastResultNanos;
+ PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
+ }
+ else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos))
+ {
+ resultNanos = mmCounterNanos - MMTimerResolutionNanos;
+ if (resultNanos < LastResultNanos)
+ resultNanos = LastResultNanos;
+ PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
}
- return perfFreq;
-}
-void Timer::initializeTimerSystem()
-{
- timeBeginPeriod(1);
- InitializeCriticalSection(&WinAPI_GetTimeCS);
+ LastResultNanos = resultNanos;
+ ::LeaveCriticalSection(&TimeCS);
-}
-void Timer::shutdownTimerSystem()
-{
- DeleteCriticalSection(&WinAPI_GetTimeCS);
- timeEndPeriod(1);
-}
+ //Tom's addition, to keep precision
+ static UInt64 initial_time = 0;
+ if (!initial_time) initial_time = resultNanos;
+ resultNanos -= initial_time;
-#else // !OVR_OS_WIN32
+ return resultNanos;
+}
-//------------------------------------------------------------------------
-// *** Standard OS Timer
-UInt32 Timer::GetTicksMs()
-{
- return (UInt32)(GetProfileTicks() / 1000);
-}
-// The profile ticks implementation is just fine for a normal timer.
-UInt64 Timer::GetTicks()
+// Delegate to PerformanceTimer.
+UInt64 Timer::GetTicksNanos()
{
- return GetProfileTicks();
-}
+ if (useFakeSeconds)
+ return (UInt64) (FakeSeconds * NanosPerSecond);
+ return Win32_PerfTimer.GetTimeNanos();
+}
void Timer::initializeTimerSystem()
{
+ Win32_PerfTimer.Initialize();
+
}
void Timer::shutdownTimerSystem()
{
+ Win32_PerfTimer.Shutdown();
}
+#else // !OVR_OS_WIN32 && !OVR_OS_ANDROID
+
-#if !defined(OVR_OS_ANDROID)
+//------------------------------------------------------------------------
+// *** Standard OS Timer
-UInt64 Timer::GetRawTicks()
+UInt64 Timer::GetTicksNanos()
{
+ if (useFakeSeconds)
+ return (UInt64) (FakeSeconds * NanosPerSecond);
+
// TODO: prefer rdtsc when available?
UInt64 result;
@@ -207,17 +276,10 @@ UInt64 Timer::GetRawTicks()
result = (UInt64)tv.tv_sec * 1000000;
result += tv.tv_usec;
- return result;
-}
-
-UInt64 Timer::GetRawFrequency()
-{
- return MksPerSecond;
+ return result * 1000;
}
-#endif // !OVR_OS_ANDROID
-
-#endif // !OVR_OS_WIN32
+#endif // OS-specific
diff --git a/LibOVR/Src/Kernel/OVR_Timer.h b/LibOVR/Src/Kernel/OVR_Timer.h
index 937b2cd..12cba3b 100644
--- a/LibOVR/Src/Kernel/OVR_Timer.h
+++ b/LibOVR/Src/Kernel/OVR_Timer.h
@@ -6,16 +6,16 @@ Content : Provides static functions for precise timing
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -43,62 +43,32 @@ class Timer
public:
enum {
MsPerSecond = 1000, // Milliseconds in one second.
- MksPerMs = 1000, // Microseconds in one millisecond.
- MksPerSecond = MsPerSecond * MksPerMs
+ NanosPerSecond = MsPerSecond * 1000 * 1000,
+ MksPerSecond = MsPerSecond * 1000
};
-
// ***** Timing APIs for Application
+
// These APIs should be used to guide animation and other program functions
// that require precision.
- // Returns ticks in milliseconds, as a 32-bit number. May wrap around every
- // 49.2 days. Use either time difference of two values of GetTicks to avoid
- // wrap-around. GetTicksMs may perform better then GetTicks.
- static UInt32 OVR_STDCALL GetTicksMs();
-
- // GetTicks returns general-purpose high resolution application timer value,
- // measured in microseconds (mks, or 1/1000000 of a second). The actual precision
- // is system-specific and may be much lower, such as 1 ms.
- static UInt64 OVR_STDCALL GetTicks();
-
// Returns global high-resolution application timer in seconds.
- static double OVR_STDCALL GetSeconds();
-
-
- // ***** Profiling APIs.
- // These functions should be used for profiling, but may have system specific
- // artifacts that make them less appropriate for general system use.
- // On Win32, for example these rely on QueryPerformanceConter may have
- // problems with thread-core switching and power modes.
-
- // Return a hi-res timer value in mks (1/1000000 of a sec).
- // Generally you want to call this at the start and end of an
- // operation, and pass the difference to
- // TicksToSeconds() to find out how long the operation took.
- static UInt64 OVR_STDCALL GetProfileTicks();
-
- // More convenient zero-based profile timer in seconds. First call initializes
- // the "zero" value; future calls return the difference. Not thread safe for first call.
- // Due to low precision of Double, may malfunction after long runtime.
- static double OVR_STDCALL GetProfileSeconds();
-
- // Get the raw cycle counter value, providing the maximum possible timer resolution.
- static UInt64 OVR_STDCALL GetRawTicks();
- static UInt64 OVR_STDCALL GetRawFrequency();
-
-
- // ***** Tick and time unit conversion.
-
- // Convert micro-second ticks value into seconds value.
- static inline double TicksToSeconds(UInt64 ticks)
- {
- return static_cast<double>(ticks) * (1.0 / (double)MksPerSecond);
- }
- // Convert Raw or frequency-unit ticks to seconds based on specified frequency.
- static inline double RawTicksToSeconds(UInt64 rawTicks, UInt64 rawFrequency)
- {
- return static_cast<double>(rawTicks) * rawFrequency;
+ static double OVR_STDCALL GetSeconds();
+
+ // Returns time in Nanoseconds, using highest possible system resolution.
+ static UInt64 OVR_STDCALL GetTicksNanos();
+
+ // Kept for compatibility.
+ // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 49.2 days.
+ // Use either time difference of two values of GetTicks to avoid wrap-around.
+ static UInt32 OVR_STDCALL GetTicksMs()
+ { return UInt32(GetTicksNanos() / 1000000); }
+
+ // for recorded data playback
+ static void SetFakeSeconds(double fakeSeconds)
+ {
+ FakeSeconds = fakeSeconds;
+ useFakeSeconds = true;
}
private:
@@ -106,12 +76,11 @@ private:
// System called during program startup/shutdown.
static void initializeTimerSystem();
static void shutdownTimerSystem();
-};
-
-
-// Global high-resolution time in seconds. This is intended to replace Timer class in OVR.
-double ovr_GetTimeInSeconds();
+ // for recorded data playback
+ static double FakeSeconds;
+ static bool useFakeSeconds;
+};
} // OVR::Timer
diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h
index 6b2922e..f45df59 100644
--- a/LibOVR/Src/Kernel/OVR_Types.h
+++ b/LibOVR/Src/Kernel/OVR_Types.h
@@ -6,16 +6,16 @@ Content : Standard library defines and simple types
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
@@ -140,6 +140,8 @@ limitations under the License.
// MSVC 8.0 (VC2005) = 1400
// MSVC 9.0 (VC2008) = 1500
// MSVC 10.0 (VC2010) = 1600
+// MSVC 11.0 (VC2012) = 1700
+// MSVC 12.0 (VC2013) = 1800
# define OVR_CC_MSVC _MSC_VER
#elif defined(__GNUC__)
@@ -159,11 +161,9 @@ limitations under the License.
// Disable MSVC warnings
#if defined(OVR_CC_MSVC)
# pragma warning(disable : 4127) // Inconsistent dll linkage
-# pragma warning(disable : 4514) // Unreferenced inline function has been removed
# pragma warning(disable : 4530) // Exception handling
-# pragma warning(disable : 4711) // function 'x()' selected for automatic inline expansion
-# pragma warning(disable : 4820) // 'n' bytes padding added after data member 'item'
# if (OVR_CC_MSVC<1300)
+# pragma warning(disable : 4514) // Unreferenced inline function has been removed
# pragma warning(disable : 4710) // Function not inlined
# pragma warning(disable : 4714) // _force_inline not inlined
# pragma warning(disable : 4786) // Debug variable name longer than 255 chars
@@ -195,12 +195,14 @@ limitations under the License.
# include <stdlib.h>
# include <crtdbg.h>
+#if 0
// Uncomment this to help debug memory leaks under Visual Studio in OVR apps only.
// This shouldn't be defined in customer releases.
# ifndef OVR_DEFINE_NEW
# define OVR_DEFINE_NEW new(__FILE__, __LINE__)
# define new OVR_DEFINE_NEW
# endif
+#endif
#endif
@@ -374,6 +376,7 @@ namespace BaseTypes
// If not in debug build, macros do nothing
#ifndef OVR_BUILD_DEBUG
+# define OVR_DEBUG_CODE(c) c
# define OVR_DEBUG_BREAK ((void)0)
# define OVR_ASSERT(p) ((void)0)
@@ -399,6 +402,8 @@ namespace BaseTypes
# define OVR_DEBUG_BREAK do { *((int *) 0) = 1; } while(0)
#endif
+#define OVR_DEBUG_CODE(c)
+
// This will cause compiler breakpoint
#define OVR_ASSERT(p) do { if (!(p)) { OVR_DEBUG_BREAK; } } while(0)
diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp
index 9d337a7..f8aa697 100644
--- a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp
+++ b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp
@@ -7,16 +7,16 @@ Notes :
Notes : Much useful info at "UTF-8 and Unicode FAQ"
http://www.cl.cam.ac.uk/~mgk25/unicode.html
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.h b/LibOVR/Src/Kernel/OVR_UTF8Util.h
index 9509629..6a596012 100644
--- a/LibOVR/Src/Kernel/OVR_UTF8Util.h
+++ b/LibOVR/Src/Kernel/OVR_UTF8Util.h
@@ -6,22 +6,23 @@ Content : UTF8 Unicode character encoding/decoding support
Created : September 19, 2012
Notes :
-Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
+Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
-Licensed under the Oculus VR SDK License Version 2.0 (the "License");
-you may not use the Oculus VR SDK except in compliance with the License,
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
+you may not use the Oculus VR Rift SDK except in compliance with the License,
which is provided at the time of installation or download, or which
otherwise accompanies this software in either electronic or hard copy form.
You may obtain a copy of the License at
-http://www.oculusvr.com/licenses/LICENSE-2.0
+http://www.oculusvr.com/licenses/LICENSE-3.1
Unless required by applicable law or agreed to in writing, the Oculus VR SDK
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+
************************************************************************************/
#ifndef OVR_UTF8Util_h