Maverick Project
 Microsoft Visual C++ 2012 Express
 Direct3D 11.0
 Kinect for Windows SDK v1.7
 DirectXTex texture processing library

■Kinect プレイヤーID Prev Top Next
関連ページ:Direct3D 自作の共通ライブラリ


プレイヤーIDを取得して輪郭抽出

今回はプレイヤーIDを取得します。
プレイヤーごとに色分けされるのですが、それだけだとつまらないので輪郭抽出してみました。
怪しい人物が映ってますが、気にしないように。

UCommon.h 共通で使用するヘッダファイル
UException.h 例外処理クラスのヘッダファイル
UDirect3D11.h Direct3Dクラスのヘッダーファイル
UDirect3D11.cpp Direct3Dクラスのソースファイル
UGraphicsPipeline.h グラフィックパイプラインクラスのヘッダーファイル
UGraphicsPipeline.cpp グラフィックパイプラインクラスのソースファイル
UMesh.h メッシュの抽象クラスのヘッダーファイル
UMesh.cpp メッシュの抽象クラスのソースファイル
UPlane03.h メッシュクラスのヘッダーファイル
UPlane03.cpp メッシュクラスのソースファイル
Sample03.hlsl hlslファイル
UKinect03.h Kinectクラスのヘッダーファイル
UKinect03.cpp Kinectクラスのソースファイル
main.cpp main関数のソースファイル

今回のネタとは関係ないですが、レンダーターゲットを切り替えるための関数を追加してます。
他にもいろいろと修正してます。結構修正しているので、すべて差し替えたほうがいいかも。すいません。

---UPlane03.h---  ↑


#ifndef UPLANE03_H
#define UPLANE03_H

#include "../../Common/Header/UCommon.h"
#include <NuiApi.h>
#include "../../Common/Header/UException.h."
#include "../../Common/Header/UMesh.h"
#include "../../Common/Header/UDirect3D11.h"

class UCPlane03: public UIMesh
{
private:
   // 頂点定義
   typedef struct _VERTEX
   {
      // 頂点座標
      float x, y, z;
      // テクセル
      float tu, tv;
   }VERTEX;

   // 頂点バッファ
   ID3D11Buffer* m_pVertexBuffer;

   // インデックスバッファ
   ID3D11Buffer* m_pIndexBuffer;

   // シェーダーリソースビュー
   ID3D11ShaderResourceView* m_pSRView;

   // サンプラーステート
   ID3D11SamplerState* m_pSamplerState;

public:
   UCPlane03();
   ~UCPlane03();
   void Invalidate();
   void CreateMesh( ID3D11Device* pD3DDevice, UINT Width, UINT Height );
   void NextFrame( ID3D11DeviceContext* pD3DDeviceContext, NUI_LOCKED_RECT ColorData );
   void Render( ID3D11DeviceContext* pD3DDeviceContext );
};

#endif

---UPlane03.cpp---  ↑

#include "UPlane03.h"

UCPlane03::UCPlane03()
{
   m_pVertexBuffer = nullptr;
   m_pIndexBuffer = nullptr;
   m_pSRView = nullptr;
   m_pSamplerState = nullptr;
}

UCPlane03::~UCPlane03()
{
   Invalidate();
}

void UCPlane03::Invalidate()
{
   SAFE_RELEASE( m_pSamplerState );
   SAFE_RELEASE( m_pSRView );
   SAFE_RELEASE( m_pIndexBuffer );
   SAFE_RELEASE( m_pVertexBuffer );
}

