JD2022-TU1/main/extern/KinectGesture/Src/ClassifierData.cpp

2668 lines
97 KiB
C++

//--------------------------------------------------------------------------------------
// 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 <float.h>
#include <assert.h>
#include <new>
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;
}
}