LeapUtil.h
Go to the documentation of this file.
00001 /******************************************************************************\
00002 * Copyright (C) Leap Motion, Inc. 2011-2013.                                   *
00003 * Leap Motion proprietary and  confidential.  Not for distribution.            *
00004 * Use subject to the terms of the Leap Motion SDK Agreement available at       *
00005 * https://developer.leapmotion.com/sdk_agreement, or another agreement between *
00006 * Leap Motion and you, your company or other organization.                     *
00007 \******************************************************************************/
00008 
00009 #ifndef __LeapUtil_h__
00010 #define __LeapUtil_h__
00011 
00012 #include "Leap.h"
00013 
00014 // Define integer types for Visual Studio 2005
00015 #if defined(_MSC_VER) && (_MSC_VER < 1600)
00016 typedef __int8 int8_t;
00017 typedef __int16 int16_t;
00018 typedef unsigned __int8 uint8_t;
00019 typedef unsigned __int16 uint16_t;
00020 #endif
00021 
00022 namespace LeapUtil {
00023 
00030 
00039 
00040 static const float kfPi       = Leap::PI;
00041 static const float kf2Pi      = kfPi + kfPi;
00042 static const float kfHalfPi   = kfPi * 0.5f;
00043 static const float kfEpsilon  = 0.00001f;
00044 
00045 template<typename T>
00046 T Min( T lhs, T rhs )
00047 {
00048   return lhs < rhs ? lhs : rhs;
00049 }
00050 
00051 template<typename T>
00052 T Max( T lhs, T rhs )
00053 {
00054   return lhs > rhs ? lhs : rhs;
00055 }
00056 
00057 template<typename T>
00058 T Clamp( T inVal, T minVal, T maxVal )
00059 {
00060   return (inVal < minVal) ? minVal : ((inVal > maxVal) ? maxVal : inVal);
00061 }
00062 
00064 template<typename InterpType, typename ParamType>
00065 InterpType Linterp( InterpType a, InterpType b, ParamType t )
00066 {
00067   return a + static_cast<InterpType>((b - a) * t);
00068 }
00069 
00071 template<class Vec2>
00072 Leap::Vector FromVector2( const Vec2& vIn, float fZ = 0.0f )
00073 {
00074   return Leap::Vector( static_cast<float>(vIn.x), static_cast<float>(vIn.y), fZ );
00075 }
00076 
00078 template<class Vec3>
00079 Leap::Vector FromVector3( const Vec3& vIn )
00080 {
00081   return Leap::Vector( static_cast<float>(vIn.x), static_cast<float>(vIn.y), static_cast<float>(vIn.z) );
00082 }
00083 
00084 inline bool IsNearZero( float fVal )
00085 {
00086  return fabs(fVal) <= kfEpsilon;
00087 }
00088 
00089 inline bool IsNearZero( const Leap::Vector& vVec )
00090 {
00091   return IsNearZero(vVec.x) && IsNearZero(vVec.y) && IsNearZero(vVec.z);
00092 }
00093 
00095 template<typename T>
00096 inline bool IsNearEqual( const T& a, const T& b )
00097 {
00098   return IsNearZero( a - b );
00099 }
00100 
00102 inline Leap::Matrix ExtractRotation( const Leap::Matrix& mtxTransform )
00103 {
00104   return Leap::Matrix( mtxTransform.xBasis, mtxTransform.yBasis, mtxTransform.zBasis );
00105 }
00106 
00108 inline Leap::Matrix RotationInverse( const Leap::Matrix& mtxRot )
00109 {
00110   return Leap::Matrix(  Leap::Vector( mtxRot.xBasis.x, mtxRot.yBasis.x, mtxRot.zBasis.x ),
00111                         Leap::Vector( mtxRot.xBasis.y, mtxRot.yBasis.y, mtxRot.zBasis.y ),
00112                         Leap::Vector( mtxRot.xBasis.z, mtxRot.yBasis.z, mtxRot.zBasis.z ) );
00113 }
00114 
00117 inline Leap::Matrix RigidInverse( const Leap::Matrix& mtxTransform )
00118 {
00119   Leap::Matrix  rigidInverse = RotationInverse( mtxTransform );
00120   rigidInverse.origin  = rigidInverse.transformDirection( -mtxTransform.origin );
00121   return rigidInverse;
00122 }
00123 
00124 inline Leap::Vector ComponentWiseMin( const Leap::Vector& vLHS, const Leap::Vector& vRHS )
00125 {
00126   return Leap::Vector( Min( vLHS.x, vRHS.x ), Min( vLHS.y, vRHS.y ), Min( vLHS.z, vRHS.z ) );
00127 }
00128 
00129 inline Leap::Vector ComponentWiseMax( const Leap::Vector& vLHS, const Leap::Vector& vRHS )
00130 {
00131   return Leap::Vector( Max( vLHS.x, vRHS.x ), Max( vLHS.y, vRHS.y ), Max( vLHS.z, vRHS.z ) );
00132 }
00133 
00134 inline Leap::Vector ComponentWiseScale( const Leap::Vector& vLHS, const Leap::Vector& vRHS )
00135 {
00136   return Leap::Vector( vLHS.x * vRHS.x, vLHS.y * vRHS.y, vLHS.z * vRHS.z );
00137 }
00138 
00139 inline Leap::Vector ComponentWiseReciprocal( const Leap::Vector& vVec )
00140 {
00141   return Leap::Vector( 1.0f/vVec.x, 1.0f/vVec.y, 1.0f/vVec.z );
00142 }
00143 
00144 inline float MinComponent( const Leap::Vector& vVec )
00145 {
00146   return Min( vVec.x, Min( vVec.y, vVec.z ) );
00147 }
00148 
00149 inline float MaxComponent( const Leap::Vector& vVec )
00150 {
00151   return Max( vVec.x, Max( vVec.y, vVec.z ) );
00152 }
00153 
00155 inline float Heading( const Leap::Vector& vVec )
00156 {
00157   return atan2f( vVec.z, vVec.x );
00158 }
00159 
00161 inline float Elevation( const Leap::Vector& vVec )
00162 {
00163   return atan2f( vVec.y, sqrtf(vVec.z * vVec.z + vVec.x * vVec.x) );
00164 }
00165 
00168 inline Leap::Vector CartesianToSpherical( const Leap::Vector& vCartesian )
00169 {
00170   return Leap::Vector( vCartesian.magnitude(), Heading(vCartesian), Elevation(vCartesian) );
00171 }
00172 
00174 inline Leap::Vector NormalizeSpherical( const Leap::Vector& vSpherical )
00175 {
00176   float fHeading  = vSpherical.y;
00177   float fElevation = vSpherical.z;
00178 
00179   for ( ; fElevation <= -kfPi; fElevation += kf2Pi );
00180   for ( ; fElevation > kfPi; fElevation -= kf2Pi );
00181 
00182   if ( fabs(fElevation) > kfHalfPi )
00183   {
00184     fHeading += kfPi;
00185     fElevation = fElevation > 0 ? (kfPi - fElevation) : -(kfPi + fElevation);
00186   }
00187 
00188   for ( ; fHeading <= -kfPi; fHeading += kf2Pi );
00189   for ( ; fHeading > kfPi; fHeading -= kf2Pi );
00190 
00191   return Leap::Vector( 1, fHeading, fElevation );
00192 }
00193 
00196 inline Leap::Vector SphericalToCartesian( const Leap::Vector& vSpherical )
00197 {
00198   const float fMagnitude    = vSpherical.x;
00199   const float fCosHeading   = cosf( vSpherical.y );
00200   const float fSinHeading   = sinf( vSpherical.y );
00201   const float fCosElevation = cosf( vSpherical.z );
00202   const float fSinElevation = sinf( vSpherical.z );
00203 
00204   return Leap::Vector(  fCosHeading   * fCosElevation  * fMagnitude,
00205                                         fSinElevation  * fMagnitude,
00206                         fSinHeading   * fCosElevation  * fMagnitude);
00207 }
00208 
00209 inline const char* BoolToStr( uint32_t bVal )
00210 {
00211   return bVal ? "On" : "Off";
00212 }
00213 
00214 template<int _HistoryLength=256>
00215 class RollingAverage
00216 {
00217 public:
00218   enum
00219   {
00220     kHistoryLength = _HistoryLength
00221   };
00222 
00223 public:
00224   RollingAverage() { Reset(); }
00225 
00226   void Reset()
00227   {
00228     m_uiCurIndex  = 0;
00229     m_fNumSamples = 0.0f;
00230     m_fSum        = 0.0f;
00231     m_fAverage    = 0.0f;
00232     for ( int i = 0; i < kHistoryLength; m_afSamples[i++] = 0.0f );
00233   }
00234 
00235   float AddSample( float fSample )
00236   {
00237     m_fNumSamples =   Min( (m_fNumSamples + 1.0f), static_cast<float>(kHistoryLength) );
00238     m_fSum        -=  m_afSamples[m_uiCurIndex];
00239     m_fSum        +=  fSample;
00240     m_fAverage    =   m_fSum * (1.0f/m_fNumSamples);
00241 
00242     m_afSamples[m_uiCurIndex] = fSample;
00243 
00244     m_uiCurIndex = static_cast<uint32_t>((m_uiCurIndex + 1) % kHistoryLength);
00245 
00246     return m_fAverage;
00247   }
00248 
00249   float     GetAverage()    const { return m_fAverage; }
00250   float     GetSum()        const { return m_fSum; }
00251   uint32_t  GetNumSamples() const { return static_cast<uint32_t>(m_fNumSamples); }
00252 
00254   float     operator[](uint32_t uiIdx) const { return m_afSamples[(m_uiCurIndex + uiIdx) % kHistoryLength]; }
00255 
00256 private:
00257   uint32_t      m_uiCurIndex;
00258   float         m_fNumSamples;
00259   float         m_fSum;
00260   float         m_fAverage;
00261   float         m_afSamples[kHistoryLength];
00262 };
00263 
00271 class Camera
00272 {
00273 public:
00274   Camera()
00275     : m_fOrbitDistance(-1.0f),
00276       m_fMaxOrbitLatitude( LeapUtil::kfPi * 0.375f ),
00277       m_fNearClip( 0.1f ),
00278       m_fFarClip( 128.0f ),
00279       m_fVerticalFOVDegrees( 40.0f ),
00280       m_fAspectRatio( 4.0f/3.0f )
00281   {}
00282 
00284   const Leap::Matrix& GetPOV() const { return m_mtxPOV; }
00285 
00286   void SetPOV( const Leap::Matrix& mtxPOV ) { m_mtxPOV = mtxPOV; }
00287 
00290   Leap::Matrix GetView() const { return LeapUtil::RigidInverse(m_mtxPOV); }
00291 
00293   const Leap::Vector& GetPosition() const { return m_mtxPOV.origin; }
00294 
00295   void SetPosition( const Leap::Vector& vPos ) { m_mtxPOV.origin = vPos; }
00296 
00298   Leap::Matrix GetRotation() const { return LeapUtil::ExtractRotation(m_mtxPOV); }
00299 
00300   void SetRotation( const Leap::Vector& vAxis, float fRadians ) { m_mtxPOV.setRotation( vAxis, fRadians ); }
00301 
00302   void SetRotation( const Leap::Matrix& mtxRot )
00303   {
00304     m_mtxPOV.xBasis = mtxRot.xBasis;
00305     m_mtxPOV.yBasis = mtxRot.yBasis;
00306     m_mtxPOV.zBasis = mtxRot.zBasis;
00307   }
00308 
00310   void SetPOVLookAt( const Leap::Vector& vCameraPosition, const Leap::Vector& vTarget, Leap::Vector vUp = Leap::Vector::yAxis() );
00311 
00313   void SetRotationLookAt( const Leap::Vector& vTarget, const Leap::Vector& vUp = Leap::Vector::yAxis() )
00314   {
00315     SetPOVLookAt( m_mtxPOV.origin, vTarget, vUp );
00316   }
00317 
00319   void Move( const Leap::Vector& vDeltaPos )
00320   {
00321     m_mtxPOV.origin += vDeltaPos;
00322   }
00323 
00325   void Rotate( const Leap::Matrix& mtxRotation )
00326   {
00327     m_mtxPOV = m_mtxPOV * LeapUtil::ExtractRotation(mtxRotation);
00328   }
00329 
00330   void Rotate( const Leap::Vector& vAxis, float fRadians )
00331   {
00332     m_mtxPOV = m_mtxPOV * Leap::Matrix( vAxis, fRadians );
00333   }
00334 
00336   const Leap::Vector& GetOrbitTarget() const
00337   {
00338     return m_vOrbitTarget;
00339   }
00340 
00341   void SetOrbitTarget( const Leap::Vector& vOrbitTarget)
00342   {
00343     m_vOrbitTarget = vOrbitTarget;
00344     updateOrbitDistance();
00345   }
00346 
00352   void RotateOrbit( float fDeltaMagnitude, float fDeltaLongitude, float fDeltaLatitude );
00353 
00356   float GetMaxOrbitLatitude() const
00357   {
00358     return m_fMaxOrbitLatitude;
00359   }
00360 
00361   void SetMaxOrbitLatitude( float fMaxOrbitLatitude )
00362   {
00363     m_fMaxOrbitLatitude = fMaxOrbitLatitude;
00364   }
00365 
00368   float CalcViewDepth( const Leap::Vector& vPos ) const
00369   {
00370     return m_mtxPOV.zBasis.dot( m_mtxPOV.origin - vPos );
00371   }
00372 
00374 
00375   void OnMouseWheel( float fDeltaZ );
00376 
00377   void OnMouseDown( const Leap::Vector& vMousePos );
00378 
00379   void OnMouseMoveOrbit( const Leap::Vector& vMousePos );
00380 
00381   float GetNearClip() const { return m_fNearClip; }
00382 
00383   float GetFarClip() const { return m_fFarClip; }
00384 
00385   void SetNearClip( float fNearClip ) { m_fNearClip = Max( 0.01f, fNearClip ); }
00386 
00387   void SetFarClip( float fFarClip ) { m_fFarClip = fFarClip; }
00388 
00389   void SetClipPlanes( float fNearClip, float fFarClip )
00390   {
00391     SetNearClip( fNearClip );
00392     SetFarClip( fFarClip );
00393   }
00394 
00395   float GetVerticalFOVDegrees() const { return m_fVerticalFOVDegrees; }
00396 
00397   void SetVerticalFOVDegrees( float fFOV ) { m_fVerticalFOVDegrees = fFOV; }
00398 
00399   float GetAspectRatio() const { return m_fAspectRatio; }
00400 
00401   void SetAspectRatio( float fAspectRatio ) { m_fAspectRatio = fAspectRatio; }
00402 
00403 private:
00404   void updateOrbitDistance()
00405   {
00406     float fOrbitDistance = (m_vOrbitTarget - m_mtxPOV.origin).magnitude();
00407 
00408     if ( !IsNearZero( fOrbitDistance - m_fOrbitDistance ) )
00409     {
00410       m_fOrbitDistance  = fOrbitDistance;
00411     }
00412   }
00413 
00414 private:
00415   Leap::Matrix  m_mtxPOV;
00416   Leap::Vector  m_vLastMousePos;
00417   Leap::Vector  m_vOrbitTarget;
00418   float         m_fOrbitDistance;
00419   float         m_fMaxOrbitLatitude;
00420   float         m_fNearClip;
00421   float         m_fFarClip;
00422   float         m_fVerticalFOVDegrees;
00423   float         m_fAspectRatio;
00424 };
00425 
00426 
00428 class ScrollMomentum {
00429 public:
00430   ScrollMomentum()
00431     : m_vDirection(Leap::Vector::yAxis()),
00432       m_fScrollSize(512.0f),
00433       m_fSpeed(0),
00434       m_fMinSpeed(0.125f),
00435       m_fDrag(0.4f),
00436       m_fDragPower(2.0f),
00437       m_fFixedTimeStep(1.0f/60.0f),
00438       m_fPendingDeltaTime(0.0f)
00439   {}
00440 
00445   const Leap::Vector& getPosition() const                             { return m_vPosition; }
00446   void                setPosition( const Leap::Vector& vPosition )    { m_vPosition = vPosition; }
00447 
00451   const Leap::Vector& getDirection() const                            { return m_vDirection; }
00452   void                setDirection( const Leap::Vector& vDirection )  { m_vDirection = vDirection.normalized(); }
00453 
00462   float               getScrollSize() const                                 { return m_fScrollSize; }
00463   void                setScrollSize( float fScrollSize )                    { m_fScrollSize = (fScrollSize > 0.0f ? fScrollSize : 1.0f); }
00464 
00471   float               getSpeed() const                                      { return m_fSpeed; }
00472   void                setSpeed( float fSpeed )                              { m_fSpeed = fSpeed; }
00473 
00478   float               getMinSpeed() const                                   { return m_fMinSpeed; }
00479   void                setMinSpeed( float fMinSpeed )                        { m_fMinSpeed = fabs(fMinSpeed); }
00480 
00485   float               getFixedTimeStep() const                              { return m_fMinSpeed; }
00486   void                setFixedTimeStep( float fFixedTimeStep )              { m_fFixedTimeStep = fabs(fFixedTimeStep); }
00487 
00491   float               getDrag() const                                       { return m_fDrag; }
00492   void                setDrag( float fDrag )                                { m_fDrag = fabs(fDrag); }
00493 
00498   float               getDragPower() const                                  { return m_fDragPower; }
00499   void                setDragPower( float fDragPower )                      { m_fDragPower = fDragPower; }
00500 
00503   const Leap::Vector  getVelocity() const                             { return m_vDirection * m_fSpeed; }
00504 
00507   void setVelocity( const Leap::Vector& vDirection, float fSpeed )
00508   {
00509     setDirection( vDirection );
00510     setSpeed( fSpeed );
00511   }
00512 
00519   void  update( float fDeltaTimeSeconds )
00520   {
00521     if ( fDeltaTimeSeconds <= 0.0f )
00522     {
00523       return;
00524     }
00525 
00526     if ( fabs(m_fSpeed) > m_fMinSpeed )
00527     {
00528       if ( m_fDrag > 0 )
00529       {
00530         // only force to fixed time step if doing drag calculation
00531 
00532         const float fMinScrollSpeed = m_fMinSpeed / m_fScrollSize;
00533         // fold the sign of speed into the scaling factor
00534         const float fScrollScale    = (m_fSpeed < 0.0f ? -1.0f : 1.0f) * m_fScrollSize;
00535         // absolute value of scaled speed (_scrollScale has same sign as speed, guaranteeing positive value)
00536         float fScrollSpeed          = m_fSpeed / fScrollScale;
00537 
00538         // include any left over time from previous update in the time to process for this update.
00539         fDeltaTimeSeconds += m_fPendingDeltaTime;
00540 
00541         // process time since last update in fixed chunks
00542         for ( ; fDeltaTimeSeconds >= m_fFixedTimeStep; fDeltaTimeSeconds -= m_fFixedTimeStep )
00543         {
00544           const float fDragForce = powf( fScrollSpeed, m_fDragPower ) * m_fDrag;
00545 
00546           // decelerate unsigned/scaled speed by drag
00547           fScrollSpeed -= fDragForce * m_fFixedTimeStep;
00548 
00549           // bail out if speed has hit minimum threshold
00550           if ( fScrollSpeed <= fMinScrollSpeed )
00551           {
00552             m_fSpeed = 0.0f;
00553             fDeltaTimeSeconds = 0.0f;
00554             break;
00555           }
00556 
00557           // update signed/unscaled speed
00558           m_fSpeed = fScrollSpeed * fScrollScale;
00559 
00560           // step position by velocity
00561           m_vPosition += m_vDirection * (m_fFixedTimeStep * m_fSpeed);
00562         }
00563 
00564         // keep track of any leftover time not processed during this update.
00565         m_fPendingDeltaTime = fDeltaTimeSeconds;
00566       }
00567       else
00568       {
00569         // simple position change with velocity and no drag - not affected by large time steps. no looping needed.
00570         m_vPosition += m_vDirection * ((m_fPendingDeltaTime + fDeltaTimeSeconds) * m_fSpeed);
00571         m_fPendingDeltaTime = 0.0f;
00572       }
00573     }
00574     else
00575     {
00576       // enforce zeroing of speeds below minimum absolute value.
00577       m_fSpeed = 0.0f;
00578       m_fPendingDeltaTime = 0.0f;
00579     }
00580   }
00581 
00582 protected:
00583   Leap::Vector  m_vPosition;
00584   Leap::Vector  m_vDirection;
00585   float         m_fScrollSize;
00586   float         m_fSpeed;
00587   float         m_fMinSpeed;
00588   float         m_fDrag;
00589   float         m_fDragPower;
00590   float         m_fFixedTimeStep;
00591   float         m_fPendingDeltaTime;
00592 };
00593 
00594 
00596 template<typename T>
00597 class SmartInstanceDestructor
00598 {
00599 public:
00600   static void Destroy( T* pPointer ) { delete pPointer; }
00601 };
00602 
00604 template<typename T>
00605 class SmartArrayDestructor
00606 {
00607 public:
00608   static void Destroy( T* pPointer ) { delete[] pPointer; }
00609 };
00610 
00624 template< typename T,
00625           class Destructor = SmartInstanceDestructor<T>,
00626           unsigned int ManagedPointerPoolSize = 512 >
00627 class SmartPointer
00628 {
00629 public:
00630   enum { kManagedPointerPoolSize = ManagedPointerPoolSize };
00631 
00632   typedef T ManagedType;
00633 
00634 private:
00635   // a managed pointer is a pointer of the desired type plus a reference count.
00636   struct ManagedPointerEntry
00637   {
00638     ManagedType*  m_pPointer;
00639     uint32_t      m_uiRefCount;
00640   };
00641 
00642   // this private, embedded class manages a pool of smart pointers for the given type.
00643   // there are separate pools for each created type of smart pointer.
00644   // the pool is managed using a simple O(1) fixed size free list allocator
00645   struct ManagedPointerPool
00646   {
00647     enum { kPoolSize = kManagedPointerPoolSize, kDeadPointer = 0xdeadbea7 };
00648 
00649     ManagedPointerPool()
00650       : m_uiNextFree(0),
00651         m_uiNumAllocated(0)
00652     {
00653       for ( uint32_t i = 0; i < static_cast<uint32_t>(kPoolSize); i++ )
00654       {
00655         m_aEntryPool[i].m_pPointer    = reinterpret_cast<ManagedType*>(kDeadPointer);
00656         m_aEntryPool[i].m_uiRefCount  = i + 1;
00657       }
00658     }
00659 
00660     // allocate a managed pointer entry for a raw pointer
00661     ManagedPointerEntry* allocEntry( ManagedType* pPointer )
00662     {
00663       ManagedPointerEntry* pEntry = NULL;
00664 
00665       // this incurs a linear search penalty each time
00666       // we create a new smart pointer from a raw pointer
00667       // but adds significant safety - it prevents
00668       // assigning the same raw pointer to two different
00669       // member entries - this would result in double
00670       // deletion when the 2nd one hit its end of life.
00671       pEntry = findEntry( pPointer );
00672 
00673       if ( pEntry )
00674       {
00675         // we found an existing managed pointer entry, just increase the reference count
00676         pEntry->m_uiRefCount++;
00677       }
00678       else if ( (m_uiNextFree < kPoolSize) && pPointer )
00679       {
00680         // grab the next free entry from the head of the free list
00681         pEntry = m_aEntryPool + m_uiNextFree;
00682 
00683         // the head of the list now becomes the next free entry in the chain
00684         // (m_uiRefCount is serving double-duty as next index member for entries that are still in the pool)
00685         m_uiNextFree = pEntry->m_uiRefCount;
00686 
00687         // initialize the entry with the pointer and a reference count of 1.
00688         pEntry->m_pPointer = pPointer;
00689         pEntry->m_uiRefCount = 1;
00690 
00691         // book keeping.
00692         m_uiNumAllocated++;
00693       }
00694 
00695       return pEntry;
00696     }
00697 
00698     // return an entry to the pool
00699     void freeEntry( ManagedPointerEntry* pEntry )
00700     {
00701       // calculate the entry index as an offset from the start of the pool
00702       const uint32_t entryIndex = static_cast<uint32_t>(pEntry - m_aEntryPool);
00703 
00704       // if this is a valid allocated entry (from this pool, and not already freed)
00705       if (  (entryIndex < kPoolSize)  &&
00706             (m_uiNumAllocated != 0)   &&
00707             (pEntry->m_pPointer != reinterpret_cast<ManagedType*>(kDeadPointer)) )
00708       {
00709         // clear the entry
00710         pEntry->m_pPointer = NULL;
00711 
00712         // push it to the head of the free list
00713         pEntry->m_uiRefCount = m_uiNextFree;
00714         m_uiNextFree = entryIndex;
00715 
00716         // book keeping.
00717         m_uiNumAllocated--;
00718       }
00719     }
00720 
00721     // look for the managed pointer entry associated with a raw pointer. returns NULL
00722     // if pPointer is NULL, dead or not found.
00723     ManagedPointerEntry* findEntry( const ManagedType* pPointer )
00724     {
00725       // don't bother if the pointer is NULL or marked as our dead value
00726       if ( pPointer && (pPointer != reinterpret_cast<ManagedType*>(kDeadPointer)) )
00727       {
00728         // linear search. stop after testing as many live entries as are allocated instead of always
00729         // searching the entire pool.
00730         for ( uint32_t i = 0, j = 0; j < m_uiNumAllocated && i < static_cast<uint32_t>(kPoolSize); i++ )
00731         {
00732           // if the entry is live (allocated)
00733           if ( m_aEntryPool[i].m_pPointer != reinterpret_cast<ManagedType*>(kDeadPointer) )
00734           {
00735             // a match? return it.
00736             if ( m_aEntryPool[i].m_pPointer == pPointer )
00737             {
00738               return m_aEntryPool + i;
00739             }
00740 
00741             // not, increment the count of live entries encountered.
00742             j++;
00743           }
00744         }
00745       }
00746 
00747       return NULL;
00748     }
00749 
00750     // number of allocated managed pointer entries
00751     uint32_t getNumAllocated() const { return m_uiNumAllocated; }
00752 
00753     // number of available managed pointer entries.
00754     uint32_t getNumFree() const { return static_cast<uint32_t>(kPoolSize) - m_uiNumAllocated; }
00755 
00756     // actual entry pool
00757     ManagedPointerEntry m_aEntryPool[kPoolSize];
00758 
00759     // head of the free list
00760     uint32_t            m_uiNextFree;
00761 
00762     // number of entries that have been allocated from the free list
00763     uint32_t            m_uiNumAllocated;
00764   };
00765 
00766   // static instance of the managed pointer pool
00767   static ManagedPointerPool& s_pool()
00768   {
00769     static ManagedPointerPool _s_pool;
00770     return _s_pool;
00771   }
00772 
00774   void refInc()
00775   {
00776     if ( m_pManagedPointer )
00777     {
00778       m_pManagedPointer->m_uiRefCount++;
00779     }
00780   }
00781 
00785   void refDec()
00786   {
00787     if ( m_pManagedPointer )
00788     {
00789       if ( m_pManagedPointer->m_uiRefCount )
00790       {
00791         m_pManagedPointer->m_uiRefCount--;
00792       }
00793 
00794       if ( !m_pManagedPointer->m_uiRefCount )
00795       {
00796         Destructor::Destroy(m_pManagedPointer->m_pPointer);
00797         s_pool().freeEntry(m_pManagedPointer);
00798       }
00799 
00800       m_pManagedPointer = NULL;
00801     }
00802   }
00803 
00804 public:
00806   SmartPointer()
00807     : m_pManagedPointer(NULL)
00808   {
00809   }
00810 
00816   explicit SmartPointer( ManagedType* pManaged )
00817     : m_pManagedPointer( s_pool().allocEntry( pManaged ) )
00818   {
00819   }
00820 
00822   SmartPointer( const SmartPointer& rhs )
00823     : m_pManagedPointer( rhs.m_pManagedPointer )
00824   {
00825     refInc();
00826   }
00827 
00830   const SmartPointer& operator =( const SmartPointer& rhs )
00831   {
00832     if ( m_pManagedPointer != rhs.m_pManagedPointer )
00833     {
00834       refDec();
00835       m_pManagedPointer = rhs.m_pManagedPointer;
00836       refInc();
00837     }
00838 
00839     return *this;
00840   }
00841 
00843   ~SmartPointer()
00844   {
00845     refDec();
00846   }
00847 
00850   ManagedType* GetPointer() const { return m_pManagedPointer ? m_pManagedPointer->m_pPointer : NULL; }
00851 
00853   uint32_t GetRefCount() const { return m_pManagedPointer ? m_pManagedPointer->m_uiRefCount : 0u; }
00854 
00856   operator ManagedType*() const { return GetPointer(); }
00857 
00858   ManagedType* operator ->() const { return GetPointer(); }
00859 
00861   operator bool() const { return m_pManagedPointer != NULL; }
00862 
00863   bool operator !() const { return !m_pManagedPointer; }
00864 
00865   bool operator ==( const ManagedType* pPointer ) const { return GetPointer() == pPointer; }
00866 
00867   bool operator !=( const ManagedType* pPointer ) const { return GetPointer() != pPointer; }
00868 
00869   bool operator ==( const SmartPointer& rhs ) const { return m_pManagedPointer == rhs.m_pManagedPointer; }
00870 
00871   bool operator !=( const SmartPointer& rhs ) const { return m_pManagedPointer != rhs.m_pManagedPointer; }
00872 
00876   void Release()
00877   {
00878     refDec();
00879   }
00880 
00882   static const SmartPointer& Null()
00883   {
00884     static SmartPointer _s_null;
00885     return _s_null;
00886   }
00887 
00889   static bool IsManaged( const ManagedType* pPointer )
00890   {
00891     return s_pool().findEntry( pPointer ) != NULL;
00892   }
00893 
00896   static uint32_t GetNumManagedPointers() { return s_pool().getNumAllocated(); }
00897 
00898 private:
00899   ManagedPointerEntry* m_pManagedPointer;
00900 };
00901 
00902 } // namespace Leap
00903 
00904 #endif // __LeapUtil_h__


leap_motion
Author(s): Florian Lier , Mirza Shah , Isaac IY Saito
autogenerated on Sat Jun 8 2019 18:47:25