void UCPlane03::CreateMesh( ID3D11Device* pD3DDevice, UINT Width, UINT Height )
{
   // 頂点データを格納する
   VERTEX v[] = { 
       1,  1, 0.0f, 1.0f, 0.0f,
      -1,  1, 0.0f, 0.0f, 0.0f,
       1, -1, 0.0f, 1.0f, 1.0f,
      -1, -1, 0.0f, 0.0f, 1.0f,
   };
      
   // 頂点バッファを作成する
   m_pVertexBuffer = CreateVertexBuffer( pD3DDevice, v, sizeof( v ), 0 );

   UINT Index[] = { 0, 1, 2, 3 };

   // インデックスバッファを作成する。
   m_pIndexBuffer = CreateIndexBuffer( pD3DDevice, Index, sizeof( Index ), 0 );

   // 空のデカールマップ用シェーダーリソースビューを作成する
   // GPU (読み取りのみ) と CPU (書き込みのみ) によるアクセスが可能なリソースとして作成する設定
   m_pSRView = CreateSRViewForDecalMap( pD3DDevice, Width, Height, UD3D11_FORMAT, UEACCESS_FLAG::UPDATE_SUBRESOURCE );

   // サンプラーステートを作成する
   m_pSamplerState = CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_CLAMP );
}

void UCPlane03::NextFrame( ID3D11DeviceContext* pD3DDeviceContext, NUI_LOCKED_RECT ColorData )
{
   ID3D11Resource* pResource = nullptr;

   __try
   {
      // シェーダーリソースビューからテクスチャーを取得する
      m_pSRView->GetResource( &pResource );

      // シェーダーリソースビューに色情報を設定する
      pD3DDeviceContext->UpdateSubresource( pResource, 0, nullptr, ColorData.pBits, ColorData.Pitch, 0 );
   }
   __finally
   {
      SAFE_RELEASE( pResource );
   }
}

void UCPlane03::Render( ID3D11DeviceContext* pD3DDeviceContext )
{
   // 頂点バッファ設定
   UINT stride = sizeof( UCPlane03::VERTEX );
   UINT offset = 0;
   pD3DDeviceContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

   // インデックスバッファ設定
   pD3DDeviceContext->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );

   // プリミティブ タイプおよびデータの順序に関する情報を設定
   pD3DDeviceContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );

   // ピクセルシェーダーのサンプラーステートを設定する
   pD3DDeviceContext->PSSetSamplers( 0, 1, &m_pSamplerState );

   // デカールマップを設定する
   pD3DDeviceContext->PSSetShaderResources( 0, 1, &m_pSRView );

   // インデックスバッファを使用した描画
    pD3DDeviceContext->DrawIndexed( 4, 0, 0 );
}

---Sample03.hlsl---  ↑

// 定数バッファ
cbuffer cbSize : register( b0 )
{
   float4 g_Size : packoffset( c0 );
};

// テクスチャー
Texture2D g_Tex : register( t0 );

// サンプラーステート
SamplerState  g_Sampler : register( s0 );

// 頂点シェーダーの入力パラメータ
struct VS_IN
{
   float3 pos   : POSITION;   // 頂点座標
   float2 texel : TEXCOORD;   // テクセル
};

// 頂点シェーダーの出力パラメータ
struct VS_OUT_PS_IN
{
   float4 pos    : SV_POSITION;
   float2 texel  : TEXCOORD0;
};

// 頂点シェーダー
VS_OUT_PS_IN VS_Main( VS_IN In )
{
   VS_OUT_PS_IN Out = { float4( In.pos, 1.0f ), In.texel };
   return Out;
}

// ピクセルシェーダ
float4 PS_Main( VS_OUT_PS_IN In ) : SV_TARGET
{
   // 色取得
   float4 col = g_Tex.Sample( g_Sampler, In.texel );

   // テクセルのオフセット値計算
   float2 offset = (float2)( 1.0f / g_Size.x, 1.0f / g_Size.y );
   
   float4 c[4];
   c[0] = g_Tex.Sample( g_Sampler, In.texel + float2( 0,  offset.y ) );
   c[1] = g_Tex.Sample( g_Sampler, In.texel + float2( 0, -offset.y ) );
   c[2] = g_Tex.Sample( g_Sampler, In.texel + float2(  offset.x,  0 ) );
   c[3] = g_Tex.Sample( g_Sampler, In.texel + float2( -offset.x,  0 ) );
   
   float a = 1;
   for( int i=0; i<4; i++ )
   {
      if( col.a != c[i].a )
      {
         a = 0;
         break;
      }
   }
   
   col.a = a;
   
   return float4( col.gbr * col.a, 1 );
}

