├── premake4.exe ├── bin ├── FreeImage.dll ├── background.bmp ├── freeglut.dll ├── FruitNinja1.jpg ├── FruitNinja2.png ├── FruitNinja3.png ├── FruitNinja4.png ├── FruitNinja5.png └── FruitNinja6.jpg ├── lib ├── FreeImage.lib └── freeglut.lib ├── .gitignore ├── include └── GL │ ├── glut.h │ ├── freeglut.h │ ├── freeglut_ext.h │ └── freeglut_std.h ├── README.md ├── ch2_01.cpp ├── LICENSE ├── common ├── GLUtilities.h ├── TextureManager.h ├── TextureManager.cpp └── GLUtilities.cpp ├── premake.lua ├── ch2_02.cpp ├── ch3_01.cpp ├── ch5_03.cpp ├── ch3_02.cpp ├── ch3_03.cpp ├── ch4_01.cpp ├── ch4_02.cpp ├── ch5_01.cpp ├── ch4_03.cpp ├── ch5_02.cpp ├── ch6_01.cpp ├── ch4_04.cpp ├── ch6_02.cpp └── ch6_03.cpp /premake4.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/premake4.exe -------------------------------------------------------------------------------- /bin/FreeImage.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FreeImage.dll -------------------------------------------------------------------------------- /bin/background.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/background.bmp -------------------------------------------------------------------------------- /bin/freeglut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/freeglut.dll -------------------------------------------------------------------------------- /lib/FreeImage.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/lib/FreeImage.lib -------------------------------------------------------------------------------- /lib/freeglut.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/lib/freeglut.lib -------------------------------------------------------------------------------- /bin/FruitNinja1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja1.jpg -------------------------------------------------------------------------------- /bin/FruitNinja2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja2.png -------------------------------------------------------------------------------- /bin/FruitNinja3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja3.png -------------------------------------------------------------------------------- /bin/FruitNinja4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja4.png -------------------------------------------------------------------------------- /bin/FruitNinja5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja5.png -------------------------------------------------------------------------------- /bin/FruitNinja6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xarray/augmented-reality-with-microsoft-kinect/HEAD/bin/FruitNinja6.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /include/GL/glut.h: -------------------------------------------------------------------------------- 1 | #ifndef __GLUT_H__ 2 | #define __GLUT_H__ 3 | 4 | /* 5 | * glut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | 19 | /*** END OF FILE ***/ 20 | 21 | #endif /* __GLUT_H__ */ 22 | -------------------------------------------------------------------------------- /include/GL/freeglut.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_H__ 2 | #define __FREEGLUT_H__ 3 | 4 | /* 5 | * freeglut.h 6 | * 7 | * The freeglut library include file 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 10 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 12 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | 17 | #include "freeglut_std.h" 18 | #include "freeglut_ext.h" 19 | 20 | /*** END OF FILE ***/ 21 | 22 | #endif /* __FREEGLUT_H__ */ 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Augmented Reality with Kinect, book source code 2 | ======================================= 3 | 4 | This is the source code package of the book Augmented Reality with Kinect, written by Rui Wang and published by the Packt Publishing in July, 2013. 5 | 6 | It already includes the FreeImage and FreeGLUT libraries. All you need is to install Microsoft Kinect correctly and prepare the Visual Studio environment for developing work. 7 | 8 | Please make sure that you have already installed a newer version (equal or greater than 2010) of Microsoft Visual Studio. You will find the solution file in the 'build' subfolder. Open it with the Visual Studio environment and compile it to see the results. 9 | 10 | Another way to taste the example code is to execute build_me.bat directly. It will call the 'premake' tool to generate solution files corresponding with your system. And then you can view and compile the newly-created solution file in the 'build' subfolder. 11 | 12 | Please feel free to contact the author if you have any problems: wangray84 at gmail dot com 13 | 14 | -------------------------------------------------------------------------------- /ch2_01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const unsigned int backgroundTexID = 1; 5 | 6 | void update() 7 | { 8 | glutPostRedisplay(); 9 | } 10 | 11 | void render() 12 | { 13 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 14 | glutSwapBuffers(); 15 | } 16 | 17 | void reshape( int w, int h ) 18 | { 19 | glViewport( 0, 0, w, h ); 20 | } 21 | 22 | void keyEvents( unsigned char key, int x, int y ) 23 | { 24 | switch ( key ) 25 | { 26 | case 27: case 'Q': case 'q': 27 | glutLeaveMainLoop(); 28 | return; 29 | } 30 | glutPostRedisplay(); 31 | } 32 | 33 | int main( int argc, char** argv ) 34 | { 35 | glutInit( &argc, argv ); 36 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 37 | glutCreateWindow( "ch2_01_OpenGL_Env" ); 38 | glutFullScreen(); 39 | 40 | glutIdleFunc( update ); 41 | glutDisplayFunc( render ); 42 | glutReshapeFunc( reshape ); 43 | glutKeyboardFunc( keyEvents ); 44 | 45 | glutMainLoop(); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /common/GLUtilities.h: -------------------------------------------------------------------------------- 1 | #ifndef GL_UTILITIES_H 2 | #define GL_UTILITIES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum VertexFormat 9 | { 10 | WITH_POSITION = 0x1, 11 | WITH_NORMAL = 0x2, 12 | WITH_COLOR = 0x4, 13 | WITH_TEXCOORD =0x8 14 | }; 15 | 16 | struct VertexData 17 | { 18 | GLfloat* vertices; 19 | GLfloat* normals; 20 | GLfloat* colors; 21 | GLfloat* texcoords; 22 | }; 23 | 24 | extern void drawSimpleMesh( int formats, unsigned int numVertices, VertexData data, 25 | GLenum drawMode, GLuint start=0, GLuint count=0 ); 26 | extern void drawIndexedMesh( int formats, unsigned int numVertices, VertexData data, 27 | GLenum drawMode, unsigned int numIndices, GLuint* indices ); 28 | 29 | struct TextureObject 30 | { 31 | GLuint id; 32 | GLenum imageFormat; 33 | GLint internalFormat; 34 | unsigned int width; 35 | unsigned int height; 36 | unsigned char* bits; 37 | }; 38 | 39 | extern TextureObject* createTexture( unsigned int w, unsigned int h, GLenum image_format=GL_RGB, 40 | GLint internal_format=GL_RGB, GLenum data_type=GL_UNSIGNED_BYTE ); 41 | extern void destroyTexture( TextureObject* tobj ); 42 | 43 | enum ProgramType 44 | { 45 | NO_PROGRAM = 0, 46 | BLUR_PROGRAM 47 | }; 48 | 49 | extern GLuint createProgram( ProgramType type ); 50 | extern void useProgram( GLuint id ); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /common/TextureManager.h: -------------------------------------------------------------------------------- 1 | //********************************************** 2 | //Singleton Texture Manager class 3 | //Written by Ben English 4 | //benjamin.english@oit.edu 5 | // 6 | //For use with OpenGL and the FreeImage library 7 | //********************************************** 8 | 9 | #ifndef TextureManager_H 10 | #define TextureManager_H 11 | 12 | #include 13 | #include 14 | #include "FreeImage.h" 15 | #include 16 | 17 | class TextureManager 18 | { 19 | public: 20 | static TextureManager* Inst(); 21 | virtual ~TextureManager(); 22 | 23 | //load a texture an make it the current texture 24 | //if texID is already in use, it will be unloaded and replaced with this texture 25 | bool LoadTexture(const char* filename, //where to load the file from 26 | const unsigned int texID, //arbitrary id you will reference the texture by 27 | //does not have to be generated with glGenTextures 28 | GLenum image_format = GL_RGB, //format the image is in 29 | GLint internal_format = GL_RGB, //format to store the image in 30 | GLint level = 0, //mipmapping level 31 | GLint border = 0); //border size 32 | 33 | //free the memory for a texture 34 | bool UnloadTexture(const unsigned int texID); 35 | 36 | //set the current texture 37 | bool BindTexture(const unsigned int texID); 38 | 39 | //free all texture memory 40 | void UnloadAllTextures(); 41 | 42 | protected: 43 | TextureManager(); 44 | TextureManager(const TextureManager& tm); 45 | TextureManager& operator=(const TextureManager& tm); 46 | 47 | static TextureManager* m_inst; 48 | std::map m_texID; 49 | }; 50 | 51 | #endif -------------------------------------------------------------------------------- /premake.lua: -------------------------------------------------------------------------------- 1 | solution "Kinect Espresso Code" 2 | configurations { "Debug", "Release" } 3 | location "./build" 4 | 5 | includedirs { "./include", "$(KINECTSDK10_DIR)/inc", "$(FTSDK_DIR)/inc" } 6 | libdirs { "./lib", "$(KINECTSDK10_DIR)/lib/x86", "$(FTSDK_DIR)/Lib/x86" } 7 | links { "opengl32", "glu32", "freeglut", "FreeImage", "Kinect10", "FaceTrackLib" } 8 | 9 | configuration "Debug" 10 | defines { "DEBUG" } 11 | flags { "Symbols" } 12 | targetdir "./bin" 13 | targetsuffix "_d" 14 | 15 | configuration "Release" 16 | defines { "NDEBUG" } 17 | flags { "Optimize" } 18 | targetdir "./bin" 19 | 20 | project "ch2_01_OpenGL_Env" 21 | kind "ConsoleApp" 22 | language "C++" 23 | files { "ch2_01.cpp" } 24 | 25 | project "ch2_02_Init_Kinect" 26 | kind "ConsoleApp" 27 | language "C++" 28 | files { "ch2_02.cpp", "./common/*.*" } 29 | 30 | project "ch3_01_Color_Depth" 31 | kind "ConsoleApp" 32 | language "C++" 33 | files { "ch3_01.cpp", "./common/*.*" } 34 | 35 | project "ch3_02_Background_Subtraction" 36 | kind "ConsoleApp" 37 | language "C++" 38 | files { "ch3_02.cpp", "./common/*.*" } 39 | 40 | project "ch3_03_Magic_Photographer" 41 | kind "ConsoleApp" 42 | language "C++" 43 | files { "ch3_03.cpp", "./common/*.*" } 44 | 45 | project "ch4_01_Skeleton_Drawer" 46 | kind "ConsoleApp" 47 | language "C++" 48 | files { "ch4_01.cpp", "./common/*.*" } 49 | 50 | project "ch4_02_Hand_Linetrails" 51 | kind "ConsoleApp" 52 | language "C++" 53 | files { "ch4_02.cpp", "./common/*.*" } 54 | 55 | project "ch4_03_Face_Tracking" 56 | kind "ConsoleApp" 57 | language "C++" 58 | files { "ch4_03.cpp", "./common/*.*" } 59 | 60 | project "ch4_04_Face_Modeling" 61 | kind "ConsoleApp" 62 | language "C++" 63 | files { "ch4_04.cpp", "./common/*.*" } 64 | 65 | project "ch5_01_Hand_Cursors" 66 | kind "ConsoleApp" 67 | language "C++" 68 | files { "ch5_01.cpp", "./common/*.*" } 69 | 70 | project "ch5_02_Swiping_And_Holding" 71 | kind "ConsoleApp" 72 | language "C++" 73 | files { "ch5_02.cpp", "./common/*.*" } 74 | 75 | project "ch5_03_Emulating_Mouse" 76 | kind "ConsoleApp" 77 | language "C++" 78 | files { "ch5_03.cpp", "./common/*.*" } 79 | 80 | project "ch6_01_Integrating_Everything" 81 | kind "ConsoleApp" 82 | language "C++" 83 | files { "ch6_01.cpp", "./common/*.*" } 84 | 85 | project "ch6_02_Cutting_Fruits" 86 | kind "ConsoleApp" 87 | language "C++" 88 | files { "ch6_02.cpp", "./common/*.*" } 89 | 90 | project "ch6_03_Playing_Game" 91 | kind "ConsoleApp" 92 | language "C++" 93 | files { "ch6_03.cpp", "./common/*.*" } 94 | -------------------------------------------------------------------------------- /ch2_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | INuiSensor* context = NULL; 8 | HANDLE colorStreamHandle = NULL; 9 | HANDLE depthStreamHandle = NULL; 10 | std::string hudText; 11 | 12 | bool initializeKinect() 13 | { 14 | int numKinects = 0; 15 | HRESULT hr = NuiGetSensorCount( &numKinects ); 16 | if ( FAILED(hr) || numKinects<=0 ) 17 | { 18 | std::cout << "No Kinect device found." << std::endl; 19 | return false; 20 | } 21 | 22 | hr = NuiCreateSensorByIndex( 0, &context ); 23 | if ( FAILED(hr) ) 24 | { 25 | std::cout << "Failed to connect to Kinect device." << std::endl; 26 | return false; 27 | } 28 | 29 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH; 30 | hr = context->NuiInitialize( nuiFlags ); 31 | if ( FAILED(hr) ) 32 | { 33 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 34 | return false; 35 | } 36 | 37 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 38 | if ( FAILED(hr) ) 39 | { 40 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 41 | return false; 42 | } 43 | 44 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &depthStreamHandle ); 45 | if ( FAILED(hr) ) 46 | { 47 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 48 | return false; 49 | } 50 | 51 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 52 | if ( FAILED(hr) ) 53 | { 54 | std::cout << "Unable to start tracking skeleton." << std::endl; 55 | return false; 56 | } 57 | return true; 58 | } 59 | 60 | bool destroyKinect() 61 | { 62 | if ( context ) 63 | { 64 | context->NuiShutdown(); 65 | return true; 66 | } 67 | return false; 68 | } 69 | 70 | void update() 71 | { 72 | NUI_IMAGE_FRAME colorFrame; 73 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 74 | if ( SUCCEEDED(hr) ) 75 | { 76 | std::stringstream ss; 77 | ss << "Frame: " << colorFrame.dwFrameNumber << " " 78 | << "Time stamp: " << (double)colorFrame.liTimeStamp.QuadPart * 0.001; 79 | hudText = ss.str(); 80 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 81 | } 82 | glutPostRedisplay(); 83 | } 84 | 85 | void render() 86 | { 87 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 88 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 89 | 90 | glMatrixMode( GL_PROJECTION ); 91 | glLoadIdentity(); 92 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 93 | 94 | glMatrixMode( GL_MODELVIEW ); 95 | glLoadIdentity(); 96 | 97 | glRasterPos2f( 0.01f, 0.01f ); 98 | glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); 99 | glutBitmapString( GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)hudText.c_str() ); 100 | 101 | glutSwapBuffers(); 102 | } 103 | 104 | void reshape( int w, int h ) 105 | { 106 | glViewport( 0, 0, w, h ); 107 | } 108 | 109 | void keyEvents( unsigned char key, int x, int y ) 110 | { 111 | switch ( key ) 112 | { 113 | case 27: case 'Q': case 'q': 114 | glutLeaveMainLoop(); 115 | return; 116 | } 117 | glutPostRedisplay(); 118 | } 119 | 120 | int main( int argc, char** argv ) 121 | { 122 | glutInit( &argc, argv ); 123 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 124 | glutCreateWindow( "ch2_02_Init_Kinect" ); 125 | glutFullScreen(); 126 | 127 | glutIdleFunc( update ); 128 | glutDisplayFunc( render ); 129 | glutReshapeFunc( reshape ); 130 | glutKeyboardFunc( keyEvents ); 131 | 132 | if ( !initializeKinect() ) return 1; 133 | glutMainLoop(); 134 | destroyKinect(); 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /common/TextureManager.cpp: -------------------------------------------------------------------------------- 1 | //********************************************** 2 | //Singleton Texture Manager class 3 | //Written by Ben English 4 | //benjamin.english@oit.edu 5 | // 6 | //For use with OpenGL and the FreeImage library 7 | //********************************************** 8 | 9 | #include "TextureManager.h" 10 | 11 | TextureManager* TextureManager::m_inst(0); 12 | 13 | TextureManager* TextureManager::Inst() 14 | { 15 | if(!m_inst) 16 | m_inst = new TextureManager(); 17 | 18 | return m_inst; 19 | } 20 | 21 | TextureManager::TextureManager() 22 | { 23 | // call this ONLY when linking with FreeImage as a static library 24 | #ifdef FREEIMAGE_LIB 25 | FreeImage_Initialise(); 26 | #endif 27 | } 28 | 29 | //these should never be called 30 | //TextureManager::TextureManager(const TextureManager& tm){} 31 | //TextureManager& TextureManager::operator=(const TextureManager& tm){} 32 | 33 | TextureManager::~TextureManager() 34 | { 35 | // call this ONLY when linking with FreeImage as a static library 36 | #ifdef FREEIMAGE_LIB 37 | FreeImage_DeInitialise(); 38 | #endif 39 | 40 | UnloadAllTextures(); 41 | m_inst = 0; 42 | } 43 | 44 | bool TextureManager::LoadTexture(const char* filename, const unsigned int texID, GLenum image_format, GLint internal_format, GLint level, GLint border) 45 | { 46 | //image format 47 | FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; 48 | //pointer to the image, once loaded 49 | FIBITMAP *dib(0); 50 | //pointer to the image data 51 | BYTE* bits(0); 52 | //image width and height 53 | unsigned int width(0), height(0); 54 | //OpenGL's image ID to map to 55 | GLuint gl_texID; 56 | 57 | //check the file signature and deduce its format 58 | fif = FreeImage_GetFileType(filename, 0); 59 | //if still unknown, try to guess the file format from the file extension 60 | if(fif == FIF_UNKNOWN) 61 | fif = FreeImage_GetFIFFromFilename(filename); 62 | //if still unkown, return failure 63 | if(fif == FIF_UNKNOWN) 64 | return false; 65 | 66 | //check that the plugin has reading capabilities and load the file 67 | if(FreeImage_FIFSupportsReading(fif)) 68 | dib = FreeImage_Load(fif, filename); 69 | //if the image failed to load, return failure 70 | if(!dib) 71 | return false; 72 | 73 | //retrieve the image data 74 | bits = FreeImage_GetBits(dib); 75 | //get the image width and height 76 | width = FreeImage_GetWidth(dib); 77 | height = FreeImage_GetHeight(dib); 78 | //if this somehow one of these failed (they shouldn't), return failure 79 | if((bits == 0) || (width == 0) || (height == 0)) 80 | return false; 81 | 82 | //if this texture ID is in use, unload the current texture 83 | if(m_texID.find(texID) != m_texID.end()) 84 | glDeleteTextures(1, &(m_texID[texID])); 85 | 86 | //generate an OpenGL texture ID for this texture 87 | glGenTextures(1, &gl_texID); 88 | //store the texture ID mapping 89 | m_texID[texID] = gl_texID; 90 | //bind to the new texture ID 91 | glBindTexture(GL_TEXTURE_2D, gl_texID); 92 | //store the texture data for OpenGL use 93 | glTexImage2D(GL_TEXTURE_2D, level, internal_format, width, height, 94 | border, image_format, GL_UNSIGNED_BYTE, bits); 95 | 96 | //Free FreeImage's copy of the data 97 | FreeImage_Unload(dib); 98 | 99 | //return success 100 | return true; 101 | } 102 | 103 | bool TextureManager::UnloadTexture(const unsigned int texID) 104 | { 105 | bool result(true); 106 | //if this texture ID mapped, unload it's texture, and remove it from the map 107 | if(m_texID.find(texID) != m_texID.end()) 108 | { 109 | glDeleteTextures(1, &(m_texID[texID])); 110 | m_texID.erase(texID); 111 | } 112 | //otherwise, unload failed 113 | else 114 | { 115 | result = false; 116 | } 117 | 118 | return result; 119 | } 120 | 121 | bool TextureManager::BindTexture(const unsigned int texID) 122 | { 123 | bool result(true); 124 | //if this texture ID mapped, bind it's texture as current 125 | if(m_texID.find(texID) != m_texID.end()) 126 | glBindTexture(GL_TEXTURE_2D, m_texID[texID]); 127 | //otherwise, binding failed 128 | else 129 | result = false; 130 | 131 | return result; 132 | } 133 | 134 | void TextureManager::UnloadAllTextures() 135 | { 136 | //start at the begginning of the texture map 137 | std::map::iterator i = m_texID.begin(); 138 | 139 | //Unload the textures untill the end of the texture map is found 140 | while(i != m_texID.end()) 141 | UnloadTexture(i->first); 142 | 143 | //clear the texture map 144 | m_texID.clear(); 145 | } -------------------------------------------------------------------------------- /ch3_01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/GLUtilities.h" 7 | 8 | INuiSensor* context = NULL; 9 | HANDLE colorStreamHandle = NULL; 10 | HANDLE depthStreamHandle = NULL; 11 | TextureObject* colorTexture = NULL; 12 | TextureObject* depthTexture = NULL; 13 | 14 | bool initializeKinect() 15 | { 16 | int numKinects = 0; 17 | HRESULT hr = NuiGetSensorCount( &numKinects ); 18 | if ( FAILED(hr) || numKinects<=0 ) 19 | { 20 | std::cout << "No Kinect device found." << std::endl; 21 | return false; 22 | } 23 | 24 | hr = NuiCreateSensorByIndex( 0, &context ); 25 | if ( FAILED(hr) ) 26 | { 27 | std::cout << "Failed to connect to Kinect device." << std::endl; 28 | return false; 29 | } 30 | 31 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH; 32 | hr = context->NuiInitialize( nuiFlags ); 33 | if ( FAILED(hr) ) 34 | { 35 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 36 | return false; 37 | } 38 | 39 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 40 | if ( FAILED(hr) ) 41 | { 42 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 43 | return false; 44 | } 45 | 46 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &depthStreamHandle ); 47 | if ( FAILED(hr) ) 48 | { 49 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 50 | return false; 51 | } 52 | 53 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 54 | if ( FAILED(hr) ) 55 | { 56 | std::cout << "Unable to start tracking skeleton." << std::endl; 57 | return false; 58 | } 59 | return true; 60 | } 61 | 62 | bool destroyKinect() 63 | { 64 | if ( context ) 65 | { 66 | context->NuiShutdown(); 67 | return true; 68 | } 69 | return false; 70 | } 71 | 72 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame, bool isDepthFrame ) 73 | { 74 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 75 | NUI_LOCKED_RECT lockedRect; 76 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 77 | if ( lockedRect.Pitch!=NULL ) 78 | { 79 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 80 | for ( int i=0; i<480; ++i ) 81 | { 82 | const BYTE* line = buffer + i * lockedRect.Pitch; 83 | const USHORT* bufferWord = (const USHORT*)line; 84 | for ( int j=0; j<640; ++j ) 85 | { 86 | if ( !isDepthFrame ) 87 | { 88 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 89 | *(ptr + 0) = line[4 * j + 2]; 90 | *(ptr + 1) = line[4 * j + 1]; 91 | *(ptr + 2) = line[4 * j + 0]; 92 | } 93 | else 94 | { 95 | unsigned char* ptr = depthTexture->bits + (i * 640 + j); 96 | *ptr = (unsigned char)NuiDepthPixelToDepth(bufferWord[j]); 97 | } 98 | } 99 | } 100 | 101 | TextureObject* tobj = (isDepthFrame ? depthTexture : colorTexture); 102 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 103 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 104 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 105 | } 106 | nuiTexture->UnlockRect( 0 ); 107 | } 108 | 109 | void update() 110 | { 111 | NUI_IMAGE_FRAME colorFrame; 112 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 113 | if ( SUCCEEDED(hr) ) 114 | { 115 | updateImageFrame( colorFrame, false ); 116 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 117 | } 118 | 119 | NUI_IMAGE_FRAME depthFrame; 120 | hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 121 | if ( SUCCEEDED(hr) ) 122 | { 123 | updateImageFrame( depthFrame, true ); 124 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 125 | } 126 | glutPostRedisplay(); 127 | } 128 | 129 | void render() 130 | { 131 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 132 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 133 | glEnable( GL_TEXTURE_2D ); 134 | 135 | glMatrixMode( GL_PROJECTION ); 136 | glLoadIdentity(); 137 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 138 | 139 | glMatrixMode( GL_MODELVIEW ); 140 | glLoadIdentity(); 141 | 142 | // Draw background quad 143 | GLfloat vertices[][3] = { 144 | { 0.0f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, 145 | { 0.5f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 146 | }; 147 | GLfloat texcoords[][2] = { 148 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 149 | }; 150 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 151 | 152 | glBindTexture( GL_TEXTURE_2D, colorTexture->id ); 153 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 154 | 155 | glTranslatef( 0.5f, 0.0f, 0.0f ); 156 | glBindTexture( GL_TEXTURE_2D, depthTexture->id ); 157 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 158 | 159 | glutSwapBuffers(); 160 | } 161 | 162 | void reshape( int w, int h ) 163 | { 164 | glViewport( 0, 0, w, h ); 165 | } 166 | 167 | void keyEvents( unsigned char key, int x, int y ) 168 | { 169 | switch ( key ) 170 | { 171 | case 27: case 'Q': case 'q': 172 | glutLeaveMainLoop(); 173 | return; 174 | } 175 | glutPostRedisplay(); 176 | } 177 | 178 | int main( int argc, char** argv ) 179 | { 180 | glutInit( &argc, argv ); 181 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 182 | glutCreateWindow( "ch3_01_Color_Depth" ); 183 | glutFullScreen(); 184 | 185 | glutIdleFunc( update ); 186 | glutDisplayFunc( render ); 187 | glutReshapeFunc( reshape ); 188 | glutKeyboardFunc( keyEvents ); 189 | 190 | if ( !initializeKinect() ) return 1; 191 | colorTexture = createTexture(640, 480, GL_RGB, 3); 192 | depthTexture = createTexture(640, 480, GL_LUMINANCE, 1); 193 | 194 | glutMainLoop(); 195 | 196 | destroyTexture( colorTexture ); 197 | destroyTexture( depthTexture ); 198 | destroyKinect(); 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /ch5_03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | INuiSensor* context = NULL; 9 | HANDLE colorStreamHandle = NULL; 10 | HANDLE depthStreamHandle = NULL; 11 | 12 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 13 | GLfloat cursors[6]; 14 | GLfloat lastCursors[6]; 15 | unsigned int holdGestureCount[2] = {0}; 16 | unsigned int swipeGestureCount[2] = {0}; 17 | 18 | bool isMouseDown = false; 19 | 20 | bool initializeKinect() 21 | { 22 | int numKinects = 0; 23 | HRESULT hr = NuiGetSensorCount( &numKinects ); 24 | if ( FAILED(hr) || numKinects<=0 ) 25 | { 26 | std::cout << "No Kinect device found." << std::endl; 27 | return false; 28 | } 29 | 30 | hr = NuiCreateSensorByIndex( 0, &context ); 31 | if ( FAILED(hr) ) 32 | { 33 | std::cout << "Failed to connect to Kinect device." << std::endl; 34 | return false; 35 | } 36 | 37 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 38 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 39 | hr = context->NuiInitialize( nuiFlags ); 40 | if ( FAILED(hr) ) 41 | { 42 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 43 | return false; 44 | } 45 | 46 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 47 | if ( FAILED(hr) ) 48 | { 49 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 50 | return false; 51 | } 52 | 53 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 54 | 0, 2, NULL, &depthStreamHandle ); 55 | if ( FAILED(hr) ) 56 | { 57 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 58 | return false; 59 | } 60 | 61 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 62 | if ( FAILED(hr) ) 63 | { 64 | std::cout << "Unable to start tracking skeleton." << std::endl; 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | bool destroyKinect() 71 | { 72 | if ( context ) 73 | { 74 | context->NuiShutdown(); 75 | return true; 76 | } 77 | return false; 78 | } 79 | 80 | void guessGesture( unsigned int index, bool inRange ) 81 | { 82 | float distance = sqrt(powf(cursors[index*3]-lastCursors[index*3], 2.0f) 83 | + powf(cursors[1+index*3]-lastCursors[1+index*3], 2.0f)); 84 | if ( distance<0.02 ) 85 | { 86 | holdGestureCount[index]++; 87 | swipeGestureCount[index] = 0; 88 | } 89 | else if ( distance>0.05 ) 90 | { 91 | holdGestureCount[index] = 0; 92 | swipeGestureCount[index]++; 93 | } 94 | else 95 | { 96 | holdGestureCount[index] = 0; 97 | swipeGestureCount[index] = 0; 98 | } 99 | } 100 | 101 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 102 | { 103 | POINT coordInDepth; 104 | USHORT depth = 0; 105 | GLfloat yMin = 0.0f, zMax = 0.0f; 106 | for ( int i=0; i<6; ++i ) lastCursors[i] = cursors[i]; 107 | 108 | for ( int i=0; i30 ) 146 | { 147 | if ( !isMouseDown ) 148 | input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN; 149 | else 150 | input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP; 151 | isMouseDown = !isMouseDown; 152 | holdGestureCount[0] = 0; 153 | } 154 | else if ( swipeGestureCount[0]>1 ) 155 | { 156 | input.mi.dwFlags = MOUSEEVENTF_WHEEL; 157 | input.mi.mouseData = WHEEL_DELTA; 158 | } 159 | else 160 | input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; 161 | SendInput( 1, &input, sizeof(INPUT) ); 162 | } 163 | } 164 | 165 | void update() 166 | { 167 | NUI_SKELETON_FRAME skeletonFrame = {0}; 168 | HRESULT hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 169 | if ( SUCCEEDED(hr) ) 170 | { 171 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 172 | for ( int n=0; n 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/GLUtilities.h" 7 | 8 | INuiSensor* context = NULL; 9 | HANDLE colorStreamHandle = NULL; 10 | HANDLE depthStreamHandle = NULL; 11 | TextureObject* colorTexture = NULL; 12 | TextureObject* playerColorTexture = NULL; 13 | 14 | bool initializeKinect() 15 | { 16 | int numKinects = 0; 17 | HRESULT hr = NuiGetSensorCount( &numKinects ); 18 | if ( FAILED(hr) || numKinects<=0 ) 19 | { 20 | std::cout << "No Kinect device found." << std::endl; 21 | return false; 22 | } 23 | 24 | hr = NuiCreateSensorByIndex( 0, &context ); 25 | if ( FAILED(hr) ) 26 | { 27 | std::cout << "Failed to connect to Kinect device." << std::endl; 28 | return false; 29 | } 30 | 31 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 32 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 33 | hr = context->NuiInitialize( nuiFlags ); 34 | if ( FAILED(hr) ) 35 | { 36 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 37 | return false; 38 | } 39 | 40 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 41 | if ( FAILED(hr) ) 42 | { 43 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 44 | return false; 45 | } 46 | 47 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 48 | 0, 2, NULL, &depthStreamHandle ); 49 | if ( FAILED(hr) ) 50 | { 51 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 52 | return false; 53 | } 54 | 55 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 56 | if ( FAILED(hr) ) 57 | { 58 | std::cout << "Unable to start tracking skeleton." << std::endl; 59 | return false; 60 | } 61 | return true; 62 | } 63 | 64 | bool destroyKinect() 65 | { 66 | if ( context ) 67 | { 68 | context->NuiShutdown(); 69 | return true; 70 | } 71 | return false; 72 | } 73 | 74 | bool setPlayerColorPixel( const USHORT depthValue, int x, int y, unsigned char alpha ) 75 | { 76 | unsigned char* ptr = playerColorTexture->bits + 4 * (y * 640 + x); 77 | if ( NuiDepthPixelToPlayerIndex(depthValue)>0 ) 78 | { 79 | LONG colorX = 0, colorY = 0; 80 | context->NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution( 81 | NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, NULL, 82 | x, y, depthValue, &colorX, &colorY ); 83 | if ( colorX>=640 || colorY>=480 ) return false; 84 | 85 | unsigned char* colorPtr = colorTexture->bits + 3 * (colorY * 640 + colorX); 86 | *(ptr + 0) = *(colorPtr + 0); 87 | *(ptr + 1) = *(colorPtr + 1); 88 | *(ptr + 2) = *(colorPtr + 2); 89 | *(ptr + 3) = alpha; 90 | } 91 | else 92 | { 93 | *(ptr + 0) = 0; 94 | *(ptr + 1) = 0; 95 | *(ptr + 2) = 0; 96 | *(ptr + 3) = 0; 97 | } 98 | return true; 99 | } 100 | 101 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame, bool isDepthFrame ) 102 | { 103 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 104 | NUI_LOCKED_RECT lockedRect; 105 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 106 | if ( lockedRect.Pitch!=NULL ) 107 | { 108 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 109 | for ( int i=0; i<480; ++i ) 110 | { 111 | const BYTE* line = buffer + i * lockedRect.Pitch; 112 | const USHORT* bufferWord = (const USHORT*)line; 113 | for ( int j=0; j<640; ++j ) 114 | { 115 | if ( !isDepthFrame ) 116 | { 117 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 118 | *(ptr + 0) = line[4 * j + 2]; 119 | *(ptr + 1) = line[4 * j + 1]; 120 | *(ptr + 2) = line[4 * j + 0]; 121 | } 122 | else 123 | setPlayerColorPixel( bufferWord[j], j, i, 255 ); 124 | } 125 | } 126 | 127 | TextureObject* tobj = (isDepthFrame ? playerColorTexture : colorTexture); 128 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 129 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 130 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 131 | } 132 | nuiTexture->UnlockRect( 0 ); 133 | } 134 | 135 | void update() 136 | { 137 | NUI_IMAGE_FRAME colorFrame; 138 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 139 | if ( SUCCEEDED(hr) ) 140 | { 141 | updateImageFrame( colorFrame, false ); 142 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 143 | } 144 | 145 | NUI_IMAGE_FRAME depthFrame; 146 | hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 147 | if ( SUCCEEDED(hr) ) 148 | { 149 | updateImageFrame( depthFrame, true ); 150 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 151 | } 152 | glutPostRedisplay(); 153 | } 154 | 155 | void render() 156 | { 157 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 158 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 159 | glEnable( GL_TEXTURE_2D ); 160 | 161 | glMatrixMode( GL_PROJECTION ); 162 | glLoadIdentity(); 163 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 164 | 165 | glMatrixMode( GL_MODELVIEW ); 166 | glLoadIdentity(); 167 | 168 | // Draw background quad 169 | GLfloat vertices[][3] = { 170 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 171 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 172 | }; 173 | GLfloat texcoords[][2] = { 174 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 175 | }; 176 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 177 | 178 | glBindTexture( GL_TEXTURE_2D, playerColorTexture->id ); 179 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 180 | 181 | glutSwapBuffers(); 182 | } 183 | 184 | void reshape( int w, int h ) 185 | { 186 | glViewport( 0, 0, w, h ); 187 | } 188 | 189 | void keyEvents( unsigned char key, int x, int y ) 190 | { 191 | switch ( key ) 192 | { 193 | case 27: case 'Q': case 'q': 194 | glutLeaveMainLoop(); 195 | return; 196 | } 197 | glutPostRedisplay(); 198 | } 199 | 200 | int main( int argc, char** argv ) 201 | { 202 | glutInit( &argc, argv ); 203 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 204 | glutCreateWindow( "ch3_02_Background_Subtraction" ); 205 | glutFullScreen(); 206 | 207 | glutIdleFunc( update ); 208 | glutDisplayFunc( render ); 209 | glutReshapeFunc( reshape ); 210 | glutKeyboardFunc( keyEvents ); 211 | 212 | if ( !initializeKinect() ) return 1; 213 | colorTexture = createTexture(640, 480, GL_RGB, 3); 214 | playerColorTexture = createTexture(640, 480, GL_RGBA, 4); 215 | 216 | glutMainLoop(); 217 | 218 | destroyTexture( colorTexture ); 219 | destroyTexture( playerColorTexture ); 220 | destroyKinect(); 221 | return 0; 222 | } 223 | -------------------------------------------------------------------------------- /ch3_03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/TextureManager.h" 7 | #include "common/GLUtilities.h" 8 | 9 | INuiSensor* context = NULL; 10 | HANDLE colorStreamHandle = NULL; 11 | HANDLE depthStreamHandle = NULL; 12 | TextureObject* colorTexture = NULL; 13 | TextureObject* playerColorTexture = NULL; 14 | 15 | const unsigned int backgroundTexID = 1; 16 | 17 | bool initializeKinect() 18 | { 19 | int numKinects = 0; 20 | HRESULT hr = NuiGetSensorCount( &numKinects ); 21 | if ( FAILED(hr) || numKinects<=0 ) 22 | { 23 | std::cout << "No Kinect device found." << std::endl; 24 | return false; 25 | } 26 | 27 | hr = NuiCreateSensorByIndex( 0, &context ); 28 | if ( FAILED(hr) ) 29 | { 30 | std::cout << "Failed to connect to Kinect device." << std::endl; 31 | return false; 32 | } 33 | 34 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 35 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 36 | hr = context->NuiInitialize( nuiFlags ); 37 | if ( FAILED(hr) ) 38 | { 39 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 40 | return false; 41 | } 42 | 43 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 44 | if ( FAILED(hr) ) 45 | { 46 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 47 | return false; 48 | } 49 | 50 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 51 | 0, 2, NULL, &depthStreamHandle ); 52 | if ( FAILED(hr) ) 53 | { 54 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 55 | return false; 56 | } 57 | 58 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 59 | if ( FAILED(hr) ) 60 | { 61 | std::cout << "Unable to start tracking skeleton." << std::endl; 62 | return false; 63 | } 64 | return true; 65 | } 66 | 67 | bool destroyKinect() 68 | { 69 | if ( context ) 70 | { 71 | context->NuiShutdown(); 72 | return true; 73 | } 74 | return false; 75 | } 76 | 77 | bool setPlayerColorPixel( const USHORT depthValue, int x, int y, unsigned char alpha ) 78 | { 79 | unsigned char* ptr = playerColorTexture->bits + 4 * (y * 640 + x); 80 | if ( NuiDepthPixelToPlayerIndex(depthValue)>0 ) 81 | { 82 | LONG colorX = 0, colorY = 0; 83 | context->NuiImageGetColorPixelCoordinatesFromDepthPixelAtResolution( 84 | NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, NULL, 85 | x, y, depthValue, &colorX, &colorY ); 86 | if ( colorX>=640 || colorY>=480 ) return false; 87 | 88 | unsigned char* colorPtr = colorTexture->bits + 3 * (colorY * 640 + colorX); 89 | *(ptr + 0) = *(colorPtr + 0); 90 | *(ptr + 1) = *(colorPtr + 1); 91 | *(ptr + 2) = *(colorPtr + 2); 92 | *(ptr + 3) = alpha; 93 | } 94 | else 95 | { 96 | *(ptr + 0) = 0; 97 | *(ptr + 1) = 0; 98 | *(ptr + 2) = 0; 99 | *(ptr + 3) = 0; 100 | } 101 | return true; 102 | } 103 | 104 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame, bool isDepthFrame ) 105 | { 106 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 107 | NUI_LOCKED_RECT lockedRect; 108 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 109 | if ( lockedRect.Pitch!=NULL ) 110 | { 111 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 112 | for ( int i=0; i<480; ++i ) 113 | { 114 | const BYTE* line = buffer + i * lockedRect.Pitch; 115 | const USHORT* bufferWord = (const USHORT*)line; 116 | for ( int j=0; j<640; ++j ) 117 | { 118 | if ( !isDepthFrame ) 119 | { 120 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 121 | *(ptr + 0) = line[4 * j + 2]; 122 | *(ptr + 1) = line[4 * j + 1]; 123 | *(ptr + 2) = line[4 * j + 0]; 124 | } 125 | else 126 | setPlayerColorPixel( bufferWord[j], j, i, 255 ); 127 | } 128 | } 129 | 130 | TextureObject* tobj = (isDepthFrame ? playerColorTexture : colorTexture); 131 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 132 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 133 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 134 | } 135 | nuiTexture->UnlockRect( 0 ); 136 | } 137 | 138 | void update() 139 | { 140 | NUI_IMAGE_FRAME colorFrame; 141 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 142 | if ( SUCCEEDED(hr) ) 143 | { 144 | updateImageFrame( colorFrame, false ); 145 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 146 | } 147 | 148 | NUI_IMAGE_FRAME depthFrame; 149 | hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 150 | if ( SUCCEEDED(hr) ) 151 | { 152 | updateImageFrame( depthFrame, true ); 153 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 154 | } 155 | glutPostRedisplay(); 156 | } 157 | 158 | void render() 159 | { 160 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 161 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 162 | glEnable( GL_TEXTURE_2D ); 163 | 164 | glMatrixMode( GL_PROJECTION ); 165 | glLoadIdentity(); 166 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 167 | 168 | glMatrixMode( GL_MODELVIEW ); 169 | glLoadIdentity(); 170 | 171 | // Draw background quad 172 | GLfloat vertices[][3] = { 173 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 174 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 175 | }; 176 | GLfloat texcoords[][2] = { 177 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 178 | }; 179 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 180 | 181 | TextureManager::Inst()->BindTexture( backgroundTexID ); 182 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 183 | 184 | glEnable( GL_BLEND ); 185 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 186 | glTranslatef( 0.0f, 0.0f, 0.1f ); 187 | 188 | glBindTexture( GL_TEXTURE_2D, playerColorTexture->id ); 189 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 190 | 191 | glDisable( GL_BLEND ); 192 | glutSwapBuffers(); 193 | } 194 | 195 | void reshape( int w, int h ) 196 | { 197 | glViewport( 0, 0, w, h ); 198 | } 199 | 200 | void keyEvents( unsigned char key, int x, int y ) 201 | { 202 | switch ( key ) 203 | { 204 | case 27: case 'Q': case 'q': 205 | glutLeaveMainLoop(); 206 | return; 207 | } 208 | glutPostRedisplay(); 209 | } 210 | 211 | int main( int argc, char** argv ) 212 | { 213 | glutInit( &argc, argv ); 214 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 215 | glutCreateWindow( "ch3_03_Magic_Photographer" ); 216 | glutFullScreen(); 217 | 218 | glutIdleFunc( update ); 219 | glutDisplayFunc( render ); 220 | glutReshapeFunc( reshape ); 221 | glutKeyboardFunc( keyEvents ); 222 | 223 | if ( TextureManager::Inst()->LoadTexture("background.bmp", backgroundTexID, GL_BGR_EXT) ) 224 | { 225 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 226 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 227 | } 228 | 229 | if ( !initializeKinect() ) return 1; 230 | colorTexture = createTexture(640, 480, GL_RGB, 3); 231 | playerColorTexture = createTexture(640, 480, GL_RGBA, 4); 232 | 233 | glutMainLoop(); 234 | 235 | destroyTexture( colorTexture ); 236 | destroyTexture( playerColorTexture ); 237 | destroyKinect(); 238 | return 0; 239 | } 240 | -------------------------------------------------------------------------------- /ch4_01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "common/GLUtilities.h" 7 | 8 | INuiSensor* context = NULL; 9 | HANDLE colorStreamHandle = NULL; 10 | HANDLE depthStreamHandle = NULL; 11 | TextureObject* colorTexture = NULL; 12 | 13 | GLfloat skeletonVertices[NUI_SKELETON_POSITION_COUNT][3]; 14 | GLuint skeletonIndices[38] = { 15 | NUI_SKELETON_POSITION_HIP_CENTER, NUI_SKELETON_POSITION_SPINE, 16 | NUI_SKELETON_POSITION_SPINE, NUI_SKELETON_POSITION_SHOULDER_CENTER, 17 | NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_HEAD, 18 | // Left arm 19 | NUI_SKELETON_POSITION_SHOULDER_LEFT, NUI_SKELETON_POSITION_ELBOW_LEFT, 20 | NUI_SKELETON_POSITION_ELBOW_LEFT, NUI_SKELETON_POSITION_WRIST_LEFT, 21 | NUI_SKELETON_POSITION_WRIST_LEFT, NUI_SKELETON_POSITION_HAND_LEFT, 22 | // Right arm 23 | NUI_SKELETON_POSITION_SHOULDER_RIGHT, NUI_SKELETON_POSITION_ELBOW_RIGHT, 24 | NUI_SKELETON_POSITION_ELBOW_RIGHT, NUI_SKELETON_POSITION_WRIST_RIGHT, 25 | NUI_SKELETON_POSITION_WRIST_RIGHT, NUI_SKELETON_POSITION_HAND_RIGHT, 26 | // Left leg 27 | NUI_SKELETON_POSITION_HIP_LEFT, NUI_SKELETON_POSITION_KNEE_LEFT, 28 | NUI_SKELETON_POSITION_KNEE_LEFT, NUI_SKELETON_POSITION_ANKLE_LEFT, 29 | NUI_SKELETON_POSITION_ANKLE_LEFT, NUI_SKELETON_POSITION_FOOT_LEFT, 30 | // Right leg 31 | NUI_SKELETON_POSITION_HIP_RIGHT, NUI_SKELETON_POSITION_KNEE_RIGHT, 32 | NUI_SKELETON_POSITION_KNEE_RIGHT, NUI_SKELETON_POSITION_ANKLE_RIGHT, 33 | NUI_SKELETON_POSITION_ANKLE_RIGHT, NUI_SKELETON_POSITION_FOOT_RIGHT, 34 | // Others 35 | NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_SHOULDER_LEFT, 36 | NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_SHOULDER_RIGHT, 37 | NUI_SKELETON_POSITION_HIP_CENTER, NUI_SKELETON_POSITION_HIP_LEFT, 38 | NUI_SKELETON_POSITION_HIP_CENTER, NUI_SKELETON_POSITION_HIP_RIGHT 39 | }; 40 | 41 | bool initializeKinect() 42 | { 43 | int numKinects = 0; 44 | HRESULT hr = NuiGetSensorCount( &numKinects ); 45 | if ( FAILED(hr) || numKinects<=0 ) 46 | { 47 | std::cout << "No Kinect device found." << std::endl; 48 | return false; 49 | } 50 | 51 | hr = NuiCreateSensorByIndex( 0, &context ); 52 | if ( FAILED(hr) ) 53 | { 54 | std::cout << "Failed to connect to Kinect device." << std::endl; 55 | return false; 56 | } 57 | 58 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 59 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 60 | hr = context->NuiInitialize( nuiFlags ); 61 | if ( FAILED(hr) ) 62 | { 63 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 64 | return false; 65 | } 66 | 67 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 68 | if ( FAILED(hr) ) 69 | { 70 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 71 | return false; 72 | } 73 | 74 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 75 | 0, 2, NULL, &depthStreamHandle ); 76 | if ( FAILED(hr) ) 77 | { 78 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 79 | return false; 80 | } 81 | 82 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 83 | if ( FAILED(hr) ) 84 | { 85 | std::cout << "Unable to start tracking skeleton." << std::endl; 86 | return false; 87 | } 88 | return true; 89 | } 90 | 91 | bool destroyKinect() 92 | { 93 | if ( context ) 94 | { 95 | context->NuiShutdown(); 96 | return true; 97 | } 98 | return false; 99 | } 100 | 101 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 102 | { 103 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 104 | NUI_LOCKED_RECT lockedRect; 105 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 106 | if ( lockedRect.Pitch!=NULL ) 107 | { 108 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 109 | for ( int i=0; i<480; ++i ) 110 | { 111 | const BYTE* line = buffer + i * lockedRect.Pitch; 112 | const USHORT* bufferWord = (const USHORT*)line; 113 | for ( int j=0; j<640; ++j ) 114 | { 115 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 116 | *(ptr + 0) = line[4 * j + 2]; 117 | *(ptr + 1) = line[4 * j + 1]; 118 | *(ptr + 2) = line[4 * j + 0]; 119 | } 120 | } 121 | 122 | TextureObject* tobj = colorTexture; 123 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 124 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 125 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 126 | } 127 | nuiTexture->UnlockRect( 0 ); 128 | } 129 | 130 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 131 | { 132 | POINT coordInDepth; 133 | USHORT depth = 0; 134 | for ( int i=0; iNuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 151 | if ( SUCCEEDED(hr) ) 152 | { 153 | updateImageFrame( colorFrame ); 154 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 155 | } 156 | 157 | NUI_SKELETON_FRAME skeletonFrame = {0}; 158 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 159 | if ( SUCCEEDED(hr) ) 160 | { 161 | for ( int n=0; nid ); 198 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 199 | 200 | // Draw skeleton 201 | glDisable( GL_TEXTURE_2D ); 202 | glLineWidth( 5.0f ); 203 | 204 | VertexData skeletonData = { &(skeletonVertices[0][0]), NULL, NULL, NULL }; 205 | drawIndexedMesh( WITH_POSITION, NUI_SKELETON_POSITION_COUNT, skeletonData, 206 | GL_LINES, 38, skeletonIndices ); 207 | 208 | glutSwapBuffers(); 209 | } 210 | 211 | void reshape( int w, int h ) 212 | { 213 | glViewport( 0, 0, w, h ); 214 | } 215 | 216 | void keyEvents( unsigned char key, int x, int y ) 217 | { 218 | switch ( key ) 219 | { 220 | case 27: case 'Q': case 'q': 221 | glutLeaveMainLoop(); 222 | return; 223 | } 224 | glutPostRedisplay(); 225 | } 226 | 227 | int main( int argc, char** argv ) 228 | { 229 | glutInit( &argc, argv ); 230 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 231 | glutCreateWindow( "ch4_01_Skeleton_Drawer" ); 232 | glutFullScreen(); 233 | 234 | glutIdleFunc( update ); 235 | glutDisplayFunc( render ); 236 | glutReshapeFunc( reshape ); 237 | glutKeyboardFunc( keyEvents ); 238 | 239 | if ( !initializeKinect() ) return 1; 240 | colorTexture = createTexture(640, 480, GL_RGB, 3); 241 | 242 | glutMainLoop(); 243 | 244 | destroyTexture( colorTexture ); 245 | destroyKinect(); 246 | return 0; 247 | } 248 | -------------------------------------------------------------------------------- /ch4_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | 15 | const unsigned int backgroundTexID = 1; 16 | 17 | struct Vertex { GLfloat x, y, z; }; 18 | std::vector leftHandTrails; 19 | std::vector rightHandTrails; 20 | GLfloat trailColors[20][4]; 21 | 22 | bool initializeKinect() 23 | { 24 | int numKinects = 0; 25 | HRESULT hr = NuiGetSensorCount( &numKinects ); 26 | if ( FAILED(hr) || numKinects<=0 ) 27 | { 28 | std::cout << "No Kinect device found." << std::endl; 29 | return false; 30 | } 31 | 32 | hr = NuiCreateSensorByIndex( 0, &context ); 33 | if ( FAILED(hr) ) 34 | { 35 | std::cout << "Failed to connect to Kinect device." << std::endl; 36 | return false; 37 | } 38 | 39 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 40 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 41 | hr = context->NuiInitialize( nuiFlags ); 42 | if ( FAILED(hr) ) 43 | { 44 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 45 | return false; 46 | } 47 | 48 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 49 | if ( FAILED(hr) ) 50 | { 51 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 52 | return false; 53 | } 54 | 55 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 56 | 0, 2, NULL, &depthStreamHandle ); 57 | if ( FAILED(hr) ) 58 | { 59 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 60 | return false; 61 | } 62 | 63 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 64 | if ( FAILED(hr) ) 65 | { 66 | std::cout << "Unable to start tracking skeleton." << std::endl; 67 | return false; 68 | } 69 | return true; 70 | } 71 | 72 | bool destroyKinect() 73 | { 74 | if ( context ) 75 | { 76 | context->NuiShutdown(); 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 83 | { 84 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 85 | NUI_LOCKED_RECT lockedRect; 86 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 87 | if ( lockedRect.Pitch!=NULL ) 88 | { 89 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 90 | for ( int i=0; i<480; ++i ) 91 | { 92 | const BYTE* line = buffer + i * lockedRect.Pitch; 93 | const USHORT* bufferWord = (const USHORT*)line; 94 | for ( int j=0; j<640; ++j ) 95 | { 96 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 97 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 98 | { 99 | *(ptr + 0) = 200; 100 | *(ptr + 1) = 80; 101 | } 102 | else 103 | { 104 | *(ptr + 0) = 0; 105 | *(ptr + 1) = 0; 106 | } 107 | } 108 | } 109 | 110 | TextureObject* tobj = playerDepthTexture; 111 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 112 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 113 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 114 | } 115 | nuiTexture->UnlockRect( 0 ); 116 | } 117 | 118 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 119 | { 120 | POINT coordInDepth; 121 | USHORT depth = 0; 122 | for ( int i=0; i20 ) leftHandTrails.erase( leftHandTrails.begin() ); 139 | } 140 | else if ( i==NUI_SKELETON_POSITION_HAND_RIGHT ) 141 | { 142 | rightHandTrails.push_back( vertex ); 143 | if ( rightHandTrails.size()>20 ) rightHandTrails.erase( rightHandTrails.begin() ); 144 | } 145 | } 146 | } 147 | 148 | void update() 149 | { 150 | NUI_IMAGE_FRAME depthFrame; 151 | HRESULT hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 152 | if ( SUCCEEDED(hr) ) 153 | { 154 | updateImageFrame( depthFrame ); 155 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 156 | } 157 | 158 | NUI_SKELETON_FRAME skeletonFrame = {0}; 159 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 160 | if ( SUCCEEDED(hr) ) 161 | { 162 | for ( int n=0; nBindTexture( backgroundTexID ); 199 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 200 | 201 | // Blend with depth quad 202 | glEnable( GL_BLEND ); 203 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 204 | glTranslatef( 0.0f, 0.0f, 0.1f ); 205 | 206 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 207 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 208 | 209 | // Blend with hand trails 210 | glDisable( GL_TEXTURE_2D ); 211 | glLineWidth( 50.0f ); 212 | 213 | VertexData leftHandData = { &(leftHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 214 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, leftHandTrails.size(), leftHandData, GL_LINE_STRIP ); 215 | 216 | VertexData rightHandData = { &(rightHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 217 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, rightHandTrails.size(), rightHandData, GL_LINE_STRIP ); 218 | 219 | glDisable( GL_BLEND ); 220 | glutSwapBuffers(); 221 | } 222 | 223 | void reshape( int w, int h ) 224 | { 225 | glViewport( 0, 0, w, h ); 226 | } 227 | 228 | void keyEvents( unsigned char key, int x, int y ) 229 | { 230 | switch ( key ) 231 | { 232 | case 27: case 'Q': case 'q': 233 | glutLeaveMainLoop(); 234 | return; 235 | } 236 | glutPostRedisplay(); 237 | } 238 | 239 | int main( int argc, char** argv ) 240 | { 241 | glutInit( &argc, argv ); 242 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 243 | glutCreateWindow( "ch4_02_Hand_Linetrails" ); 244 | glutFullScreen(); 245 | 246 | glutIdleFunc( update ); 247 | glutDisplayFunc( render ); 248 | glutReshapeFunc( reshape ); 249 | glutKeyboardFunc( keyEvents ); 250 | 251 | if ( TextureManager::Inst()->LoadTexture("background.bmp", backgroundTexID, GL_BGR_EXT) ) 252 | { 253 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 254 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 255 | } 256 | 257 | for ( int i=0; i<20; ++i ) 258 | { 259 | trailColors[i][0] = 1.0f; 260 | trailColors[i][1] = 1.0f; 261 | trailColors[i][2] = 1.0f; 262 | trailColors[i][3] = (float)(i + 1) / 20.0f; 263 | } 264 | 265 | if ( !initializeKinect() ) return 1; 266 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 267 | 268 | glutMainLoop(); 269 | 270 | destroyTexture( playerDepthTexture ); 271 | destroyKinect(); 272 | return 0; 273 | } 274 | -------------------------------------------------------------------------------- /ch5_01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | const unsigned int backgroundTexID = 1; 15 | 16 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 17 | GLfloat cursors[6]; 18 | GLfloat cursorColors[8]; 19 | 20 | bool initializeKinect() 21 | { 22 | int numKinects = 0; 23 | HRESULT hr = NuiGetSensorCount( &numKinects ); 24 | if ( FAILED(hr) || numKinects<=0 ) 25 | { 26 | std::cout << "No Kinect device found." << std::endl; 27 | return false; 28 | } 29 | 30 | hr = NuiCreateSensorByIndex( 0, &context ); 31 | if ( FAILED(hr) ) 32 | { 33 | std::cout << "Failed to connect to Kinect device." << std::endl; 34 | return false; 35 | } 36 | 37 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 38 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 39 | hr = context->NuiInitialize( nuiFlags ); 40 | if ( FAILED(hr) ) 41 | { 42 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 43 | return false; 44 | } 45 | 46 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 47 | if ( FAILED(hr) ) 48 | { 49 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 50 | return false; 51 | } 52 | 53 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 54 | 0, 2, NULL, &depthStreamHandle ); 55 | if ( FAILED(hr) ) 56 | { 57 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 58 | return false; 59 | } 60 | 61 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 62 | if ( FAILED(hr) ) 63 | { 64 | std::cout << "Unable to start tracking skeleton." << std::endl; 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | bool destroyKinect() 71 | { 72 | if ( context ) 73 | { 74 | context->NuiShutdown(); 75 | return true; 76 | } 77 | return false; 78 | } 79 | 80 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 81 | { 82 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 83 | NUI_LOCKED_RECT lockedRect; 84 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 85 | if ( lockedRect.Pitch!=NULL ) 86 | { 87 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 88 | for ( int i=0; i<480; ++i ) 89 | { 90 | const BYTE* line = buffer + i * lockedRect.Pitch; 91 | const USHORT* bufferWord = (const USHORT*)line; 92 | for ( int j=0; j<640; ++j ) 93 | { 94 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 95 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 96 | { 97 | *(ptr + 0) = 200; 98 | *(ptr + 1) = 40; 99 | } 100 | else 101 | { 102 | *(ptr + 0) = 0; 103 | *(ptr + 1) = 0; 104 | } 105 | } 106 | } 107 | 108 | TextureObject* tobj = playerDepthTexture; 109 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 110 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 111 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 112 | } 113 | nuiTexture->UnlockRect( 0 ); 114 | } 115 | 116 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 117 | { 118 | POINT coordInDepth; 119 | USHORT depth = 0; 120 | GLfloat yMin = 0.0f, zMax = 0.0f; 121 | for ( int i=0; iNuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 156 | if ( SUCCEEDED(hr) ) 157 | { 158 | updateImageFrame( depthFrame ); 159 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 160 | } 161 | 162 | NUI_SKELETON_FRAME skeletonFrame = {0}; 163 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 164 | if ( SUCCEEDED(hr) ) 165 | { 166 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 167 | for ( int n=0; nBindTexture( backgroundTexID ); 204 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 205 | 206 | // Blend with depth quad 207 | glEnable( GL_BLEND ); 208 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 209 | glTranslatef( 0.0f, 0.0f, 0.1f ); 210 | 211 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 212 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 213 | 214 | // Draw cursors 215 | glDisable( GL_TEXTURE_2D ); 216 | glPointSize( 50.0f ); 217 | 218 | VertexData cursorData = { &(cursors[0]), NULL, &(cursorColors[0]), NULL }; 219 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, 2, cursorData, GL_POINTS ); 220 | 221 | glDisable( GL_BLEND ); 222 | glutSwapBuffers(); 223 | } 224 | 225 | void reshape( int w, int h ) 226 | { 227 | glViewport( 0, 0, w, h ); 228 | } 229 | 230 | void keyEvents( unsigned char key, int x, int y ) 231 | { 232 | switch ( key ) 233 | { 234 | case 27: case 'Q': case 'q': 235 | glutLeaveMainLoop(); 236 | return; 237 | } 238 | glutPostRedisplay(); 239 | } 240 | 241 | int main( int argc, char** argv ) 242 | { 243 | glutInit( &argc, argv ); 244 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 245 | glutCreateWindow( "ch5_01_Hand_Cursors" ); 246 | glutFullScreen(); 247 | 248 | glutIdleFunc( update ); 249 | glutDisplayFunc( render ); 250 | glutReshapeFunc( reshape ); 251 | glutKeyboardFunc( keyEvents ); 252 | 253 | if ( TextureManager::Inst()->LoadTexture("background.bmp", backgroundTexID, GL_BGR_EXT) ) 254 | { 255 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 256 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 257 | } 258 | 259 | if ( !initializeKinect() ) return 1; 260 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 261 | 262 | smoothParams.fCorrection = 0.5f; 263 | smoothParams.fJitterRadius = 1.0f; 264 | smoothParams.fMaxDeviationRadius = 0.5f; 265 | smoothParams.fPrediction = 0.4f; 266 | smoothParams.fSmoothing = 0.2f; 267 | for ( int i=0; i<8; ++i ) cursorColors[i] = 1.0f; 268 | 269 | glutMainLoop(); 270 | 271 | destroyTexture( playerDepthTexture ); 272 | destroyKinect(); 273 | return 0; 274 | } 275 | -------------------------------------------------------------------------------- /include/GL/freeglut_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_EXT_H__ 2 | #define __FREEGLUT_EXT_H__ 3 | 4 | /* 5 | * freeglut_ext.h 6 | * 7 | * The non-GLUT-compatible extensions to the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Additional GLUT Key definitions for the Special key function 37 | */ 38 | #define GLUT_KEY_NUM_LOCK 0x006D 39 | #define GLUT_KEY_BEGIN 0x006E 40 | #define GLUT_KEY_DELETE 0x006F 41 | #define GLUT_KEY_SHIFT_L 0x0070 42 | #define GLUT_KEY_SHIFT_R 0x0071 43 | #define GLUT_KEY_CTRL_L 0x0072 44 | #define GLUT_KEY_CTRL_R 0x0073 45 | #define GLUT_KEY_ALT_L 0x0074 46 | #define GLUT_KEY_ALT_R 0x0075 47 | 48 | /* 49 | * GLUT API Extension macro definitions -- behaviour when the user clicks on an "x" to close a window 50 | */ 51 | #define GLUT_ACTION_EXIT 0 52 | #define GLUT_ACTION_GLUTMAINLOOP_RETURNS 1 53 | #define GLUT_ACTION_CONTINUE_EXECUTION 2 54 | 55 | /* 56 | * Create a new rendering context when the user opens a new window? 57 | */ 58 | #define GLUT_CREATE_NEW_CONTEXT 0 59 | #define GLUT_USE_CURRENT_CONTEXT 1 60 | 61 | /* 62 | * Direct/Indirect rendering context options (has meaning only in Unix/X11) 63 | */ 64 | #define GLUT_FORCE_INDIRECT_CONTEXT 0 65 | #define GLUT_ALLOW_DIRECT_CONTEXT 1 66 | #define GLUT_TRY_DIRECT_CONTEXT 2 67 | #define GLUT_FORCE_DIRECT_CONTEXT 3 68 | 69 | /* 70 | * GLUT API Extension macro definitions -- the glutGet parameters 71 | */ 72 | #define GLUT_INIT_STATE 0x007C 73 | 74 | #define GLUT_ACTION_ON_WINDOW_CLOSE 0x01F9 75 | 76 | #define GLUT_WINDOW_BORDER_WIDTH 0x01FA 77 | #define GLUT_WINDOW_HEADER_HEIGHT 0x01FB 78 | 79 | #define GLUT_VERSION 0x01FC 80 | 81 | #define GLUT_RENDERING_CONTEXT 0x01FD 82 | #define GLUT_DIRECT_RENDERING 0x01FE 83 | 84 | #define GLUT_FULL_SCREEN 0x01FF 85 | 86 | /* 87 | * New tokens for glutInitDisplayMode. 88 | * Only one GLUT_AUXn bit may be used at a time. 89 | * Value 0x0400 is defined in OpenGLUT. 90 | */ 91 | #define GLUT_AUX 0x1000 92 | 93 | #define GLUT_AUX1 0x1000 94 | #define GLUT_AUX2 0x2000 95 | #define GLUT_AUX3 0x4000 96 | #define GLUT_AUX4 0x8000 97 | 98 | /* 99 | * Context-related flags, see freeglut_state.c 100 | */ 101 | #define GLUT_INIT_MAJOR_VERSION 0x0200 102 | #define GLUT_INIT_MINOR_VERSION 0x0201 103 | #define GLUT_INIT_FLAGS 0x0202 104 | #define GLUT_INIT_PROFILE 0x0203 105 | 106 | /* 107 | * Flags for glutInitContextFlags, see freeglut_init.c 108 | */ 109 | #define GLUT_DEBUG 0x0001 110 | #define GLUT_FORWARD_COMPATIBLE 0x0002 111 | 112 | 113 | /* 114 | * Flags for glutInitContextProfile, see freeglut_init.c 115 | */ 116 | #define GLUT_CORE_PROFILE 0x0001 117 | #define GLUT_COMPATIBILITY_PROFILE 0x0002 118 | 119 | /* 120 | * Process loop function, see freeglut_main.c 121 | */ 122 | FGAPI void FGAPIENTRY glutMainLoopEvent( void ); 123 | FGAPI void FGAPIENTRY glutLeaveMainLoop( void ); 124 | FGAPI void FGAPIENTRY glutExit ( void ); 125 | 126 | /* 127 | * Window management functions, see freeglut_window.c 128 | */ 129 | FGAPI void FGAPIENTRY glutFullScreenToggle( void ); 130 | FGAPI void FGAPIENTRY glutLeaveFullScreen( void ); 131 | 132 | /* 133 | * Window-specific callback functions, see freeglut_callbacks.c 134 | */ 135 | FGAPI void FGAPIENTRY glutMouseWheelFunc( void (* callback)( int, int, int, int ) ); 136 | FGAPI void FGAPIENTRY glutCloseFunc( void (* callback)( void ) ); 137 | FGAPI void FGAPIENTRY glutWMCloseFunc( void (* callback)( void ) ); 138 | /* A. Donev: Also a destruction callback for menus */ 139 | FGAPI void FGAPIENTRY glutMenuDestroyFunc( void (* callback)( void ) ); 140 | 141 | /* 142 | * State setting and retrieval functions, see freeglut_state.c 143 | */ 144 | FGAPI void FGAPIENTRY glutSetOption ( GLenum option_flag, int value ); 145 | FGAPI int * FGAPIENTRY glutGetModeValues(GLenum mode, int * size); 146 | /* A.Donev: User-data manipulation */ 147 | FGAPI void* FGAPIENTRY glutGetWindowData( void ); 148 | FGAPI void FGAPIENTRY glutSetWindowData(void* data); 149 | FGAPI void* FGAPIENTRY glutGetMenuData( void ); 150 | FGAPI void FGAPIENTRY glutSetMenuData(void* data); 151 | 152 | /* 153 | * Font stuff, see freeglut_font.c 154 | */ 155 | FGAPI int FGAPIENTRY glutBitmapHeight( void* font ); 156 | FGAPI GLfloat FGAPIENTRY glutStrokeHeight( void* font ); 157 | FGAPI void FGAPIENTRY glutBitmapString( void* font, const unsigned char *string ); 158 | FGAPI void FGAPIENTRY glutStrokeString( void* font, const unsigned char *string ); 159 | 160 | /* 161 | * Geometry functions, see freeglut_geometry.c 162 | */ 163 | FGAPI void FGAPIENTRY glutWireRhombicDodecahedron( void ); 164 | FGAPI void FGAPIENTRY glutSolidRhombicDodecahedron( void ); 165 | FGAPI void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale ); 166 | FGAPI void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale ); 167 | FGAPI void FGAPIENTRY glutWireCylinder( GLdouble radius, GLdouble height, GLint slices, GLint stacks); 168 | FGAPI void FGAPIENTRY glutSolidCylinder( GLdouble radius, GLdouble height, GLint slices, GLint stacks); 169 | 170 | /* 171 | * Extension functions, see freeglut_ext.c 172 | */ 173 | typedef void (*GLUTproc)(); 174 | FGAPI GLUTproc FGAPIENTRY glutGetProcAddress( const char *procName ); 175 | 176 | /* 177 | * Multi-touch/multi-pointer extensions 178 | */ 179 | 180 | #define GLUT_HAS_MULTI 1 181 | 182 | FGAPI void FGAPIENTRY glutMultiEntryFunc( void (* callback)( int, int ) ); 183 | FGAPI void FGAPIENTRY glutMultiButtonFunc( void (* callback)( int, int, int, int, int ) ); 184 | FGAPI void FGAPIENTRY glutMultiMotionFunc( void (* callback)( int, int, int ) ); 185 | FGAPI void FGAPIENTRY glutMultiPassiveFunc( void (* callback)( int, int, int ) ); 186 | 187 | /* 188 | * Joystick functions, see freeglut_joystick.c 189 | */ 190 | /* USE OF THESE FUNCTIONS IS DEPRECATED !!!!! */ 191 | /* If you have a serious need for these functions in your application, please either 192 | * contact the "freeglut" developer community at freeglut-developer@lists.sourceforge.net, 193 | * switch to the OpenGLUT library, or else port your joystick functionality over to PLIB's 194 | * "js" library. 195 | */ 196 | int glutJoystickGetNumAxes( int ident ); 197 | int glutJoystickGetNumButtons( int ident ); 198 | int glutJoystickNotWorking( int ident ); 199 | float glutJoystickGetDeadBand( int ident, int axis ); 200 | void glutJoystickSetDeadBand( int ident, int axis, float db ); 201 | float glutJoystickGetSaturation( int ident, int axis ); 202 | void glutJoystickSetSaturation( int ident, int axis, float st ); 203 | void glutJoystickSetMinRange( int ident, float *axes ); 204 | void glutJoystickSetMaxRange( int ident, float *axes ); 205 | void glutJoystickSetCenter( int ident, float *axes ); 206 | void glutJoystickGetMinRange( int ident, float *axes ); 207 | void glutJoystickGetMaxRange( int ident, float *axes ); 208 | void glutJoystickGetCenter( int ident, float *axes ); 209 | 210 | /* 211 | * Initialization functions, see freeglut_init.c 212 | */ 213 | FGAPI void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion ); 214 | FGAPI void FGAPIENTRY glutInitContextFlags( int flags ); 215 | FGAPI void FGAPIENTRY glutInitContextProfile( int profile ); 216 | 217 | /* to get the typedef for va_list */ 218 | #include 219 | 220 | FGAPI void FGAPIENTRY glutInitErrorFunc( void (* vError)( const char *fmt, va_list ap ) ); 221 | FGAPI void FGAPIENTRY glutInitWarningFunc( void (* vWarning)( const char *fmt, va_list ap ) ); 222 | 223 | /* 224 | * GLUT API macro definitions -- the display mode definitions 225 | */ 226 | #define GLUT_CAPTIONLESS 0x0400 227 | #define GLUT_BORDERLESS 0x0800 228 | #define GLUT_SRGB 0x1000 229 | 230 | #ifdef __cplusplus 231 | } 232 | #endif 233 | 234 | /*** END OF FILE ***/ 235 | 236 | #endif /* __FREEGLUT_EXT_H__ */ 237 | -------------------------------------------------------------------------------- /ch4_03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/GLUtilities.h" 8 | 9 | INuiSensor* context = NULL; 10 | HANDLE colorStreamHandle = NULL; 11 | HANDLE depthStreamHandle = NULL; 12 | TextureObject* colorTexture = NULL; 13 | TextureObject* packedDepthTexture = NULL; 14 | 15 | IFTFaceTracker* tracker = NULL; 16 | IFTResult* faceResult = NULL; 17 | FT_SENSOR_DATA sensorData; 18 | RECT faceRect; 19 | bool isFaceTracked = false; 20 | 21 | bool initializeKinect() 22 | { 23 | int numKinects = 0; 24 | HRESULT hr = NuiGetSensorCount( &numKinects ); 25 | if ( FAILED(hr) || numKinects<=0 ) 26 | { 27 | std::cout << "No Kinect device found." << std::endl; 28 | return false; 29 | } 30 | 31 | hr = NuiCreateSensorByIndex( 0, &context ); 32 | if ( FAILED(hr) ) 33 | { 34 | std::cout << "Failed to connect to Kinect device." << std::endl; 35 | return false; 36 | } 37 | 38 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 39 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 40 | hr = context->NuiInitialize( nuiFlags ); 41 | if ( FAILED(hr) ) 42 | { 43 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 44 | return false; 45 | } 46 | 47 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 48 | if ( FAILED(hr) ) 49 | { 50 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 51 | return false; 52 | } 53 | 54 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 55 | 0, 2, NULL, &depthStreamHandle ); 56 | if ( FAILED(hr) ) 57 | { 58 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 59 | return false; 60 | } 61 | 62 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 63 | if ( FAILED(hr) ) 64 | { 65 | std::cout << "Unable to start tracking skeleton." << std::endl; 66 | return false; 67 | } 68 | return true; 69 | } 70 | 71 | bool initializeFaceTracker() 72 | { 73 | tracker = FTCreateFaceTracker(); 74 | if ( !tracker ) 75 | { 76 | std::cout << "Can't create face tracker" << std::endl; 77 | return false; 78 | } 79 | 80 | FT_CAMERA_CONFIG colorConfig = {640, 480, NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS}; 81 | FT_CAMERA_CONFIG depthConfig = {640, 480, NUI_CAMERA_DEPTH_NOMINAL_FOCAL_LENGTH_IN_PIXELS * 2}; 82 | HRESULT hr = tracker->Initialize( &colorConfig, &depthConfig, NULL, NULL ); 83 | if ( FAILED(hr) ) 84 | { 85 | std::cout << "Can't initialize face tracker" << std::endl; 86 | return false; 87 | } 88 | 89 | hr = tracker->CreateFTResult( &faceResult ); 90 | if ( FAILED(hr) ) 91 | { 92 | std::cout << "Can't create face tracker result" << std::endl; 93 | return false; 94 | } 95 | 96 | sensorData.pVideoFrame = FTCreateImage(); 97 | sensorData.pDepthFrame = FTCreateImage(); 98 | if ( !sensorData.pDepthFrame || !sensorData.pDepthFrame ) 99 | { 100 | std::cout << "Can't create color/depth images" << std::endl; 101 | return false; 102 | } 103 | sensorData.pVideoFrame->Attach( 640, 480, (void*)colorTexture->bits, FTIMAGEFORMAT_UINT8_R8G8B8, 640*3 ); 104 | sensorData.pDepthFrame->Attach( 640, 480, (void*)packedDepthTexture->bits, FTIMAGEFORMAT_UINT16_D13P3, 640 ); 105 | sensorData.ZoomFactor = 1.0f; 106 | sensorData.ViewOffset.x = 0; 107 | sensorData.ViewOffset.y = 0; 108 | return true; 109 | } 110 | 111 | bool destroyKinect() 112 | { 113 | if ( context ) 114 | { 115 | context->NuiShutdown(); 116 | return true; 117 | } 118 | return false; 119 | } 120 | 121 | bool destroyFaceTracker() 122 | { 123 | if ( faceResult ) faceResult->Release(); 124 | if ( tracker ) tracker->Release(); 125 | return true; 126 | } 127 | 128 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame, bool isDepthFrame ) 129 | { 130 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 131 | NUI_LOCKED_RECT lockedRect; 132 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 133 | if ( lockedRect.Pitch!=NULL ) 134 | { 135 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 136 | for ( int i=0; i<480; ++i ) 137 | { 138 | const BYTE* line = buffer + i * lockedRect.Pitch; 139 | const USHORT* bufferWord = (const USHORT*)line; 140 | for ( int j=0; j<640; ++j ) 141 | { 142 | if ( !isDepthFrame ) 143 | { 144 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 145 | *(ptr + 0) = line[4 * j + 2]; 146 | *(ptr + 1) = line[4 * j + 1]; 147 | *(ptr + 2) = line[4 * j + 0]; 148 | } 149 | else 150 | { 151 | USHORT* ptr = (USHORT*)packedDepthTexture->bits + (i * 640 + j); 152 | *ptr = bufferWord[j]; 153 | } 154 | } 155 | } 156 | 157 | TextureObject* tobj = (isDepthFrame ? packedDepthTexture : colorTexture); 158 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 159 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 160 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 161 | } 162 | nuiTexture->UnlockRect( 0 ); 163 | } 164 | 165 | void update() 166 | { 167 | NUI_IMAGE_FRAME colorFrame; 168 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 169 | if ( SUCCEEDED(hr) ) 170 | { 171 | updateImageFrame( colorFrame, false ); 172 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 173 | } 174 | 175 | NUI_IMAGE_FRAME depthFrame; 176 | hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 177 | if ( SUCCEEDED(hr) ) 178 | { 179 | updateImageFrame( depthFrame, true ); 180 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 181 | } 182 | 183 | if ( tracker && faceResult ) 184 | { 185 | if ( !isFaceTracked ) 186 | { 187 | hr = tracker->StartTracking( &sensorData, NULL, NULL, faceResult ); 188 | if ( SUCCEEDED(hr) && SUCCEEDED(faceResult->GetStatus()) ) isFaceTracked = true; 189 | } 190 | else 191 | { 192 | hr = tracker->ContinueTracking( &sensorData, NULL, faceResult ); 193 | if ( FAILED(hr) || FAILED(faceResult->GetStatus()) ) isFaceTracked = false; 194 | } 195 | } 196 | glutPostRedisplay(); 197 | } 198 | 199 | void render() 200 | { 201 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 202 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 203 | glEnable( GL_TEXTURE_2D ); 204 | 205 | glMatrixMode( GL_PROJECTION ); 206 | glLoadIdentity(); 207 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 208 | 209 | glMatrixMode( GL_MODELVIEW ); 210 | glLoadIdentity(); 211 | 212 | // Draw color quad 213 | GLfloat vertices[][3] = { 214 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 215 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 216 | }; 217 | GLfloat texcoords[][2] = { 218 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 219 | }; 220 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 221 | 222 | glBindTexture( GL_TEXTURE_2D, colorTexture->id ); 223 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 224 | 225 | // Draw face tracking plane 226 | if ( isFaceTracked ) 227 | faceResult->GetFaceRect( &faceRect ); 228 | 229 | float l = (float)faceRect.left / 640.0f; 230 | float r = (float)faceRect.right / 640.0f; 231 | float b = 1.0f - (float)faceRect.bottom / 480.0f; 232 | float t = 1.0f - (float)faceRect.top / 480.0f; 233 | GLfloat faceVertices[][3] = { 234 | { l, b, 0.1f }, { r, b, 0.1f }, { r, t, 0.1f }, { l, t, 0.1f } 235 | }; 236 | VertexData faceData = { &(faceVertices[0][0]), NULL, NULL, NULL }; 237 | 238 | glDisable( GL_TEXTURE_2D ); 239 | glLineWidth( 5.0f ); 240 | drawSimpleMesh( WITH_POSITION, 4, faceData, GL_LINE_LOOP ); 241 | 242 | glutSwapBuffers(); 243 | } 244 | 245 | void reshape( int w, int h ) 246 | { 247 | glViewport( 0, 0, w, h ); 248 | } 249 | 250 | void keyEvents( unsigned char key, int x, int y ) 251 | { 252 | switch ( key ) 253 | { 254 | case 27: case 'Q': case 'q': 255 | glutLeaveMainLoop(); 256 | return; 257 | } 258 | glutPostRedisplay(); 259 | } 260 | 261 | int main( int argc, char** argv ) 262 | { 263 | glutInit( &argc, argv ); 264 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 265 | glutCreateWindow( "ch4_03_Face_Tracking" ); 266 | glutFullScreen(); 267 | 268 | glutIdleFunc( update ); 269 | glutDisplayFunc( render ); 270 | glutReshapeFunc( reshape ); 271 | glutKeyboardFunc( keyEvents ); 272 | 273 | if ( !initializeKinect() ) return 1; 274 | colorTexture = createTexture(640, 480, GL_RGB, 3); 275 | packedDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 276 | if ( !initializeFaceTracker() ) return 1; 277 | 278 | glutMainLoop(); 279 | 280 | destroyFaceTracker(); 281 | destroyTexture( colorTexture ); 282 | destroyTexture( packedDepthTexture ); 283 | destroyKinect(); 284 | return 0; 285 | } 286 | -------------------------------------------------------------------------------- /common/GLUtilities.cpp: -------------------------------------------------------------------------------- 1 | #include "GLUtilities.h" 2 | 3 | #ifndef GL_ARB_vertex_shader 4 | #define GL_VERTEX_SHADER_ARB 0x8B31 5 | #endif 6 | 7 | #ifndef GL_ARB_fragment_shader 8 | #define GL_FRAGMENT_SHADER_ARB 0x8B30 9 | #endif 10 | 11 | #ifndef GL_VERSION_2_0 12 | #define GL_COMPILE_STATUS 0x8B81 13 | #define GL_LINK_STATUS 0x8B82 14 | #endif 15 | 16 | typedef GLuint (APIENTRY *CreateProgramProc)(); 17 | typedef void (APIENTRY *LinkProgramProc)( GLuint program ); 18 | typedef void (APIENTRY *UseProgramProc)( GLuint program ); 19 | typedef void (APIENTRY *GetProgramivProc)( GLuint program, GLenum pname, GLint* params ); 20 | typedef GLuint (APIENTRY *CreateShaderProc)( GLenum type ); 21 | typedef void (APIENTRY *ShaderSourceProc)( GLuint shader, GLsizei count, const char** string, const GLint* length ); 22 | typedef void (APIENTRY *CompileShaderProc)( GLuint shader ); 23 | typedef void (APIENTRY *GetShaderivProc)( GLuint shader, GLenum pname, GLint* params ); 24 | typedef GLint (APIENTRY *GetUniformLocationProc)( GLuint program, const char* name ); 25 | typedef void (APIENTRY *Uniform1iProc)( GLint location, GLint v0 ); 26 | typedef void (APIENTRY *AttachShaderProc)( GLuint program, GLuint shader ); 27 | 28 | CreateProgramProc glCreateProgram; 29 | LinkProgramProc glLinkProgram; 30 | UseProgramProc glUseProgram; 31 | GetProgramivProc glGetProgram; 32 | CreateShaderProc glCreateShader; 33 | ShaderSourceProc glShaderSource; 34 | CompileShaderProc glCompileShader; 35 | GetShaderivProc glGetShader; 36 | GetUniformLocationProc glGetUniformLocation; 37 | Uniform1iProc glUniform1i; 38 | AttachShaderProc glAttachObject; 39 | 40 | bool g_programInitialized = false; 41 | static void initializeProgram() 42 | { 43 | glCreateProgram = (CreateProgramProc)wglGetProcAddress("glCreateProgramObjectARB"); 44 | glLinkProgram = (LinkProgramProc)wglGetProcAddress("glLinkProgramARB"); 45 | glUseProgram = (UseProgramProc)wglGetProcAddress("glUseProgramObjectARB"); 46 | glGetProgram = (GetProgramivProc)wglGetProcAddress("glGetProgramiv"); 47 | glCreateShader = (CreateShaderProc)wglGetProcAddress("glCreateShaderObjectARB"); 48 | glShaderSource = (ShaderSourceProc)wglGetProcAddress("glShaderSourceARB"); 49 | glCompileShader = (CompileShaderProc)wglGetProcAddress("glCompileShaderARB"); 50 | glGetShader = (GetShaderivProc)wglGetProcAddress("glGetShaderiv"); 51 | glGetUniformLocation = (GetUniformLocationProc)wglGetProcAddress("glGetUniformLocationARB"); 52 | glUniform1i = (Uniform1iProc)wglGetProcAddress("glUniform1iARB"); 53 | glAttachObject = (AttachShaderProc)wglGetProcAddress("glAttachObjectARB"); 54 | g_programInitialized = true; 55 | } 56 | 57 | void drawSimpleMesh( int formats, unsigned int numVertices, VertexData data, 58 | GLenum drawMode, GLuint start, GLuint count ) 59 | { 60 | if ( formats&WITH_NORMAL ) 61 | { 62 | glEnableClientState( GL_NORMAL_ARRAY ); 63 | glNormalPointer( GL_FLOAT, 0, data.normals ); 64 | } 65 | if ( formats&WITH_COLOR ) 66 | { 67 | glEnableClientState( GL_COLOR_ARRAY ); 68 | glColorPointer( 4, GL_FLOAT, 0, data.colors ); 69 | } 70 | if ( formats&WITH_TEXCOORD ) 71 | { 72 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 73 | glTexCoordPointer( 2, GL_FLOAT, 0, data.texcoords ); 74 | } 75 | if ( formats&WITH_POSITION ) 76 | { 77 | glEnableClientState( GL_VERTEX_ARRAY ); 78 | glVertexPointer( 3, GL_FLOAT, 0, data.vertices ); 79 | } 80 | 81 | glDrawArrays( drawMode, start, count>0 ? count : numVertices ); 82 | 83 | if ( formats&WITH_NORMAL ) glDisableClientState( GL_NORMAL_ARRAY ); 84 | if ( formats&WITH_COLOR ) glDisableClientState( GL_COLOR_ARRAY ); 85 | if ( formats&WITH_TEXCOORD ) glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 86 | if ( formats&WITH_POSITION ) glDisableClientState( GL_VERTEX_ARRAY ); 87 | } 88 | 89 | void drawIndexedMesh( int formats, unsigned int numVertices, VertexData data, 90 | GLenum drawMode, unsigned int numIndices, GLuint* indices ) 91 | { 92 | if ( formats&WITH_POSITION ) 93 | { 94 | glEnableClientState( GL_VERTEX_ARRAY ); 95 | glVertexPointer( 3, GL_FLOAT, 0, data.vertices ); 96 | } 97 | if ( formats&WITH_NORMAL ) 98 | { 99 | glEnableClientState( GL_NORMAL_ARRAY ); 100 | glVertexPointer( 3, GL_FLOAT, 0, data.normals ); 101 | } 102 | if ( formats&WITH_COLOR ) 103 | { 104 | glEnableClientState( GL_COLOR_ARRAY ); 105 | glVertexPointer( 4, GL_FLOAT, 0, data.colors ); 106 | } 107 | if ( formats&WITH_TEXCOORD ) 108 | { 109 | glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 110 | glTexCoordPointer( 2, GL_FLOAT, 0, data.texcoords ); 111 | } 112 | 113 | glDrawElements( drawMode, numIndices, GL_UNSIGNED_INT, indices ); 114 | 115 | if ( formats&WITH_POSITION ) glDisableClientState( GL_VERTEX_ARRAY ); 116 | if ( formats&WITH_NORMAL ) glDisableClientState( GL_NORMAL_ARRAY ); 117 | if ( formats&WITH_COLOR ) glDisableClientState( GL_COLOR_ARRAY ); 118 | if ( formats&WITH_TEXCOORD ) glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 119 | } 120 | 121 | TextureObject* createTexture( unsigned int w, unsigned int h, GLenum image_format, 122 | GLint internal_format, GLenum data_type ) 123 | { 124 | TextureObject* tobj = new TextureObject; 125 | tobj->width = w; 126 | tobj->height = h; 127 | tobj->imageFormat = image_format; 128 | tobj->internalFormat = internal_format; 129 | 130 | unsigned int numComponents = 1; 131 | switch ( image_format ) 132 | { 133 | case GL_LUMINANCE_ALPHA: numComponents = 2; break; 134 | case GL_RGB: case GL_BGR_EXT: numComponents = 3; break; 135 | case GL_RGBA: case GL_BGRA_EXT: numComponents = 4; break; 136 | default: break; 137 | } 138 | tobj->bits = new unsigned char[w * h * numComponents]; 139 | 140 | glGenTextures( 1, &(tobj->id) ); 141 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 142 | glTexImage2D( GL_TEXTURE_2D, 0, internal_format, w, h, 0, image_format, data_type, tobj->bits ); 143 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 144 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 145 | return tobj; 146 | } 147 | 148 | void destroyTexture( TextureObject* tobj ) 149 | { 150 | if ( tobj ) 151 | { 152 | glDeleteTextures( 1, &(tobj->id) ); 153 | delete tobj->bits; 154 | delete tobj; 155 | } 156 | } 157 | 158 | GLuint createProgram( ProgramType type ) 159 | { 160 | if ( !g_programInitialized ) initializeProgram(); 161 | GLuint programID = glCreateProgram(); 162 | GLuint vertexShaderID = glCreateShader( GL_VERTEX_SHADER_ARB ); 163 | GLuint fragmentShaderID = glCreateShader( GL_FRAGMENT_SHADER_ARB ); 164 | 165 | GLint canCompile = 0; 166 | switch ( type ) 167 | { 168 | case BLUR_PROGRAM: 169 | { 170 | static const char* vertexCode = { 171 | "void main() {\n" 172 | " gl_Position = ftransform();\n" 173 | " gl_TexCoord[0] = gl_MultiTexCoord0;\n" 174 | "}\n" 175 | }; 176 | glShaderSource( vertexShaderID, 1, &vertexCode, NULL ); 177 | glCompileShader( vertexShaderID ); 178 | glGetShader( vertexShaderID, GL_COMPILE_STATUS, &canCompile ); 179 | if ( canCompile==GL_FALSE ) return 0; 180 | 181 | static const char* fragmentCode = { 182 | "uniform sampler2D defaultTex;\n" 183 | "void main() {\n" 184 | " vec2 uv = gl_TexCoord[0].st;\n" 185 | " vec2 off0 = vec2(1.0/gl_FragCoord.x, 0.0);\n" 186 | " vec2 off1 = vec2(0.0, 1.0/gl_FragCoord.y);\n" 187 | " vec2 off2 = vec2(1.0/gl_FragCoord.x, 1.0/gl_FragCoord.y);\n" 188 | " vec2 off3 = vec2(1.0/gl_FragCoord.x,-1.0/gl_FragCoord.y);\n" 189 | 190 | " vec4 c11 = texture2D(defaultTex, uv);\n" 191 | " vec4 c01 = texture2D(defaultTex, uv - off0);\n" 192 | " vec4 c21 = texture2D(defaultTex, uv + off0);\n" 193 | " vec4 c10 = texture2D(defaultTex, uv - off1);\n" 194 | " vec4 c12 = texture2D(defaultTex, uv + off1);\n" 195 | " vec4 c00 = texture2D(defaultTex, uv - off2);\n" 196 | " vec4 c22 = texture2D(defaultTex, uv + off2);\n" 197 | " vec4 c20 = texture2D(defaultTex, uv - off3);\n" 198 | " vec4 c02 = texture2D(defaultTex, uv + off3);\n" 199 | 200 | " vec4 target = 4.0 * c11 + 2.0 * (c01 + c21 + c10 + c12)\n" 201 | " + (c00 + c02 + c20 + c22);\n" 202 | " gl_FragColor = target / 16.0;\n" 203 | "}\n" 204 | }; 205 | glShaderSource( fragmentShaderID, 1, &fragmentCode, NULL ); 206 | glCompileShader( fragmentShaderID ); 207 | glGetShader( fragmentShaderID, GL_COMPILE_STATUS, &canCompile ); 208 | if ( canCompile==GL_FALSE ) return 0; 209 | } 210 | break; 211 | default: break; 212 | } 213 | 214 | glAttachObject( programID, vertexShaderID ); 215 | glAttachObject( programID, fragmentShaderID ); 216 | glLinkProgram( programID ); 217 | 218 | glGetProgram( programID, GL_LINK_STATUS, &canCompile ); 219 | if ( canCompile==GL_FALSE ) return 0; 220 | return programID; 221 | } 222 | 223 | void useProgram( GLuint id ) 224 | { 225 | if ( !g_programInitialized ) initializeProgram(); 226 | glUseProgram( id ); 227 | 228 | if ( id!=0 ) 229 | { 230 | GLint loc = glGetUniformLocation( id, "defaultTex" ); 231 | glUniform1i( loc, 0 ); 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /ch5_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | const unsigned int backgroundTexID = 1; 15 | 16 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 17 | GLfloat cursors[6]; 18 | GLfloat lastCursors[6]; 19 | GLfloat cursorColors[8]; 20 | unsigned int holdGestureCount[2] = {0}; 21 | unsigned int swipeGestureCount[2] = {0}; 22 | 23 | bool initializeKinect() 24 | { 25 | int numKinects = 0; 26 | HRESULT hr = NuiGetSensorCount( &numKinects ); 27 | if ( FAILED(hr) || numKinects<=0 ) 28 | { 29 | std::cout << "No Kinect device found." << std::endl; 30 | return false; 31 | } 32 | 33 | hr = NuiCreateSensorByIndex( 0, &context ); 34 | if ( FAILED(hr) ) 35 | { 36 | std::cout << "Failed to connect to Kinect device." << std::endl; 37 | return false; 38 | } 39 | 40 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 41 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 42 | hr = context->NuiInitialize( nuiFlags ); 43 | if ( FAILED(hr) ) 44 | { 45 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 46 | return false; 47 | } 48 | 49 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 50 | if ( FAILED(hr) ) 51 | { 52 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 53 | return false; 54 | } 55 | 56 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 57 | 0, 2, NULL, &depthStreamHandle ); 58 | if ( FAILED(hr) ) 59 | { 60 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 61 | return false; 62 | } 63 | 64 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 65 | if ( FAILED(hr) ) 66 | { 67 | std::cout << "Unable to start tracking skeleton." << std::endl; 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | bool destroyKinect() 74 | { 75 | if ( context ) 76 | { 77 | context->NuiShutdown(); 78 | return true; 79 | } 80 | return false; 81 | } 82 | 83 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 84 | { 85 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 86 | NUI_LOCKED_RECT lockedRect; 87 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 88 | if ( lockedRect.Pitch!=NULL ) 89 | { 90 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 91 | for ( int i=0; i<480; ++i ) 92 | { 93 | const BYTE* line = buffer + i * lockedRect.Pitch; 94 | const USHORT* bufferWord = (const USHORT*)line; 95 | for ( int j=0; j<640; ++j ) 96 | { 97 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 98 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 99 | { 100 | *(ptr + 0) = 200; 101 | *(ptr + 1) = 40; 102 | } 103 | else 104 | { 105 | *(ptr + 0) = 0; 106 | *(ptr + 1) = 0; 107 | } 108 | } 109 | } 110 | 111 | TextureObject* tobj = playerDepthTexture; 112 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 113 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 114 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 115 | } 116 | nuiTexture->UnlockRect( 0 ); 117 | } 118 | 119 | void guessGesture( unsigned int index, bool inRange ) 120 | { 121 | if ( !inRange ) 122 | { 123 | holdGestureCount[index] = 0; 124 | swipeGestureCount[index] = 0; 125 | cursorColors[3 + index*4] = 0.2f; 126 | } 127 | else 128 | { 129 | float distance = sqrt(powf(cursors[index*3]-lastCursors[index*3], 2.0f) 130 | + powf(cursors[1+index*3]-lastCursors[1+index*3], 2.0f)); 131 | if ( distance<0.02 ) 132 | { 133 | holdGestureCount[index]++; 134 | swipeGestureCount[index] = 0; 135 | } 136 | else if ( distance>0.05 ) 137 | { 138 | holdGestureCount[index] = 0; 139 | swipeGestureCount[index]++; 140 | } 141 | else 142 | { 143 | holdGestureCount[index] = 0; 144 | swipeGestureCount[index] = 0; 145 | } 146 | cursorColors[3 + index*4] = 1.0f; 147 | } 148 | } 149 | 150 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 151 | { 152 | POINT coordInDepth; 153 | USHORT depth = 0; 154 | GLfloat yMin = 0.0f, zMax = 0.0f; 155 | for ( int i=0; i> NUI_IMAGE_PLAYER_INDEX_SHIFT) * 0.00025f; 165 | } 166 | else if ( i==NUI_SKELETON_POSITION_HAND_LEFT ) 167 | { 168 | cursors[0] = (GLfloat)coordInDepth.x / 640.0f; 169 | cursors[1] = 1.0f - (GLfloat)coordInDepth.y / 480.0f; 170 | cursors[2] = (GLfloat)NuiDepthPixelToDepth(depth) * 0.00025f; 171 | } 172 | else if ( i==NUI_SKELETON_POSITION_HAND_RIGHT ) 173 | { 174 | cursors[3] = (GLfloat)coordInDepth.x / 640.0f; 175 | cursors[4] = 1.0f - (GLfloat)coordInDepth.y / 480.0f; 176 | cursors[5] = (GLfloat)NuiDepthPixelToDepth(depth) * 0.00025f; 177 | } 178 | } 179 | 180 | guessGesture( 0, (yMinNuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 189 | if ( SUCCEEDED(hr) ) 190 | { 191 | updateImageFrame( depthFrame ); 192 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 193 | } 194 | 195 | NUI_SKELETON_FRAME skeletonFrame = {0}; 196 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 197 | if ( SUCCEEDED(hr) ) 198 | { 199 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 200 | for ( int n=0; nBindTexture( backgroundTexID ); 237 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 238 | 239 | // Blend with depth quad 240 | glEnable( GL_BLEND ); 241 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 242 | glTranslatef( 0.0f, 0.0f, 0.1f ); 243 | 244 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 245 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 246 | 247 | // Draw cursors 248 | glDisable( GL_TEXTURE_2D ); 249 | glPointSize( 50.0f ); 250 | 251 | VertexData cursorData = { &(cursors[0]), NULL, &(cursorColors[0]), NULL }; 252 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, 2, cursorData, GL_POINTS ); 253 | glDisable( GL_BLEND ); 254 | 255 | // Write out current gestures 256 | std::string text = "Gestures (L/R): "; 257 | for ( int i=0; i<2; ++i ) 258 | { 259 | if ( holdGestureCount[i]>30 ) text += "Hold;"; 260 | else if ( swipeGestureCount[i]>1 ) text += "Swipe;"; 261 | else text += "None;"; 262 | } 263 | glRasterPos2f( 0.01f, 0.01f ); 264 | glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); 265 | glutBitmapString( GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)text.c_str() ); 266 | 267 | glutSwapBuffers(); 268 | } 269 | 270 | void reshape( int w, int h ) 271 | { 272 | glViewport( 0, 0, w, h ); 273 | } 274 | 275 | void keyEvents( unsigned char key, int x, int y ) 276 | { 277 | switch ( key ) 278 | { 279 | case 27: case 'Q': case 'q': 280 | glutLeaveMainLoop(); 281 | return; 282 | } 283 | glutPostRedisplay(); 284 | } 285 | 286 | int main( int argc, char** argv ) 287 | { 288 | glutInit( &argc, argv ); 289 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 290 | glutCreateWindow( "ch5_02_Swiping_And_Holding" ); 291 | glutFullScreen(); 292 | 293 | glutIdleFunc( update ); 294 | glutDisplayFunc( render ); 295 | glutReshapeFunc( reshape ); 296 | glutKeyboardFunc( keyEvents ); 297 | 298 | if ( TextureManager::Inst()->LoadTexture("background.bmp", backgroundTexID, GL_BGR_EXT) ) 299 | { 300 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 301 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 302 | } 303 | 304 | if ( !initializeKinect() ) return 1; 305 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 306 | 307 | smoothParams.fCorrection = 0.5f; 308 | smoothParams.fJitterRadius = 1.0f; 309 | smoothParams.fMaxDeviationRadius = 0.5f; 310 | smoothParams.fPrediction = 0.4f; 311 | smoothParams.fSmoothing = 0.2f; 312 | for ( int i=0; i<8; ++i ) cursorColors[i] = 1.0f; 313 | 314 | glutMainLoop(); 315 | 316 | destroyTexture( playerDepthTexture ); 317 | destroyKinect(); 318 | return 0; 319 | } 320 | -------------------------------------------------------------------------------- /ch6_01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | 15 | struct Vertex { GLfloat x, y, z; }; 16 | std::vector leftHandTrails; 17 | std::vector rightHandTrails; 18 | GLfloat trailColors[20][4]; 19 | 20 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 21 | unsigned int holdGestureCount[2] = {0}; 22 | const unsigned int backgroundTexID = 1; 23 | 24 | bool initializeKinect() 25 | { 26 | int numKinects = 0; 27 | HRESULT hr = NuiGetSensorCount( &numKinects ); 28 | if ( FAILED(hr) || numKinects<=0 ) 29 | { 30 | std::cout << "No Kinect device found." << std::endl; 31 | return false; 32 | } 33 | 34 | hr = NuiCreateSensorByIndex( 0, &context ); 35 | if ( FAILED(hr) ) 36 | { 37 | std::cout << "Failed to connect to Kinect device." << std::endl; 38 | return false; 39 | } 40 | 41 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 42 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 43 | hr = context->NuiInitialize( nuiFlags ); 44 | if ( FAILED(hr) ) 45 | { 46 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 47 | return false; 48 | } 49 | 50 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 51 | if ( FAILED(hr) ) 52 | { 53 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 54 | return false; 55 | } 56 | 57 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 58 | 0, 2, NULL, &depthStreamHandle ); 59 | if ( FAILED(hr) ) 60 | { 61 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 62 | return false; 63 | } 64 | 65 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 66 | if ( FAILED(hr) ) 67 | { 68 | std::cout << "Unable to start tracking skeleton." << std::endl; 69 | return false; 70 | } 71 | return true; 72 | } 73 | 74 | bool destroyKinect() 75 | { 76 | if ( context ) 77 | { 78 | context->NuiShutdown(); 79 | return true; 80 | } 81 | return false; 82 | } 83 | 84 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 85 | { 86 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 87 | NUI_LOCKED_RECT lockedRect; 88 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 89 | if ( lockedRect.Pitch!=NULL ) 90 | { 91 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 92 | for ( int i=0; i<480; ++i ) 93 | { 94 | const BYTE* line = buffer + i * lockedRect.Pitch; 95 | const USHORT* bufferWord = (const USHORT*)line; 96 | for ( int j=0; j<640; ++j ) 97 | { 98 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 99 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 100 | { 101 | *(ptr + 0) = 200; 102 | *(ptr + 1) = 80; 103 | } 104 | else 105 | { 106 | *(ptr + 0) = 0; 107 | *(ptr + 1) = 0; 108 | } 109 | } 110 | } 111 | 112 | TextureObject* tobj = playerDepthTexture; 113 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 114 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 115 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 116 | } 117 | nuiTexture->UnlockRect( 0 ); 118 | } 119 | 120 | void guessGesture( unsigned int index, bool inRange ) 121 | { 122 | if ( !inRange ) 123 | { 124 | holdGestureCount[index] = 0; 125 | } 126 | else 127 | { 128 | float distance = 0.0f, currentX = 0.0f, currentY = 0.0f; 129 | if ( index==0 ) // left hand 130 | { 131 | currentX = leftHandTrails.back().x; 132 | currentY = leftHandTrails.back().y; 133 | distance = sqrt(powf(currentX-leftHandTrails.front().x, 2.0f) 134 | + powf(currentY-leftHandTrails.front().y, 2.0f)); 135 | } 136 | else // right hand 137 | { 138 | currentX = rightHandTrails.back().x; 139 | currentY = rightHandTrails.back().y; 140 | distance = sqrt(powf(currentX-rightHandTrails.front().x, 2.0f) 141 | + powf(currentY-rightHandTrails.front().y, 2.0f)); 142 | } 143 | 144 | if ( distance<0.02 ) 145 | holdGestureCount[index]++; 146 | else 147 | holdGestureCount[index] = 0; 148 | 149 | if ( holdGestureCount[index]>30 ) 150 | { 151 | if ( currentY>0.9f && currentX<0.1f ) // Restart 152 | {} 153 | else if ( currentY>0.9f && currentX>0.9f ) // Exit 154 | glutLeaveMainLoop(); 155 | } 156 | } 157 | } 158 | 159 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 160 | { 161 | POINT coordInDepth; 162 | USHORT depth = 0; 163 | GLfloat yMin = 0.0f, zMax = 0.0f; 164 | for ( int i=0; i20 ) leftHandTrails.erase( leftHandTrails.begin() ); 184 | } 185 | else if ( i==NUI_SKELETON_POSITION_HAND_RIGHT ) 186 | { 187 | rightHandTrails.push_back( vertex ); 188 | if ( rightHandTrails.size()>20 ) rightHandTrails.erase( rightHandTrails.begin() ); 189 | } 190 | } 191 | 192 | guessGesture( 0, (yMinNuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 200 | if ( SUCCEEDED(hr) ) 201 | { 202 | updateImageFrame( depthFrame ); 203 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 204 | } 205 | 206 | NUI_SKELETON_FRAME skeletonFrame = {0}; 207 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 208 | if ( SUCCEEDED(hr) ) 209 | { 210 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 211 | for ( int n=0; nBindTexture( backgroundTexID ); 248 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 249 | 250 | // Blend with depth quad 251 | glEnable( GL_BLEND ); 252 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 253 | glTranslatef( 0.0f, 0.0f, 0.1f ); 254 | 255 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 256 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 257 | 258 | // Blend with hand trails 259 | glDisable( GL_TEXTURE_2D ); 260 | glLineWidth( 50.0f ); 261 | 262 | VertexData leftHandData = { &(leftHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 263 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, leftHandTrails.size(), leftHandData, GL_LINE_STRIP ); 264 | 265 | VertexData rightHandData = { &(rightHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 266 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, rightHandTrails.size(), rightHandData, GL_LINE_STRIP ); 267 | 268 | glDisable( GL_BLEND ); 269 | glutSwapBuffers(); 270 | } 271 | 272 | void reshape( int w, int h ) 273 | { 274 | glViewport( 0, 0, w, h ); 275 | } 276 | 277 | void keyEvents( unsigned char key, int x, int y ) 278 | { 279 | switch ( key ) 280 | { 281 | case 27: case 'Q': case 'q': 282 | glutLeaveMainLoop(); 283 | return; 284 | } 285 | glutPostRedisplay(); 286 | } 287 | 288 | int main( int argc, char** argv ) 289 | { 290 | glutInit( &argc, argv ); 291 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 292 | glutCreateWindow( "ch6_01_Integrating_Everything" ); 293 | glutFullScreen(); 294 | 295 | glutIdleFunc( update ); 296 | glutDisplayFunc( render ); 297 | glutReshapeFunc( reshape ); 298 | glutKeyboardFunc( keyEvents ); 299 | 300 | if ( TextureManager::Inst()->LoadTexture("FruitNinja1.jpg", backgroundTexID, GL_BGR_EXT) ) 301 | { 302 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 303 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 304 | } 305 | 306 | for ( int i=0; i<20; ++i ) 307 | { 308 | trailColors[i][0] = 1.0f; 309 | trailColors[i][1] = 1.0f; 310 | trailColors[i][2] = 1.0f; 311 | trailColors[i][3] = (float)(i + 1) / 20.0f; 312 | } 313 | 314 | if ( !initializeKinect() ) return 1; 315 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 316 | 317 | smoothParams.fCorrection = 0.5f; 318 | smoothParams.fJitterRadius = 1.0f; 319 | smoothParams.fMaxDeviationRadius = 0.5f; 320 | smoothParams.fPrediction = 0.4f; 321 | smoothParams.fSmoothing = 0.2f; 322 | 323 | glutMainLoop(); 324 | 325 | destroyTexture( playerDepthTexture ); 326 | destroyKinect(); 327 | return 0; 328 | } 329 | -------------------------------------------------------------------------------- /ch4_04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* colorTexture = NULL; 14 | TextureObject* packedDepthTexture = NULL; 15 | 16 | IFTFaceTracker* tracker = NULL; 17 | IFTResult* faceResult = NULL; 18 | FT_SENSOR_DATA sensorData; 19 | std::vector faceVertices(1); 20 | std::vector faceTriangles(1); 21 | bool isFaceTracked = false; 22 | 23 | bool initializeKinect() 24 | { 25 | int numKinects = 0; 26 | HRESULT hr = NuiGetSensorCount( &numKinects ); 27 | if ( FAILED(hr) || numKinects<=0 ) 28 | { 29 | std::cout << "No Kinect device found." << std::endl; 30 | return false; 31 | } 32 | 33 | hr = NuiCreateSensorByIndex( 0, &context ); 34 | if ( FAILED(hr) ) 35 | { 36 | std::cout << "Failed to connect to Kinect device." << std::endl; 37 | return false; 38 | } 39 | 40 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 41 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 42 | hr = context->NuiInitialize( nuiFlags ); 43 | if ( FAILED(hr) ) 44 | { 45 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 46 | return false; 47 | } 48 | 49 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 50 | if ( FAILED(hr) ) 51 | { 52 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 53 | return false; 54 | } 55 | 56 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 57 | 0, 2, NULL, &depthStreamHandle ); 58 | if ( FAILED(hr) ) 59 | { 60 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 61 | return false; 62 | } 63 | 64 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 65 | if ( FAILED(hr) ) 66 | { 67 | std::cout << "Unable to start tracking skeleton." << std::endl; 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | bool initializeFaceTracker() 74 | { 75 | tracker = FTCreateFaceTracker(); 76 | if ( !tracker ) 77 | { 78 | std::cout << "Can't create face tracker" << std::endl; 79 | return false; 80 | } 81 | 82 | FT_CAMERA_CONFIG colorConfig = {640, 480, NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS}; 83 | FT_CAMERA_CONFIG depthConfig = {640, 480, NUI_CAMERA_DEPTH_NOMINAL_FOCAL_LENGTH_IN_PIXELS * 2}; 84 | HRESULT hr = tracker->Initialize( &colorConfig, &depthConfig, NULL, NULL ); 85 | if ( FAILED(hr) ) 86 | { 87 | std::cout << "Can't initialize face tracker" << std::endl; 88 | return false; 89 | } 90 | 91 | hr = tracker->CreateFTResult( &faceResult ); 92 | if ( FAILED(hr) ) 93 | { 94 | std::cout << "Can't create face tracker result" << std::endl; 95 | return false; 96 | } 97 | 98 | sensorData.pVideoFrame = FTCreateImage(); 99 | sensorData.pDepthFrame = FTCreateImage(); 100 | if ( !sensorData.pDepthFrame || !sensorData.pDepthFrame ) 101 | { 102 | std::cout << "Can't create color/depth images" << std::endl; 103 | return false; 104 | } 105 | sensorData.pVideoFrame->Attach( 640, 480, (void*)colorTexture->bits, FTIMAGEFORMAT_UINT8_R8G8B8, 640*3 ); 106 | sensorData.pDepthFrame->Attach( 640, 480, (void*)packedDepthTexture->bits, FTIMAGEFORMAT_UINT16_D13P3, 640 ); 107 | sensorData.ZoomFactor = 1.0f; 108 | sensorData.ViewOffset.x = 0; 109 | sensorData.ViewOffset.y = 0; 110 | return true; 111 | } 112 | 113 | bool destroyKinect() 114 | { 115 | if ( context ) 116 | { 117 | context->NuiShutdown(); 118 | return true; 119 | } 120 | return false; 121 | } 122 | 123 | bool destroyFaceTracker() 124 | { 125 | if ( faceResult ) faceResult->Release(); 126 | if ( tracker ) tracker->Release(); 127 | return true; 128 | } 129 | 130 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame, bool isDepthFrame ) 131 | { 132 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 133 | NUI_LOCKED_RECT lockedRect; 134 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 135 | if ( lockedRect.Pitch!=NULL ) 136 | { 137 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 138 | for ( int i=0; i<480; ++i ) 139 | { 140 | const BYTE* line = buffer + i * lockedRect.Pitch; 141 | const USHORT* bufferWord = (const USHORT*)line; 142 | for ( int j=0; j<640; ++j ) 143 | { 144 | if ( !isDepthFrame ) 145 | { 146 | unsigned char* ptr = colorTexture->bits + 3 * (i * 640 + j); 147 | *(ptr + 0) = line[4 * j + 2]; 148 | *(ptr + 1) = line[4 * j + 1]; 149 | *(ptr + 2) = line[4 * j + 0]; 150 | } 151 | else 152 | { 153 | USHORT* ptr = (USHORT*)packedDepthTexture->bits + (i * 640 + j); 154 | *ptr = bufferWord[j]; 155 | } 156 | } 157 | } 158 | 159 | TextureObject* tobj = (isDepthFrame ? packedDepthTexture : colorTexture); 160 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 161 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 162 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 163 | } 164 | nuiTexture->UnlockRect( 0 ); 165 | } 166 | 167 | void obtainFaceModelData() 168 | { 169 | IFTModel* model = NULL; 170 | HRESULT hr = tracker->GetFaceModel( &model ); 171 | if ( FAILED(hr) ) return; 172 | 173 | // Obtain AUs and SUs 174 | FLOAT* auList = NULL; 175 | UINT numAU = 0; 176 | if ( FAILED(faceResult->GetAUCoefficients(&auList, &numAU)) ) 177 | { 178 | model->Release(); 179 | return; 180 | } 181 | 182 | FLOAT* suList = NULL; 183 | UINT numSU = 0; 184 | BOOL haveConverged = FALSE; 185 | if ( FAILED(tracker->GetShapeUnits(NULL, &suList, &numSU, &haveConverged)) ) 186 | { 187 | model->Release(); 188 | return; 189 | } 190 | 191 | // Obtain face model position, rotation and scale 192 | FLOAT scale, rotation[3], pos[3]; 193 | if ( FAILED(hr = faceResult->Get3DPose(&scale, rotation, pos)) ) 194 | { 195 | model->Release(); 196 | return; 197 | } 198 | 199 | // Get face model vertices and triangles 200 | FT_TRIANGLE* triangles = NULL; 201 | UINT numTriangles = 0, numVertices = model->GetVertexCount(); 202 | std::vector points2D( numVertices ); 203 | 204 | POINT viewOffset = {0, 0}; 205 | FT_CAMERA_CONFIG colorConfig = {640, 480, NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS}; 206 | if ( SUCCEEDED(model->GetTriangles(&triangles, &numTriangles)) && 207 | SUCCEEDED(model->GetProjectedShape(&colorConfig, 1.0, viewOffset, 208 | suList, numSU, auList, numAU, scale, rotation, pos, &(points2D[0]), numVertices)) ) 209 | { 210 | faceVertices.resize( 3 * numVertices ); 211 | for ( unsigned int i=0; iRelease(); 227 | } 228 | 229 | void update() 230 | { 231 | NUI_IMAGE_FRAME colorFrame; 232 | HRESULT hr = context->NuiImageStreamGetNextFrame( colorStreamHandle, 0, &colorFrame ); 233 | if ( SUCCEEDED(hr) ) 234 | { 235 | updateImageFrame( colorFrame, false ); 236 | context->NuiImageStreamReleaseFrame( colorStreamHandle, &colorFrame ); 237 | } 238 | 239 | NUI_IMAGE_FRAME depthFrame; 240 | hr = context->NuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 241 | if ( SUCCEEDED(hr) ) 242 | { 243 | updateImageFrame( depthFrame, true ); 244 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 245 | } 246 | 247 | if ( tracker && faceResult ) 248 | { 249 | if ( !isFaceTracked ) 250 | { 251 | hr = tracker->StartTracking( &sensorData, NULL, NULL, faceResult ); 252 | if ( SUCCEEDED(hr) && SUCCEEDED(faceResult->GetStatus()) ) isFaceTracked = true; 253 | } 254 | else 255 | { 256 | hr = tracker->ContinueTracking( &sensorData, NULL, faceResult ); 257 | if ( FAILED(hr) || FAILED(faceResult->GetStatus()) ) isFaceTracked = false; 258 | } 259 | } 260 | glutPostRedisplay(); 261 | } 262 | 263 | void render() 264 | { 265 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 266 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 267 | glEnable( GL_TEXTURE_2D ); 268 | 269 | glMatrixMode( GL_PROJECTION ); 270 | glLoadIdentity(); 271 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 272 | 273 | glMatrixMode( GL_MODELVIEW ); 274 | glLoadIdentity(); 275 | 276 | // Draw color quad 277 | GLfloat vertices[][3] = { 278 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 279 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 280 | }; 281 | GLfloat texcoords[][2] = { 282 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 283 | }; 284 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 285 | 286 | glBindTexture( GL_TEXTURE_2D, colorTexture->id ); 287 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 288 | 289 | // Draw face tracking plane 290 | if ( isFaceTracked ) 291 | obtainFaceModelData(); 292 | 293 | glDisable( GL_TEXTURE_2D ); 294 | glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 295 | 296 | VertexData faceMeshData = { &(faceVertices[0]), NULL, NULL, NULL }; 297 | drawIndexedMesh( WITH_POSITION, faceVertices.size()/3, faceMeshData, 298 | GL_TRIANGLES, faceTriangles.size(), &(faceTriangles[0]) ); 299 | 300 | glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 301 | glutSwapBuffers(); 302 | } 303 | 304 | void reshape( int w, int h ) 305 | { 306 | glViewport( 0, 0, w, h ); 307 | } 308 | 309 | void keyEvents( unsigned char key, int x, int y ) 310 | { 311 | switch ( key ) 312 | { 313 | case 27: case 'Q': case 'q': 314 | glutLeaveMainLoop(); 315 | return; 316 | } 317 | glutPostRedisplay(); 318 | } 319 | 320 | int main( int argc, char** argv ) 321 | { 322 | glutInit( &argc, argv ); 323 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 324 | glutCreateWindow( "ch4_04_Face_Modeling" ); 325 | glutFullScreen(); 326 | 327 | glutIdleFunc( update ); 328 | glutDisplayFunc( render ); 329 | glutReshapeFunc( reshape ); 330 | glutKeyboardFunc( keyEvents ); 331 | 332 | if ( !initializeKinect() ) return 1; 333 | colorTexture = createTexture(640, 480, GL_RGB, 3); 334 | packedDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 335 | if ( !initializeFaceTracker() ) return 1; 336 | 337 | glutMainLoop(); 338 | 339 | destroyFaceTracker(); 340 | destroyTexture( colorTexture ); 341 | destroyTexture( packedDepthTexture ); 342 | destroyKinect(); 343 | return 0; 344 | } 345 | -------------------------------------------------------------------------------- /ch6_02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | 15 | struct Vertex { GLfloat x, y, z; }; 16 | std::vector leftHandTrails; 17 | std::vector rightHandTrails; 18 | GLfloat trailColors[20][4]; 19 | 20 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 21 | unsigned int holdGestureCount[2] = {0}; 22 | const unsigned int backgroundTexID = 1; 23 | const unsigned int objectTexIDs[4] = {2, 3, 4, 5}; 24 | 25 | float randomValue( float min, float max ) 26 | { 27 | return (min + (float)rand()/(RAND_MAX+1.0f) * (max - min)); 28 | } 29 | 30 | class FruitObject 31 | { 32 | public: 33 | FruitObject( unsigned int id, bool b, GLfloat s, 34 | GLfloat tx=0.0f, GLfloat ty=0.0f, GLfloat tw=1.0f, GLfloat th=1.0f ) 35 | { 36 | canSlice = b; size = s; 37 | texOffset[0] = tx; texOffset[1] = ty; 38 | texOffset[2] = tx + tw; texOffset[3] = ty + th; 39 | position.x = 0.0f; position.y = 0.0f; position.z = 0.0f; 40 | velocity.x = 0.0f; velocity.y = 0.0f; velocity.z = 0.0f; 41 | objectID = id; 42 | } 43 | 44 | void update() 45 | { 46 | position.x += velocity.x; 47 | position.y += velocity.y; 48 | 49 | const GLfloat gravity = -0.001f; 50 | velocity.y += gravity; 51 | } 52 | 53 | void render() 54 | { 55 | GLfloat vertices[][3] = { 56 | { 0.0f, 0.0f, 0.0f }, { size, 0.0f, 0.0f }, 57 | { size, size, 0.0f }, { 0.0f, size, 0.0f } 58 | }; 59 | GLfloat texcoords[][2] = { 60 | {texOffset[0], texOffset[1]}, {texOffset[2], texOffset[1]}, 61 | {texOffset[2], texOffset[3]}, {texOffset[0], texOffset[3]} 62 | }; 63 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 64 | 65 | glPushMatrix(); 66 | glTranslatef( position.x, position.y, position.z ); 67 | TextureManager::Inst()->BindTexture( objectTexIDs[objectID] ); 68 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 69 | glPopMatrix(); 70 | } 71 | 72 | GLfloat size; 73 | GLfloat texOffset[4]; 74 | Vertex position; 75 | Vertex velocity; 76 | unsigned int objectID; 77 | bool canSlice; 78 | }; 79 | std::vector _fruitObjects; 80 | 81 | bool initializeKinect() 82 | { 83 | int numKinects = 0; 84 | HRESULT hr = NuiGetSensorCount( &numKinects ); 85 | if ( FAILED(hr) || numKinects<=0 ) 86 | { 87 | std::cout << "No Kinect device found." << std::endl; 88 | return false; 89 | } 90 | 91 | hr = NuiCreateSensorByIndex( 0, &context ); 92 | if ( FAILED(hr) ) 93 | { 94 | std::cout << "Failed to connect to Kinect device." << std::endl; 95 | return false; 96 | } 97 | 98 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 99 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 100 | hr = context->NuiInitialize( nuiFlags ); 101 | if ( FAILED(hr) ) 102 | { 103 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 104 | return false; 105 | } 106 | 107 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 108 | if ( FAILED(hr) ) 109 | { 110 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 111 | return false; 112 | } 113 | 114 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 115 | 0, 2, NULL, &depthStreamHandle ); 116 | if ( FAILED(hr) ) 117 | { 118 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 119 | return false; 120 | } 121 | 122 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 123 | if ( FAILED(hr) ) 124 | { 125 | std::cout << "Unable to start tracking skeleton." << std::endl; 126 | return false; 127 | } 128 | return true; 129 | } 130 | 131 | bool destroyKinect() 132 | { 133 | if ( context ) 134 | { 135 | context->NuiShutdown(); 136 | return true; 137 | } 138 | return false; 139 | } 140 | 141 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 142 | { 143 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 144 | NUI_LOCKED_RECT lockedRect; 145 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 146 | if ( lockedRect.Pitch!=NULL ) 147 | { 148 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 149 | for ( int i=0; i<480; ++i ) 150 | { 151 | const BYTE* line = buffer + i * lockedRect.Pitch; 152 | const USHORT* bufferWord = (const USHORT*)line; 153 | for ( int j=0; j<640; ++j ) 154 | { 155 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 156 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 157 | { 158 | *(ptr + 0) = 200; 159 | *(ptr + 1) = 80; 160 | } 161 | else 162 | { 163 | *(ptr + 0) = 0; 164 | *(ptr + 1) = 0; 165 | } 166 | } 167 | } 168 | 169 | TextureObject* tobj = playerDepthTexture; 170 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 171 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 172 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 173 | } 174 | nuiTexture->UnlockRect( 0 ); 175 | } 176 | 177 | void guessGesture( unsigned int index, bool inRange ) 178 | { 179 | if ( !inRange ) 180 | { 181 | holdGestureCount[index] = 0; 182 | } 183 | else 184 | { 185 | float distance = 0.0f, currentX = 0.0f, currentY = 0.0f; 186 | if ( index==0 ) // left hand 187 | { 188 | currentX = leftHandTrails.back().x; 189 | currentY = leftHandTrails.back().y; 190 | distance = sqrt(powf(currentX-leftHandTrails.front().x, 2.0f) 191 | + powf(currentY-leftHandTrails.front().y, 2.0f)); 192 | } 193 | else // right hand 194 | { 195 | currentX = rightHandTrails.back().x; 196 | currentY = rightHandTrails.back().y; 197 | distance = sqrt(powf(currentX-rightHandTrails.front().x, 2.0f) 198 | + powf(currentY-rightHandTrails.front().y, 2.0f)); 199 | } 200 | 201 | if ( distance<0.02 ) 202 | holdGestureCount[index]++; 203 | else 204 | holdGestureCount[index] = 0; 205 | 206 | if ( holdGestureCount[index]>30 ) 207 | { 208 | if ( currentY>0.9f && currentX<0.1f ) // Restart 209 | {} 210 | else if ( currentY>0.9f && currentX>0.9f ) // Exit 211 | glutLeaveMainLoop(); 212 | } 213 | } 214 | } 215 | 216 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 217 | { 218 | POINT coordInDepth; 219 | USHORT depth = 0; 220 | GLfloat yMin = 0.0f, zMax = 0.0f; 221 | for ( int i=0; i20 ) leftHandTrails.erase( leftHandTrails.begin() ); 241 | } 242 | else if ( i==NUI_SKELETON_POSITION_HAND_RIGHT ) 243 | { 244 | rightHandTrails.push_back( vertex ); 245 | if ( rightHandTrails.size()>20 ) rightHandTrails.erase( rightHandTrails.begin() ); 246 | } 247 | } 248 | 249 | guessGesture( 0, (yMinNuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 257 | if ( SUCCEEDED(hr) ) 258 | { 259 | updateImageFrame( depthFrame ); 260 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 261 | } 262 | 263 | NUI_SKELETON_FRAME skeletonFrame = {0}; 264 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 265 | if ( SUCCEEDED(hr) ) 266 | { 267 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 268 | for ( int n=0; n newObjects; 281 | for ( std::vector::iterator itr=_fruitObjects.begin(); 282 | itr!=_fruitObjects.end(); ) 283 | { 284 | FruitObject& fruit = (*itr); 285 | bool isSliced = false; 286 | if ( fruit.canSlice ) 287 | { 288 | float distance = sqrt(powf(fruit.position.x-leftHandTrails.back().x, 2.0f) 289 | + powf(fruit.position.y-leftHandTrails.back().y, 2.0f)); 290 | if ( distance0.5f ) obj.velocity.x = -obj.velocity.x; 352 | newObjects.push_back( obj ); 353 | } 354 | _fruitObjects.insert( _fruitObjects.end(), newObjects.begin(), newObjects.end() ); 355 | glutPostRedisplay(); 356 | } 357 | 358 | void render() 359 | { 360 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 361 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 362 | glEnable( GL_TEXTURE_2D ); 363 | 364 | glMatrixMode( GL_PROJECTION ); 365 | glLoadIdentity(); 366 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 367 | 368 | glMatrixMode( GL_MODELVIEW ); 369 | glLoadIdentity(); 370 | 371 | // Draw background quad 372 | GLfloat vertices[][3] = { 373 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 374 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 375 | }; 376 | GLfloat texcoords[][2] = { 377 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 378 | }; 379 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 380 | 381 | TextureManager::Inst()->BindTexture( backgroundTexID ); 382 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 383 | 384 | // Blend with depth quad 385 | glEnable( GL_BLEND ); 386 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 387 | glTranslatef( 0.0f, 0.0f, 0.1f ); 388 | 389 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 390 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 391 | 392 | // Blend with fruit objects 393 | for ( unsigned int i=0; i<_fruitObjects.size(); ++i ) 394 | _fruitObjects[i].render(); 395 | 396 | // Blend with hand trails 397 | glDisable( GL_TEXTURE_2D ); 398 | glLineWidth( 50.0f ); 399 | 400 | VertexData leftHandData = { &(leftHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 401 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, leftHandTrails.size(), leftHandData, GL_LINE_STRIP ); 402 | 403 | VertexData rightHandData = { &(rightHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 404 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, rightHandTrails.size(), rightHandData, GL_LINE_STRIP ); 405 | 406 | glDisable( GL_BLEND ); 407 | glutSwapBuffers(); 408 | } 409 | 410 | void reshape( int w, int h ) 411 | { 412 | glViewport( 0, 0, w, h ); 413 | } 414 | 415 | void keyEvents( unsigned char key, int x, int y ) 416 | { 417 | switch ( key ) 418 | { 419 | case 27: case 'Q': case 'q': 420 | glutLeaveMainLoop(); 421 | return; 422 | } 423 | glutPostRedisplay(); 424 | } 425 | 426 | int main( int argc, char** argv ) 427 | { 428 | glutInit( &argc, argv ); 429 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 430 | glutCreateWindow( "ch6_02_Cutting_Fruits" ); 431 | glutFullScreen(); 432 | 433 | glutIdleFunc( update ); 434 | glutDisplayFunc( render ); 435 | glutReshapeFunc( reshape ); 436 | glutKeyboardFunc( keyEvents ); 437 | 438 | if ( TextureManager::Inst()->LoadTexture("FruitNinja1.jpg", backgroundTexID, GL_BGR_EXT) ) 439 | { 440 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 441 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 442 | } 443 | 444 | for ( int i=0; i<4; ++i ) 445 | { 446 | std::stringstream ss; 447 | ss << "FruitNinja" << i+2 << ".png"; 448 | if ( TextureManager::Inst()->LoadTexture(ss.str().c_str(), objectTexIDs[i], GL_BGRA_EXT, 4) ) 449 | { 450 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 451 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 452 | } 453 | } 454 | 455 | for ( int i=0; i<20; ++i ) 456 | { 457 | trailColors[i][0] = 1.0f; 458 | trailColors[i][1] = 1.0f; 459 | trailColors[i][2] = 1.0f; 460 | trailColors[i][3] = (float)(i + 1) / 20.0f; 461 | } 462 | 463 | if ( !initializeKinect() ) return 1; 464 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 465 | 466 | smoothParams.fCorrection = 0.5f; 467 | smoothParams.fJitterRadius = 1.0f; 468 | smoothParams.fMaxDeviationRadius = 0.5f; 469 | smoothParams.fPrediction = 0.4f; 470 | smoothParams.fSmoothing = 0.2f; 471 | 472 | Vertex defaultPoint = {0.0f, 0.0f, 0.0f}; 473 | leftHandTrails.push_back( defaultPoint ); 474 | rightHandTrails.push_back( defaultPoint ); 475 | 476 | glutMainLoop(); 477 | 478 | destroyTexture( playerDepthTexture ); 479 | destroyKinect(); 480 | return 0; 481 | } 482 | -------------------------------------------------------------------------------- /ch6_03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "common/TextureManager.h" 8 | #include "common/GLUtilities.h" 9 | 10 | INuiSensor* context = NULL; 11 | HANDLE colorStreamHandle = NULL; 12 | HANDLE depthStreamHandle = NULL; 13 | TextureObject* playerDepthTexture = NULL; 14 | 15 | struct Vertex { GLfloat x, y, z; }; 16 | std::vector leftHandTrails; 17 | std::vector rightHandTrails; 18 | GLfloat trailColors[20][4]; 19 | 20 | NUI_TRANSFORM_SMOOTH_PARAMETERS smoothParams; 21 | unsigned int holdGestureCount[2] = {0}; 22 | unsigned int swipeGestureCount[2] = {0}; 23 | 24 | const unsigned int backgroundTexID = 1; 25 | const unsigned int objectTexIDs[4] = {2, 3, 4, 5}; 26 | const unsigned int gameOverTexID = 6; 27 | int score = 0, life = 100; 28 | 29 | float randomValue( float min, float max ) 30 | { 31 | return (min + (float)rand()/(RAND_MAX+1.0f) * (max - min)); 32 | } 33 | 34 | class FruitObject 35 | { 36 | public: 37 | FruitObject( unsigned int id, bool b, GLfloat s, 38 | GLfloat tx=0.0f, GLfloat ty=0.0f, GLfloat tw=1.0f, GLfloat th=1.0f ) 39 | { 40 | canSlice = b; size = s; 41 | texOffset[0] = tx; texOffset[1] = ty; 42 | texOffset[2] = tx + tw; texOffset[3] = ty + th; 43 | position.x = 0.0f; position.y = 0.0f; position.z = 0.0f; 44 | velocity.x = 0.0f; velocity.y = 0.0f; velocity.z = 0.0f; 45 | objectID = id; 46 | } 47 | 48 | void update() 49 | { 50 | position.x += velocity.x; 51 | position.y += velocity.y; 52 | 53 | const GLfloat gravity = -0.001f; 54 | velocity.y += gravity; 55 | } 56 | 57 | void render() 58 | { 59 | GLfloat vertices[][3] = { 60 | { 0.0f, 0.0f, 0.0f }, { size, 0.0f, 0.0f }, 61 | { size, size, 0.0f }, { 0.0f, size, 0.0f } 62 | }; 63 | GLfloat texcoords[][2] = { 64 | {texOffset[0], texOffset[1]}, {texOffset[2], texOffset[1]}, 65 | {texOffset[2], texOffset[3]}, {texOffset[0], texOffset[3]} 66 | }; 67 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 68 | 69 | glPushMatrix(); 70 | glTranslatef( position.x, position.y, position.z ); 71 | TextureManager::Inst()->BindTexture( objectTexIDs[objectID] ); 72 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 73 | glPopMatrix(); 74 | } 75 | 76 | GLfloat size; 77 | GLfloat texOffset[4]; 78 | Vertex position; 79 | Vertex velocity; 80 | unsigned int objectID; 81 | bool canSlice; 82 | }; 83 | std::vector _fruitObjects; 84 | 85 | bool initializeKinect() 86 | { 87 | int numKinects = 0; 88 | HRESULT hr = NuiGetSensorCount( &numKinects ); 89 | if ( FAILED(hr) || numKinects<=0 ) 90 | { 91 | std::cout << "No Kinect device found." << std::endl; 92 | return false; 93 | } 94 | 95 | hr = NuiCreateSensorByIndex( 0, &context ); 96 | if ( FAILED(hr) ) 97 | { 98 | std::cout << "Failed to connect to Kinect device." << std::endl; 99 | return false; 100 | } 101 | 102 | DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_SKELETON | NUI_INITIALIZE_FLAG_USES_COLOR | 103 | NUI_INITIALIZE_FLAG_USES_DEPTH_AND_PLAYER_INDEX; 104 | hr = context->NuiInitialize( nuiFlags ); 105 | if ( FAILED(hr) ) 106 | { 107 | std::cout << "Failed to intialize Kinect: " << std::hex << (long)hr << std::dec << std::endl; 108 | return false; 109 | } 110 | 111 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, 0, 2, NULL, &colorStreamHandle ); 112 | if ( FAILED(hr) ) 113 | { 114 | std::cout << "Unable to create color stream: " << std::hex << (long)hr << std::dec << std::endl; 115 | return false; 116 | } 117 | 118 | hr = context->NuiImageStreamOpen( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_640x480, 119 | 0, 2, NULL, &depthStreamHandle ); 120 | if ( FAILED(hr) ) 121 | { 122 | std::cout << "Unable to create depth stream: " << std::hex << (long)hr << std::dec << std::endl; 123 | return false; 124 | } 125 | 126 | hr = context->NuiSkeletonTrackingEnable( NULL, 0 ); 127 | if ( FAILED(hr) ) 128 | { 129 | std::cout << "Unable to start tracking skeleton." << std::endl; 130 | return false; 131 | } 132 | return true; 133 | } 134 | 135 | bool destroyKinect() 136 | { 137 | if ( context ) 138 | { 139 | context->NuiShutdown(); 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | void updateImageFrame( NUI_IMAGE_FRAME& imageFrame ) 146 | { 147 | INuiFrameTexture* nuiTexture = imageFrame.pFrameTexture; 148 | NUI_LOCKED_RECT lockedRect; 149 | nuiTexture->LockRect( 0, &lockedRect, NULL, 0 ); 150 | if ( lockedRect.Pitch!=NULL ) 151 | { 152 | const BYTE* buffer = (const BYTE*)lockedRect.pBits; 153 | for ( int i=0; i<480; ++i ) 154 | { 155 | const BYTE* line = buffer + i * lockedRect.Pitch; 156 | const USHORT* bufferWord = (const USHORT*)line; 157 | for ( int j=0; j<640; ++j ) 158 | { 159 | unsigned char* ptr = playerDepthTexture->bits + 2 * (i * 640 + j); 160 | if ( NuiDepthPixelToPlayerIndex(bufferWord[j])>0 ) 161 | { 162 | *(ptr + 0) = 200; 163 | *(ptr + 1) = 80; 164 | } 165 | else 166 | { 167 | *(ptr + 0) = 0; 168 | *(ptr + 1) = 0; 169 | } 170 | } 171 | } 172 | 173 | TextureObject* tobj = playerDepthTexture; 174 | glBindTexture( GL_TEXTURE_2D, tobj->id ); 175 | glTexImage2D( GL_TEXTURE_2D, 0, tobj->internalFormat, tobj->width, tobj->height, 176 | 0, tobj->imageFormat, GL_UNSIGNED_BYTE, tobj->bits ); 177 | } 178 | nuiTexture->UnlockRect( 0 ); 179 | } 180 | 181 | void guessGesture( unsigned int index, bool inRange ) 182 | { 183 | if ( !inRange ) 184 | { 185 | holdGestureCount[index] = 0; 186 | swipeGestureCount[index] = 0; 187 | } 188 | else 189 | { 190 | float distance = 0.0f, currentX = 0.0f, currentY = 0.0f; 191 | if ( index==0 ) // left hand 192 | { 193 | currentX = leftHandTrails.back().x; 194 | currentY = leftHandTrails.back().y; 195 | distance = sqrt(powf(currentX-leftHandTrails.front().x, 2.0f) 196 | + powf(currentY-leftHandTrails.front().y, 2.0f)); 197 | } 198 | else // right hand 199 | { 200 | currentX = rightHandTrails.back().x; 201 | currentY = rightHandTrails.back().y; 202 | distance = sqrt(powf(currentX-rightHandTrails.front().x, 2.0f) 203 | + powf(currentY-rightHandTrails.front().y, 2.0f)); 204 | } 205 | 206 | if ( distance<0.02 ) 207 | { 208 | holdGestureCount[index]++; 209 | swipeGestureCount[index] = 0; 210 | } 211 | else if ( distance>0.05 ) 212 | { 213 | holdGestureCount[index] = 0; 214 | swipeGestureCount[index]++; 215 | } 216 | else 217 | { 218 | holdGestureCount[index] = 0; 219 | swipeGestureCount[index] = 0; 220 | } 221 | 222 | if ( holdGestureCount[index]>30 ) 223 | { 224 | if ( currentY>0.9f && currentX<0.1f ) // Restart 225 | { score = 0; life = 100; } 226 | else if ( currentY>0.9f && currentX>0.9f ) // Exit 227 | glutLeaveMainLoop(); 228 | } 229 | } 230 | } 231 | 232 | void updateSkeletonData( NUI_SKELETON_DATA& data ) 233 | { 234 | POINT coordInDepth; 235 | USHORT depth = 0; 236 | GLfloat yMin = 0.0f, zMax = 0.0f; 237 | for ( int i=0; i20 ) leftHandTrails.erase( leftHandTrails.begin() ); 257 | } 258 | else if ( i==NUI_SKELETON_POSITION_HAND_RIGHT ) 259 | { 260 | rightHandTrails.push_back( vertex ); 261 | if ( rightHandTrails.size()>20 ) rightHandTrails.erase( rightHandTrails.begin() ); 262 | } 263 | } 264 | 265 | guessGesture( 0, (yMinNuiImageStreamGetNextFrame( depthStreamHandle, 0, &depthFrame ); 273 | if ( SUCCEEDED(hr) ) 274 | { 275 | updateImageFrame( depthFrame ); 276 | context->NuiImageStreamReleaseFrame( depthStreamHandle, &depthFrame ); 277 | } 278 | 279 | NUI_SKELETON_FRAME skeletonFrame = {0}; 280 | hr = context->NuiSkeletonGetNextFrame( 0, &skeletonFrame ); 281 | if ( SUCCEEDED(hr) ) 282 | { 283 | context->NuiTransformSmooth( &skeletonFrame, &smoothParams ); 284 | for ( int n=0; n newObjects; 297 | for ( std::vector::iterator itr=_fruitObjects.begin(); 298 | itr!=_fruitObjects.end(); ) 299 | { 300 | FruitObject& fruit = (*itr); 301 | bool isSliced = false; 302 | if ( fruit.canSlice ) 303 | { 304 | float distance = sqrt(powf(fruit.position.x-leftHandTrails.back().x, 2.0f) 305 | + powf(fruit.position.y-leftHandTrails.back().y, 2.0f)); 306 | if ( distance0.5f ) obj.velocity.x = -obj.velocity.x; 374 | newObjects.push_back( obj ); 375 | } 376 | _fruitObjects.insert( _fruitObjects.end(), newObjects.begin(), newObjects.end() ); 377 | glutPostRedisplay(); 378 | } 379 | 380 | void render() 381 | { 382 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 383 | glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); 384 | glEnable( GL_TEXTURE_2D ); 385 | 386 | glMatrixMode( GL_PROJECTION ); 387 | glLoadIdentity(); 388 | glOrtho( 0.0, 1.0, 0.0, 1.0, -1.0, 1.0 ); 389 | 390 | glMatrixMode( GL_MODELVIEW ); 391 | glLoadIdentity(); 392 | 393 | // Draw background quad 394 | GLfloat vertices[][3] = { 395 | { 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, 396 | { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } 397 | }; 398 | GLfloat texcoords[][2] = { 399 | {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} 400 | }; 401 | VertexData meshData = { &(vertices[0][0]), NULL, NULL, &(texcoords[0][0]) }; 402 | 403 | if ( life<=0 ) TextureManager::Inst()->BindTexture( gameOverTexID ); 404 | else TextureManager::Inst()->BindTexture( backgroundTexID ); 405 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 406 | 407 | // Blend with depth quad 408 | glEnable( GL_BLEND ); 409 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 410 | glTranslatef( 0.0f, 0.0f, 0.1f ); 411 | 412 | glBindTexture( GL_TEXTURE_2D, playerDepthTexture->id ); 413 | drawSimpleMesh( WITH_POSITION|WITH_TEXCOORD, 4, meshData, GL_QUADS ); 414 | 415 | // Blend with fruit objects 416 | for ( unsigned int i=0; i<_fruitObjects.size(); ++i ) 417 | _fruitObjects[i].render(); 418 | 419 | // Blend with hand trails 420 | glDisable( GL_TEXTURE_2D ); 421 | glLineWidth( 50.0f ); 422 | 423 | VertexData leftHandData = { &(leftHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 424 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, leftHandTrails.size(), leftHandData, GL_LINE_STRIP ); 425 | 426 | VertexData rightHandData = { &(rightHandTrails[0].x), NULL, &(trailColors[0][0]), NULL }; 427 | drawSimpleMesh( WITH_POSITION|WITH_COLOR, rightHandTrails.size(), rightHandData, GL_LINE_STRIP ); 428 | 429 | glDisable( GL_BLEND ); 430 | 431 | // Draw HUD text 432 | std::stringstream ss; 433 | ss << "Score: " << score << " Life: " << (life<0 ? 0 : life); 434 | 435 | glRasterPos2f( 0.01f, 0.01f ); 436 | glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); 437 | glutBitmapString( GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)ss.str().c_str() ); 438 | 439 | glutSwapBuffers(); 440 | } 441 | 442 | void reshape( int w, int h ) 443 | { 444 | glViewport( 0, 0, w, h ); 445 | } 446 | 447 | void keyEvents( unsigned char key, int x, int y ) 448 | { 449 | switch ( key ) 450 | { 451 | case 27: case 'Q': case 'q': 452 | glutLeaveMainLoop(); 453 | return; 454 | } 455 | glutPostRedisplay(); 456 | } 457 | 458 | int main( int argc, char** argv ) 459 | { 460 | glutInit( &argc, argv ); 461 | glutInitDisplayMode( GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH|GLUT_MULTISAMPLE ); 462 | glutCreateWindow( "ch6_03_Playing_Game" ); 463 | glutFullScreen(); 464 | 465 | glutIdleFunc( update ); 466 | glutDisplayFunc( render ); 467 | glutReshapeFunc( reshape ); 468 | glutKeyboardFunc( keyEvents ); 469 | 470 | if ( TextureManager::Inst()->LoadTexture("FruitNinja1.jpg", backgroundTexID, GL_BGR_EXT) ) 471 | { 472 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 473 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 474 | } 475 | 476 | for ( int i=0; i<4; ++i ) 477 | { 478 | std::stringstream ss; 479 | ss << "FruitNinja" << i+2 << ".png"; 480 | if ( TextureManager::Inst()->LoadTexture(ss.str().c_str(), objectTexIDs[i], GL_BGRA_EXT, 4) ) 481 | { 482 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 483 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 484 | } 485 | } 486 | 487 | if ( TextureManager::Inst()->LoadTexture("FruitNinja6.jpg", gameOverTexID, GL_BGR_EXT) ) 488 | { 489 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 490 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 491 | } 492 | 493 | for ( int i=0; i<20; ++i ) 494 | { 495 | trailColors[i][0] = 1.0f; 496 | trailColors[i][1] = 1.0f; 497 | trailColors[i][2] = 1.0f; 498 | trailColors[i][3] = (float)(i + 1) / 20.0f; 499 | } 500 | 501 | if ( !initializeKinect() ) return 1; 502 | playerDepthTexture = createTexture(640, 480, GL_LUMINANCE_ALPHA, 2); 503 | 504 | smoothParams.fCorrection = 0.5f; 505 | smoothParams.fJitterRadius = 1.0f; 506 | smoothParams.fMaxDeviationRadius = 0.5f; 507 | smoothParams.fPrediction = 0.4f; 508 | smoothParams.fSmoothing = 0.2f; 509 | 510 | Vertex defaultPoint = {0.0f, 0.0f, 0.0f}; 511 | leftHandTrails.push_back( defaultPoint ); 512 | rightHandTrails.push_back( defaultPoint ); 513 | 514 | glutMainLoop(); 515 | 516 | destroyTexture( playerDepthTexture ); 517 | destroyKinect(); 518 | return 0; 519 | } 520 | -------------------------------------------------------------------------------- /include/GL/freeglut_std.h: -------------------------------------------------------------------------------- 1 | #ifndef __FREEGLUT_STD_H__ 2 | #define __FREEGLUT_STD_H__ 3 | 4 | /* 5 | * freeglut_std.h 6 | * 7 | * The GLUT-compatible part of the freeglut library include file 8 | * 9 | * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. 10 | * Written by Pawel W. Olszta, 11 | * Creation date: Thu Dec 2 1999 12 | * 13 | * Permission is hereby granted, free of charge, to any person obtaining a 14 | * copy of this software and associated documentation files (the "Software"), 15 | * to deal in the Software without restriction, including without limitation 16 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | * and/or sell copies of the Software, and to permit persons to whom the 18 | * Software is furnished to do so, subject to the following conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be included 21 | * in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 27 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 28 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Under windows, we have to differentiate between static and dynamic libraries 37 | */ 38 | #ifdef _WIN32 39 | /* #pragma may not be supported by some compilers. 40 | * Discussion by FreeGLUT developers suggests that 41 | * Visual C++ specific code involving pragmas may 42 | * need to move to a separate header. 24th Dec 2003 43 | */ 44 | 45 | /* Define FREEGLUT_LIB_PRAGMAS to 1 to include library 46 | * pragmas or to 0 to exclude library pragmas. 47 | * The default behavior depends on the compiler/platform. 48 | */ 49 | # ifndef FREEGLUT_LIB_PRAGMAS 50 | # if ( defined(_MSC_VER) || defined(__WATCOMC__) ) && !defined(_WIN32_WCE) 51 | # define FREEGLUT_LIB_PRAGMAS 1 52 | # else 53 | # define FREEGLUT_LIB_PRAGMAS 0 54 | # endif 55 | # endif 56 | 57 | # ifndef WIN32_LEAN_AND_MEAN 58 | # define WIN32_LEAN_AND_MEAN 1 59 | # endif 60 | # ifndef NOMINMAX 61 | # define NOMINMAX 62 | # endif 63 | # include 64 | 65 | /* Windows static library */ 66 | # ifdef FREEGLUT_STATIC 67 | 68 | #error Static linking is not supported with this build. Please remove the FREEGLUT_STATIC preprocessor directive, or download the source code from http://freeglut.sf.net/ and build against that. 69 | 70 | /* Windows shared library (DLL) */ 71 | # else 72 | 73 | # define FGAPIENTRY __stdcall 74 | # if defined(FREEGLUT_EXPORTS) 75 | # define FGAPI __declspec(dllexport) 76 | # else 77 | # define FGAPI __declspec(dllimport) 78 | 79 | /* Link with Win32 shared freeglut lib */ 80 | # if FREEGLUT_LIB_PRAGMAS 81 | # pragma comment (lib, "freeglut.lib") 82 | # endif 83 | 84 | # endif 85 | 86 | # endif 87 | 88 | /* Drag in other Windows libraries as required by FreeGLUT */ 89 | # if FREEGLUT_LIB_PRAGMAS 90 | # pragma comment (lib, "glu32.lib") /* link OpenGL Utility lib */ 91 | # pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib */ 92 | # pragma comment (lib, "gdi32.lib") /* link Windows GDI lib */ 93 | # pragma comment (lib, "winmm.lib") /* link Windows MultiMedia lib */ 94 | # pragma comment (lib, "user32.lib") /* link Windows user lib */ 95 | # endif 96 | 97 | #else 98 | 99 | /* Non-Windows definition of FGAPI and FGAPIENTRY */ 100 | # define FGAPI 101 | # define FGAPIENTRY 102 | 103 | #endif 104 | 105 | /* 106 | * The freeglut and GLUT API versions 107 | */ 108 | #define FREEGLUT 1 109 | #define GLUT_API_VERSION 4 110 | #define FREEGLUT_VERSION_2_0 1 111 | #define GLUT_XLIB_IMPLEMENTATION 13 112 | 113 | /* 114 | * Always include OpenGL and GLU headers 115 | */ 116 | #include 117 | #include 118 | 119 | /* 120 | * GLUT API macro definitions -- the special key codes: 121 | */ 122 | #define GLUT_KEY_F1 0x0001 123 | #define GLUT_KEY_F2 0x0002 124 | #define GLUT_KEY_F3 0x0003 125 | #define GLUT_KEY_F4 0x0004 126 | #define GLUT_KEY_F5 0x0005 127 | #define GLUT_KEY_F6 0x0006 128 | #define GLUT_KEY_F7 0x0007 129 | #define GLUT_KEY_F8 0x0008 130 | #define GLUT_KEY_F9 0x0009 131 | #define GLUT_KEY_F10 0x000A 132 | #define GLUT_KEY_F11 0x000B 133 | #define GLUT_KEY_F12 0x000C 134 | #define GLUT_KEY_LEFT 0x0064 135 | #define GLUT_KEY_UP 0x0065 136 | #define GLUT_KEY_RIGHT 0x0066 137 | #define GLUT_KEY_DOWN 0x0067 138 | #define GLUT_KEY_PAGE_UP 0x0068 139 | #define GLUT_KEY_PAGE_DOWN 0x0069 140 | #define GLUT_KEY_HOME 0x006A 141 | #define GLUT_KEY_END 0x006B 142 | #define GLUT_KEY_INSERT 0x006C 143 | 144 | /* 145 | * GLUT API macro definitions -- mouse state definitions 146 | */ 147 | #define GLUT_LEFT_BUTTON 0x0000 148 | #define GLUT_MIDDLE_BUTTON 0x0001 149 | #define GLUT_RIGHT_BUTTON 0x0002 150 | #define GLUT_DOWN 0x0000 151 | #define GLUT_UP 0x0001 152 | #define GLUT_LEFT 0x0000 153 | #define GLUT_ENTERED 0x0001 154 | 155 | /* 156 | * GLUT API macro definitions -- the display mode definitions 157 | */ 158 | #define GLUT_RGB 0x0000 159 | #define GLUT_RGBA 0x0000 160 | #define GLUT_INDEX 0x0001 161 | #define GLUT_SINGLE 0x0000 162 | #define GLUT_DOUBLE 0x0002 163 | #define GLUT_ACCUM 0x0004 164 | #define GLUT_ALPHA 0x0008 165 | #define GLUT_DEPTH 0x0010 166 | #define GLUT_STENCIL 0x0020 167 | #define GLUT_MULTISAMPLE 0x0080 168 | #define GLUT_STEREO 0x0100 169 | #define GLUT_LUMINANCE 0x0200 170 | 171 | /* 172 | * GLUT API macro definitions -- windows and menu related definitions 173 | */ 174 | #define GLUT_MENU_NOT_IN_USE 0x0000 175 | #define GLUT_MENU_IN_USE 0x0001 176 | #define GLUT_NOT_VISIBLE 0x0000 177 | #define GLUT_VISIBLE 0x0001 178 | #define GLUT_HIDDEN 0x0000 179 | #define GLUT_FULLY_RETAINED 0x0001 180 | #define GLUT_PARTIALLY_RETAINED 0x0002 181 | #define GLUT_FULLY_COVERED 0x0003 182 | 183 | /* 184 | * GLUT API macro definitions -- fonts definitions 185 | * 186 | * Steve Baker suggested to make it binary compatible with GLUT: 187 | */ 188 | #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WATCOMC__) 189 | # define GLUT_STROKE_ROMAN ((void *)0x0000) 190 | # define GLUT_STROKE_MONO_ROMAN ((void *)0x0001) 191 | # define GLUT_BITMAP_9_BY_15 ((void *)0x0002) 192 | # define GLUT_BITMAP_8_BY_13 ((void *)0x0003) 193 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *)0x0004) 194 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *)0x0005) 195 | # define GLUT_BITMAP_HELVETICA_10 ((void *)0x0006) 196 | # define GLUT_BITMAP_HELVETICA_12 ((void *)0x0007) 197 | # define GLUT_BITMAP_HELVETICA_18 ((void *)0x0008) 198 | #else 199 | /* 200 | * I don't really know if it's a good idea... But here it goes: 201 | */ 202 | extern void* glutStrokeRoman; 203 | extern void* glutStrokeMonoRoman; 204 | extern void* glutBitmap9By15; 205 | extern void* glutBitmap8By13; 206 | extern void* glutBitmapTimesRoman10; 207 | extern void* glutBitmapTimesRoman24; 208 | extern void* glutBitmapHelvetica10; 209 | extern void* glutBitmapHelvetica12; 210 | extern void* glutBitmapHelvetica18; 211 | 212 | /* 213 | * Those pointers will be used by following definitions: 214 | */ 215 | # define GLUT_STROKE_ROMAN ((void *) &glutStrokeRoman) 216 | # define GLUT_STROKE_MONO_ROMAN ((void *) &glutStrokeMonoRoman) 217 | # define GLUT_BITMAP_9_BY_15 ((void *) &glutBitmap9By15) 218 | # define GLUT_BITMAP_8_BY_13 ((void *) &glutBitmap8By13) 219 | # define GLUT_BITMAP_TIMES_ROMAN_10 ((void *) &glutBitmapTimesRoman10) 220 | # define GLUT_BITMAP_TIMES_ROMAN_24 ((void *) &glutBitmapTimesRoman24) 221 | # define GLUT_BITMAP_HELVETICA_10 ((void *) &glutBitmapHelvetica10) 222 | # define GLUT_BITMAP_HELVETICA_12 ((void *) &glutBitmapHelvetica12) 223 | # define GLUT_BITMAP_HELVETICA_18 ((void *) &glutBitmapHelvetica18) 224 | #endif 225 | 226 | /* 227 | * GLUT API macro definitions -- the glutGet parameters 228 | */ 229 | #define GLUT_WINDOW_X 0x0064 230 | #define GLUT_WINDOW_Y 0x0065 231 | #define GLUT_WINDOW_WIDTH 0x0066 232 | #define GLUT_WINDOW_HEIGHT 0x0067 233 | #define GLUT_WINDOW_BUFFER_SIZE 0x0068 234 | #define GLUT_WINDOW_STENCIL_SIZE 0x0069 235 | #define GLUT_WINDOW_DEPTH_SIZE 0x006A 236 | #define GLUT_WINDOW_RED_SIZE 0x006B 237 | #define GLUT_WINDOW_GREEN_SIZE 0x006C 238 | #define GLUT_WINDOW_BLUE_SIZE 0x006D 239 | #define GLUT_WINDOW_ALPHA_SIZE 0x006E 240 | #define GLUT_WINDOW_ACCUM_RED_SIZE 0x006F 241 | #define GLUT_WINDOW_ACCUM_GREEN_SIZE 0x0070 242 | #define GLUT_WINDOW_ACCUM_BLUE_SIZE 0x0071 243 | #define GLUT_WINDOW_ACCUM_ALPHA_SIZE 0x0072 244 | #define GLUT_WINDOW_DOUBLEBUFFER 0x0073 245 | #define GLUT_WINDOW_RGBA 0x0074 246 | #define GLUT_WINDOW_PARENT 0x0075 247 | #define GLUT_WINDOW_NUM_CHILDREN 0x0076 248 | #define GLUT_WINDOW_COLORMAP_SIZE 0x0077 249 | #define GLUT_WINDOW_NUM_SAMPLES 0x0078 250 | #define GLUT_WINDOW_STEREO 0x0079 251 | #define GLUT_WINDOW_CURSOR 0x007A 252 | 253 | #define GLUT_SCREEN_WIDTH 0x00C8 254 | #define GLUT_SCREEN_HEIGHT 0x00C9 255 | #define GLUT_SCREEN_WIDTH_MM 0x00CA 256 | #define GLUT_SCREEN_HEIGHT_MM 0x00CB 257 | #define GLUT_MENU_NUM_ITEMS 0x012C 258 | #define GLUT_DISPLAY_MODE_POSSIBLE 0x0190 259 | #define GLUT_INIT_WINDOW_X 0x01F4 260 | #define GLUT_INIT_WINDOW_Y 0x01F5 261 | #define GLUT_INIT_WINDOW_WIDTH 0x01F6 262 | #define GLUT_INIT_WINDOW_HEIGHT 0x01F7 263 | #define GLUT_INIT_DISPLAY_MODE 0x01F8 264 | #define GLUT_ELAPSED_TIME 0x02BC 265 | #define GLUT_WINDOW_FORMAT_ID 0x007B 266 | 267 | /* 268 | * GLUT API macro definitions -- the glutDeviceGet parameters 269 | */ 270 | #define GLUT_HAS_KEYBOARD 0x0258 271 | #define GLUT_HAS_MOUSE 0x0259 272 | #define GLUT_HAS_SPACEBALL 0x025A 273 | #define GLUT_HAS_DIAL_AND_BUTTON_BOX 0x025B 274 | #define GLUT_HAS_TABLET 0x025C 275 | #define GLUT_NUM_MOUSE_BUTTONS 0x025D 276 | #define GLUT_NUM_SPACEBALL_BUTTONS 0x025E 277 | #define GLUT_NUM_BUTTON_BOX_BUTTONS 0x025F 278 | #define GLUT_NUM_DIALS 0x0260 279 | #define GLUT_NUM_TABLET_BUTTONS 0x0261 280 | #define GLUT_DEVICE_IGNORE_KEY_REPEAT 0x0262 281 | #define GLUT_DEVICE_KEY_REPEAT 0x0263 282 | #define GLUT_HAS_JOYSTICK 0x0264 283 | #define GLUT_OWNS_JOYSTICK 0x0265 284 | #define GLUT_JOYSTICK_BUTTONS 0x0266 285 | #define GLUT_JOYSTICK_AXES 0x0267 286 | #define GLUT_JOYSTICK_POLL_RATE 0x0268 287 | 288 | /* 289 | * GLUT API macro definitions -- the glutLayerGet parameters 290 | */ 291 | #define GLUT_OVERLAY_POSSIBLE 0x0320 292 | #define GLUT_LAYER_IN_USE 0x0321 293 | #define GLUT_HAS_OVERLAY 0x0322 294 | #define GLUT_TRANSPARENT_INDEX 0x0323 295 | #define GLUT_NORMAL_DAMAGED 0x0324 296 | #define GLUT_OVERLAY_DAMAGED 0x0325 297 | 298 | /* 299 | * GLUT API macro definitions -- the glutVideoResizeGet parameters 300 | */ 301 | #define GLUT_VIDEO_RESIZE_POSSIBLE 0x0384 302 | #define GLUT_VIDEO_RESIZE_IN_USE 0x0385 303 | #define GLUT_VIDEO_RESIZE_X_DELTA 0x0386 304 | #define GLUT_VIDEO_RESIZE_Y_DELTA 0x0387 305 | #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 0x0388 306 | #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 0x0389 307 | #define GLUT_VIDEO_RESIZE_X 0x038A 308 | #define GLUT_VIDEO_RESIZE_Y 0x038B 309 | #define GLUT_VIDEO_RESIZE_WIDTH 0x038C 310 | #define GLUT_VIDEO_RESIZE_HEIGHT 0x038D 311 | 312 | /* 313 | * GLUT API macro definitions -- the glutUseLayer parameters 314 | */ 315 | #define GLUT_NORMAL 0x0000 316 | #define GLUT_OVERLAY 0x0001 317 | 318 | /* 319 | * GLUT API macro definitions -- the glutGetModifiers parameters 320 | */ 321 | #define GLUT_ACTIVE_SHIFT 0x0001 322 | #define GLUT_ACTIVE_CTRL 0x0002 323 | #define GLUT_ACTIVE_ALT 0x0004 324 | 325 | /* 326 | * GLUT API macro definitions -- the glutSetCursor parameters 327 | */ 328 | #define GLUT_CURSOR_RIGHT_ARROW 0x0000 329 | #define GLUT_CURSOR_LEFT_ARROW 0x0001 330 | #define GLUT_CURSOR_INFO 0x0002 331 | #define GLUT_CURSOR_DESTROY 0x0003 332 | #define GLUT_CURSOR_HELP 0x0004 333 | #define GLUT_CURSOR_CYCLE 0x0005 334 | #define GLUT_CURSOR_SPRAY 0x0006 335 | #define GLUT_CURSOR_WAIT 0x0007 336 | #define GLUT_CURSOR_TEXT 0x0008 337 | #define GLUT_CURSOR_CROSSHAIR 0x0009 338 | #define GLUT_CURSOR_UP_DOWN 0x000A 339 | #define GLUT_CURSOR_LEFT_RIGHT 0x000B 340 | #define GLUT_CURSOR_TOP_SIDE 0x000C 341 | #define GLUT_CURSOR_BOTTOM_SIDE 0x000D 342 | #define GLUT_CURSOR_LEFT_SIDE 0x000E 343 | #define GLUT_CURSOR_RIGHT_SIDE 0x000F 344 | #define GLUT_CURSOR_TOP_LEFT_CORNER 0x0010 345 | #define GLUT_CURSOR_TOP_RIGHT_CORNER 0x0011 346 | #define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 0x0012 347 | #define GLUT_CURSOR_BOTTOM_LEFT_CORNER 0x0013 348 | #define GLUT_CURSOR_INHERIT 0x0064 349 | #define GLUT_CURSOR_NONE 0x0065 350 | #define GLUT_CURSOR_FULL_CROSSHAIR 0x0066 351 | 352 | /* 353 | * GLUT API macro definitions -- RGB color component specification definitions 354 | */ 355 | #define GLUT_RED 0x0000 356 | #define GLUT_GREEN 0x0001 357 | #define GLUT_BLUE 0x0002 358 | 359 | /* 360 | * GLUT API macro definitions -- additional keyboard and joystick definitions 361 | */ 362 | #define GLUT_KEY_REPEAT_OFF 0x0000 363 | #define GLUT_KEY_REPEAT_ON 0x0001 364 | #define GLUT_KEY_REPEAT_DEFAULT 0x0002 365 | 366 | #define GLUT_JOYSTICK_BUTTON_A 0x0001 367 | #define GLUT_JOYSTICK_BUTTON_B 0x0002 368 | #define GLUT_JOYSTICK_BUTTON_C 0x0004 369 | #define GLUT_JOYSTICK_BUTTON_D 0x0008 370 | 371 | /* 372 | * GLUT API macro definitions -- game mode definitions 373 | */ 374 | #define GLUT_GAME_MODE_ACTIVE 0x0000 375 | #define GLUT_GAME_MODE_POSSIBLE 0x0001 376 | #define GLUT_GAME_MODE_WIDTH 0x0002 377 | #define GLUT_GAME_MODE_HEIGHT 0x0003 378 | #define GLUT_GAME_MODE_PIXEL_DEPTH 0x0004 379 | #define GLUT_GAME_MODE_REFRESH_RATE 0x0005 380 | #define GLUT_GAME_MODE_DISPLAY_CHANGED 0x0006 381 | 382 | /* 383 | * Initialization functions, see fglut_init.c 384 | */ 385 | FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv ); 386 | FGAPI void FGAPIENTRY glutInitWindowPosition( int x, int y ); 387 | FGAPI void FGAPIENTRY glutInitWindowSize( int width, int height ); 388 | FGAPI void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode ); 389 | FGAPI void FGAPIENTRY glutInitDisplayString( const char* displayMode ); 390 | 391 | /* 392 | * Process loop function, see freeglut_main.c 393 | */ 394 | FGAPI void FGAPIENTRY glutMainLoop( void ); 395 | 396 | /* 397 | * Window management functions, see freeglut_window.c 398 | */ 399 | FGAPI int FGAPIENTRY glutCreateWindow( const char* title ); 400 | FGAPI int FGAPIENTRY glutCreateSubWindow( int window, int x, int y, int width, int height ); 401 | FGAPI void FGAPIENTRY glutDestroyWindow( int window ); 402 | FGAPI void FGAPIENTRY glutSetWindow( int window ); 403 | FGAPI int FGAPIENTRY glutGetWindow( void ); 404 | FGAPI void FGAPIENTRY glutSetWindowTitle( const char* title ); 405 | FGAPI void FGAPIENTRY glutSetIconTitle( const char* title ); 406 | FGAPI void FGAPIENTRY glutReshapeWindow( int width, int height ); 407 | FGAPI void FGAPIENTRY glutPositionWindow( int x, int y ); 408 | FGAPI void FGAPIENTRY glutShowWindow( void ); 409 | FGAPI void FGAPIENTRY glutHideWindow( void ); 410 | FGAPI void FGAPIENTRY glutIconifyWindow( void ); 411 | FGAPI void FGAPIENTRY glutPushWindow( void ); 412 | FGAPI void FGAPIENTRY glutPopWindow( void ); 413 | FGAPI void FGAPIENTRY glutFullScreen( void ); 414 | 415 | /* 416 | * Display-connected functions, see freeglut_display.c 417 | */ 418 | FGAPI void FGAPIENTRY glutPostWindowRedisplay( int window ); 419 | FGAPI void FGAPIENTRY glutPostRedisplay( void ); 420 | FGAPI void FGAPIENTRY glutSwapBuffers( void ); 421 | 422 | /* 423 | * Mouse cursor functions, see freeglut_cursor.c 424 | */ 425 | FGAPI void FGAPIENTRY glutWarpPointer( int x, int y ); 426 | FGAPI void FGAPIENTRY glutSetCursor( int cursor ); 427 | 428 | /* 429 | * Overlay stuff, see freeglut_overlay.c 430 | */ 431 | FGAPI void FGAPIENTRY glutEstablishOverlay( void ); 432 | FGAPI void FGAPIENTRY glutRemoveOverlay( void ); 433 | FGAPI void FGAPIENTRY glutUseLayer( GLenum layer ); 434 | FGAPI void FGAPIENTRY glutPostOverlayRedisplay( void ); 435 | FGAPI void FGAPIENTRY glutPostWindowOverlayRedisplay( int window ); 436 | FGAPI void FGAPIENTRY glutShowOverlay( void ); 437 | FGAPI void FGAPIENTRY glutHideOverlay( void ); 438 | 439 | /* 440 | * Menu stuff, see freeglut_menu.c 441 | */ 442 | FGAPI int FGAPIENTRY glutCreateMenu( void (* callback)( int menu ) ); 443 | FGAPI void FGAPIENTRY glutDestroyMenu( int menu ); 444 | FGAPI int FGAPIENTRY glutGetMenu( void ); 445 | FGAPI void FGAPIENTRY glutSetMenu( int menu ); 446 | FGAPI void FGAPIENTRY glutAddMenuEntry( const char* label, int value ); 447 | FGAPI void FGAPIENTRY glutAddSubMenu( const char* label, int subMenu ); 448 | FGAPI void FGAPIENTRY glutChangeToMenuEntry( int item, const char* label, int value ); 449 | FGAPI void FGAPIENTRY glutChangeToSubMenu( int item, const char* label, int value ); 450 | FGAPI void FGAPIENTRY glutRemoveMenuItem( int item ); 451 | FGAPI void FGAPIENTRY glutAttachMenu( int button ); 452 | FGAPI void FGAPIENTRY glutDetachMenu( int button ); 453 | 454 | /* 455 | * Global callback functions, see freeglut_callbacks.c 456 | */ 457 | FGAPI void FGAPIENTRY glutTimerFunc( unsigned int time, void (* callback)( int ), int value ); 458 | FGAPI void FGAPIENTRY glutIdleFunc( void (* callback)( void ) ); 459 | 460 | /* 461 | * Window-specific callback functions, see freeglut_callbacks.c 462 | */ 463 | FGAPI void FGAPIENTRY glutKeyboardFunc( void (* callback)( unsigned char, int, int ) ); 464 | FGAPI void FGAPIENTRY glutSpecialFunc( void (* callback)( int, int, int ) ); 465 | FGAPI void FGAPIENTRY glutReshapeFunc( void (* callback)( int, int ) ); 466 | FGAPI void FGAPIENTRY glutVisibilityFunc( void (* callback)( int ) ); 467 | FGAPI void FGAPIENTRY glutDisplayFunc( void (* callback)( void ) ); 468 | FGAPI void FGAPIENTRY glutMouseFunc( void (* callback)( int, int, int, int ) ); 469 | FGAPI void FGAPIENTRY glutMotionFunc( void (* callback)( int, int ) ); 470 | FGAPI void FGAPIENTRY glutPassiveMotionFunc( void (* callback)( int, int ) ); 471 | FGAPI void FGAPIENTRY glutEntryFunc( void (* callback)( int ) ); 472 | 473 | FGAPI void FGAPIENTRY glutKeyboardUpFunc( void (* callback)( unsigned char, int, int ) ); 474 | FGAPI void FGAPIENTRY glutSpecialUpFunc( void (* callback)( int, int, int ) ); 475 | FGAPI void FGAPIENTRY glutJoystickFunc( void (* callback)( unsigned int, int, int, int ), int pollInterval ); 476 | FGAPI void FGAPIENTRY glutMenuStateFunc( void (* callback)( int ) ); 477 | FGAPI void FGAPIENTRY glutMenuStatusFunc( void (* callback)( int, int, int ) ); 478 | FGAPI void FGAPIENTRY glutOverlayDisplayFunc( void (* callback)( void ) ); 479 | FGAPI void FGAPIENTRY glutWindowStatusFunc( void (* callback)( int ) ); 480 | 481 | FGAPI void FGAPIENTRY glutSpaceballMotionFunc( void (* callback)( int, int, int ) ); 482 | FGAPI void FGAPIENTRY glutSpaceballRotateFunc( void (* callback)( int, int, int ) ); 483 | FGAPI void FGAPIENTRY glutSpaceballButtonFunc( void (* callback)( int, int ) ); 484 | FGAPI void FGAPIENTRY glutButtonBoxFunc( void (* callback)( int, int ) ); 485 | FGAPI void FGAPIENTRY glutDialsFunc( void (* callback)( int, int ) ); 486 | FGAPI void FGAPIENTRY glutTabletMotionFunc( void (* callback)( int, int ) ); 487 | FGAPI void FGAPIENTRY glutTabletButtonFunc( void (* callback)( int, int, int, int ) ); 488 | 489 | /* 490 | * State setting and retrieval functions, see freeglut_state.c 491 | */ 492 | FGAPI int FGAPIENTRY glutGet( GLenum query ); 493 | FGAPI int FGAPIENTRY glutDeviceGet( GLenum query ); 494 | FGAPI int FGAPIENTRY glutGetModifiers( void ); 495 | FGAPI int FGAPIENTRY glutLayerGet( GLenum query ); 496 | 497 | /* 498 | * Font stuff, see freeglut_font.c 499 | */ 500 | FGAPI void FGAPIENTRY glutBitmapCharacter( void* font, int character ); 501 | FGAPI int FGAPIENTRY glutBitmapWidth( void* font, int character ); 502 | FGAPI void FGAPIENTRY glutStrokeCharacter( void* font, int character ); 503 | FGAPI int FGAPIENTRY glutStrokeWidth( void* font, int character ); 504 | FGAPI int FGAPIENTRY glutBitmapLength( void* font, const unsigned char* string ); 505 | FGAPI int FGAPIENTRY glutStrokeLength( void* font, const unsigned char* string ); 506 | 507 | /* 508 | * Geometry functions, see freeglut_geometry.c 509 | */ 510 | FGAPI void FGAPIENTRY glutWireCube( GLdouble size ); 511 | FGAPI void FGAPIENTRY glutSolidCube( GLdouble size ); 512 | FGAPI void FGAPIENTRY glutWireSphere( GLdouble radius, GLint slices, GLint stacks ); 513 | FGAPI void FGAPIENTRY glutSolidSphere( GLdouble radius, GLint slices, GLint stacks ); 514 | FGAPI void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks ); 515 | FGAPI void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks ); 516 | 517 | FGAPI void FGAPIENTRY glutWireTorus( GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings ); 518 | FGAPI void FGAPIENTRY glutSolidTorus( GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings ); 519 | FGAPI void FGAPIENTRY glutWireDodecahedron( void ); 520 | FGAPI void FGAPIENTRY glutSolidDodecahedron( void ); 521 | FGAPI void FGAPIENTRY glutWireOctahedron( void ); 522 | FGAPI void FGAPIENTRY glutSolidOctahedron( void ); 523 | FGAPI void FGAPIENTRY glutWireTetrahedron( void ); 524 | FGAPI void FGAPIENTRY glutSolidTetrahedron( void ); 525 | FGAPI void FGAPIENTRY glutWireIcosahedron( void ); 526 | FGAPI void FGAPIENTRY glutSolidIcosahedron( void ); 527 | 528 | /* 529 | * Teapot rendering functions, found in freeglut_teapot.c 530 | */ 531 | FGAPI void FGAPIENTRY glutWireTeapot( GLdouble size ); 532 | FGAPI void FGAPIENTRY glutSolidTeapot( GLdouble size ); 533 | 534 | /* 535 | * Game mode functions, see freeglut_gamemode.c 536 | */ 537 | FGAPI void FGAPIENTRY glutGameModeString( const char* string ); 538 | FGAPI int FGAPIENTRY glutEnterGameMode( void ); 539 | FGAPI void FGAPIENTRY glutLeaveGameMode( void ); 540 | FGAPI int FGAPIENTRY glutGameModeGet( GLenum query ); 541 | 542 | /* 543 | * Video resize functions, see freeglut_videoresize.c 544 | */ 545 | FGAPI int FGAPIENTRY glutVideoResizeGet( GLenum query ); 546 | FGAPI void FGAPIENTRY glutSetupVideoResizing( void ); 547 | FGAPI void FGAPIENTRY glutStopVideoResizing( void ); 548 | FGAPI void FGAPIENTRY glutVideoResize( int x, int y, int width, int height ); 549 | FGAPI void FGAPIENTRY glutVideoPan( int x, int y, int width, int height ); 550 | 551 | /* 552 | * Colormap functions, see freeglut_misc.c 553 | */ 554 | FGAPI void FGAPIENTRY glutSetColor( int color, GLfloat red, GLfloat green, GLfloat blue ); 555 | FGAPI GLfloat FGAPIENTRY glutGetColor( int color, int component ); 556 | FGAPI void FGAPIENTRY glutCopyColormap( int window ); 557 | 558 | /* 559 | * Misc keyboard and joystick functions, see freeglut_misc.c 560 | */ 561 | FGAPI void FGAPIENTRY glutIgnoreKeyRepeat( int ignore ); 562 | FGAPI void FGAPIENTRY glutSetKeyRepeat( int repeatMode ); 563 | FGAPI void FGAPIENTRY glutForceJoystickFunc( void ); 564 | 565 | /* 566 | * Misc functions, see freeglut_misc.c 567 | */ 568 | FGAPI int FGAPIENTRY glutExtensionSupported( const char* extension ); 569 | FGAPI void FGAPIENTRY glutReportErrors( void ); 570 | 571 | /* Comment from glut.h of classic GLUT: 572 | 573 | Win32 has an annoying issue where there are multiple C run-time 574 | libraries (CRTs). If the executable is linked with a different CRT 575 | from the GLUT DLL, the GLUT DLL will not share the same CRT static 576 | data seen by the executable. In particular, atexit callbacks registered 577 | in the executable will not be called if GLUT calls its (different) 578 | exit routine). GLUT is typically built with the 579 | "/MD" option (the CRT with multithreading DLL support), but the Visual 580 | C++ linker default is "/ML" (the single threaded CRT). 581 | 582 | One workaround to this issue is requiring users to always link with 583 | the same CRT as GLUT is compiled with. That requires users supply a 584 | non-standard option. GLUT 3.7 has its own built-in workaround where 585 | the executable's "exit" function pointer is covertly passed to GLUT. 586 | GLUT then calls the executable's exit function pointer to ensure that 587 | any "atexit" calls registered by the application are called if GLUT 588 | needs to exit. 589 | 590 | Note that the __glut*WithExit routines should NEVER be called directly. 591 | To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ 592 | 593 | /* to get the prototype for exit() */ 594 | #include 595 | 596 | #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) && !defined(__WATCOMC__) 597 | FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); 598 | FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); 599 | FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int)); 600 | #ifndef FREEGLUT_BUILDING_LIB 601 | #if defined(__GNUC__) 602 | #define FGUNUSED __attribute__((unused)) 603 | #else 604 | #define FGUNUSED 605 | #endif 606 | static void FGAPIENTRY FGUNUSED glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } 607 | #define glutInit glutInit_ATEXIT_HACK 608 | static int FGAPIENTRY FGUNUSED glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } 609 | #define glutCreateWindow glutCreateWindow_ATEXIT_HACK 610 | static int FGAPIENTRY FGUNUSED glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); } 611 | #define glutCreateMenu glutCreateMenu_ATEXIT_HACK 612 | #endif 613 | #endif 614 | 615 | #ifdef __cplusplus 616 | } 617 | #endif 618 | 619 | /*** END OF FILE ***/ 620 | 621 | #endif /* __FREEGLUT_STD_H__ */ 622 | 623 | --------------------------------------------------------------------------------