//-------------------------------------------------------------------------------------- // ClassifierData.cpp // // This file defines all the features and classifier data that are used during the // training process on the PC and the gesture detection and runtime on the Xbox 360. // // Advanced Technology Group (ATG) // Copyright (C) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- #pragma once #include "ClassifierData.h" #include "GestureDetector.h" #include "NuiTypes.h" #include #include #include namespace KinectGesture { //-------------------------------------------------------------------------------------- // Defines, constants and statics //-------------------------------------------------------------------------------------- static const FLOAT g_fInvalidValue = -FLT_MAX; RingBuffer ClassifierData::m_SkeletonDataHistory[ KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES ]; MUSCLE_FRAME ClassifierData::m_Muscles[ KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES ]; VelocityGridFromSkeleton ClassifierData::m_OpticalFlow[ KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES ]; //-------------------------------------------------------------------------------------- // Name: ClassifierData // Desc: Constructor //-------------------------------------------------------------------------------------- ClassifierData::ClassifierData() { for ( UINT i = 0; i < KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES; i++ ) { m_fValue[ i ] = g_fInvalidValue; } m_uID = 0; m_bRejectInferred = FALSE; m_Type = NUM_FEATURES; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierData::Read( FILE* pFile ) { fread( &m_uID, sizeof( m_uID ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); m_uID = ByteSwap32BitRead( m_uID ); fread( &m_bRejectInferred, sizeof( m_bRejectInferred ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); m_bRejectInferred = ByteSwap32BitRead( m_bRejectInferred ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierData::Read( VOID* pBuffer ) { mread( &m_uID, sizeof( m_uID ), 1, pBuffer ); m_uID = ByteSwap32BitRead( m_uID ); mread( &m_bRejectInferred, sizeof( m_bRejectInferred ), 1, pBuffer ); m_bRejectInferred = ByteSwap32BitRead( m_bRejectInferred ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierData::Write( FILE* pFile ) { UINT uBigEndianValue = ByteSwap32BitWrite( (UINT)m_Type ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); uBigEndianValue = ByteSwap32BitWrite( m_uID ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); uBigEndianValue = ByteSwap32BitWrite( m_bRejectInferred ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierData::Write( VOID* pBuffer ) { UINT uBigEndianValue = /*ByteSwap32Bit*/( (UINT)m_Type ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); uBigEndianValue = /*ByteSwap32Bit*/( m_uID ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); uBigEndianValue = /*ByteSwap32Bit*/( m_bRejectInferred ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: Copy // Desc: Copy data from a source //-------------------------------------------------------------------------------------- VOID ClassifierData::Copy( ClassifierData* pSource ) { for ( UINT i = 0; i < KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES; i++ ) { m_fValue[ i ] = pSource->m_fValue[ i ]; } m_bRejectInferred = pSource->m_bRejectInferred; } //-------------------------------------------------------------------------------------- // Name: MakeUID // Desc: generate a unique 32-bit identifier for comparison //-------------------------------------------------------------------------------------- UINT ClassifierData::MakeUID() { return m_Type | ((UINT)m_bRejectInferred<<7); } //-------------------------------------------------------------------------------------- // Name: Initialize // Desc: Initialize data //-------------------------------------------------------------------------------------- VOID ClassifierData::Initialize() { for ( UINT i = 0; i < KINECT_GESTURE_MAX_SIMULTANEOUS_GESTURES; i++ ) { #ifdef _XBOX XMemSet( &m_Muscles[ i ], 0, sizeof( MUSCLE_FRAME ) ); XMemSet( &m_OpticalFlow[ i ], 0, sizeof( VelocityGridFromSkeleton ) ); #else memset( &m_Muscles[ i ], 0, sizeof( MUSCLE_FRAME ) ); memset( &m_OpticalFlow[ i ], 0, sizeof( VelocityGridFromSkeleton ) ); #endif m_SkeletonDataHistory[ i ].Clear(); } } //-------------------------------------------------------------------------------------- // Name: CreatNewInstance // Desc: Read the type from file and create a new instance based on that type //-------------------------------------------------------------------------------------- ClassifierData* ClassifierData::CreatNewInstance( FILE* pFile ) { UINT uValue; fread( &uValue, sizeof( uValue ), 1, pFile ); if ( ferror( pFile ) ) { return NULL; } uValue = ByteSwap32BitRead( uValue ); return CreatNewInstance( uValue ); } //-------------------------------------------------------------------------------------- // Name: CreatNewInstance // Desc: Read the type from file and create a new instance based on that type //-------------------------------------------------------------------------------------- ClassifierData* ClassifierData::CreatNewInstance( VOID* pBuffer ) { UINT uValue; mread( &uValue, sizeof( uValue ), 1, pBuffer ); uValue = ByteSwap32BitRead( uValue ); return CreatNewInstance( uValue ); } //-------------------------------------------------------------------------------------- // Name: CreatNewInstance // Desc: Read the type from file and create a new instance based on that type //-------------------------------------------------------------------------------------- ClassifierData* ClassifierData::CreatNewInstance( const UINT uValue ) { EType type = (EType)uValue; switch( type ) { #ifdef ADD_TYPE_DIFF_POSITION_X case TYPE_DIFF_POSITION_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionX ), 4 ); return new (pMem) ClassifierDataUsingDiffPositionX; } #endif #ifdef ADD_TYPE_DIFF_POSITION_Y case TYPE_DIFF_POSITION_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionY ), 4 ); return new (pMem) ClassifierDataUsingDiffPositionY; } #endif #ifdef ADD_TYPE_DIFF_POSITION_Z case TYPE_DIFF_POSITION_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionZ ), 4 ); return new (pMem) ClassifierDataUsingDiffPositionZ; } #endif #ifdef ADD_TYPE_ANGLE case TYPE_ANGLE: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngles ), 4 ); return new (pMem) ClassifierDataUsingAngles; } #endif #ifdef ADD_TYPE_TIME_SPACE_ANGLE case TYPE_TIME_SPACE_ANGLE: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingTimeSpaceAngles ), 4 ); return new (pMem) ClassifierDataUsingTimeSpaceAngles; } #endif #ifdef ADD_TYPE_POSITION_SPEED case TYPE_POSITION_SPEED: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionSpeed ), 4 ); return new (pMem) ClassifierDataUsingPositionSpeed; } #endif #ifdef ADD_TYPE_POSITION_SPEED_SQ case TYPE_POSITION_SPEED_SQ: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionSpeedSQ ), 4 ); return new (pMem) ClassifierDataUsingPositionSpeedSQ; } #endif #ifdef ADD_TYPE_POSITION_ACCELERATION case TYPE_POSITION_ACCELERATION: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAcceleration ), 4 ); return new (pMem) ClassifierDataUsingPositionAcceleration; } #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_X case TYPE_POSITION_ACCELERATION_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationX ), 4 ); return new (pMem) ClassifierDataUsingPositionAccelerationX; } #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_Y case TYPE_POSITION_ACCELERATION_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationY ), 4 ); return new (pMem) ClassifierDataUsingPositionAccelerationY; } #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_Z case TYPE_POSITION_ACCELERATION_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationZ ), 4 ); return new (pMem) ClassifierDataUsingPositionAccelerationZ; } #endif #ifdef ADD_TYPE_POSITION_VELOCITY_X case TYPE_POSITION_VELOCITY_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityX ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocityX; } #endif #ifdef ADD_TYPE_POSITION_VELOCITY_Y case TYPE_POSITION_VELOCITY_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityY ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocityY; } #endif #ifdef ADD_TYPE_POSITION_VELOCITY_Z case TYPE_POSITION_VELOCITY_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityZ ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocityZ; } #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_X case TYPE_POSITION_VELOCITYSQ_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQX ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocitySQX; } #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_Y case TYPE_POSITION_VELOCITYSQ_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQY ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocitySQY; } #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_Z case TYPE_POSITION_VELOCITYSQ_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQZ ), 4 ); return new (pMem) ClassifierDataUsingPositionVelocitySQZ; } #endif #ifdef ADD_TYPE_ANGLE_VELOCITY case TYPE_ANGLE_VELOCITY: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngleVelocities ), 4 ); return new (pMem) ClassifierDataUsingAngleVelocities; } #endif #ifdef ADD_TYPE_ANGLE_ACCELERATION case TYPE_ANGLE_ACCELERATION: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngleAcceleration ), 4 ); return new (pMem) ClassifierDataUsingAngleAcceleration; } #endif #ifdef ADD_TYPE_MUSCLE_FORCES case TYPE_MUSCLE_FORCE_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceX ), 4 ); return new (pMem) ClassifierDataUsingMuscleForceX; } case TYPE_MUSCLE_FORCE_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceY ), 4 ); return new (pMem) ClassifierDataUsingMuscleForceY; } case TYPE_MUSCLE_FORCE_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceZ ), 4 ); return new (pMem) ClassifierDataUsingMuscleForceZ; } #endif #ifdef ADD_TYPE_MUSCLE_TORQUES case TYPE_MUSCLE_TORQUE_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueX ), 4 ); return new (pMem) ClassifierDataUsingMuscleTorqueX; } case TYPE_MUSCLE_TORQUE_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueY ), 4 ); return new (pMem) ClassifierDataUsingMuscleTorqueY; } case TYPE_MUSCLE_TORQUE_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueZ ), 4 ); return new (pMem) ClassifierDataUsingMuscleTorqueZ; } #endif #ifdef ADD_TYPE_MUSCLE_POWER case TYPE_MUSCLE_POWER: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMusclePower ), 4 ); return new (pMem) ClassifierDataUsingMusclePower; } #endif #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_X case TYPE_DIFF_MUSCLE_FORCE_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceX ), 4 ); return new (pMem) ClassifierDataUsingDiffMuscleForceX; } #endif #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_Y case TYPE_DIFF_MUSCLE_FORCE_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceY ), 4 ); return new (pMem) ClassifierDataUsingDiffMuscleForceY; } #endif #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_Z case TYPE_DIFF_MUSCLE_FORCE_Z: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceZ ), 4 ); return new (pMem) ClassifierDataUsingDiffMuscleForceZ; } #endif #ifdef ADD_TYPE_BONE_LENGTH_CHANGES case TYPE_BONE_LENGTH_CHANGES: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingBoneLengthChanges ), 4 ); return new (pMem) ClassifierDataUsingBoneLengthChanges; } #endif #ifdef ADD_TYPE_OPTICAL_FLOW case TYPE_OPTICAL_FLOW_X: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowX ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowX; } case TYPE_OPTICAL_FLOW_Y: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowY ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowY; } case TYPE_OPTICAL_FLOW_LENGTH_SQ: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowLengthSq ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowLengthSq; } case TYPE_OPTICAL_FLOW_TANGENT: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowTangent ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowTangent; } case TYPE_OPTICAL_FLOW_X_DIFF: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowXDiff ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowXDiff; } case TYPE_OPTICAL_FLOW_Y_DIFF: { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowYDiff ), 4 ); return new (pMem) ClassifierDataUsingOpticalFlowYDiff; } #endif default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } return NULL; } //-------------------------------------------------------------------------------------- // Name: UpdateHistory // Desc: Update the sliding window of skeleton frames //-------------------------------------------------------------------------------------- VOID ClassifierData::UpdateHistory( const UINT uPlayerIdx, const GESTURE_SKELETON_TYPE* pSkeletonData, const FLOAT fDeltaTimeInSeconds, BOOL* bReset, const VelocityGrid* opticalFlowGrid ) { *bReset = ( fDeltaTimeInSeconds == 0.0f ) ? TRUE : FALSE; m_SkeletonDataHistory[ uPlayerIdx ].AddToFront( pSkeletonData ); // Check that we have the same player, otherwise reset the states UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uPreviousFrameIndex ); GESTURE_SKELETON_TYPE* pPreviousSkeletonData2 = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); assert( pSkeletonData ); assert( pPreviousSkeletonData ); if ( GESTURE_GET_TRACKING_ID( pSkeletonData ) != GESTURE_GET_TRACKING_ID( pPreviousSkeletonData ) || GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_GET_TRACKING( pPreviousSkeletonData ) || GESTURE_GET_TRACKING_ID( pPreviousSkeletonData ) != GESTURE_GET_TRACKING_ID( pPreviousSkeletonData2 ) || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_GET_TRACKING( pPreviousSkeletonData2 ) ) { m_SkeletonDataHistory[ uPlayerIdx ].Splat( pSkeletonData ); *bReset = TRUE; } if ( opticalFlowGrid != NULL ) { #ifdef _XBOX XMemCpy( &m_OpticalFlow[ uPlayerIdx ].mGrid, opticalFlowGrid, sizeof( VelocityGrid ) ); #else memcpy( &m_OpticalFlow[ uPlayerIdx ].mGrid, opticalFlowGrid, sizeof( VelocityGrid ) ); #endif } if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_SkeletonDataHistory[ uPlayerIdx ].Splat( pSkeletonData ); #ifdef _XBOX XMemSet( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); #else memset( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); #endif if ( opticalFlowGrid == NULL ) { #ifdef _XBOX XMemSet( &m_OpticalFlow[ uPlayerIdx ].mGrid, 0, sizeof( VelocityGrid ) ); #else memset( &m_OpticalFlow[ uPlayerIdx ].mGrid, 0, sizeof( VelocityGrid ) ); #endif } return; } #if defined( __ORBIS__ ) || defined( TARGET_ORBIS ) || defined( ITF_ORBIS ) || defined(GESTURE_TRAINER) // MuscleFrameCalculate expects an array of vectors representing joint positions // but they are an array of structs on PS4 so copy them locally in to one. XMVECTOR joints[ GESTURE_JOINT_COUNT ]; GESTURE_JOINT_TRACKING_STATE jointTrackingStates[ GESTURE_JOINT_COUNT ]; for( int jointIdx = 0; jointIdx != GESTURE_JOINT_COUNT; ++jointIdx ) { joints[ jointIdx ] = GESTURE_GET_JOINT_POS( pSkeletonData, jointIdx ); jointTrackingStates[ jointIdx ] = GESTURE_GET_JOINT_TRACKING( pSkeletonData, jointIdx ); } #else const XMVECTOR* joints = GESTURE_GET_JOINT_POS_ARRAY( pSkeletonData ); const GESTURE_JOINT_TRACKING_STATE* jointTrackingStates = &GESTURE_GET_JOINT_TRACKING( pSkeletonData, 0 ); #endif if ( *bReset ) { m_SkeletonDataHistory[ uPlayerIdx ].Splat( pSkeletonData ); #ifdef _XBOX XMemSet( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); #else memset( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); #endif if ( opticalFlowGrid == NULL ) { #ifdef _XBOX XMemSet( &m_OpticalFlow[ uPlayerIdx ].mGrid, 0, sizeof( VelocityGrid ) ); #else memset( &m_OpticalFlow[ uPlayerIdx ].mGrid, 0, sizeof( VelocityGrid ) ); #endif VelocityGridCalculate( &m_OpticalFlow[ uPlayerIdx ], NULL, pSkeletonData, 0.033f ); } MuscleFrameCalculate( &m_Muscles[ uPlayerIdx ], NULL, joints, XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), jointTrackingStates, 0.033f ); } else { MuscleFrameCalculate( &m_Muscles[ uPlayerIdx ], &m_Muscles[ uPlayerIdx ], joints, XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), jointTrackingStates, fDeltaTimeInSeconds ); if ( opticalFlowGrid == NULL ) { VelocityGridCalculate( &m_OpticalFlow[ uPlayerIdx ], &m_OpticalFlow[ uPlayerIdx ], pSkeletonData, fDeltaTimeInSeconds ); } } } //-------------------------------------------------------------------------------------- // Name: Reset // Desc: Reset the history for a player - used when a new skeleton is acquired //-------------------------------------------------------------------------------------- VOID ClassifierData::Reset( const UINT uPlayerIdx, const GESTURE_SKELETON_TYPE* pSkeletonData ) { m_SkeletonDataHistory[ uPlayerIdx ].Splat( pSkeletonData ); #ifdef _XBOX XMemSet( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); XMemSet( &m_OpticalFlow[ uPlayerIdx ], 0, sizeof( VelocityGridFromSkeleton ) ); #else memset( &m_Muscles[ uPlayerIdx ], 0, sizeof( MUSCLE_FRAME ) ); memset( &m_OpticalFlow[ uPlayerIdx ], 0, sizeof( VelocityGridFromSkeleton ) ); #endif #if defined( __ORBIS__ ) || defined( TARGET_ORBIS ) || defined( ITF_ORBIS ) || defined(GESTURE_TRAINER) // MuscleFrameCalculate expects an array of vectors representing joint positions // but they are an array of structs on PS4 so copy them locally in to one. XMVECTOR joints[ GESTURE_JOINT_COUNT ]; GESTURE_JOINT_TRACKING_STATE jointTrackingStates[ GESTURE_JOINT_COUNT ]; for( int jointIdx = 0; jointIdx != GESTURE_JOINT_COUNT; ++jointIdx ) { joints[ jointIdx ] = GESTURE_GET_JOINT_POS( pSkeletonData, jointIdx ); jointTrackingStates[ jointIdx ] = GESTURE_GET_JOINT_TRACKING( pSkeletonData, jointIdx ); } #else const XMVECTOR* joints = GESTURE_GET_JOINT_POS_ARRAY( pSkeletonData ); const GESTURE_JOINT_TRACKING_STATE* jointTrackingStates = &GESTURE_GET_JOINT_TRACKING( pSkeletonData, 0 ); #endif MuscleFrameCalculate( &m_Muscles[ uPlayerIdx ], NULL, joints, XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), jointTrackingStates, 0.033f ); VelocityGridCalculate( &m_OpticalFlow[ uPlayerIdx ], NULL, pSkeletonData, 0.033f ); } //-------------------------------------------------------------------------------------- // Name: GetEnergyLevel // Desc: Approximate enegy level for a player using muscle data //-------------------------------------------------------------------------------------- FLOAT ClassifierData::GetEnergyLevel( const UINT uPlayerIdx ) { FLOAT fEnergy = 0.0f; UINT uMuscle = 0; for( uMuscle = 0; uMuscle < GESTURE_JOINT_COUNT; ++uMuscle ) { fEnergy += m_Muscles[uPlayerIdx].Muscles[uMuscle].mLimbMassEstimate * XMVectorGetX( XMVector3Length( m_Muscles[uPlayerIdx].Muscles[uMuscle].mLimbLinearAcceleration ) ); } return fEnergy; } //-------------------------------------------------------------------------------------- // Name: ClassifierDataBaseClassForOneJoint // Desc: Constructor //-------------------------------------------------------------------------------------- ClassifierDataBaseClassForOneJoint::ClassifierDataBaseClassForOneJoint( const GESTURE_JOINT_INDEX jointIndex ) : ClassifierData() { m_jointIndex = jointIndex; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForOneJoint::Read( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Read( pFile ) ); UINT uValue; fread( &uValue, sizeof( uValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); uValue = ByteSwap32BitRead( uValue ); m_jointIndex = (GESTURE_JOINT_INDEX)uValue; return S_OK; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForOneJoint::Read( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Read( pBuffer ) ); UINT uValue; mread( &uValue, sizeof( uValue ), 1, pBuffer ); uValue = ByteSwap32BitRead( uValue ); m_jointIndex = (GESTURE_JOINT_INDEX)uValue; return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForOneJoint::Write( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Write( pFile ) ); UINT uBigEndianValue; uBigEndianValue = ByteSwap32BitWrite( (UINT)m_jointIndex ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForOneJoint::Write( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Write( pBuffer ) ); UINT uBigEndianValue; uBigEndianValue = /*ByteSwap32Bit*/( (UINT)m_jointIndex ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: MakeUID // Desc: generate a unique 32-bit identifier for comparison //-------------------------------------------------------------------------------------- UINT ClassifierDataBaseClassForOneJoint::MakeUID() { return m_Type | ((UINT)m_bRejectInferred<<7) | ((UINT)m_jointIndex<<8); } //-------------------------------------------------------------------------------------- // Name: ClassifierDataBaseClassForTwoJoints // Desc: Constrcutor //-------------------------------------------------------------------------------------- ClassifierDataBaseClassForTwoJoints::ClassifierDataBaseClassForTwoJoints( const GESTURE_JOINT_INDEX jointIndex0, const GESTURE_JOINT_INDEX jointIndex1 ) : ClassifierData() { m_jointIndices[ 0 ] = jointIndex0; m_jointIndices[ 1 ] = jointIndex1; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForTwoJoints::Read( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Read( pFile ) ); UINT uValue; for ( UINT i = 0; i < 2; i++ ) { fread( &uValue, sizeof( uValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); uValue = ByteSwap32BitRead( uValue ); m_jointIndices[ i ] = (GESTURE_JOINT_INDEX)uValue; } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForTwoJoints::Read( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Read( pBuffer ) ); UINT uValue; for ( UINT i = 0; i < 2; i++ ) { mread( &uValue, sizeof( uValue ), 1, pBuffer ); #ifndef GESTURE_EVALUATOR uValue = ByteSwap32BitRead( uValue ); #endif m_jointIndices[ i ] = (GESTURE_JOINT_INDEX)uValue; } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForTwoJoints::Write( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Write( pFile ) ); UINT uBigEndianValue; for ( UINT i = 0; i < 2; i++) { uBigEndianValue = ByteSwap32BitWrite( (UINT)m_jointIndices[ i ] ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForTwoJoints::Write( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Write( pBuffer ) ); UINT uBigEndianValue; for ( UINT i = 0; i < 2; i++) { uBigEndianValue = /*ByteSwap32Bit*/( (UINT)m_jointIndices[ i ] ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); } return S_OK; } //-------------------------------------------------------------------------------------- // Name: MakeUID // Desc: generate a unique 32-bit identifier for comparison //-------------------------------------------------------------------------------------- UINT ClassifierDataBaseClassForTwoJoints::MakeUID() { return m_Type | ((UINT)m_bRejectInferred<<7) | ((UINT)m_jointIndices[0]<<8) | ((UINT)m_jointIndices[1]<<16); } //-------------------------------------------------------------------------------------- // Name: ClassifierDataBaseClassForThreeJoints // Desc: Constructor //-------------------------------------------------------------------------------------- ClassifierDataBaseClassForThreeJoints::ClassifierDataBaseClassForThreeJoints( const GESTURE_JOINT_INDEX jointIndex0, const GESTURE_JOINT_INDEX jointIndex1, const GESTURE_JOINT_INDEX jointIndex2 ) : ClassifierData() { m_jointIndices[ 0 ] = jointIndex0; m_jointIndices[ 1 ] = jointIndex1; m_jointIndices[ 2 ] = jointIndex2; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForThreeJoints::Read( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Read( pFile ) ); UINT uValue; for ( UINT i = 0; i < 3; i++ ) { fread( &uValue, sizeof( uValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); uValue = ByteSwap32BitRead( uValue ); m_jointIndices[ i ] = (GESTURE_JOINT_INDEX)uValue; } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Read // Desc: Read data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForThreeJoints::Read( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Read( pBuffer ) ); UINT uValue; for ( UINT i = 0; i < 3; i++ ) { mread( &uValue, sizeof( uValue ), 1, pBuffer ); uValue = ByteSwap32BitRead( uValue ); m_jointIndices[ i ] = (GESTURE_JOINT_INDEX)uValue; } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForThreeJoints::Write( FILE* pFile ) { RETURN_ON_FAIL( ClassifierData::Write( pFile ) ); UINT uBigEndianValue; for ( UINT i = 0; i < 3; i++) { uBigEndianValue = ByteSwap32BitWrite( (UINT)m_jointIndices[ i ] ); fwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pFile ); RETURN_ON_FILE_ERROR( pFile ); } return S_OK; } //-------------------------------------------------------------------------------------- // Name: Write // Desc: Write data //-------------------------------------------------------------------------------------- HRESULT ClassifierDataBaseClassForThreeJoints::Write( VOID* pBuffer ) { RETURN_ON_FAIL( ClassifierData::Write( pBuffer ) ); UINT uBigEndianValue; for ( UINT i = 0; i < 3; i++) { uBigEndianValue = /*ByteSwap32Bit*/( (UINT)m_jointIndices[ i ] ); mwrite( &uBigEndianValue, sizeof( uBigEndianValue ), 1, pBuffer ); } return S_OK; } //-------------------------------------------------------------------------------------- // Name: MakeUID // Desc: generate a unique 32-bit identifier for comparison //-------------------------------------------------------------------------------------- UINT ClassifierDataBaseClassForThreeJoints::MakeUID() { return m_Type | ((UINT)m_bRejectInferred<<7) | ((UINT)m_jointIndices[0]<<8) | ((UINT)m_jointIndices[1]<<16) | ((UINT)m_jointIndices[2]<<24); } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingDiffPositionX::Update( const UINT uPlayerIdx, VOID* ) { // This classifier type operates only on the current frame GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); assert( pSkeletonData ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints GESTURE_JOINT_TRACKING_STATE jointTrackingState0 = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 0 ] ); GESTURE_JOINT_TRACKING_STATE jointTrackingState1 = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 1 ] ); if ( m_bRejectInferred ) { if ( jointTrackingState0 != GESTURE_JOINT_TRACKED || jointTrackingState1 != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( jointTrackingState0 == GESTURE_JOINT_NOT_TRACKED || jointTrackingState1 == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions const XMVECTOR vJoint0 = GESTURE_GET_JOINT_POS( pSkeletonData, m_jointIndices[ 0 ] ); const XMVECTOR vJoint1 = GESTURE_GET_JOINT_POS( pSkeletonData, m_jointIndices[ 1 ] ); const XMVECTOR vDiff = vJoint0 - vJoint1; switch ( m_Type ) { #ifdef ADD_TYPE_DIFF_POSITION_X case TYPE_DIFF_POSITION_X: m_fValue[ uPlayerIdx ] = XMVectorGetX( vDiff ); break; #endif #ifdef ADD_TYPE_DIFF_POSITION_Y case TYPE_DIFF_POSITION_Y: m_fValue[ uPlayerIdx ] = XMVectorGetY( vDiff ); break; #endif #ifdef ADD_TYPE_DIFF_POSITION_Z case TYPE_DIFF_POSITION_Z: m_fValue[ uPlayerIdx ] = XMVectorGetZ( vDiff ); break; #endif default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone the data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffPositionX* ClassifierDataUsingDiffPositionX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionX ), 4 ); ClassifierDataUsingDiffPositionX* pClone = new (pMem) ClassifierDataUsingDiffPositionX( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone the data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffPositionY* ClassifierDataUsingDiffPositionY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionY ), 4 ); ClassifierDataUsingDiffPositionY* pClone = new (pMem) ClassifierDataUsingDiffPositionY( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone the data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffPositionZ* ClassifierDataUsingDiffPositionZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffPositionZ ), 4 ); ClassifierDataUsingDiffPositionZ* pClone = new (pMem) ClassifierDataUsingDiffPositionZ( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update the data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingAngles::Update( const UINT uPlayerIdx, VOID* ) { // This classifier type operates only on the current frame GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); assert( pSkeletonData ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints GESTURE_JOINT_TRACKING_STATE firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 0 ] ); GESTURE_JOINT_TRACKING_STATE secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 1 ] ); GESTURE_JOINT_TRACKING_STATE lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions that form the angle const XMVECTOR vFirstJoint = GESTURE_GET_JOINT_POS( pSkeletonData, m_jointIndices[ 0 ] ); const XMVECTOR vMiddleJoint = GESTURE_GET_JOINT_POS( pSkeletonData, m_jointIndices[ 1 ] ); const XMVECTOR vLastJoint = GESTURE_GET_JOINT_POS( pSkeletonData, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors const XMVECTOR vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); const XMVECTOR vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees const XMVECTOR vAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); m_fValue[ uPlayerIdx ] = XMConvertToDegrees( XMVectorGetX( vAngle ) ); } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone the data //-------------------------------------------------------------------------------------- ClassifierDataUsingAngles* ClassifierDataUsingAngles::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngles ), 4 ); ClassifierDataUsingAngles* pClone = new (pMem) ClassifierDataUsingAngles( m_jointIndices[ 0 ], m_jointIndices[ 1 ], m_jointIndices[ 2 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update the data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingTimeSpaceAngles::Update( const UINT uPlayerIdx, VOID* ) { // Check that all skeletons are tracked const UINT uIdx0 = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); const UINT uIdx1 = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uIdx0 ); const UINT uIdx2 = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uIdx1 ); const GESTURE_SKELETON_TYPE* pSkeletonData0 = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uIdx0 ); const GESTURE_SKELETON_TYPE* pSkeletonData1 = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uIdx1 ); const GESTURE_SKELETON_TYPE* pSkeletonData2 = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uIdx2 ); assert( pSkeletonData0 ); assert( pSkeletonData1 ); assert( pSkeletonData2 ); if ( GESTURE_GET_TRACKING( pSkeletonData0 ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pSkeletonData1 ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pSkeletonData2 ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints const GESTURE_JOINT_TRACKING_STATE firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData0, m_jointIndex ); const GESTURE_JOINT_TRACKING_STATE secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData1, m_jointIndex ); const GESTURE_JOINT_TRACKING_STATE lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pSkeletonData2, m_jointIndex ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions that form the angle const XMVECTOR vFirstJoint = GESTURE_GET_JOINT_POS( pSkeletonData0, m_jointIndex ); const XMVECTOR vMiddleJoint = GESTURE_GET_JOINT_POS( pSkeletonData1, m_jointIndex ); const XMVECTOR vLastJoint = GESTURE_GET_JOINT_POS( pSkeletonData2, m_jointIndex ); // Calculate 2 normalized direction vectors const XMVECTOR vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); const XMVECTOR vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees const XMVECTOR vAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); m_fValue[ uPlayerIdx ] = XMConvertToDegrees( XMVectorGetX( vAngle ) ); } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingTimeSpaceAngles* ClassifierDataUsingTimeSpaceAngles::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingTimeSpaceAngles ), 4 ); ClassifierDataUsingTimeSpaceAngles* pClone = new (pMem) ClassifierDataUsingTimeSpaceAngles( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingPositionSpeed::Update( const UINT uPlayerIdx, VOID* pData ) { // This classifier type operates on the current and previous frames const UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); const UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pCurrentSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); assert( pCurrentSkeletonData ); assert( pPreviousSkeletonData ); if ( GESTURE_GET_TRACKING( pCurrentSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking state for joints const GESTURE_JOINT_TRACKING_STATE currentJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndex ); const GESTURE_JOINT_TRACKING_STATE previousJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndex ); if ( m_bRejectInferred ) { if ( currentJointTrackingState != GESTURE_JOINT_TRACKED || previousJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( currentJointTrackingState == GESTURE_JOINT_NOT_TRACKED || previousJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions const XMVECTOR vCurrentPosition = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndex ); const XMVECTOR vPreviousPosition = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndex ); // Calc the speed of joint position const FLOAT fDeltaTimeInSeconds = *((FLOAT*)pData); const XMVECTOR vVelocity = ( vCurrentPosition - vPreviousPosition ) / fDeltaTimeInSeconds; FLOAT fVelocity = 0.0f; switch( m_Type ) { #ifdef ADD_TYPE_POSITION_SPEED case TYPE_POSITION_SPEED: fVelocity = fabsf( XMVectorGetX( XMVector3LengthEst( vVelocity ) ) ); break; #endif #ifdef ADD_TYPE_POSITION_SPEED_SQ case TYPE_POSITION_SPEED_SQ: fVelocity = fabsf( XMVectorGetX( XMVector3LengthEst( vVelocity ) ) ); fVelocity = fVelocity * fVelocity; break; #endif #ifdef ADD_TYPE_POSITION_VELOCITY_X case TYPE_POSITION_VELOCITY_X: fVelocity = XMVectorGetX( vVelocity ); break; #endif #ifdef ADD_TYPE_POSITION_VELOCITY_Y case TYPE_POSITION_VELOCITY_Y: fVelocity = XMVectorGetY( vVelocity ); break; #endif #ifdef ADD_TYPE_POSITION_VELOCITY_Z case TYPE_POSITION_VELOCITY_Z: fVelocity = XMVectorGetZ( vVelocity ); break; #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_X case TYPE_POSITION_VELOCITYSQ_X: fVelocity = XMVectorGetX( vVelocity ); fVelocity = fVelocity * fVelocity; break; #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_Y case TYPE_POSITION_VELOCITYSQ_Y: fVelocity = XMVectorGetY( vVelocity ); fVelocity = fVelocity * fVelocity; break; #endif #ifdef ADD_TYPE_POSITION_VELOCITYSQ_Z case TYPE_POSITION_VELOCITYSQ_Z: fVelocity = XMVectorGetZ( vVelocity ); fVelocity = fVelocity * fVelocity; break; #endif default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fDeltaTimeInSeconds - FLT_EPSILON ) >= 0.0f ) ? fVelocity : 0.0f; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionSpeed* ClassifierDataUsingPositionSpeed::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionSpeed ), 4 ); ClassifierDataUsingPositionSpeed* pClone = new (pMem) ClassifierDataUsingPositionSpeed( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingPositionAcceleration::Update( const UINT uPlayerIdx, VOID* pData ) { // This classifier type operates on 3 frames to calculate acceleration const UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); const UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); const UINT uOldFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uPreviousFrameIndex ); const GESTURE_SKELETON_TYPE* pCurrentSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); const GESTURE_SKELETON_TYPE* pOldSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uOldFrameIndex ); assert( pCurrentSkeletonData ); assert( pPreviousSkeletonData ); assert( pOldSkeletonData ); if ( GESTURE_GET_TRACKING( pCurrentSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pOldSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking state for joints const GESTURE_JOINT_TRACKING_STATE currentJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndex ); const GESTURE_JOINT_TRACKING_STATE previousJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndex ); const GESTURE_JOINT_TRACKING_STATE oldJointTrackingState = GESTURE_GET_JOINT_TRACKING( pOldSkeletonData, m_jointIndex ); if ( m_bRejectInferred ) { if ( currentJointTrackingState != GESTURE_JOINT_TRACKED || previousJointTrackingState != GESTURE_JOINT_TRACKED || oldJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( currentJointTrackingState == GESTURE_JOINT_NOT_TRACKED || previousJointTrackingState == GESTURE_JOINT_NOT_TRACKED || oldJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions const XMVECTOR vCurrentPosition = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndex ); const XMVECTOR vPreviousPosition = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndex ); const XMVECTOR vOldPosition = GESTURE_GET_JOINT_POS( pOldSkeletonData, m_jointIndex ); // Calc the acceleration of joint position const FLOAT fDeltaTimeInSeconds = *((FLOAT*)pData); const XMVECTOR vAcceleration = ( vCurrentPosition - ( vPreviousPosition * 2.0f ) + vOldPosition) / ( 2.0f * fDeltaTimeInSeconds ); FLOAT fAcceleration = 0.0f; switch( m_Type ) { #ifdef ADD_TYPE_POSITION_ACCELERATION case TYPE_POSITION_ACCELERATION: fAcceleration = fabsf(XMVectorGetX( XMVector3LengthEst( vAcceleration ) )); break; #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_X case TYPE_POSITION_ACCELERATION_X: fAcceleration = XMVectorGetX( vAcceleration ); break; #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_Y case TYPE_POSITION_ACCELERATION_Y: fAcceleration = XMVectorGetY( vAcceleration ); break; #endif #ifdef ADD_TYPE_POSITION_ACCELERATION_Z case TYPE_POSITION_ACCELERATION_Z: fAcceleration = XMVectorGetZ( vAcceleration ); break; #endif default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fDeltaTimeInSeconds - FLT_EPSILON ) >= 0.0f ) ? fAcceleration : 0.0f; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionAcceleration* ClassifierDataUsingPositionAcceleration::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAcceleration ), 4 ); ClassifierDataUsingPositionAcceleration* pClone = new (pMem) ClassifierDataUsingPositionAcceleration( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionAccelerationX* ClassifierDataUsingPositionAccelerationX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationX ), 4 ); ClassifierDataUsingPositionAccelerationX* pClone = new (pMem) ClassifierDataUsingPositionAccelerationX( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionAccelerationY* ClassifierDataUsingPositionAccelerationY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationY ), 4 ); ClassifierDataUsingPositionAccelerationY* pClone = new (pMem) ClassifierDataUsingPositionAccelerationY( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionAccelerationZ* ClassifierDataUsingPositionAccelerationZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionAccelerationZ ), 4 ); ClassifierDataUsingPositionAccelerationZ* pClone = new (pMem) ClassifierDataUsingPositionAccelerationZ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Cone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionSpeedSQ* ClassifierDataUsingPositionSpeedSQ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionSpeedSQ ), 4 ); ClassifierDataUsingPositionSpeedSQ* pClone = new (pMem) ClassifierDataUsingPositionSpeedSQ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocityX* ClassifierDataUsingPositionVelocityX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityX ), 4 ); ClassifierDataUsingPositionVelocityX* pClone = new (pMem) ClassifierDataUsingPositionVelocityX( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocityY* ClassifierDataUsingPositionVelocityY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityY ), 4 ); ClassifierDataUsingPositionVelocityY* pClone = new (pMem) ClassifierDataUsingPositionVelocityY( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocityZ* ClassifierDataUsingPositionVelocityZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocityZ ), 4 ); ClassifierDataUsingPositionVelocityZ* pClone = new (pMem) ClassifierDataUsingPositionVelocityZ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocitySQX* ClassifierDataUsingPositionVelocitySQX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQX ), 4 ); ClassifierDataUsingPositionVelocitySQX* pClone = new (pMem) ClassifierDataUsingPositionVelocitySQX( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocitySQY* ClassifierDataUsingPositionVelocitySQY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQY ), 4 ); ClassifierDataUsingPositionVelocitySQY* pClone = new (pMem) ClassifierDataUsingPositionVelocitySQY( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingPositionVelocitySQZ* ClassifierDataUsingPositionVelocitySQZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingPositionVelocitySQZ ), 4 ); ClassifierDataUsingPositionVelocitySQZ* pClone = new (pMem) ClassifierDataUsingPositionVelocitySQZ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingAngleVelocities::Update( const UINT uPlayerIdx, VOID* pData ) { const UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); const UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); // This classifier type operates on the current and previous frame const GESTURE_SKELETON_TYPE* pCurrentSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); assert( pCurrentSkeletonData ); assert( pPreviousSkeletonData ); if ( GESTURE_GET_TRACKING( pCurrentSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints GESTURE_JOINT_TRACKING_STATE firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 0 ] ); GESTURE_JOINT_TRACKING_STATE secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 1 ] ); GESTURE_JOINT_TRACKING_STATE lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the tracking states for joints firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 0 ] ); secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 1 ] ); lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions that form the angle XMVECTOR vFirstJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 0 ] ); XMVECTOR vMiddleJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 1 ] ); XMVECTOR vLastJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors XMVECTOR vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); XMVECTOR vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees XMVECTOR vCurrentAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); // Get the joint positions that form the angle vFirstJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 0 ] ); vMiddleJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 1 ] ); vLastJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees XMVECTOR vPreviousAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); // Calc angle velocity FLOAT fDeltaTimeInSeconds = *((FLOAT*)pData); XMVECTOR vDifference = vCurrentAngle - vPreviousAngle; FLOAT fVelocity = XMVectorGetX( vDifference ) / fDeltaTimeInSeconds; // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fDeltaTimeInSeconds - FLT_EPSILON ) >= 0.0f ) ? fVelocity : 0.0f; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingAngleVelocities* ClassifierDataUsingAngleVelocities::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngleVelocities ), 4 ); ClassifierDataUsingAngleVelocities* pClone = new (pMem) ClassifierDataUsingAngleVelocities( m_jointIndices[ 0 ], m_jointIndices[ 1 ], m_jointIndices[ 2 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingAngleAcceleration::Update( const UINT uPlayerIdx, VOID* pData ) { const UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); const UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); const UINT uPreviousFrameIndex2 = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uPreviousFrameIndex ); // This classifier type operates on the current and previous frame const GESTURE_SKELETON_TYPE* pCurrentSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData2 = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex2 ); assert( pCurrentSkeletonData ); assert( pPreviousSkeletonData ); assert( pPreviousSkeletonData2 ); if ( GESTURE_GET_TRACKING( pCurrentSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData2 ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints GESTURE_JOINT_TRACKING_STATE firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 0 ] ); GESTURE_JOINT_TRACKING_STATE secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 1 ] ); GESTURE_JOINT_TRACKING_STATE lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the tracking states for joints firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 0 ] ); secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 1 ] ); lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the tracking states for joints firstJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData2, m_jointIndices[ 0 ] ); secondJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData2, m_jointIndices[ 1 ] ); lastJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData2, m_jointIndices[ 2 ] ); if ( m_bRejectInferred ) { if ( firstJointTrackingState != GESTURE_JOINT_TRACKED || secondJointTrackingState != GESTURE_JOINT_TRACKED || lastJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( firstJointTrackingState == GESTURE_JOINT_NOT_TRACKED || secondJointTrackingState == GESTURE_JOINT_NOT_TRACKED || lastJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the joint positions that form the angle XMVECTOR vFirstJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 0 ] ); XMVECTOR vMiddleJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 1 ] ); XMVECTOR vLastJoint = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors XMVECTOR vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); XMVECTOR vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees XMVECTOR vCurrentAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); // Get the joint positions that form the angle vFirstJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 0 ] ); vMiddleJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 1 ] ); vLastJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees const XMVECTOR vPreviousAngle = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); // Get the joint positions that form the angle vFirstJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData2, m_jointIndices[ 0 ] ); vMiddleJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData2, m_jointIndices[ 1 ] ); vLastJoint = GESTURE_GET_JOINT_POS( pPreviousSkeletonData2, m_jointIndices[ 2 ] ); // Calculate 2 normalized direction vectors vFirstNormal = XMVector3NormalizeEst( vFirstJoint - vMiddleJoint ); vSecondNormal = XMVector3NormalizeEst( vLastJoint - vMiddleJoint ); // Calculate angle in degrees const XMVECTOR vPreviousAngle2 = XMVector2AngleBetweenNormalsEst( vFirstNormal, vSecondNormal ); // Calc angle velocities const FLOAT fDeltaTimeInSeconds = *((FLOAT*)pData); const FLOAT fInvDeltaTimeInSeconds = 1.0f / fDeltaTimeInSeconds; XMVECTOR vDifference = vCurrentAngle - vPreviousAngle; const FLOAT fCurrentVelocity = XMVectorGetX( vDifference ) * fInvDeltaTimeInSeconds; vDifference = vPreviousAngle - vPreviousAngle2; const FLOAT fPreviousVelocity = XMVectorGetX( vDifference ) * fInvDeltaTimeInSeconds; const FLOAT fAccel = ( fCurrentVelocity - fPreviousVelocity ) * fInvDeltaTimeInSeconds; // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fDeltaTimeInSeconds - FLT_EPSILON ) >= 0.0f ) ? fAccel : 0.0f; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingAngleAcceleration* ClassifierDataUsingAngleAcceleration::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingAngleAcceleration ), 4 ); ClassifierDataUsingAngleAcceleration* pClone = new (pMem) ClassifierDataUsingAngleAcceleration( m_jointIndices[ 0 ], m_jointIndices[ 1 ], m_jointIndices[ 2 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingMuscleForceX::Update( const UINT uPlayerIdx, VOID* ) { // Check that skeleton is tracked const GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } if ( m_bRejectInferred ) { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } const FLOAT fNormalizeConstant = m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mForceNormalizationConstant; FLOAT fForce = 0.0f; #ifdef ADD_TYPE_MUSCLE_FORCES switch ( m_Type ) { case TYPE_MUSCLE_FORCE_X: fForce = XMVectorGetX( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalForce ) / fNormalizeConstant; break; case TYPE_MUSCLE_FORCE_Y: fForce = XMVectorGetY( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalForce ) / fNormalizeConstant; break; case TYPE_MUSCLE_FORCE_Z: fForce = XMVectorGetZ( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalForce ) / fNormalizeConstant; break; default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } #endif // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fNormalizeConstant - FLT_EPSILON ) >= 0.0f ) ? fForce : g_fInvalidValue; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleForceX* ClassifierDataUsingMuscleForceX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceX ), 4 ); ClassifierDataUsingMuscleForceX* pClone = new (pMem) ClassifierDataUsingMuscleForceX( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleForceY* ClassifierDataUsingMuscleForceY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceY ), 4 ); ClassifierDataUsingMuscleForceY* pClone = new (pMem) ClassifierDataUsingMuscleForceY( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleForceZ* ClassifierDataUsingMuscleForceZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleForceZ ), 4 ); ClassifierDataUsingMuscleForceZ* pClone = new (pMem) ClassifierDataUsingMuscleForceZ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingMuscleTorqueX::Update( const UINT uPlayerIdx, VOID* ) { // Check that skeleton is tracked const GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } if ( m_bRejectInferred ) { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } const FLOAT fNormalizeConstant = m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mTorqueNormalizationConstant; FLOAT fTorque = 0.0f; #ifdef ADD_TYPE_MUSCLE_TORQUES switch ( m_Type ) { case TYPE_MUSCLE_TORQUE_X: fTorque = XMVectorGetX( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalTorque ) / fNormalizeConstant; break; case TYPE_MUSCLE_TORQUE_Y: fTorque = XMVectorGetY( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalTorque ) / fNormalizeConstant; break; case TYPE_MUSCLE_TORQUE_Z: fTorque = XMVectorGetZ( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ].mDynamicExternalTorque ) / fNormalizeConstant; break; default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } #endif // This should automatically compile to __fsel() on Xbox m_fValue[ uPlayerIdx ] = ( ( fNormalizeConstant - FLT_EPSILON ) >= 0.0f ) ? fTorque : g_fInvalidValue; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleTorqueX* ClassifierDataUsingMuscleTorqueX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueX ), 4 ); ClassifierDataUsingMuscleTorqueX* pClone = new (pMem) ClassifierDataUsingMuscleTorqueX( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleTorqueY* ClassifierDataUsingMuscleTorqueY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueY ), 4 ); ClassifierDataUsingMuscleTorqueY* pClone = new (pMem) ClassifierDataUsingMuscleTorqueY( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMuscleTorqueZ* ClassifierDataUsingMuscleTorqueZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMuscleTorqueZ ), 4 ); ClassifierDataUsingMuscleTorqueZ* pClone = new (pMem) ClassifierDataUsingMuscleTorqueZ( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingMusclePower::Update( const UINT uPlayerIdx, VOID* ) { // Check that skeleton is tracked const GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } if ( m_bRejectInferred ) { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndex ) == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } m_fValue[ uPlayerIdx ] = MuscleDataGetLinearPower( &m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndex ] ); } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingMusclePower* ClassifierDataUsingMusclePower::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingMusclePower ), 4 ); ClassifierDataUsingMusclePower* pClone = new (pMem) ClassifierDataUsingMusclePower( m_jointIndex ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingDiffMuscleForceX::Update( const UINT uPlayerIdx, VOID* ) { // This classifier type operates only on one keyframe const GESTURE_SKELETON_TYPE* pSkeletonData = GetCurrentSkeleton( uPlayerIdx ); if ( GESTURE_GET_TRACKING( pSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking states for joints const GESTURE_JOINT_TRACKING_STATE jointTrackingState0 = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 0 ] ); const GESTURE_JOINT_TRACKING_STATE jointTrackingState1 = GESTURE_GET_JOINT_TRACKING( pSkeletonData, m_jointIndices[ 1 ] ); if ( m_bRejectInferred ) { if ( jointTrackingState0 != GESTURE_JOINT_TRACKED || jointTrackingState1 != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( jointTrackingState0 == GESTURE_JOINT_NOT_TRACKED || jointTrackingState1 == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } const FLOAT fNormalizeConstant0 = m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndices[ 0 ] ].mTorqueNormalizationConstant; const FLOAT fNormalizeConstant1 = m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndices[ 1 ] ].mTorqueNormalizationConstant; const XMVECTOR vDiff = ( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndices[ 0 ] ].mDynamicExternalForce / fNormalizeConstant0 ) - ( m_Muscles[ uPlayerIdx ].Muscles[ m_jointIndices[ 1 ] ].mDynamicExternalForce / fNormalizeConstant1 ); FLOAT fDiff = 0.0f; switch( m_Type ) { #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_X case TYPE_DIFF_MUSCLE_FORCE_X: fDiff = XMVectorGetX( vDiff ); break; #endif #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_Y case TYPE_DIFF_MUSCLE_FORCE_Y: fDiff = XMVectorGetY( vDiff ); break; #endif #ifdef ADD_TYPE_DIFF_MUSCLE_FORCE_Z case TYPE_DIFF_MUSCLE_FORCE_Z: fDiff = XMVectorGetZ( vDiff ); break; #endif default:break; // Gets rid of 'warning : x enumeration values not handled in switch:...' } // This should automatically compile to __fsel() on Xbox fDiff = ( ( fNormalizeConstant0 - FLT_EPSILON ) >= 0.0f ) ? fDiff : g_fInvalidValue; m_fValue[ uPlayerIdx ] = ( ( fNormalizeConstant1 - FLT_EPSILON ) >= 0.0f ) ? fDiff : g_fInvalidValue; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffMuscleForceX* ClassifierDataUsingDiffMuscleForceX::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceX ), 4 ); ClassifierDataUsingDiffMuscleForceX* pClone = new (pMem) ClassifierDataUsingDiffMuscleForceX( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffMuscleForceY* ClassifierDataUsingDiffMuscleForceY::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceY ), 4 ); ClassifierDataUsingDiffMuscleForceY* pClone = new (pMem) ClassifierDataUsingDiffMuscleForceY( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingDiffMuscleForceZ* ClassifierDataUsingDiffMuscleForceZ::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingDiffMuscleForceZ ), 4 ); ClassifierDataUsingDiffMuscleForceZ* pClone = new (pMem) ClassifierDataUsingDiffMuscleForceZ( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingBoneLengthChanges::Update( const UINT uPlayerIdx, VOID* ) { // Calculates the % bone difference between 3 frames in time const UINT uCurrentFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetCurrentFrameIndex(); UINT uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uCurrentFrameIndex ); uPreviousFrameIndex = m_SkeletonDataHistory[ uPlayerIdx ].GetPreviousFrameIndex( uPreviousFrameIndex ); const GESTURE_SKELETON_TYPE* pCurrentSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uCurrentFrameIndex ); const GESTURE_SKELETON_TYPE* pPreviousSkeletonData = m_SkeletonDataHistory[ uPlayerIdx ].GetAt( uPreviousFrameIndex ); assert( pCurrentSkeletonData ); assert( pPreviousSkeletonData ); if ( GESTURE_GET_TRACKING( pCurrentSkeletonData ) != GESTURE_SKELETON_TRACKED || GESTURE_GET_TRACKING( pPreviousSkeletonData ) != GESTURE_SKELETON_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } // Get the tracking state for joints const GESTURE_JOINT_TRACKING_STATE currentParentJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 0 ] ); const GESTURE_JOINT_TRACKING_STATE currentChildJointTrackingState = GESTURE_GET_JOINT_TRACKING( pCurrentSkeletonData, m_jointIndices[ 1 ] ); const GESTURE_JOINT_TRACKING_STATE prevParentJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 0 ] ); const GESTURE_JOINT_TRACKING_STATE prevChildJointTrackingState = GESTURE_GET_JOINT_TRACKING( pPreviousSkeletonData, m_jointIndices[ 1 ] ); if ( m_bRejectInferred ) { if ( currentParentJointTrackingState != GESTURE_JOINT_TRACKED || currentChildJointTrackingState != GESTURE_JOINT_TRACKED || prevParentJointTrackingState != GESTURE_JOINT_TRACKED || prevChildJointTrackingState != GESTURE_JOINT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } else { if ( currentParentJointTrackingState == GESTURE_JOINT_NOT_TRACKED || currentChildJointTrackingState == GESTURE_JOINT_NOT_TRACKED || prevParentJointTrackingState == GESTURE_JOINT_NOT_TRACKED || prevChildJointTrackingState == GESTURE_JOINT_NOT_TRACKED ) { m_fValue[ uPlayerIdx ] = g_fInvalidValue; return; } } // Get the bone lengths const XMVECTOR vCurrentBone = GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 0 ] ) - GESTURE_GET_JOINT_POS( pCurrentSkeletonData, m_jointIndices[ 1 ] ); const XMVECTOR vPreviousBone = GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 0 ] ) - GESTURE_GET_JOINT_POS( pPreviousSkeletonData, m_jointIndices[ 1 ] ); const FLOAT fCurrentBoneLength = XMVectorGetX( XMVector3LengthEst( vCurrentBone ) ); const FLOAT fPreviousBoneLength = XMVectorGetX( XMVector3LengthEst( vPreviousBone ) ); // return the change m_fValue[ uPlayerIdx ] = fCurrentBoneLength / fPreviousBoneLength; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone the data //-------------------------------------------------------------------------------------- ClassifierDataUsingBoneLengthChanges* ClassifierDataUsingBoneLengthChanges::Clone() { void* pMem = AllocateAligned( sizeof( ClassifierDataUsingBoneLengthChanges ), 4 ); ClassifierDataUsingBoneLengthChanges* pClone = new (pMem) ClassifierDataUsingBoneLengthChanges( m_jointIndices[ 0 ], m_jointIndices[ 1 ] ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowX::Update( const UINT uPlayerIdx, VOID* ) { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][0]; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowX* ClassifierDataUsingOpticalFlowX::Clone() { int ij = (m_jointIndex - GESTURE_JOINT_COUNT); void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowX ), 4 ); ClassifierDataUsingOpticalFlowX* pClone = new (pMem) ClassifierDataUsingOpticalFlowX( ij ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowY::Update( const UINT uPlayerIdx, VOID* ) { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][1]; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowY* ClassifierDataUsingOpticalFlowY::Clone() { int ij = (m_jointIndex - GESTURE_JOINT_COUNT); void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowY ), 4 ); ClassifierDataUsingOpticalFlowY* pClone = new (pMem) ClassifierDataUsingOpticalFlowY( ij ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowLengthSq::Update( const UINT uPlayerIdx, VOID* ) { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = 0.0f; const float lenSqr = ( m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][0] * m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][0] ) + ( m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][1] * m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][1] ); if( lenSqr > FLT_EPSILON ) { m_fValue[ uPlayerIdx ] = sqrt( lenSqr ); } } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowLengthSq* ClassifierDataUsingOpticalFlowLengthSq::Clone() { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowLengthSq ), 4 ); ClassifierDataUsingOpticalFlowLengthSq* pClone = new (pMem) ClassifierDataUsingOpticalFlowLengthSq( i, j ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowTangent::Update( const UINT uPlayerIdx, VOID* ) { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = atan2f( m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][0], m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i][j][1] ); } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowTangent* ClassifierDataUsingOpticalFlowTangent::Clone() { int i = (m_jointIndex - GESTURE_JOINT_COUNT) % 3; int j = (m_jointIndex - GESTURE_JOINT_COUNT) / 3; void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowTangent ), 4 ); ClassifierDataUsingOpticalFlowTangent* pClone = new (pMem) ClassifierDataUsingOpticalFlowTangent( i, j ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowXDiff::Update( const UINT uPlayerIdx, VOID* ) { int i0 = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT) % 3; int j0 = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT) / 3; int i1 = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT) % 3; int j1 = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i0][j0][0] - m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i1][j1][0]; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowXDiff* ClassifierDataUsingOpticalFlowXDiff::Clone() { int a = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT); int b = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT); void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowXDiff ), 4 ); ClassifierDataUsingOpticalFlowXDiff* pClone = new (pMem) ClassifierDataUsingOpticalFlowXDiff( a, b ); if ( pClone ) { pClone->Copy( this ); } return pClone; } //-------------------------------------------------------------------------------------- // Name: Update // Desc: Update data //-------------------------------------------------------------------------------------- VOID ClassifierDataUsingOpticalFlowYDiff::Update( const UINT uPlayerIdx, VOID* ) { int i0 = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT) % 3; int j0 = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT) / 3; int i1 = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT) % 3; int j1 = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT) / 3; m_fValue[ uPlayerIdx ] = m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i0][j0][1] - m_OpticalFlow[ uPlayerIdx ].mGrid.mVelocity[i1][j1][1]; } //-------------------------------------------------------------------------------------- // Name: Clone // Desc: Clone data //-------------------------------------------------------------------------------------- ClassifierDataUsingOpticalFlowYDiff* ClassifierDataUsingOpticalFlowYDiff::Clone() { int a = (m_jointIndices[ 0 ] - GESTURE_JOINT_COUNT); int b = (m_jointIndices[ 1 ] - GESTURE_JOINT_COUNT); void* pMem = AllocateAligned( sizeof( ClassifierDataUsingOpticalFlowYDiff ), 4 ); ClassifierDataUsingOpticalFlowYDiff* pClone = new (pMem) ClassifierDataUsingOpticalFlowYDiff( a, b ); if ( pClone ) { pClone->Copy( this ); } return pClone; } }