輪郭抽出やってます。説明はいらないですよね。たいしたことやってません。

---UKinect03.h---  ↑


#ifndef KINECT03_H
#define KINECT03_H

#include "../../Common/Header/UCommon.h"
#include <NuiApi.h>
#include "../../Common/Header/UException.h"

// Kinect用ライブラリ
#pragma comment( lib, "Kinect10.lib" )

class UCKinect03
{
private:
   INuiSensor* m_pKinectSensor;
   HANDLE m_ImageStreamHandle, m_DepthStreamHandle;
   DWORD m_Flags;

   static const NUI_IMAGE_RESOLUTION m_ImageResolution = NUI_IMAGE_RESOLUTION_640x480;
   static const NUI_IMAGE_RESOLUTION m_DepthResolution = NUI_IMAGE_RESOLUTION_640x480;

   // 次のフレームのイメージフレーム作成
   void CreateImageFrame( HANDLE StreamHandle, NUI_IMAGE_FRAME* pImageFrame, NUI_LOCKED_RECT* pRect );

   // メモリ解放
   void ReleaseImageFrame( HANDLE StreamHandle, NUI_IMAGE_FRAME* ImageFrame );

public:
   UCKinect03();
   ~UCKinect03();
   void CreateKinect( DWORD Flags, DWORD& pWidth, DWORD& pHeight );

   // カラーデータを取得
   void NextFrameImageData( NUI_LOCKED_RECT* pRect );
   // 深度データとプレイヤーIDを取得
   void NextFrameDepthAndPlayerIndexData( NUI_LOCKED_RECT* pRect );

   // カラーデータのa成分にプレイヤーID値を格納する
   void MergeImageDataAndPlayerIndexData( NUI_LOCKED_RECT* pImageData, NUI_LOCKED_RECT* pDepthData );
};

#endif

---UKinect03.cpp---  ↑

#include "../../Common/Header/UKinect03.h"

UCKinect03::UCKinect03()
{
   m_pKinectSensor = nullptr;
}

UCKinect03::~UCKinect03()
{
   if( m_pKinectSensor != nullptr )
      m_pKinectSensor->NuiShutdown();

   SAFE_RELEASE( m_pKinectSensor );
}

