C++でKinectInteractionのライブラリを使ってみます。
基本的には Kinect for Windows SDK v1.7 の Interactionを使ってみる(C#) と同じになります。
すべてコードはこちらを参照いただくとして、要所を書いていきます。
一応取得できるのですが、途中で認識できなくなる場合もあるので、もしかしたら何か足りないかもしれません。
InteractionStreamの初期化
NuiCreateInteractionStream を使って INuiInteractionStream を初期化します。C#と同様にKinectのインスタンスおよびINuiInteractionClient の派生クラスを渡します。インスタンスが生成できたら、Streamを有効にします。
// インタラクションライブラリの初期化ERROR_CHECK( ::NuiCreateInteractionStream( kinect, &adapter, &stream ) );
stream->Enable( 0 );
INuiInteractionClient
INuiInteractionClient::GetInteractionInfoAtLocation() を実装します。C++では引数として渡されるので、それに設定します。なお、QueryInterface、AddRef、Releaseも実装する必要があります。
class KinectAdapter : public INuiInteractionClient{
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv)
{
return S_OK;
}
ULONG STDMETHODCALLTYPE AddRef()
{
return 1;
}
ULONG STDMETHODCALLTYPE Release()
{
return 0;
}
HRESULT STDMETHODCALLTYPE GetInteractionInfoAtLocation(DWORD skeletonTrackingId,
NUI_HAND_TYPE handType, FLOAT x, FLOAT y, _Out_ NUI_INTERACTION_INFO *pInteractionInfo)
{
pInteractionInfo->IsGripTarget = TRUE;
return S_OK;
}
};
Depthデータの設定
Depthデータを渡します。拡張された距離データを渡します。
void processDepth(){
// 距離カメラのフレームデータを取得する
NUI_IMAGE_FRAME depthFrame = { 0 };
ERROR_CHECK( kinect->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ) );
// フレームデータを元に、拡張距離データを取得する
BOOL nearMode = FALSE;
INuiFrameTexture *frameTexture = 0;
kinect->NuiImageFrameGetDepthImagePixelFrameTexture( depthStreamHandle, &depthFrame,
&nearMode, &frameTexture );
// 距離データを取得する
NUI_LOCKED_RECT depthData = { 0 };
frameTexture->LockRect( 0, &depthData, 0, 0 );
if ( depthData.Pitch == 0 ) {
std::cout << "zero" << std::endl;
}
// Depthデータを設定する
ERROR_CHECK( stream->ProcessDepth( depthData.size, depthData.pBits, depthFrame.liTimeStamp ));
// フレームデータを解放する
ERROR_CHECK( kinect->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ) );
}
Skeletonデータの設定
Skeletonデータをわたします。
void processSkeleton(){
// スケルトンのフレームを取得する
NUI_SKELETON_FRAME skeletonFrame = { 0 };
kinect->NuiSkeletonGetNextFrame( 0, &skeletonFrame );
// スケルトンデータを設定する
Vector4 reading = { 0 };
kinect->NuiAccelerometerGetCurrentReading( &reading );
ERROR_CHECK( stream->ProcessSkeleton( NUI_SKELETON_COUNT, skeletonFrame.SkeletonData,
&reading, skeletonFrame.liTimeStamp ) );
}
インタラクションフレームの処理
すれーむを処理します。こちらもすべてのプレイヤーの左右の手の情報が来るので、必要なものを使います。
void processInteraction(){
// インタラクションフレームを取得する
NUI_INTERACTION_FRAME interactionFrame = { 0 } ;
auto ret = stream->GetNextFrame( 0, &interactionFrame );
if ( ret != S_OK ) {
return;
}
for ( auto user : interactionFrame.UserInfos ) {
if ( user.SkeletonTrackingId != 0 ) {
for ( auto hand : user.HandPointerInfos ) {
std::cout << EventTypeToString( hand.HandEventType ) << " " << std::endl;
}
}
}
}