//-------------------------------------------------------------------------------------- // Name: FilterAdaptiveDoubleExponential::UpdateSmoothingParameters() // Desc: Updates the smoothing parameters based on the smoothing filter's trend //-------------------------------------------------------------------------------------- VOID FilterAdaptiveDoubleExponential::Update( const NUI_SKELETON_DATA* pSkeletonData, const FLOAT fDeltaTime ) { for (UINT i = 0; i < NUI_SKELETON_POSITION_COUNT; i++) { XMVECTOR vPreviousPosition = m_DoubleExponentialFilter.m_History[ i ].m_vRawPosition; XMVECTOR vCurrentPosition = pSkeletonData->SkeletonPositions[ i ]; XMVECTOR vVelocity = ( vCurrentPosition - vPreviousPosition ) / fDeltaTime; FLOAT fVelocity = fabsf( XMVectorGetX( XMVector3Length( vVelocity ) ) ); UpdateSmoothingParameters( i, fVelocity, pSkeletonData->eSkeletonPositionTrackingState[i] ); m_DoubleExponentialFilter.Update( pSkeletonData, i, m_SmoothingParams[ i ] ); } // Copy filtered data to output data XMemCpy( m_FilteredJoints, m_DoubleExponentialFilter.GetFilteredJoints(), sizeof( m_FilteredJoints ) ); }
//-------------------------------------------------------------------------------------- // Name: CreatePooledVertexDeclaration() // Desc: Function to coalesce vertex declarations into a shared pool of vertex declarations //-------------------------------------------------------------------------------------- HRESULT WINAPI CreatePooledVertexDeclaration( const D3DVERTEXELEMENT9* pVertexElements, D3DVertexDeclaration** ppVertexDeclaration ) { static std::vector <VTX_DECL> m_VertexDecls; // Count the number of vertex elements DWORD dwNumElements = 0; while( pVertexElements[dwNumElements].Stream < 16 ) dwNumElements++; assert( dwNumElements <= MAXD3DDECLLENGTH ); // Check for a previously-created vertex decl for( unsigned int i = 0; i < m_VertexDecls.size(); i++ ) { if( ( m_VertexDecls[i].dwNumElements == dwNumElements ) && ( !memcmp( m_VertexDecls[i].pElements, pVertexElements, sizeof( D3DVERTEXELEMENT9 ) * dwNumElements ) ) ) { // If found, return it ( *ppVertexDeclaration ) = m_VertexDecls[i].pDeclaration; return S_OK; } } // No previously-created vertex decl was found, so create one ( *ppVertexDeclaration ) = D3DDevice_CreateVertexDeclaration( pVertexElements ); // And save a record of it VTX_DECL d; XMemCpy( d.pElements, pVertexElements, sizeof( D3DVERTEXELEMENT9 ) * dwNumElements ); d.dwNumElements = dwNumElements; d.pDeclaration = ( *ppVertexDeclaration ); d.pDeclaration->AddRef(); m_VertexDecls.push_back( d ); return S_OK; }
//-------------------------------------------------------------------------------------- // Name: FilterAdaptiveDoubleExponential::UpdateSmoothingParameters() // Desc: Updates the smoothing parameters of a joint based on he current joint velocity //-------------------------------------------------------------------------------------- VOID FilterAdaptiveDoubleExponential::UpdateSmoothingParameters( UINT i, FLOAT fVelocity, NUI_SKELETON_POSITION_TRACKING_STATE eTrackingState ) { NUI_TRANSFORM_SMOOTH_PARAMETERS LerpedParams; static const FLOAT fBigJitterThreshold = 5.0f; // meters per second static const FLOAT fLowLatencyThreshold = 1.5f; // meters per second static const FLOAT fHighLatencyThreshold = 0.25f; // meters per second BOOL bDetectBigJitter = FALSE; // Parameters for hands should should be the same as wrists, otherwise they look unnatural switch( i ) { case NUI_SKELETON_POSITION_HAND_LEFT: XMemCpy( &m_SmoothingParams[ NUI_SKELETON_POSITION_HAND_LEFT ], &m_SmoothingParams[ NUI_SKELETON_POSITION_WRIST_LEFT ], sizeof( NUI_TRANSFORM_SMOOTH_PARAMETERS ) ); break; case NUI_SKELETON_POSITION_HAND_RIGHT: XMemCpy( &m_SmoothingParams[ NUI_SKELETON_POSITION_HAND_RIGHT ], &m_SmoothingParams[ NUI_SKELETON_POSITION_WRIST_RIGHT ], sizeof( NUI_TRANSFORM_SMOOTH_PARAMETERS ) ); break; case NUI_SKELETON_POSITION_FOOT_LEFT: XMemCpy( &m_SmoothingParams[ NUI_SKELETON_POSITION_FOOT_LEFT ], &m_SmoothingParams[ NUI_SKELETON_POSITION_ANKLE_LEFT ], sizeof( NUI_TRANSFORM_SMOOTH_PARAMETERS ) ); break; case NUI_SKELETON_POSITION_FOOT_RIGHT: XMemCpy( &m_SmoothingParams[ NUI_SKELETON_POSITION_FOOT_RIGHT ], &m_SmoothingParams[ NUI_SKELETON_POSITION_ANKLE_RIGHT ], sizeof( NUI_TRANSFORM_SMOOTH_PARAMETERS ) ); break; default: { // Lerp between high and low latency params FLOAT fLerp = max( 0.0f, min( 1.0f, ( fVelocity - fHighLatencyThreshold ) / ( fLowLatencyThreshold - fHighLatencyThreshold ) ) ); // Detected a big jitter if ( fVelocity > fBigJitterThreshold || fLerp - m_fPreviousLerp[ i ] > 0.999f ) { bDetectBigJitter = TRUE; fLerp = ( fLerp * 0.25f ) + ( m_fPreviousLerp[ i ] * 0.75f ); } m_fPreviousLerp[ i ] = fLerp; LerpedParams.fSmoothing = m_HighLatencySmoothingParams.fSmoothing + fLerp * ( m_LowLatencySmoothingParams.fSmoothing - m_HighLatencySmoothingParams.fSmoothing ); LerpedParams.fCorrection = m_HighLatencySmoothingParams.fCorrection + fLerp * ( m_LowLatencySmoothingParams.fCorrection - m_HighLatencySmoothingParams.fCorrection ); LerpedParams.fPrediction = m_HighLatencySmoothingParams.fPrediction + fLerp * ( m_LowLatencySmoothingParams.fPrediction - m_HighLatencySmoothingParams.fPrediction ); LerpedParams.fJitterRadius = m_HighLatencySmoothingParams.fJitterRadius + fLerp * ( m_LowLatencySmoothingParams.fJitterRadius - m_HighLatencySmoothingParams.fJitterRadius ); LerpedParams.fMaxDeviationRadius = m_HighLatencySmoothingParams.fMaxDeviationRadius + fLerp * ( m_LowLatencySmoothingParams.fMaxDeviationRadius - m_HighLatencySmoothingParams.fMaxDeviationRadius ); XMemCpy( &m_SmoothingParams[ i ], &LerpedParams, sizeof( NUI_TRANSFORM_SMOOTH_PARAMETERS ) ); } } if ( bDetectBigJitter ) { m_SmoothingParams[ i ].fJitterRadius *= 2.0f; m_SmoothingParams[ i ].fMaxDeviationRadius *= 2.0f; m_SmoothingParams[ i ].fPrediction /= 2.0f; } else if ( eTrackingState == NUI_SKELETON_POSITION_INFERRED ) { // if the joint is not tracked, but inferred, we make sure it gets smoothed more by doubling the jitter radius m_SmoothingParams[ i ].fJitterRadius *= 2.0f; m_SmoothingParams[ i ].fMaxDeviationRadius *= 2.0f; } }
//-------------------------------------------------------------------------------------- // Name: NuiMenu::SetMenuSettings() // Desc: CHnages the settings for this object. //-------------------------------------------------------------------------------------- VOID NuiMenu::SetMenuSettings( const NUI_MENU_SETTINGS* pNuiMenuSettings ) { assert( pNuiMenuSettings != NULL ); XMemCpy( &m_settings, pNuiMenuSettings, sizeof( NUI_MENU_SETTINGS ) ); }
//-------------------------------------------------------------------------------------- // Name: NuiMenu::GetMenuSettings() // Desc: Obtains the current menu settings. //-------------------------------------------------------------------------------------- VOID NuiMenu::GetMenuSettings( NUI_MENU_SETTINGS* pNuiMenuSettings ) const { assert( pNuiMenuSettings != NULL ); XMemCpy( pNuiMenuSettings, &m_settings, sizeof( NUI_MENU_SETTINGS ) ); }