void UCKinect03::CreateKinect( DWORD Flags, DWORD& pWidth, DWORD& pHeight )
{
   HRESULT hr = E_FAIL;
   int count = 0;

   pWidth = 0;
   pHeight = 0;
   m_Flags = Flags;

   // マシンに接続されている Kinectセンサー 数を取得する。
   if( FAILED( hr = ::NuiGetSensorCount( &count ) ) )
      throw( UCException( hr, _T("UCKinect03::CreateKinect()でエラーが発生しました。接続されているKinectセンサーの数を取得できません。") ) );

   if( count == 0 )
      throw( UCException( -1, _T("UCKinect03::CreateKinect()でエラーが発生しました。Kinectセンサーが接続されていません。") ) );

   // 指定したインデックスの INuiSensor のインスタンスを作成する
   // ここでは 0 番目のインスタンスのみ作成する
   if( FAILED( hr = ::NuiCreateSensorByIndex( 0, &m_pKinectSensor ) ) )
      throw( UCException( hr, _T("UCKinect03::CreateKinect()でエラーが発生しました。Kinectセンサーが接続されていません。") ) );

   HRESULT status = E_FAIL;

   for( int i=0; i<50; i++ )
   {
      TCHAR msg[256];

      // Kinectセンサー の接続状態を取得する
      status = m_pKinectSensor->NuiStatus();
   
      // 正常
      if( status == S_OK )
         break;
      // Kinectセンサーが接続されているが、初期化中
      // Kinectセンサー接続直後にアプリを起動するとこの状態になるときがある
      else if( status == S_NUI_INITIALIZING )
      {
         _stprintf_s( msg, _T("■□■HRESULT:0x%x [ %s ]\n"), hr, _T(":Kinectセンサーが接続されているが、初期化中\n") );
         OutputDebugString( msg );
      }
      // Kinectセンサーが接続されているが、エラーが発生
      // Kinectセンサー接続直後にアプリを起動するとこの状態になるときがある
      else
      {
         _stprintf_s( msg, _T("■□■HRESULT:0x%x [ %s ]\n"), hr, _T(":Kinectセンサーが接続されているが、エラーが発生\n") );
         OutputDebugString( msg );
      }

      Sleep( 1000 );
   }
   if( status != S_OK )
      throw( UCException( -1, _T("UCKinect03::CreateKinect()でエラーが発生しました。Kinectセンサーが接続されているが、初期化が完了しなかった") ) );

   // Kinectを初期化する。
   if( FAILED( hr = m_pKinectSensor->NuiInitialize( m_Flags ) ) )
      throw( UCException( -1, _T("UCKinect03::CreateKinect()でエラーが発生しました。Kinectの初期化に失敗した") ) );

   // RGBカメラを使用する場合
   if( m_Flags & NUI_INITIALIZE_FLAG_USES_COLOR )
   {
      // イメージストリームをオープンする
      if( FAILED( hr = m_pKinectSensor->NuiImageStreamOpen( 
                            NUI_IMAGE_TYPE_COLOR,                   // カラーデータを取得する
                            m_ImageResolution,                      // イメージストリームの解像度を指定する
                            0, 2, nullptr, 
                            &m_ImageStreamHandle                    // 開始されたイメージストリームのハンドル
                            ) ) )
        throw( UCException( hr, _T("UCKinect03::CreateKinect()でエラーが発生しました。イメージストリームをオープンできなかった") ) );
   }

   // 深度カメラを使用し、プレイヤーIDを使用しない場合
   if( m_Flags & NUI_INITIALIZE_FLAG_USES_DEPTH )
   {
      // イメージストリームをオープンする
      if( FAILED( hr = m_pKinectSensor->NuiImageStreamOpen( 
                            NUI_IMAGE_TYPE_DEPTH,                   // 深度データを取得する
                            m_DepthResolution,                      // 深度ストリームの解像度を指定する
                            0, 2, nullptr, 
                            &m_DepthStreamHandle                    // 開始された深度ストリームのハンドル
                            ) ) )
        throw( UCException( hr, _T("UCKinect03::CreateKinect()でエラーが発生しました。深度ストリームをオープンできなかった") ) );
   }

   // 深度カメラを使用し、プレイヤーIDを使用する場合
   else if( m_Flags & NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX )
   {
      // イメージストリームをオープンする
      if( FAILED( hr = m_pKinectSensor->NuiImageStreamOpen( 
                            NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX,  // 深度データとプレイヤーIDを取得する
                            m_DepthResolution,                      // 深度ストリームの解像度を指定する
                            0, 2, nullptr, 
                            &m_DepthStreamHandle                    // 開始された深度ストリーム + プレイヤーIDのハンドル
                            ) ) )
        throw( UCException( hr, _T("UCKinect03::CreateKinect()でエラーが発生しました。深度ストリーム + プレイヤーIDをオープンできなかった") ) );
   }

   // NUI_IMAGE_RESOLUTION列挙型の値から実際の解像度値を取得する
   ::NuiImageResolutionToSize( m_ImageResolution, pWidth, pHeight );
}

