Microsoft Visual C++ 2012 Express Direct3D 11.0 Kinect for Windows SDK v1.7 DirectXTex texture processing library |
■Kinect スケルトンの検出 | Prev Top Next |
関連ページ:Direct3D 自作の共通ライブラリ |
UCommon.h | 共通で使用するヘッダファイル |
UException.h | 例外処理クラスのヘッダファイル |
UDirect3D11.h | Direct3Dクラスのヘッダーファイル |
UDirect3D11.cpp | Direct3Dクラスのソースファイル |
UGraphicsPipeline.h | グラフィックパイプラインクラスのヘッダーファイル |
UGraphicsPipeline.cpp | グラフィックパイプラインクラスのソースファイル |
UMesh.h | メッシュの抽象クラスのヘッダーファイル |
UMesh.cpp | メッシュの抽象クラスのソースファイル |
UDDSLoader.h | DDSファイルをロードしてシェーダーリソースビューを作成するサンプルクラスのヘッダファイル。 R8G8B8A8またはR8G8B8X8のみサポートし、ミップマップ、キューブマップ、ボリュームマップは未対応。 |
UDDSLoader.cpp | DDSファイルをロードしてシェーダーリソースビューを作成するサンプルクラスのソースファイル。 |
UPlane04_0.h | RGBカメラから取得したイメージをレンダリングするためのメッシュクラスのヘッダーファイル |
UPlane04_0.cpp | RGBカメラから取得したイメージをレンダリングするためのメッシュクラスのソースファイル |
UPlane04_1.h | ジョイントをレンダリングするためのメッシュクラスのヘッダーファイル |
UPlane04_1.cpp | ジョイントをレンダリングするためのメッシュクラスのソースファイル |
Sample04.hlsl | hlslファイル |
UKinect04.h | Kinectクラスのヘッダーファイル |
UKinect04.cpp | Kinectクラスのソースファイル |
main.cpp | main関数のソースファイル |
#ifndef UPLANE04_0_H #define UPLANE04_0_H #include "../../Common/Header/UCommon.h" #include "../../Common/Header/UException.h." #include "../../Common/Header/UMesh.h" #include "../../Common/Header/UDirect3D11.h" #include <NuiApi.h> class UCPlane04_0: public UIMesh { private: // 頂点定義 typedef struct _VERTEX { // 頂点座標 float x, y, z; // テクセル float tu, tv; }VERTEX; // Direct3D用定数バッファ設定用構造体 typedef struct _CONSTANT_BUFFER { XMFLOAT4 Position; XMFLOAT4 Color; _CONSTANT_BUFFER(){}; _CONSTANT_BUFFER( XMFLOAT4 position, XMFLOAT4 color ) { ::CopyMemory( &Position, &position, sizeof( XMFLOAT4 ) ); ::CopyMemory( &Color, &color, sizeof( XMFLOAT4 ) ); }; }CONSTANT_BUFFER; // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // インデックスバッファ ID3D11Buffer* m_pIndexBuffer; // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; // 定数バッファ ID3D11Buffer* m_pConstantBuffers; public: UCPlane04_0(); ~UCPlane04_0(); void Invalidate(); void CreateMesh( ID3D11Device* pD3DDevice, UINT Width, UINT Height, ID3D11Buffer** ppConstantBuffers ); void NextFrame( ID3D11DeviceContext* pD3DDeviceContext, NUI_LOCKED_RECT* pRect ); void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; #endif
#include "UPlane04_0.h" UCPlane04_0::UCPlane04_0() { m_pVertexBuffer = nullptr; m_pIndexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; } UCPlane04_0::~UCPlane04_0() { Invalidate(); } void UCPlane04_0::Invalidate() { SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pSRView ); SAFE_RELEASE( m_pIndexBuffer ); SAFE_RELEASE( m_pVertexBuffer ); } void UCPlane04_0::CreateMesh( ID3D11Device* pD3DDevice, UINT Width, UINT Height, ID3D11Buffer** ppConstantBuffers ) { // 頂点データを格納する 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 ); m_pConstantBuffers = *ppConstantBuffers; } void UCPlane04_0::NextFrame( ID3D11DeviceContext* pD3DDeviceContext, NUI_LOCKED_RECT* pRect ) { ID3D11Resource* pResource = nullptr; __try { // シェーダーリソースビューからテクスチャーを取得する m_pSRView->GetResource( &pResource ); // シェーダーリソースビューに色情報を設定する pD3DDeviceContext->UpdateSubresource( pResource, 0, nullptr, pRect->pBits, pRect->Pitch, 0 ); } __finally { SAFE_RELEASE( pResource ); } } void UCPlane04_0::Render( ID3D11DeviceContext* pD3DDeviceContext ) { HRESULT hr = E_FAIL; // 頂点バッファ設定 UINT stride = sizeof( UCPlane04_0::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 ); D3D11_MAPPED_SUBRESOURCE mappedResource; if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UCException( -1, _T("UCPlane04_0::Render()でエラーが発生しました。Map()が失敗しました。") ) ); CONSTANT_BUFFER* cbuffer = (CONSTANT_BUFFER*)(mappedResource.pData); ::CopyMemory( &cbuffer->Position, &XMFLOAT4( 0, 0, 0, 0 ), sizeof( XMFLOAT4 )); ::CopyMemory( &cbuffer->Color, &XMFLOAT4( 1, 1, 1, 1 ), sizeof( XMFLOAT4 )); pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 ); // 定数バッファを設定 pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); // インデックスバッファを使用した描画 pD3DDeviceContext->DrawIndexed( 4, 0, 0 ); }
#ifndef UPLANE04_1_H #define UPLANE04_1_H #include "../../Common/Header/UCommon.h" #include "../../Common/Header/UException.h." #include "../../Common/Header/UMesh.h" #include "../../Common/Header/UDDSLoader.h" #include "../../Common/Header/UDirect3D11.h" #include <NuiApi.h> class UCPlane04_1: public UIMesh { private: // 頂点定義 typedef struct _VERTEX { // 頂点座標 float x, y, z; // テクセル float tu, tv; }VERTEX; // Direct3D用定数バッファ設定用構造体 typedef struct _CONSTANT_BUFFER { XMFLOAT4 Position; XMFLOAT4 Color; _CONSTANT_BUFFER(){}; _CONSTANT_BUFFER( XMFLOAT4 position, XMFLOAT4 color ) { ::CopyMemory( &Position, &position, sizeof( XMFLOAT4 ) ); ::CopyMemory( &Color, &color, sizeof( XMFLOAT4 ) ); }; }CONSTANT_BUFFER; // 頂点バッファ ID3D11Buffer* m_pVertexBuffer; // インデックスバッファ ID3D11Buffer* m_pIndexBuffer; // シェーダーリソースビュー ID3D11ShaderResourceView* m_pSRView; // サンプラーステート ID3D11SamplerState* m_pSamplerState; UINT m_SkeletonFrameCount; // ジョイント座標 CONSTANT_BUFFER* m_SkeletonFrameArray; // スケルトン座標をスクリーン座標系に変換する void TransformSkeletonToScreenCoordinate( Vector4* pSkeletonPosition, NUI_IMAGE_RESOLUTION imageFrameResolution, NUI_IMAGE_RESOLUTION depthFrameResolution, LONG* pColorX, LONG* pColorY ); // スクリーン座標系の座標を射影座標系の座標に変換する inline float TransformScreenToProjectionCoordinate( float ScreenSize, float ScreenPos ) { return ScreenPos / ScreenSize * 2.0f - 1.0f; } // 定数バッファ ID3D11Buffer* m_pConstantBuffers; public: UCPlane04_1(); ~UCPlane04_1(); void Invalidate(); void CreateMesh( ID3D11Device* pD3DDevice, float Width, float Height, TCHAR* pTextureFileName, UINT SkeletonFrameCount, ID3D11Buffer** ppConstantBuffers ); // Kinectから取得したスケルトンをDirect3D用に変換する void NextFrame( NUI_SKELETON_FRAME* pSrvSkeleton, NUI_IMAGE_RESOLUTION imageFrameResolution, NUI_IMAGE_RESOLUTION depthFrameResolution, float Width, float Height ); void Render( ID3D11DeviceContext* pD3DDeviceContext ); }; #endif
#include "UPlane04_1.h" UCPlane04_1::UCPlane04_1() { m_pVertexBuffer = nullptr; m_pIndexBuffer = nullptr; m_pSRView = nullptr; m_pSamplerState = nullptr; m_SkeletonFrameCount = 0; m_SkeletonFrameArray = nullptr; } UCPlane04_1::~UCPlane04_1() { Invalidate(); } void UCPlane04_1::Invalidate() { SAFE_DELETE_ARRAY( m_SkeletonFrameArray ); SAFE_RELEASE( m_pSamplerState ); SAFE_RELEASE( m_pSRView ); SAFE_RELEASE( m_pIndexBuffer ); SAFE_RELEASE( m_pVertexBuffer ); } void UCPlane04_1::CreateMesh( ID3D11Device* pD3DDevice, float Width, float Height, TCHAR* pTextureFileName, UINT SkeletonFrameCount, ID3D11Buffer** ppConstantBuffers ) { // 頂点データを格納する VERTEX v[] = { Width, Height, 0.0f, 1.0f, 0.0f, -Width, Height, 0.0f, 0.0f, 0.0f, Width, -Height, 0.0f, 1.0f, 1.0f, -Width, -Height, 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 ); // デカールマップをロード CreateDDSTextureFromFile( pD3DDevice, pTextureFileName, &m_pSRView ); // サンプラーステートを作成する m_pSamplerState = CreateSamplerState( pD3DDevice, D3D11_TEXTURE_ADDRESS_CLAMP ); m_SkeletonFrameCount = SkeletonFrameCount; m_SkeletonFrameArray = NEW CONSTANT_BUFFER[m_SkeletonFrameCount]; m_pConstantBuffers = *ppConstantBuffers; } // スケルトン座標をスクリーン座標系に変換する void UCPlane04_1::TransformSkeletonToScreenCoordinate( Vector4* pSkeletonPosition, NUI_IMAGE_RESOLUTION imageFrameResolution, NUI_IMAGE_RESOLUTION depthFrameResolution, LONG* pColorX, LONG* pColorY ) { HRESULT hr = E_FAIL; FLOAT depthX = 0, depthY = 0; *pColorX = *pColorY = 0; // スケルトンの座標を深度イメージの座標系に変換する ::NuiTransformSkeletonToDepthImage( *pSkeletonPosition, &depthX, &depthY, imageFrameResolution ); // 深度イメージの座標からカラーイメージの座標を取得する if( FAILED( hr = ::NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution( imageFrameResolution, depthFrameResolution, nullptr, (LONG)depthX, (LONG)depthY, 0, pColorX, pColorY ) ) ) throw( UCException( hr, _T("TransformSkeletonToColorPixelCoordinate()でエラーが発生しました。カラーイメージの座標を取得できなかった") ) ); } // Kinectから取得したスケルトンをDirect3D用に変換する void UCPlane04_1::NextFrame( NUI_SKELETON_FRAME* pSrvSkeleton, NUI_IMAGE_RESOLUTION imageFrameResolution, NUI_IMAGE_RESOLUTION depthFrameResolution, float Width, float Height ) { // レンダリングするジョイント数 UINT SkeletonCount = 0; LONG ColorX, ColorY; float x, y; for( int i=0; i<NUI_SKELETON_COUNT; i++ ) { NUI_SKELETON_DATA* skeletonData = &pSrvSkeleton->SkeletonData[i]; // スケルトンの追跡状態をチェックする switch( skeletonData->eTrackingState ) { // スケルトンが追跡されている case NUI_SKELETON_TRACKED: for( int j=0; j<NUI_SKELETON_POSITION_COUNT; j++ ) { // ジョイントの追跡状態をチェックする switch( skeletonData->eSkeletonPositionTrackingState[j] ) { // ジョイントの座標が追跡されている case NUI_SKELETON_POSITION_TRACKED: TransformSkeletonToScreenCoordinate( &skeletonData->SkeletonPositions[j], imageFrameResolution, depthFrameResolution, &ColorX, &ColorY ); x = TransformScreenToProjectionCoordinate( Width, (float)ColorX ); y = -TransformScreenToProjectionCoordinate( Height, (float)ColorY ); m_SkeletonFrameArray[SkeletonCount++] = CONSTANT_BUFFER( XMFLOAT4( x, y, 0, 0 ), XMFLOAT4( 1.0f, 0.2f, 0.2f, 1.0f ) ); break; // ジョイントの座標が推測されている case NUI_SKELETON_POSITION_INFERRED: TransformSkeletonToScreenCoordinate( &skeletonData->SkeletonPositions[j], imageFrameResolution, depthFrameResolution, &ColorX, &ColorY ); x = TransformScreenToProjectionCoordinate( Width, (float)ColorX ); y = -TransformScreenToProjectionCoordinate( Height, (float)ColorY ); m_SkeletonFrameArray[SkeletonCount++] = CONSTANT_BUFFER( XMFLOAT4( x, y, 0, 0 ), XMFLOAT4( 0, 1.0f, 0.0f, 1.0f ) ); break; // ジョイントの座標が追跡されていない default: break; } } break; // プレイヤーの位置情報のみ追跡されている case NUI_SKELETON_POSITION_ONLY: TransformSkeletonToScreenCoordinate( &skeletonData->Position, imageFrameResolution, depthFrameResolution, &ColorX, &ColorY ); x = TransformScreenToProjectionCoordinate( Width, (float)ColorX ); y = -TransformScreenToProjectionCoordinate( Height, (float)ColorY ); m_SkeletonFrameArray[SkeletonCount++] = CONSTANT_BUFFER( XMFLOAT4( x, y, 0, 0 ), XMFLOAT4( 0, 1.0f, 0, 1.0f ) ); break; // 追跡されていない case NUI_SKELETON_NOT_TRACKED: break; } } m_SkeletonFrameCount = SkeletonCount; } void UCPlane04_1::Render( ID3D11DeviceContext* pD3DDeviceContext ) { HRESULT hr = E_FAIL; // 頂点バッファ設定 UINT stride = sizeof( UCPlane04_1::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 ); for( UINT i=0; i<m_SkeletonFrameCount; i++ ) { D3D11_MAPPED_SUBRESOURCE mappedResource; if( FAILED( hr = pD3DDeviceContext->Map( m_pConstantBuffers, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource ) ) ) throw( UCException( -1, _T("UCPlane04_1::Render()でエラーが発生しました。Map()が失敗しました。") ) ); CONSTANT_BUFFER* cbuffer = (CONSTANT_BUFFER*)(mappedResource.pData); ::CopyMemory( &cbuffer->Position, &m_SkeletonFrameArray[i].Position, sizeof( XMFLOAT4 )); ::CopyMemory( &cbuffer->Color, &m_SkeletonFrameArray[i].Color, sizeof( XMFLOAT4 )); pD3DDeviceContext->Unmap( m_pConstantBuffers, 0 ); // 定数バッファを設定 pD3DDeviceContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); pD3DDeviceContext->PSSetConstantBuffers( 0, 1, &m_pConstantBuffers ); // インデックスバッファを使用した描画 pD3DDeviceContext->DrawIndexed( 4, 0, 0 ); } }
// 定数バッファ cbuffer cbSize : register( b0 ) { float4 g_VertexOffset : packoffset( c0 ); // 頂点の平行移動値 float4 g_VertexColor : packoffset( c1 ); // 頂点カラー値 }; // テクスチャー 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; float4 color : TEXCOORD1; }; // 頂点シェーダー VS_OUT_PS_IN VS_Main( VS_IN In ) { VS_OUT_PS_IN Out; Out.pos = float4( In.pos + g_VertexOffset.xyz, 1.0f ); Out.texel = In.texel; Out.color = g_VertexColor; return Out; } // ピクセルシェーダ float4 PS_Main( VS_OUT_PS_IN In ) : SV_TARGET { // 色取得 float4 col = g_Tex.Sample( g_Sampler, In.texel ) * In.color; return col.gbra; }
#ifndef KINECT04_H #define KINECT04_H #include "../../Common/Header/UCommon.h" #include <NuiApi.h> #include "../../Common/Header/UException.h" // Kinect用ライブラリ #pragma comment( lib, "Kinect10.lib" ) class UCKinect04 { 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: UCKinect04(); ~UCKinect04(); void CreateKinect( DWORD Flags, BOOL NearModeEnaled ); // カラーデータを取得する void NextFrameImageData( NUI_LOCKED_RECT* pRect ); // スケルトンデータを取得する void NextFrameSkeletonData( NUI_SKELETON_FRAME* pSkeletonFrame ); // イメージフレームの解像度を取得する inline void GetImageResolutionToSize( DWORD& pWidth, DWORD& pHeight ) { ::NuiImageResolutionToSize( m_ImageResolution, pWidth, pHeight ); } const NUI_IMAGE_RESOLUTION GetImageResolution(){ return m_ImageResolution; }; const NUI_IMAGE_RESOLUTION GetDepthResolution(){ return m_DepthResolution; }; }; #endif
#include "../../Common/Header/UKinect04.h" UCKinect04::UCKinect04() { m_pKinectSensor = nullptr; } UCKinect04::~UCKinect04() { if( m_pKinectSensor != nullptr ) m_pKinectSensor->NuiShutdown(); SAFE_RELEASE( m_pKinectSensor ); } void UCKinect04::CreateKinect( DWORD Flags, BOOL NearModeEnaled ) { HRESULT hr = E_FAIL; int count = 0; m_Flags = Flags; // マシンに接続されている Kinectセンサー 数を取得する。 if( FAILED( hr = ::NuiGetSensorCount( &count ) ) ) throw( UCException( hr, _T("UCKinect04::CreateKinect()でエラーが発生しました。接続されているKinectセンサーの数を取得できません。") ) ); if( count == 0 ) throw( UCException( -1, _T("UCKinect04::CreateKinect()でエラーが発生しました。Kinectセンサーが接続されていません。") ) ); // 指定したインデックスの INuiSensor のインスタンスを作成する // ここでは 0 番目のインスタンスのみ作成する if( FAILED( hr = ::NuiCreateSensorByIndex( 0, &m_pKinectSensor ) ) ) throw( UCException( hr, _T("UCKinect04::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("UCKinect04::CreateKinect()でエラーが発生しました。Kinectセンサーが接続されているが、初期化が完了しなかった") ) ); // Kinectを初期化する。 if( FAILED( hr = m_pKinectSensor->NuiInitialize( m_Flags ) ) ) throw( UCException( -1, _T("UCKinect04::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("UCKinect04::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("UCKinect04::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("UCKinect04::CreateKinect()でエラーが発生しました。深度ストリーム + プレイヤーIDをオープンできなかった") ) ); } // Nearモードを有効にする? if( NearModeEnaled ) { // Kinect for XBOX は Nearモード は対応していない! if( FAILED( hr = m_pKinectSensor->NuiImageStreamSetImageFrameFlags( m_DepthStreamHandle, NUI_IMAGE_STREAM_FLAG_ENABLE_NEAR_MODE ) ) ) throw( UCException( hr, _T("UCKinect04::CreateKinect()でエラーが発生しました。イメージフレームの設定に失敗した") ) ); } // スケルトントラッキングを有効にする? if( Flags & NUI_INITIALIZE_FLAG_USES_SKELETON ) { if( FAILED( hr = m_pKinectSensor->NuiSkeletonTrackingEnable( nullptr, 0 ) ) ) throw( UCException( hr, _T("UCKinect04::CreateKinect()でエラーが発生しました。スケルトントラッキングを有効にできなかった") ) ); } } void UCKinect04::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("UCKinect04::CreateImageFrame()でエラーが発生しました。次のイメージフレームを取得できなかった") ) ); // イメージフレームからカラーデータを取得する if( FAILED( hr = pImageFrame->pFrameTexture->LockRect( 0, &LockRect, nullptr, 0 ) ) ) throw( UCException( hr, _T("UCKinect04::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 UCKinect04::ReleaseImageFrame( HANDLE StreamHandle, NUI_IMAGE_FRAME* ImageFrame ) { HRESULT hr = E_FAIL; // ロックを解除する if( FAILED( hr = ImageFrame->pFrameTexture->UnlockRect( 0 ) ) ) throw( UCException( hr, _T("UCKinect04::ReleaseImageFrame()でエラーが発生しました。ロックを解除できなかった") ) ); // イメージストリームから取得したイメージフレームを解放する if( FAILED( hr = m_pKinectSensor->NuiImageStreamReleaseFrame( StreamHandle, ImageFrame ) ) ) throw( UCException( hr, _T("UCKinect04::ReleaseImageFrame()でエラーが発生しました。イメージストリームから取得したイメージフレームを解放できなかった") ) ); } void UCKinect04::NextFrameImageData( NUI_LOCKED_RECT* pRect ) { NUI_IMAGE_FRAME ImageFrame; CreateImageFrame( m_ImageStreamHandle, &ImageFrame, pRect ); ReleaseImageFrame( m_ImageStreamHandle, &ImageFrame ); // 線形合成した場合でも正しくレンダリングできるようにRGBカメラの結果のアルファ値は常に255にする for( INT i=3; i<pRect->size; i+=4 ) pRect->pBits[i] = 255; } // スケルトンデータを取得する void UCKinect04::NextFrameSkeletonData( NUI_SKELETON_FRAME* pSkeletonFrame ) { HRESULT hr = E_FAIL; if( FAILED( hr = m_pKinectSensor->NuiSkeletonGetNextFrame( INFINITE, pSkeletonFrame ) ) ) throw( UCException( hr, _T("UCKinect04::NextFrameSkeletonData()でエラーが発生しました。スケルトンの次のフレームのデータを取得できなかった") ) ); }
#include "../../Common/Header/UCommon.h" #include "../../Common/Header/UException.h" #include "../../Common/Header/UDirect3D11.h" #include "../../Common/Header/UGraphicsPipeline.h" #include "../../Common/Header/UKinect04.h" #include "../../Common/Header/UDDSLoader.h" #include "UPlane04_0.h" #include "UPlane04_1.h" #include <NuiApi.h> // Direct3D用定数バッファ設定用構造体 typedef struct _CONSTANT_BUFFER { XMFLOAT4 Position; XMFLOAT4 Color; _CONSTANT_BUFFER(){}; _CONSTANT_BUFFER( XMFLOAT4 position, XMFLOAT4 color ) { ::CopyMemory( &Position, &position, sizeof( XMFLOAT4 ) ); ::CopyMemory( &Color, &color, sizeof( XMFLOAT4 ) ); }; }CONSTANT_BUFFER; // シェーダーオブジェクトを作成するとき、ファイルから読むか、メモリから読むかを切り替える #if defined(DEBUG) || defined(_DEBUG) #define UNCOMPILED_SHADER // ファイルを読み込んでコンパイルする #else #include "../../Common/HLSL/Sample04_VS_Main.h" #include "../../Common/HLSL/Sample04_PS_Main.h" #endif // アプリケーション名 TCHAR* AppName = _T("Kinect_Tutrial04"); // Direct3D関連の自作クラス UCDirect3D11* g_pDirect3D11 = nullptr; // グラフィックパイプライン関連の自作クラス UCGraphicsPipeline* g_pGraphicsPipeline = nullptr; // シェーダー用定数バッファ ID3D11Buffer* g_pConstantBuffers[1] = { nullptr }; // Kinectセンサーオブジェクト UCKinect04* g_pKinect = nullptr; // 平面オブジェクト UCPlane04_0* g_pPlane_0 = nullptr; // ジョイント UCPlane04_1* g_pPlane_1 = nullptr; // メモリ解放 void Invalidate() { for( int i=0; i<_countof( g_pConstantBuffers ); i++ ) SAFE_RELEASE( g_pConstantBuffers[i] ); SAFE_DELETE( g_pKinect ); SAFE_DELETE( g_pPlane_0 ); SAFE_DELETE( g_pPlane_1 ); 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() { 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/Sample04.hlsl"), "VS_Main", layout, _countof( layout ) ); g_pGraphicsPipeline->CreatePixelShaderFromFile( g_pDirect3D11->m_pD3DDevice, _T("../../Common/HLSL/Sample04.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::ALIGNMENT }; g_pGraphicsPipeline->CreateBlendState( g_pDirect3D11->m_pD3DDevice, BlendStateType, 1 ); // シェーダー用の定数バッファを作成する g_pConstantBuffers[0] = g_pGraphicsPipeline->CreateConstantBuffer( g_pDirect3D11->m_pD3DDevice, nullptr, sizeof( CONSTANT_BUFFER ), D3D11_CPU_ACCESS_WRITE ); } // メッシュを作成する void CreateMesh( DWORD Width, DWORD Height ) { // RGBカメラのイメージをレンダリングするためのメッシュを作成する g_pPlane_0->CreateMesh( g_pDirect3D11->m_pD3DDevice, Width, Height, g_pConstantBuffers ); // ジョイントをレンダリングするためのメッシュを作成する // 矩形サイズは射影空間上でのサイズで指定する float size = 0.0001f; float x = size * (float)Height; float y = size * (float)Width; g_pPlane_1->CreateMesh( g_pDirect3D11->m_pD3DDevice, x, y, _T("res\\01.dds"), NUI_SKELETON_COUNT + NUI_SKELETON_COUNT * NUI_SKELETON_POSITION_COUNT, g_pConstantBuffers ); } void CreateResource( HINSTANCE hInstance ) { // Direct3D 関連自作クラスのインスタンスを作成 // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。 g_pDirect3D11 = NEW UCDirect3D11(); g_pGraphicsPipeline = NEW UCGraphicsPipeline(); g_pPlane_0 = NEW UCPlane04_0(); g_pPlane_1 = NEW UCPlane04_1(); g_pKinect = NEW UCKinect04(); DWORD Width = 0, Height = 0; // Kinectセンサーオブジェクトを作成 // RGBカメラとプレイヤーIDを使用する g_pKinect->CreateKinect( NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON, FALSE ); g_pKinect->GetImageResolutionToSize( Width, Height ); // Direct3Dの作成 CreateDirect3D( hInstance, Width, Height ); // グラフィックパイプラインリソースの作成 CreateGraphicePipeline(); // リソースの作成 CreateMesh( Width, Height ); } void NextFrame() { NUI_LOCKED_RECT imageDataFromKinect = { 0 }; NUI_SKELETON_FRAME skeletonFrameFromKinect = { 0 }; DWORD Width, Height; g_pKinect->GetImageResolutionToSize( Width, Height ); __try { // ***************************************************************** // イメージフレーム // ***************************************************************** // Kinect側の次のフレームのイメージフレームの作成 g_pKinect->NextFrameImageData( &imageDataFromKinect ); // シェーダーリソースビューを作成する g_pPlane_0->NextFrame( g_pDirect3D11->m_pD3DDeviceContext, &imageDataFromKinect ); // ***************************************************************** // スケルトンフレーム // ***************************************************************** // Kinect側の次のフレームのスケルトンデータの作成 g_pKinect->NextFrameSkeletonData( &skeletonFrameFromKinect ); // 定数バッファ設定用の変数の更新 g_pPlane_1->NextFrame( &skeletonFrameFromKinect, g_pKinect->GetImageResolution(), g_pKinect->GetDepthResolution(), (float)Width, (float)Height ); } __finally { SAFE_DELETE_ARRAY( imageDataFromKinect.pBits ); } } // 描画処理 HRESULT Render() { HRESULT hr = E_FAIL; float ClearColor[4] = { 0.0f, 0.0f, 0.0f, 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_pPlane_0->Render( g_pDirect3D11->m_pD3DDeviceContext ); g_pPlane_1->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; }