// ******************************************************************************** // // The spherical interpolation applies only to normal vectors Vec4 OrE::Math::Slerp(const Vec4& v1, const Vec4& v2, const float t) { float fOmega = Arccos( Clamp(v1.Dot(v2), -1.0f, 1.0f) ); //float fInvSin = 1.0f/Sin( fOmega ); float f1 = Sin( fOmega * (1.0f-t) );// * fInvSin; float f2 = Sin( fOmega * t );// * fInvSin; return Vec4( v1.x*f1+v2.x*f2, v1.y*f1+v2.y*f2, v1.z*f1+v2.z*f2, v1.w*f1+v2.w*f2 ).Normalize(); }
//-------------------------------------------------------------------------------------- // Name: CombiJointFilter() // Desc: A filter for the positional data. This filter uses a combination of velocity // position history to filter the joint positions. //-------------------------------------------------------------------------------------- void FilterCombination::Update( const SKinSkeletonRawData& pSkeletonData, const float fDeltaTime ) { // Process each joint for ( uint32 nJoint = 0; nJoint < KIN_SKELETON_POSITION_COUNT; ++nJoint ) { // Remember where the camera thinks this joint should be m_History[ nJoint ].m_vWantedPos = pSkeletonData.vSkeletonPositions[ nJoint ]; Vec4 vDelta; vDelta = m_History[ nJoint ].m_vWantedPos - m_History[ nJoint ].m_vLastWantedPos; { Vec4 vBlended; // Calculate the vBlended value - could optimize this by remembering the running total and // subtracting the oldest value and then adding the newest. Saves adding them all up on each frame. vBlended = Vec4(0,0,0,0); for( uint32 k = 0; k < m_nUseTaps; ++k) { vBlended = vBlended + m_History[ nJoint ].m_vPrevDeltas[k]; } vBlended = vBlended / ((float)m_nUseTaps); vBlended.w = 0.0f; vDelta.w = 0.0f; float fDeltaLength = vDelta.GetLength(); float fBlendedLength = vBlended.GetLength(); m_History[ nJoint ].m_fWantedLocalBlendRate = m_fDefaultApplyRate; m_History[ nJoint ].m_bActive[0] = false; m_History[ nJoint ].m_bActive[1] = false; m_History[ nJoint ].m_bActive[2] = false; // Does the current velocity and history have a reasonable magnitude? if( fDeltaLength >= m_fDeltaLengthThreshold && fBlendedLength >= m_fBlendedLengthThreshold ) { float fDotProd; float fConfidence; if( m_bDotProdNormalize ) { Vec4 vDeltaOne = vDelta; vDeltaOne.Normalize(); Vec4 vBlendedOne = vBlended; vBlendedOne.Normalize(); fDotProd = vDeltaOne.Dot( vBlendedOne ); } else { fDotProd = vDelta.Dot(vBlended); } // Is the current frame aligned to the recent history? if( fDotProd >= m_fDotProdThreshold ) { fConfidence = fDotProd; m_History[ nJoint ].m_fWantedLocalBlendRate = min( fConfidence, 1.0f ); m_History[ nJoint ].m_bActive[0] = true; } } assert( m_History[ nJoint ].m_fWantedLocalBlendRate <= 1.0f ); } // Push the previous deltas down the history for( int j = m_nUseTaps-2; j >= 0; --j ) { m_History[ nJoint ].m_vPrevDeltas[j+1] = m_History[ nJoint ].m_vPrevDeltas[j]; } // Store the current history m_History[ nJoint ].m_vPrevDeltas[0] = vDelta; // Remember where the camera thought this joint was on the this frame m_History[ nJoint ].m_vLastWantedPos = m_History[ nJoint ].m_vWantedPos; } // Secondary and tertiary blending for ( uint32 pass = 0; pass < 2; ++pass ) { for ( uint32 bone = 0; bone < g_numBones; ++bone ) { float fRate1; float fRate2; fRate1 = m_History[ g_Bones[bone].startJoint ].m_fWantedLocalBlendRate; fRate2 = m_History[ g_Bones[bone].endJoint ].m_fWantedLocalBlendRate; // Blend down? Start to end if( (fRate1 * m_fDownBlendRate) > fRate2) { // Yes, apply m_History[ g_Bones[bone].endJoint ].m_fWantedLocalBlendRate = ( fRate1 * m_fDownBlendRate ); // Flag m_History[ g_Bones[bone].endJoint ].m_bActive[pass+1] = true; } // Blend down? End to start if( ( fRate2 * m_fDownBlendRate ) > fRate1) { // Yes, apply m_History[ g_Bones[bone].startJoint ].m_fWantedLocalBlendRate = ( fRate2 * m_fDownBlendRate ); // Flag m_History[ g_Bones[bone].startJoint ].m_bActive[pass+1] = true; } } } // Apply for ( uint32 joint = 0; joint < KIN_SKELETON_POSITION_COUNT; ++joint ) { // Blend the blend rate m_History[ joint ].m_fActualLocalBlendRate = Lerp(m_History[ joint ].m_fActualLocalBlendRate, m_History[ joint ].m_fWantedLocalBlendRate, m_fBlendBlendRate); // Blend the actual position towards the wanted positon m_History[ joint ].m_vPos = Lerp(m_History[ joint ].m_vPos, m_History[ joint ].m_vWantedPos, m_History[ joint ].m_fActualLocalBlendRate); m_FilteredJoints[ joint ] = m_History[ joint ].m_vPos; } }
float Dot(const Vec4& v1, const Vec4& v2) { return v1.Dot(v2); }