void UCKinect03::CreateImageFrame( HANDLE StreamHandle, NUI_IMAGE_FRAME* pImageFrame, NUI_LOCKED_RECT* pRect )
{
   HRESULT hr = E_FAIL;
   NUI_LOCKED_RECT LockRect;

   ::ZeroMemory( pRect, sizeof( NUI_LOCKED_RECT ) );

   // 指定されたイメージストリームから次のイメージフレームを取得する
   if( FAILED( hr = m_pKinectSensor->NuiImageStreamGetNextFrame( StreamHandle, INFINITE, pImageFrame ) ) )
      throw( UCException( hr, _T("UCKinect03::CreateImageFrame()でエラーが発生しました。次のイメージフレームを取得できなかった") ) );

   // イメージフレームからカラーデータを取得する
   if( FAILED( hr = pImageFrame->pFrameTexture->LockRect( 0, &LockRect, nullptr, 0 ) ) )
      throw( UCException( hr, _T("UCKinect03::CreateImageFrame()でエラーが発生しました。イメージフレームからイメージデータを取得できなかった") ) );

   // コピー
   pRect->pBits = NEW BYTE[ LockRect.size ];
   ::CopyMemory( pRect->pBits, LockRect.pBits, sizeof( BYTE ) * LockRect.size );
   pRect->Pitch = LockRect.Pitch;
   pRect->size = LockRect.size;
}

void UCKinect03::ReleaseImageFrame( HANDLE StreamHandle, NUI_IMAGE_FRAME* ImageFrame )
{
   HRESULT hr = E_FAIL;

   // ロックを解除する
   if( FAILED( hr = ImageFrame->pFrameTexture->UnlockRect( 0 ) ) )
      throw( UCException( hr, _T("UCKinect03::ReleaseImageFrame()でエラーが発生しました。ロックを解除できなかった") ) );

   // イメージストリームから取得したイメージフレームを解放する
   if( FAILED( hr = m_pKinectSensor->NuiImageStreamReleaseFrame( StreamHandle, ImageFrame ) ) )
      throw( UCException( hr, _T("UCKinect03::ReleaseImageFrame()でエラーが発生しました。イメージストリームから取得したイメージフレームを解放できなかった") ) );
}

void UCKinect03::NextFrameImageData( NUI_LOCKED_RECT* pRect )
{
   NUI_IMAGE_FRAME ImageFrame;

   CreateImageFrame( m_ImageStreamHandle, &ImageFrame, pRect );
   ReleaseImageFrame( m_ImageStreamHandle, &ImageFrame );
}

void UCKinect03::NextFrameDepthAndPlayerIndexData( NUI_LOCKED_RECT* pRect )
{
   NUI_IMAGE_FRAME ImageFrame;

   CreateImageFrame( m_DepthStreamHandle, &ImageFrame, pRect );
   ReleaseImageFrame( m_DepthStreamHandle, &ImageFrame );
}

// カラーデータのa成分にプレイヤーID値を格納する
void UCKinect03::MergeImageDataAndPlayerIndexData( NUI_LOCKED_RECT* pImageData, NUI_LOCKED_RECT* pDepthData )
{   
   HRESULT hr = E_FAIL;

   // 解像度を取得する
   DWORD imageWidth, imageHeight, depthWidth, depthHeight;
   ::NuiImageResolutionToSize( m_ImageResolution, imageWidth, imageHeight );
   ::NuiImageResolutionToSize( m_DepthResolution, depthWidth, depthHeight );

   USHORT* depth = (USHORT*)pDepthData->pBits;

   // 深度データをループ
   for( DWORD i=0; i<(pDepthData->size/sizeof(USHORT)); i++ )
   {
      // 深度フレームの X 方向の位置
      LONG depthX = i % depthWidth;
      // 深度フレームの Y 方向の位置
      LONG depthY = i / depthWidth;

      LONG colorX = 0;
      LONG colorY = 0;

      // 深度イメージの座標をカラーイメージの座標に変換する
      if( FAILED( hr = m_pKinectSensor->NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution(
                                                         m_ImageResolution,
                                                         m_DepthResolution,
                                                         0,
                                                         depthX, depthY,
                                                         depth[i],
                                                         &colorX, &colorY ) ) )
         throw( UCException( hr, _T("UCKinect03::MergeImageDataAndPlayerIndexData()でエラーが発生しました。深度イメージの座標をカラーイメージの座標に変換できなかった") ) );

      // 誤差を吸収する
      if( colorX > (LONG)imageWidth )
         colorX = imageWidth;

      if( colorY > (LONG)imageHeight )
         colorY = imageHeight;

      // カラーイメージのピクセル単位でのインデックス値
      int index = ((colorY * imageWidth) + colorX) * 4;

      // 深度値を取り除いてプレイヤーID値を取得する
      USHORT pid = ::NuiDepthPixelToPlayerIndex( depth[i] );

     if( pid > 0 )
        pImageData->pBits[index+3] = 255;
   }
}

