Interface for Kinect (Microsoft Official Kinect SDK Beta v2)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
ngvincent
Posts: 5
Joined: Sat Jan 14, 2012 6:24 am

Interface for Kinect (Microsoft Official Kinect SDK Beta v2)

Post by ngvincent »

In case someone doesn't want to spend too much time. I have the Depth and RGB images working, will be adding the Skeleton structure later

You need:
Windows 7
Kinect hardware
Microsoft Official Kinect SDK Beta v2
Visual Studio 2010
Irrlicht (I am using the latest 1.7.2)
DirectX June 2010 SDK
?Windows SDK 7.1

I trust you know how to add the Irrlicht AND Kinect SDK into your /include and /lib directories in your VS2010 project


CIrrDeviceKinect.h

Code: Select all

#ifndef __C_IRR_DEVICE_KINECT_INCLUDED__
#define __C_IRR_DEVICE_KINECT_INCLUDED__
 
 
#include <irrlicht.h>
 
#include <basetyps.h>
#include <WTypes.h>
#include "MSR_NuiApi.h"
#include <SDKDDKVer.h>
 
using namespace irr;
 
class CIrrDeviceKinect 
        {
        public:
                CIrrDeviceKinect(int id, IrrlichtDevice* p, DWORD flags);
                CIrrDeviceKinect();
            ~CIrrDeviceKinect();
 
                HRESULT                                 Nui_Init();
                void                                    Nui_UnInit();
 
                int                                             getKinectID(){return Kinect;}
                void                                    setKinectID(int id){Kinect = id;} 
 
                // Call this function if you want the latest textures updated from the kinect
                void                                    Update();
 
                static int              getNumberOfKinects();
 
                video::ITexture* m_tdepth;
                video::ITexture* m_trgb;
                
                // No idea what these two functions are for
                //static void CALLBACK    Nui_StatusProcThunk(const NuiStatusData *pStatusData);
                //void CALLBACK           Nui_StatusProc(const NuiStatusData *pStatusData);
        private:
                int                     Kinect;
                BSTR                                    m_instanceId;
                POINT                                   m_points[NUI_SKELETON_POSITION_COUNT];
                INuiInstance*                   m_pNuiInstance;
                DWORD                                   nuiFlags;
 
                
                video::IImage* m_depth;
                video::IImage* m_rgb;
 
                // Storage used during the separate thread Nui_ProcessThread
                BYTE*                                   m_parallel_depth;
                BYTE*                                   m_parallel_rgb;
                
                
                static DWORD WINAPI     Nui_ProcessThread(LPVOID pParam);
                DWORD WINAPI            Nui_ProcessThread();
                
                void                                    Nui_GotDepthAlert();
                void                                    Nui_GotVideoAlert();
                void                                    Nui_GotSkeletonAlert();
                void                                    Nui_Zero();
                
                RGBQUAD Nui_DrawDepthImage(int x, int y, USHORT s);
                
                // thread handling
                HANDLE                                  m_hThNuiProcess;
                HANDLE                                  m_hEvNuiProcessStop;
                HANDLE                                  m_hNextDepthFrameEvent;
                HANDLE                                  m_hNextVideoFrameEvent;
                HANDLE                                  m_hNextSkeletonEvent;
                HANDLE                                  m_pDepthStreamHandle;
                HANDLE                                  m_pVideoStreamHandle;
 
                // Need for callback/events
                IrrlichtDevice* parent;
                video::IVideoDriver* driver;
        };
#endif
CIrrDeviceKinect.cpp

Code: Select all

#include "CIrrDeviceKinect.h"
#include <mmsystem.h>
#include <assert.h>
 
