/*******************************************************
* *
* UnityKinectPlugin.cpp - This module is a simple *
* plugin to access basic kinect functionality *
* within the unity3d engine *
* *
* Developed by Peter Kinney *
* *
*******************************************************/
// Note:
// 1. DirectX SDK must be installed before compiling.
// 2. DirectX SDK include path should be added after the VC include
// path, because strsafe.h in DirectX SDK may be older.
// 3. platform SDK lib path should be added before the VC lib
// path, because uuid.lib in VC lib path may be older
//使用opengl 完成unity3d中的纹理设置
#include "stdafx.h"
#include "UnityKinectPlugin.h"
#include <gl/gl.h>
// Global Variables:
NUI_SKELETON_FRAME skeletonFrame, prevFrame;
HANDLE m_hNextDepthFrameEvent;
HANDLE m_hNextVideoFrameEvent;
HANDLE m_hNextSkeletonEvent;
HANDLE m_pDepthStreamHandle;
HANDLE m_pVideoStreamHandle;
clock_t lastFrameClocks;
float frameDT;
float kinectHeight;
int colorTexId; //彩色图像ID
int depthTexId; //深度图像ID
//const int width_320=320;
//const int height_240=240;
////640*480 每秒30帧
//const int width_640=640;
//const int height_480=480;
////1280*1024 大约每秒15帧
//const int width_1280=1280;
//const int height_1024=1024;
BYTE pBuffer_1280[1280*1024*3];
BYTE pBuffer_640[640*1024*3];
BYTE Buffer_320[320*240*4];
static int m_type;
#if _MSC_VER // this is defined when compiling with Visual Studio
#define EXPORT_API __declspec(dllexport) // Visual Studio needs annotating exported functions with this
#else
#define EXPORT_API // XCode does not need annotating exported functions, so define is empty
#endif
extern "C"
{
//Unity3D 可以调用的方法
RGBQUAD Nui_ShortToQuad_Depth( USHORT s )
{
USHORT RealDepth = (s & 0xfff8) >> 3;
USHORT Player = s & 7;
// transform 13-bit depth information into an 8-bit intensity appropriate
// for display (we disregard information in most significant bit)
BYTE l = 255 - (BYTE)(256*RealDepth/0x0fff);
RGBQUAD q;
q.rgbRed = q.rgbBlue = q.rgbGreen = 0;
switch( Player )
{
case 0:
q.rgbRed = l / 2;
q.rgbBlue = l / 2;
q.rgbGreen = l / 2;
break;
case 1:
q.rgbRed = l;
break;
case 2:
q.rgbGreen = l;
break;
case 3:
q.rgbRed = l / 4;
q.rgbGreen = l;
q.rgbBlue = l;
break;
case 4:
q.rgbRed = l;
q.rgbGreen = l;
q.rgbBlue = l / 4;
break;
case 5:
q.rgbRed = l;
q.rgbGreen = l / 4;
q.rgbBlue = l;
break;
case 6:
q.rgbRed = l / 2;
q.rgbGreen = l / 2;
q.rgbBlue = l;
break;
case 7:
q.rgbRed = 255 - ( l / 2 );
q.rgbGreen = 255 - ( l / 2 );
q.rgbBlue = 255 - ( l / 2 );
}
return q;
}
bool EXPORT_API startKinect(int _dTexId,int _cTexId,int type){
HRESULT hr;
m_type=type;
//初始化kinect,骨骼信息
hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR);
if ( FAILED( hr ) )
{
//初始化kinect失败
return false;
}
//初始化成功
m_hNextDepthFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNextVideoFrameEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_hNextSkeletonEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if(m_type==0){
hr = NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_640x480,
0,
2,
m_hNextVideoFrameEvent,
&m_pVideoStreamHandle );
if( FAILED( hr ) )
return false;
hr = NuiImageStreamOpen(
NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX,
NUI_IMAGE_RESOLUTION_320x240,
0,
2,
m_hNextDepthFrameEvent,
&m_pDepthStreamHandle );
if(FAILED(hr))
return false;
}
else
{
hr = NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR,
NUI_IMAGE_RESOLUTION_1280x1024,
0,
2,
m_hNextVideoFrameEvent,
&m_pVideoStreamHandle );
if(FAILED(hr))
return false;
hr = NuiImageStreamOpen(
NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX,
NUI_IMAGE_RESOLUTION_320x240,
0,
2,
m_hNextDepthFrameEvent,
&m_pDepthStreamHandle );
if(FAILED(hr))
return false;
}
colorTexId=_cTexId;
depthTexId=_dTexId;
return true;
}
void EXPORT_API Nui_Zero()
{
m_hNextDepthFrameEvent = NULL;
m_hNextVideoFrameEvent = NULL;
m_hNextSkeletonEvent = NULL;
m_pDepthStreamHandle = NULL;
m_pVideoStreamHandle = NULL;
//m_hThNuiProcess=NULL;
//m_hEvNuiProcessStop=NULL;
}
//kinect motor 马达 设置马达的弧度
void EXPORT_API setKinectAngle(long angle){
NuiCameraElevationSetAngle(angle);
return;
}
//关闭kinect
void EXPORT_API stopKinect(){
//uninitialize the kinect
NuiShutdown();
if( m_hNextSkeletonEvent && ( m_hNextSkeletonEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextSkeletonEvent );
m_hNextSkeletonEvent = NULL;
}
if( m_hNextDepthFrameEvent && ( m_hNextDepthFrameEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextDepthFrameEvent );
m_hNextDepthFrameEvent = NULL;
}
if( m_hNextVideoFrameEvent && ( m_hNextVideoFrameEvent != INVALID_HANDLE_VALUE ) )
{
CloseHandle( m_hNextVideoFrameEvent );
m_hNextVideoFrameEvent = NULL;
}
return;
}
void EXPORT_API Nui_GotDepthAlert( )
{
const NUI_IMAGE_FRAME * pImageFrame = NULL;
HRESULT hr = NuiImageStreamGetNextFrame(
m_pDepthStreamHandle,
0,
&pImageFrame );
if( FAILED( hr ) )
{
return;
}
glBindTexture( GL_TEXTURE_2D,depthTexId );
NuiImageBuffer * pTexture = pImageFrame->pFrameTexture;
KINECT_LOCKED_RECT LockedRect;
pTexture->LockRect( 0, &LockedRect, NULL, 0 );
if( LockedRect.Pitch != 0 )
{
BYTE * pBuffer = (BYTE*) LockedRect.pBits;
USHORT * pBufferRun = (USHORT*) pBuffer;
BYTE* pBuffer_320=&Buffer_320[0];
RGBQUAD * rgbrun = (RGBQUAD *)pBuffer_320;
for( int y = 0 ; y < 240 ; y++ )
{
for( int x = 0 ; x < 320 ; x++ )
{
RGBQUAD quad = Nui_ShortToQuad_Depth( *pBufferRun );
pBufferRun++;
*rgbrun = quad;
rgbrun++;
}
}
/* for( int y = 0 ; y < 240*320 ; y++ )
{
*pBuffer_320= *pBuffer;
pBuffer_320++;
*pBuffer_320= *pBuffer;
pBuffer_320++;
*pBuffer_320= *pBuffer;
pBuffer_320++;
*pBuffer_320= *pBuffer;
pBuffer_320++;
pBuffer++;
}*/
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 320, 240, 0, GL_RGBA, GL_UNSIGNED_BYTE, &Buffer_320[0]);
}
else
{
OutputDebugString( L"Buffer length of received texture is bogus\r\n" );
}
NuiImageStreamReleaseFrame( m_pDepthStreamHandle, pImageFrame );
}
//polls the kinect for a new frame of skeleton data, returns true if the new frame was ready
bool EXPORT_API updateFrame(){
HRESULT hr;
//if there is a new skeleton frame, update the data.
NUI_SKELETON_FRAME tempSkeleton;
hr = NuiSkeletonGetNextFrame( 0 , &tempSkeleton);
if(! FAILED( hr ) )
{
//save the time that the new frame came in
clock_t time = clock();
frameDT = (time - lastFrameClocks) / (float)CLOCKS_PER_SEC;
lastFrameClocks = clock();
//store the old frame in prevFrame for use in velocity calculations
prevFrame = skeletonFrame;
//save the new frame
skeletonFrame = tempSkeleto