前回のソースから微妙に組み替えてはいますが、大きな変更点はないはずです。

---main.cpp---  ↑

#include "../../Common/Header/UCommon.h"
#include "../../Common/Header/UException.h"
#include "../../Common/Header/UDirect3D11.h"
#include "../../Common/Header/UGraphicsPipeline.h"
#include "../../Common/Header/UKinect03.h"
#include "UPlane03.h"
#include <NuiApi.h>

// 定数バッファ用定義
typedef struct _VECTOR4
{
    float x, y, z, w;
}VECTOR4;

// シェーダーオブジェクトを作成するとき、ファイルから読むか、メモリから読むかを切り替える
#if defined(DEBUG) || defined(_DEBUG)
   #define UNCOMPILED_SHADER     // ファイルを読み込んでコンパイルする
#else
   #include "../../Common/HLSL/Sample03_VS_Main.h"
   #include "../../Common/HLSL/Sample03_PS_Main.h"
#endif

// アプリケーション名
TCHAR* AppName = _T("Kinect_Tutrial03");

// Direct3D関連の自作クラス
UCDirect3D11* g_pDirect3D11 = nullptr;

// グラフィックパイプライン関連の自作クラス
UCGraphicsPipeline* g_pGraphicsPipeline = nullptr;

// シェーダー用定数バッファ
ID3D11Buffer* g_pConstantBuffers[1] = { nullptr };

// Kinectセンサーオブジェクト
UCKinect03* g_pKinect03 = nullptr;

// 平面オブジェクト
UCPlane03* g_pPlane03 = nullptr;

// メモリ解放
void Invalidate()
{
   for( int i=0; i<_countof( g_pConstantBuffers ); i++ )
      SAFE_RELEASE( g_pConstantBuffers[i] );

   SAFE_DELETE( g_pKinect03 );
   SAFE_DELETE( g_pPlane03 );
   SAFE_DELETE( g_pGraphicsPipeline );
   SAFE_DELETE( g_pDirect3D11 );
}

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
{
   switch( msg )
   {
   case WM_KEYUP:
      // アプリ終了
      if( wParam == VK_ESCAPE )
         ::DestroyWindow( hWnd );
      break;

   case WM_DESTROY:
      ::PostQuitMessage(0);
      break;

   default:
      return ::DefWindowProc( hWnd, msg, wParam, lParam );
   }

   return 0L;
}