CIrrDeviceKinect::CIrrDeviceKinect(int id, IrrlichtDevice* p, DWORD flags)
        {
                Kinect = id;
                parent = p;
                nuiFlags = flags;
 
                driver = parent->getVideoDriver();
                m_depth = driver->createImage(video::ECF_R8G8B8, core::vector2d<u32>(320,240));
                m_rgb = driver->createImage(video::ECF_R8G8B8, core::vector2d<u32>(640,480));
        
                m_tdepth = driver->addTexture("Depth", m_depth);
                m_trgb = driver->addTexture("RGB", m_rgb);
 
                m_parallel_depth = new BYTE[320*240*4];
                m_parallel_rgb = new BYTE[640*480*4];
 
        }
        CIrrDeviceKinect::CIrrDeviceKinect()
        {
                Kinect = 0;
                parent = NULL;
                nuiFlags = 0;
        }
 
        CIrrDeviceKinect::~CIrrDeviceKinect()
        {
                Nui_UnInit();
                Nui_Zero();
                m_depth->drop();
                m_rgb->drop();
 
                delete [] m_parallel_depth;
                delete [] m_parallel_rgb;
        }
 
        HRESULT CIrrDeviceKinect::Nui_Init()
        {
                HRESULT hr;
                        
                hr = MSR_NuiCreateInstanceByIndex(Kinect, &m_pNuiInstance);
 
                if(FAILED(hr))
                {
                        return hr;
                }
 
                m_instanceId = m_pNuiInstance->NuiInstanceName();
 
                m_hNextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                m_hNextVideoFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                m_hNextSkeletonEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
                hr = m_pNuiInstance->NuiInitialize(nuiFlags);
 
                if (E_NUI_SKELETAL_ENGINE_BUSY == hr)
                {
                        nuiFlags = NUI_INITIALIZE_FLAG_USES_DEPTH |  NUI_INITIALIZE_FLAG_USES_COLOR;
                        hr = m_pNuiInstance->NuiInitialize(nuiFlags);
                }
 
                if(FAILED(hr))
                {
                        return hr;
                }
                if (HasSkeletalEngine(m_pNuiInstance))
                {
                        hr = m_pNuiInstance->NuiSkeletonTrackingEnable( m_hNextSkeletonEvent, 0 );
                        if( FAILED( hr ) )
                        {
                                 return hr;
                        }
                }
 
                hr = m_pNuiInstance->NuiImageStreamOpen(
        NUI_IMAGE_TYPE_COLOR,
        NUI_IMAGE_RESOLUTION_640x480,
        0,
        2,
        m_hNextVideoFrameEvent,
                &m_pVideoStreamHandle );
 
                if( FAILED( hr ) )
                {
                        return hr;
                }
 
                hr = m_pNuiInstance->NuiImageStreamOpen(
                        HasSkeletalEngine(m_pNuiInstance) ? NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX : NUI_IMAGE_TYPE_DEPTH,
                        NUI_IMAGE_RESOLUTION_320x240,
                        0,
                        2,
                        m_hNextDepthFrameEvent,
                        &m_pDepthStreamHandle );
                if( FAILED( hr ) )
                {
                        return hr;
                }
 
                // Start the Nui processing thread
                m_hEvNuiProcessStop=CreateEvent(NULL,FALSE,FALSE,NULL);
                m_hThNuiProcess=CreateThread(NULL,0,Nui_ProcessThread,this,0,NULL);
 
 
                return hr;
        }
 
        void CIrrDeviceKinect::Nui_UnInit()
        {
                if (m_pNuiInstance)
                {
                        m_pNuiInstance->NuiShutdown();
                }
        }
 
        void CIrrDeviceKinect::Nui_GotDepthAlert()
        {
                const NUI_IMAGE_FRAME * pImageFrame = NULL;
 
                HRESULT hr = m_pNuiInstance->NuiImageStreamGetNextFrame(
                        m_pDepthStreamHandle,
                        0,
                        &pImageFrame );
 
                if( FAILED( hr ) )
                {
                        return;
                }
                INuiFrameTexture * pTexture = pImageFrame->pFrameTexture;
 
                NUI_LOCKED_RECT LockedRect;
                pTexture->LockRect( 0, &LockedRect, NULL, 0 );
                if( LockedRect.Pitch != 0 )
                {
                        BYTE * pBuffer = (BYTE*) LockedRect.pBits;
                        BYTE * write = m_parallel_depth;
                        USHORT * pBufferRun = (USHORT*) pBuffer;
                        for( int y = 0 ; y < 240 ; y++ )
                        {
                                for( int x = 0 ; x < 320 ; x++ )
                                {
                                        RGBQUAD q = Nui_DrawDepthImage(x, y, *pBufferRun );
                                        *write = q.rgbRed;
                                        write++;
                                        *write = q.rgbGreen;
                                        write++;
                                        *write = q.rgbBlue;
                                        write++;
                                        write++; // last channel is alpha/unused
                                        pBufferRun++;
                                }
                        }
                }
                
                m_pNuiInstance->NuiImageStreamReleaseFrame( m_pDepthStreamHandle, pImageFrame );
        }
 
        void CIrrDeviceKinect::Nui_GotVideoAlert()
        {
                const NUI_IMAGE_FRAME * pImageFrame = NULL;
 
                HRESULT hr = m_pNuiInstance->NuiImageStreamGetNextFrame(
                        m_pVideoStreamHandle,
                        0,
                        &pImageFrame );
                if( FAILED( hr ) )
                {
                        return;
                }
                 INuiFrameTexture * pTexture = pImageFrame->pFrameTexture;
                NUI_LOCKED_RECT LockedRect;
                pTexture->LockRect( 0, &LockedRect, NULL, 0 );
                if( LockedRect.Pitch != 0 )
                {
                        BYTE * pBuffer = (BYTE*) LockedRect.pBits;
                        BYTE * write = m_parallel_rgb;
                        RGBQUAD * test = (RGBQUAD* )pBuffer;
                        for(int y = 0; y < 480; y++)
                        {
                                for(int x = 0; x < 640; x++)
                                {
                                        *write = test->rgbBlue;
                                        write++;
                                        *write = test->rgbGreen;
                                        write++;
                                        *write = test->rgbRed;
                                        write++;
                                        write++; // skipping reserved
                                        test++;
                                }
                        }
                }
 
 
                m_pNuiInstance->NuiImageStreamReleaseFrame( m_pVideoStreamHandle, pImageFrame );
        }
 
        void CIrrDeviceKinect::Nui_GotSkeletonAlert()
        {
                NUI_SKELETON_FRAME SkeletonFrame;
 
                bool bFoundSkeleton = false;
 
                if( SUCCEEDED(m_pNuiInstance->NuiSkeletonGetNextFrame( 0, &SkeletonFrame )) )
                {
                        for( int i = 0 ; i < NUI_SKELETON_COUNT ; i++ )
                        {
                                if( SkeletonFrame.SkeletonData[i].eTrackingState == NUI_SKELETON_TRACKED )
                                {
                                        bFoundSkeleton = true;
                                }
                        }
                }
 
 
        }
 
        void CIrrDeviceKinect::Nui_Zero()
        {
                m_pNuiInstance = NULL;
                m_hThNuiProcess = NULL;
                m_hEvNuiProcessStop = NULL;
                m_hNextDepthFrameEvent = NULL;
                m_hNextVideoFrameEvent = NULL;
                m_hNextSkeletonEvent = NULL;
                m_pDepthStreamHandle = NULL;
                m_pVideoStreamHandle = NULL;
                ZeroMemory(m_points, sizeof(m_points));
        }
 
        DWORD WINAPI CIrrDeviceKinect::Nui_ProcessThread(LPVOID pParam)
        {
                CIrrDeviceKinect* pthis = (CIrrDeviceKinect*) pParam;
                return pthis->Nui_ProcessThread();
        }
 
        DWORD WINAPI CIrrDeviceKinect::Nui_ProcessThread()
        {
                HANDLE hEvents[4];
                int nEventIdx;
 
                hEvents[0] = m_hEvNuiProcessStop;
                hEvents[1] = m_hNextDepthFrameEvent;
                hEvents[2] = m_hNextVideoFrameEvent;
                hEvents[3] = m_hNextSkeletonEvent;
 
                // Kinect sensory loop
                while(TRUE)
                {
                        // Wait for an event to be signalled
                        nEventIdx = WaitForMultipleObjects(sizeof(hEvents) / sizeof(hEvents[0]), hEvents, FALSE, 1000);
 
                        // If the stop event, stop looping and exit
                        if(nEventIdx == 0)
                                break;
 
                        // Process signal events
                        switch(nEventIdx)
                        {
                        case 1:
                                Nui_GotDepthAlert();
                                break;
                        case 2:
                                Nui_GotVideoAlert();
                                break;
                        case 3:
                                Nui_GotSkeletonAlert();
                                break;
                        }
                }
 
 
 
                return (0);
        }
        
