2668 lines
97 KiB
C++
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;
|
|
}
|
|
|
|
|
|
|
|
}
|