// Direct3Dの作成
void CreateDirect3D( HINSTANCE hInstance, DWORD Width, DWORD Height )
{
   DXGI_MODE_DESC* pModeDescArray = nullptr;

   __try
   {
      DXGI_MODE_DESC  ModeDesc;
      UINT num;

      // ディスプレイモード一覧の数を取得する
      g_pDirect3D11->GetDisplayMode( nullptr, &num );

      pModeDescArray = NEW DXGI_MODE_DESC[num];
      // ディスプレイモード一覧を取得する
      g_pDirect3D11->GetDisplayMode( pModeDescArray, &num );

      bool find = false;
      for( UINT i=0; i<num; i++ )
      {
         // 適切な解像度のディスプレイモードを検索する
         if( pModeDescArray[i].Width == Width && pModeDescArray[i].Height == Height )
         {
            find = true;
            ::CopyMemory( &ModeDesc, &pModeDescArray[i], sizeof( DXGI_MODE_DESC ) );
            break;
         }
      }

      if( find == false )
         throw( UCException( -1, _T("InitDirect3D()でエラーが発生しました。適切なディスプレイモードの解像度を取得できません。") ) );

      // ウィンドウの作成およびDirect3D の作成
      g_pDirect3D11->CreateDirect3D11( AppName, hInstance, WndProc, &ModeDesc, TRUE, TRUE );
   }
   __finally
   {
      SAFE_DELETE_ARRAY( pModeDescArray );
   }
}

void CreateGraphicePipeline( DWORD Width, DWORD Height )
{
   D3D11_INPUT_ELEMENT_DESC layout[] = {
         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
   };
   
   // シェーダーを作成する
#if defined(DEBUG) || defined(_DEBUG)
   g_pGraphicsPipeline->CreateVertexShaderFromFile( g_pDirect3D11->m_pD3DDevice, _T("../../Common/HLSL/Sample03.hlsl"), "VS_Main", layout, _countof( layout ) );
   g_pGraphicsPipeline->CreatePixelShaderFromFile(  g_pDirect3D11->m_pD3DDevice, _T("../../Common/HLSL/Sample03.hlsl"), "PS_Main" );
#else
   g_pGraphicsPipeline->CreateVertexShaderFromMemory( g_pDirect3D11->m_pD3DDevice, (LPBYTE)g_VS_Main, sizeof( g_VS_Main ), layout, _countof( layout ) );
   g_pGraphicsPipeline->CreatePixelShaderFromMemory(  g_pDirect3D11->m_pD3DDevice, (LPBYTE)g_PS_Main, sizeof( g_PS_Main ) );
#endif

   // ラスタライザーステートを作成する
   g_pGraphicsPipeline->CreateRasterizerState( g_pDirect3D11->m_pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK );

   // 深度ステンシルステートを作成する
   g_pGraphicsPipeline->CreateDepthStencilState( g_pDirect3D11->m_pD3DDevice, FALSE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL );

   // ブレンドステートを作成する
   UCGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UCGraphicsPipeline::UEBLEND_STATE::NONE };
   g_pGraphicsPipeline->CreateBlendState( g_pDirect3D11->m_pD3DDevice, BlendStateType, 1 );

   // シェーダー用の定数バッファを作成する
   VECTOR4 vec;
   vec.x = (float)Width;
   vec.y = (float)Height;
   g_pConstantBuffers[0] = g_pGraphicsPipeline->CreateConstantBuffer( g_pDirect3D11->m_pD3DDevice, (LPVOID)&vec, sizeof( VECTOR4 ), 0 );
}

// 各種リソースを作成する
void CreateMesh( DWORD Width, DWORD Height )
{
   g_pPlane03->CreateMesh( g_pDirect3D11->m_pD3DDevice, Width, Height );
}

void CreateResource( HINSTANCE hInstance )
{
    // Direct3D 関連自作クラスのインスタンスを作成
    // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。
    g_pDirect3D11 = NEW UCDirect3D11();
    g_pGraphicsPipeline = NEW UCGraphicsPipeline();
    g_pPlane03 = NEW UCPlane03();
    g_pKinect03 = NEW UCKinect03();

    DWORD Width = 0, Height = 0;

    // Kinectセンサーオブジェクトを作成
   // RGBカメラとプレイヤーIDを使用する
    g_pKinect03->CreateKinect( NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX, Width, Height );

    // Direct3Dの作成
    CreateDirect3D( hInstance, Width, Height );

    // グラフィックパイプラインリソースの作成
    CreateGraphicePipeline( Width, Height );

    // リソースの作成
    CreateMesh( Width, Height );
}