RGBQUAD CIrrDeviceKinect::Nui_DrawDepthImage(int x, int y, USHORT s )
        {
    bool hasPlayerData = HasSkeletalEngine(m_pNuiInstance);
    USHORT RealDepth = hasPlayerData ? (s & 0xfff8) >> 3 : s & 0xffff;
    USHORT Player = hasPlayerData ? s & 7 : 0;
 
    // 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 );
    }
 
        //m_pdepth->setPixel(x, y, video::SColor(255, q.rgbRed, q.rgbGreen, q.rgbBlue));
        return q;
        
}
 
void CIrrDeviceKinect::Update()
{
        // TODO: Critical section or mutex locks?
 
        BYTE* write = (BYTE*)m_tdepth->lock();
        memcpy(write, m_parallel_depth, 320*240*4);
        write = 0;
        m_tdepth->unlock();
 
        write = (BYTE*) m_trgb->lock();
        memcpy(write, m_parallel_rgb, 640*480*4);
        write = 0;
        m_trgb->unlock();
}
 
int CIrrDeviceKinect::getNumberOfKinects()
{
        int numberOfKinects = 0;
        MSR_NUIGetDeviceCount(&numberOfKinects);
        return numberOfKinects;
}
ngvincent
Posts: 5
Joined: Sat Jan 14, 2012 6:24 am

Re: Interface for Kinect (Microsoft Official Kinect SDK Beta

Post by ngvincent »

main.cpp

Code: Select all

#include <irrlicht.h>
#include "CIrrDeviceKinect.h"
#include <iostream>
#include "driverChoice.h"
 
using namespace irr;
 
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
// Uncomment below to remove the Command Line window
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
 
int main()
{
        // Prompt user for driver type
        video::E_DRIVER_TYPE driverType=driverChoiceConsole();
        if (driverType==video::EDT_COUNT)
                return 1;
 
        IrrlichtDevice *device =
                createDevice( driverType, core::dimension2d<u32>(960, 480), 16,
                        false, false, false, 0);
        //Full screen mode
        /*IrrlichtDevice *device =
                createDevice( driverType, core::dimension2d<u32>(1680,1050), 16,
                        true, false, false, 0);*/
 
        if (!device)
                return 1;
 
        device->setWindowCaption(L"Kinect Demo");
 
        video::IVideoDriver* driver = device->getVideoDriver();
        scene::ISceneManager* smgr = device->getSceneManager();
        gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
 
        guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer with Kinect functionality!",
                core::rect<s32>(10,10,260,22), true);
        
        smgr->addCameraSceneNode(0, core::vector3df(0,30,-40), core::vector3df(0,5,0));
 
        // Get number of kinects connected to system
        int numOfKinects = CIrrDeviceKinect::getNumberOfKinects();
        std::cout << "Number of kinects: " << numOfKinects << std::endl;
        if(numOfKinects < 1)
        {
                return 1;
        }
 
        // Initialize Kinect
        CIrrDeviceKinect kinect(0, device, NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON |  NUI_INITIALIZE_FLAG_USES_COLOR); 
        // Start processing Kinect events. Function will create separate thread
        // The kinect's IR beam (leftmost circle) should be activated. You should see a red grid emitting from the sensor.
        if(FAILED(kinect.Nui_Init()))
        {
                return 1;
        } 
 
        while(device->run())
        {
                driver->beginScene(true, true, video::SColor(255,100,101,140));
 
                smgr->drawAll();
                guienv->drawAll();
 
                // Force Kinect to update our RGB and DEPTH images and SKELETON info (work-in-progress)
                kinect.Update();
 
 
                 driver->draw2DImage(kinect.m_trgb, core::position2d<s32>(320,0),
                         core::rect<s32>(0,0,640,480), 0,
                         video::SColor(255,255,255,255), true);
                 driver->draw2DImage(kinect.m_tdepth, core::position2d<s32>(0,0),
                        core::rect<s32>(0,0,320,240), 0,
                        video::SColor(255,255,255,255), true);
                driver->endScene();
        }
 
        device->drop();
 
        // If things go well, the kinect's IR beam emitter should stop emitting beam, and shut down properly.
 
        return 0;
}
 