void NextFrame()
{
   NUI_LOCKED_RECT imageData = { 0 }, depthData = { 0 };
   __try
   {
      // Kinect側の次のフレームのイメージフレームの作成
      g_pKinect03->NextFrameImageData( &imageData );
      g_pKinect03->NextFrameDepthAndPlayerIndexData( &depthData  );

      // カラーデータのa成分にプレイヤーIDを格納する
      g_pKinect03->MergeImageDataAndPlayerIndexData( &imageData, &depthData );

      // Direct3D側を次のフレームに進める
      g_pPlane03->NextFrame( g_pDirect3D11->m_pD3DDeviceContext, imageData );
   }

   __finally
   {
      SAFE_DELETE_ARRAY( imageData.pBits );
      SAFE_DELETE_ARRAY( depthData.pBits );
   }
}

// 描画処理
HRESULT Render()
{
   HRESULT hr = E_FAIL;
   float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f };

    // バックバッファをクリアする。
   g_pDirect3D11->ClearBackBuffer( ClearColor ); 

   // 深度バッファをクリアする。
   g_pDirect3D11->ClearDepthStencilView( D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );

   // 各種グラフィックパイプラインを設定
   g_pGraphicsPipeline->SetVertexShader( g_pDirect3D11->m_pD3DDeviceContext );
   g_pGraphicsPipeline->SetPixelShader( g_pDirect3D11->m_pD3DDeviceContext );
   g_pGraphicsPipeline->SetRasterizerState( g_pDirect3D11->m_pD3DDeviceContext );
   g_pGraphicsPipeline->SetDepthStencilState( g_pDirect3D11->m_pD3DDeviceContext );
   g_pGraphicsPipeline->SetBlendState( g_pDirect3D11->m_pD3DDeviceContext );

   // 定数バッファを設定
   g_pDirect3D11->m_pD3DDeviceContext->VSSetConstantBuffers( 0, _countof( g_pConstantBuffers ), g_pConstantBuffers );
   g_pDirect3D11->m_pD3DDeviceContext->PSSetConstantBuffers( 0, _countof( g_pConstantBuffers ), g_pConstantBuffers );

   // レンダリング
   g_pPlane03->Render( g_pDirect3D11->m_pD3DDeviceContext );

   // レンダリングされたイメージをユーザーに表示。
   if( FAILED( hr = g_pDirect3D11->Present( 0, 0 ) ) )
      throw( UCException( hr, _T("IDXGISwapChain::Present()が失敗しました") ) );

   return hr;
}
 
// メイン関数
int APIENTRY _tWinMain( HINSTANCE hInstance,
                        HINSTANCE,
                        LPTSTR,
                        INT )
{
   // メモリリーク検出
   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF);

   MSG msg = {0};

   try
   {
      CreateResource( hInstance );

      ::ShowWindow( g_pDirect3D11->m_hWnd, SW_SHOW );
      ::UpdateWindow( g_pDirect3D11->m_hWnd );

      // メッセージループ
      do
      { 
        if( ::PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
        {
          ::TranslateMessage(&msg); 
          ::DispatchMessage(&msg); 
        }
        else
        {
          NextFrame();
          Render();
        }
      }while( msg.message != WM_QUIT );
   }
   catch( UCException ex )
   {
      ::MessageBox( nullptr, ex.m_pErrorStr, _T("エラー"), MB_OK );
   }

   Invalidate();
   ::UnregisterClass( AppName, hInstance );

   return msg.wParam;
}

アプリ起動後すぐにプレイヤーが認識されるわけではないようです。 認識されない場合は、両手を動かしてみてください。

web拍手 by FC2

Prev Top Next

inserted by FC2 system