,
sourisman
Posts: 1
Joined: Sun Apr 08, 2012 2:39 am

Re: Interface for Kinect (Microsoft Official Kinect SDK Beta

Post by sourisman »

Hi,
Thank you for your great code.
I try to translate it for the new version of the Sdk (v1 for microsoft)
I don't understand why the deapth perfectly work and the standart video don't want to display....
I don't have any compilation error..
There is my code :

main.cpp :

Code: Select all

#include "stdafx.h"
 
#include "CIrrDeviceKinect.h"
#include "driverChoice.h"
 
#include <NuiApi.h>
#include <vector>
#include <sstream>
#include <cstring>
#include <string>
#include <irrlicht.h>
#include <cmath>
#include <iostream>
 
using namespace std;
using namespace irr;
using namespace core;
using namespace io;
using namespace gui;
using namespace video;
using namespace scene;
 
#define NX 640  
#define NY 480
#define NB_PHOTO 150
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
//Declaraction de variable irrlicht
IrrlichtDevice *device = 0;
irr::scene::ICameraSceneNode* cameraPrincipale;
int tailleEcranX(1600);
int tailleEcranY(900);
 
int compteur = 0;
 
int main()
{
 
        //Irrlicht
        device = irr::createDevice( // creation device
                irr::video::EDT_OPENGL,                      // l'API est OpenGL
                irr::core::dimension2d<irr::u32>(tailleEcranX,tailleEcranY),   // taille de la fenetre
                32,     //bits par pixel
                false   //fullscreen
        );
 
        irr::video::IVideoDriver *driver = device->getVideoDriver();                    // creation driver
    irr::scene::ISceneManager *sceneManager = device->getSceneManager ();                // creation scene manager
        gui::IGUIEnvironment* guienv = device->getGUIEnvironment();                                             //creation GUI ENVIRONEMENT
        cameraPrincipale = sceneManager->addCameraSceneNode (0,             // ajout camera fixe
    irr::core::vector3df (0,0,20),
    irr::core::vector3df (0,0,400));
 
        int numOfKinects = CIrrDeviceKinect::getNumberOfKinects();
        std::cout << "Number of kinects: " << numOfKinects << std::endl;
        if(numOfKinects < 1)
        {
                return 1;
        }
 
 
    /* RENDU */
 
    irr::video::SColor color(                  // contient la couleur blanc
    0,                              // composante A alpha (transparence)
    0,                                   // composante R rouge
    0,                                   // composante G verte
    0);                                  // composante B bleue
 
        CIrrDeviceKinect kinect(0, device, NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX | NUI_INITIALIZE_FLAG_USES_SKELETON |  NUI_INITIALIZE_FLAG_USES_COLOR);
 
        if(FAILED(kinect.Nui_Init()))
        {
                return 1;
        } 
 
 
        // Boucle principale
        while (1)
        {               
 
                        driver->beginScene(true, true, video::SColor(255,100,101,140));         // demarre le rendu
            
            sceneManager->drawAll ();                                   // calcule le rendu
                        guienv->drawAll();
 
                        kinect.Update();
 
                        driver->draw2DImage(kinect.m_trgb, core::position2d<s32>(0,0),
                         core::rect<s32>(0,0,640,480), 0,
                         video::SColor(255,255,255,255), true);
 
                        driver->draw2DImage(kinect.m_tdepth, core::position2d<s32>(0,600),
                        core::rect<s32>(0,0,320,240), 0,
                        video::SColor(255,255,255,255), true);
 
                        driver->endScene ();                                            // affiche le rendu
        }
 
        device->drop();
        
        return 0;
}
 
CIrrDeviceKinect.h :

Code: Select all

#ifndef __C_IRR_DEVICE_KINECT_INCLUDED__
#define __C_IRR_DEVICE_KINECT_INCLUDED__
 
 
#include <irrlicht.h>
 
#include <basetyps.h>
#include <WTypes.h>
#include "NuiApi.h"
#include <SDKDDKVer.h>
 
 
using namespace irr;
 
class CIrrDeviceKinect 
        {
        public:
                CIrrDeviceKinect(int id, IrrlichtDevice* p, DWORD flags);
                CIrrDeviceKinect();
            ~CIrrDeviceKinect();
 
                HRESULT                                 Nui_Init();
                void                                    Nui_UnInit();
 
                int                                             getKinectID(){return Kinect;}
                void                                    setKinectID(int id){Kinect = id;} 
 
                // Call this function if you want the latest textures updated from the kinect
                void                                    Update();
 
                static int              getNumberOfKinects();
 
                video::ITexture* m_tdepth;
                video::ITexture* m_trgb;
                
                // No idea what these two functions are for
                //static void CALLBACK    Nui_StatusProcThunk(const NuiStatusData *pStatusData);
                //void CALLBACK           Nui_StatusProc(const NuiStatusData *pStatusData);
        private:
                int                     Kinect;
                BSTR                                    m_instanceId;
                POINT                                   m_points[NUI_SKELETON_POSITION_COUNT];
                INuiSensor *                  m_pNuiInstance;
                DWORD                                   nuiFlags;
 
                
                video::IImage* m_depth;
                video::IImage* m_rgb;
 
                // Storage used during the separate thread Nui_ProcessThread
                BYTE*                                   m_parallel_depth;
                BYTE*                                   m_parallel_rgb;
                
                
                static DWORD WINAPI     Nui_ProcessThread(LPVOID pParam);
                DWORD WINAPI            Nui_ProcessThread();
                
                void                                    Nui_GotDepthAlert();
                void                                    Nui_GotColorAlert();
                void                                    Nui_GotSkeletonAlert();
                void                                    Nui_Zero();
                
                RGBQUAD Nui_DrawDepthImage(int x, int y, USHORT s);
                
                // thread handling
                HANDLE                                  m_hThNuiProcess;
                HANDLE                                  m_hEvNuiProcessStop;
                HANDLE                                  m_hNextDepthFrameEvent;
                HANDLE                                  m_hNextColorFrameEvent;
                HANDLE                                  m_hNextSkeletonEvent;
                HANDLE                                  m_pDepthStreamHandle;
                HANDLE                                  m_pVideoStreamHandle;
 
                // Need for callback/events
                IrrlichtDevice* parent;
                video::IVideoDriver* driver;
        };
#endif
 
CIrrDeviceKinect.cpp :

Code: Select all

#include "CIrrDeviceKinect.h"
#include <mmsystem.h>
#include <assert.h>
 
#include "stdafx.h"
 
CIrrDeviceKinect::CIrrDeviceKinect(int id, IrrlichtDevice* p, DWORD flags)
        {
                Kinect = id;
                parent = p;
                nuiFlags = flags;
 
                driver = parent->getVideoDriver();
                m_depth = driver->createImage(video::ECF_R8G8B8, core::vector2d<u32>(320,240));
                m_rgb = driver->createImage(video::ECF_R8G8B8, core::vector2d<u32>(640,480));
        
                m_tdepth = driver->addTexture("Depth", m_depth);
                m_trgb = driver->addTexture("RGB", m_rgb);
 
                m_parallel_depth = new BYTE[320*240*4];
                m_parallel_rgb = new BYTE[640*480*4];
 
        }
        CIrrDeviceKinect::CIrrDeviceKinect()
        {
                Kinect = 0;
                parent = NULL;
                nuiFlags = 0;
        }
 
        CIrrDeviceKinect::~CIrrDeviceKinect()
        {
                Nui_UnInit();
                Nui_Zero();
                m_depth->drop();
                m_rgb->drop();
 
                delete [] m_parallel_depth;
                delete [] m_parallel_rgb;
        }
 
        HRESULT CIrrDeviceKinect::Nui_Init()
        {
                HRESULT hr;
                        
                hr = NuiCreateSensorByIndex(Kinect, &m_pNuiInstance);
 
                if(FAILED(hr))
                {
                        return hr;
                }
 
                m_instanceId = m_pNuiInstance->NuiDeviceConnectionId();
 
                m_hNextDepthFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                m_hNextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
                m_hNextSkeletonEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
                hr = m_pNuiInstance->NuiInitialize(nuiFlags);
 
                if (E_NUI_SKELETAL_ENGINE_BUSY == hr)
                {
                        nuiFlags = NUI_INITIALIZE_FLAG_USES_DEPTH |  NUI_INITIALIZE_FLAG_USES_COLOR;
                        hr = m_pNuiInstance->NuiInitialize(nuiFlags);
 
                }
 
                if(FAILED(hr))
                {
                        return hr;
                }
                if (HasSkeletalEngine(m_pNuiInstance))
                {
                        hr = m_pNuiInstance->NuiSkeletonTrackingEnable( m_hNextSkeletonEvent, 0 );
                        if( FAILED( hr ) )
                        {
                                 return hr;
                        }
                }
 
                hr = m_pNuiInstance->NuiImageStreamOpen(
                                                NUI_IMAGE_TYPE_COLOR,
                                                NUI_IMAGE_RESOLUTION_640x480,
                                                0,
                                                2,
                                                m_hNextColorFrameEvent,
                                                &m_pVideoStreamHandle );
 
                                if ( FAILED( hr ) )
                                {
                                        return hr;
                                }
 
                                hr = m_pNuiInstance->NuiImageStreamOpen(
                        HasSkeletalEngine(m_pNuiInstance) ? NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX : NUI_IMAGE_TYPE_DEPTH,
                        NUI_IMAGE_RESOLUTION_320x240,
                        0,
                        2,
                        m_hNextDepthFrameEvent,
                        &m_pDepthStreamHandle );
                if( FAILED( hr ) )
                {
                        return hr;
                }
 
                // Start the Nui processing thread
                m_hEvNuiProcessStop=CreateEvent(NULL,FALSE,FALSE,NULL);
                m_hThNuiProcess=CreateThread(NULL,0,Nui_ProcessThread,this,0,NULL);
 
 
                return hr;
        }
 
        void CIrrDeviceKinect::Nui_UnInit()
        {
                if (m_pNuiInstance)
                {
                        m_pNuiInstance->NuiShutdown();
                }
        }
 
        void CIrrDeviceKinect::Nui_GotDepthAlert()
        {
                NUI_IMAGE_FRAME pImageFrame;
 
                HRESULT hr = m_pNuiInstance->NuiImageStreamGetNextFrame(
                        m_pDepthStreamHandle,
                        0,
                        &pImageFrame );
 
                if( FAILED( hr ) )
                {
                        return;
                }
                INuiFrameTexture * pTexture = pImageFrame.pFrameTexture;
 
                NUI_LOCKED_RECT LockedRect;
                pTexture->LockRect( 0, &LockedRect, NULL, 0 );
                if( LockedRect.Pitch != 0 )
                {
                        BYTE * pBuffer = (BYTE*) LockedRect.pBits;
                        BYTE * write = m_parallel_depth;
                        USHORT * pBufferRun = (USHORT*) pBuffer;
                        for( int y = 0 ; y < 240 ; y++ )
                        {
                                for( int x = 0 ; x < 320 ; x++ )
                                {
                                        RGBQUAD q = Nui_DrawDepthImage(x, y, *pBufferRun );
                                        *write = q.rgbRed;
                                        write++;
                                        *write = q.rgbGreen;
                                        write++;
                                        *write = q.rgbBlue;
                                        write++;
                                        write++; // last channel is alpha/unused
                                        pBufferRun++;
                                }
                        }
                }
                
                m_pNuiInstance->NuiImageStreamReleaseFrame( m_pDepthStreamHandle, &pImageFrame );
        }
 
        void CIrrDeviceKinect::Nui_GotColorAlert()
        {
                        
                NUI_IMAGE_FRAME pImageFrame;
 
                HRESULT hr = m_pNuiInstance->NuiImageStreamGetNextFrame(
                        m_pVideoStreamHandle,
                        0,
                        &pImageFrame );
                if( FAILED( hr ) )
                {
                        return;
                }
                 INuiFrameTexture * pTexture = pImageFrame.pFrameTexture;
                NUI_LOCKED_RECT LockedRect;
                pTexture->LockRect( 0, &LockedRect, NULL, 0 );
                if( LockedRect.Pitch != 0 )
                {
                        BYTE * pBuffer = (BYTE*) LockedRect.pBits;
                        BYTE * write = m_parallel_rgb;
                        RGBQUAD * test = (RGBQUAD* )pBuffer;
                        for(int y = 0; y < 480; y++)
                        {
                                for(int x = 0; x < 640; x++)
                                {
                                        *write = test->rgbBlue;
                                        write++;
                                        *write = test->rgbGreen;
                                        write++;
                                        *write = test->rgbRed;
                                        write++;
                                        write++; // skipping reserved
                                        test++;
                                }
                        }
                }
 
                m_pNuiInstance->NuiImageStreamReleaseFrame( m_pVideoStreamHandle, &pImageFrame );
        }
 
        void CIrrDeviceKinect::Nui_GotSkeletonAlert()
        {
                NUI_SKELETON_FRAME SkeletonFrame;
 
                bool bFoundSkeleton = false;
 
                if( SUCCEEDED(m_pNuiInstance->NuiSkeletonGetNextFrame( 0, &SkeletonFrame )) )
                {
                        for( int i = 0 ; i < NUI_SKELETON_COUNT ; i++ )
                        {
                                if( SkeletonFrame.SkeletonData[i].eTrackingState == NUI_SKELETON_TRACKED )
                                {
                                        bFoundSkeleton = true;
                                }
                        }
                }
 
 
        }
 
        void CIrrDeviceKinect::Nui_Zero()
        {
                m_pNuiInstance = NULL;
                m_hThNuiProcess = NULL;
                m_hEvNuiProcessStop = NULL;
                m_hNextDepthFrameEvent = NULL;
                m_hNextColorFrameEvent = NULL;
                m_hNextSkeletonEvent = NULL;
                m_pDepthStreamHandle = NULL;
                m_pVideoStreamHandle = NULL;
                ZeroMemory(m_points, sizeof(m_points));
        }
 
        DWORD WINAPI CIrrDeviceKinect::Nui_ProcessThread(LPVOID pParam)
        {
                CIrrDeviceKinect* pthis = (CIrrDeviceKinect*) pParam;
                return pthis->Nui_ProcessThread();
        }
 
        DWORD WINAPI CIrrDeviceKinect::Nui_ProcessThread()
        {
                HANDLE hEvents[4];
                int nEventIdx;
 
                hEvents[0] = m_hEvNuiProcessStop;
                hEvents[1] = m_hNextDepthFrameEvent;
                hEvents[2] = m_hNextColorFrameEvent;
                hEvents[3] = m_hNextSkeletonEvent;
 
                // Kinect sensory loop
                while(TRUE)
                {
                        // Wait for an event to be signalled
                        nEventIdx = WaitForMultipleObjects(sizeof(hEvents) / sizeof(hEvents[0]), hEvents, FALSE, 1000);
 
                        // If the stop event, stop looping and exit
                        if(nEventIdx == 0)
                                break;
 
                        // Process signal events
                        switch(nEventIdx)
                        {
                        case 1:
                                Nui_GotDepthAlert();
                                break;
                        case 2:
                                Nui_GotColorAlert();
                                break;
                        case 3:
                                Nui_GotSkeletonAlert();
                                break;
                        }
                }
 
 
 
                return (0);
        }
        
RGBQUAD CIrrDeviceKinect::Nui_DrawDepthImage(int x, int y, USHORT s )
        {
    bool hasPlayerData = HasSkeletalEngine(m_pNuiInstance);
    USHORT RealDepth = hasPlayerData ? (s & 0xfff8) >> 3 : s & 0xffff;
    USHORT Player = hasPlayerData ? s & 7 : 0;
 
    // 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 );
    }
 
        //m_pdepth->setPixel(x, y, video::SColor(255, q.rgbRed, q.rgbGreen, q.rgbBlue));
        return q;
        
}
 
void CIrrDeviceKinect::Update()
{
        // TODO: Critical section or mutex locks?
 
        BYTE* write = (BYTE*)m_tdepth->lock();
        memcpy(write, m_parallel_depth, 320*240*4);
        write = 0;
        m_tdepth->unlock();
 
        write = (BYTE*)m_trgb->lock();
        memcpy(write, m_parallel_rgb, 640*480*4);
        write = 0;
        m_trgb->unlock();
}
 
int CIrrDeviceKinect::getNumberOfKinects()
{
        int numberOfKinects = 0;
        NuiGetSensorCount(&numberOfKinects);
        return numberOfKinects;
}
 
Thanx you very much if you have any idea about this.... :)
Post Reply