├── releasenot.txt ├── .gitignore ├── VirtualDevice ├── VirtualDevice.h ├── VirtualDevice.vcxproj └── VirtualDevice.cpp ├── README.md ├── PathSetting.props ├── LICENSE ├── Samples ├── BasicSample │ ├── main.cpp │ └── BasicSample.vcxproj ├── NiTESample │ ├── VirtualDeviceHelper.h │ ├── main.cpp │ └── NiTESample.vcxproj ├── ExistedDeviceSample │ ├── main.cpp │ └── ExistedDevice.vcxproj └── DepthToWorldSample │ ├── OpenGLCamera.h │ ├── DepthToWorld.vcxproj │ └── main.cpp ├── VirtualDevice.sln └── APACHE_LICENSE_2 /releasenot.txt: -------------------------------------------------------------------------------- 1 | 2014/05/20 2 | Fix the bug that no properties of VideoStream when recording 3 | 4 | 2013/11/008 5 | First release -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /VirtualDevice/VirtualDevice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a simple example to show how to use the virtual device. 3 | * This sample will open an existed real device, read the depth frame with listener, 4 | * then copy to the virtual device. 5 | * 6 | * http://viml.nchc.org.tw/home/ 7 | */ 8 | 9 | #pragma once 10 | 11 | // definition of customized property 12 | #define GET_VIRTUAL_STREAM_IMAGE 100000 13 | #define SET_VIRTUAL_STREAM_IMAGE 100001 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VirtualDeviceForOpenNI2 2 | ======================= 3 | 4 | This project provides a virtual device module for OpenNI 2, which accept user feed any depth, color images. 5 | 6 | With the virtual device, you can: 7 | 8 | 1. create a device in OpenNI, to get the data from sensor with their own SDK 9 | 2. modify the raw data from sensor, let middleware libraries use modified data 10 | 11 | 12 | The pre-compiled binary for windows could be downlod: https://github.com/VIML/VirtualDeviceForOpenNI2/releases 13 | 14 | 15 | --- 16 | 17 | This is a free and Open Source project for non-commercial use. 18 | Please email us a note, if you use this product in any area of work. 19 | For commercial use, please contact us for further information. 20 | 21 | email: viml.nchc@gmail.com / charlie.nchc@gmail.com 22 | 23 | --- 24 | 25 | - More information: https://github.com/VIML/VirtualDeviceForOpenNI2/wiki 26 | - Chinese version: http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=509 27 | -------------------------------------------------------------------------------- /PathSetting.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(SolutionDir)\..\OpenNI2Dev\ 6 | $(SolutionDir)\..\..\OpenCV-2.4.6.0\opencv 7 | opencv_core246d.lib;opencv_highgui246d.lib;opencv_imgproc246d.lib 8 | opencv_core246.lib;opencv_highgui246.lib;opencv_imgproc246.lib 9 | 10 | 11 | 12 | $(OpenNI_SDK_Path) 13 | 14 | 15 | $(OpenCV_Path) 16 | 17 | 18 | $(OpenCV_Libs_Debug) 19 | 20 | 21 | $(OpenCV_Libs_Release) 22 | 23 | 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013, Visualization and Interactive Media Laboratory 2 | 3 | This product includes software developed at the "Visualization and 4 | Interactive Media Laboratory" at the "National Center for High-performance 5 | Computing" in Taiwan. 6 | 7 | Our website: http://viml.nchc.org.tw/ 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 10 | use this file except in compliance with the License. You may obtain a copy 11 | of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | 21 | Please email us a note, if you use this product in any area of work. 22 | Your feedback will give us the incentives to improve and evolve. 23 | 24 | For commercial use, please contact us for further information. 25 | 26 | email: viml.nchc@gmail.com / charlie.nchc@gmail.com 27 | -------------------------------------------------------------------------------- /Samples/BasicSample/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a basic example to show how to use the virtual device. 3 | * This sample will create a new thread to generate dummy frame, and read by OpenNI API. 4 | * 5 | * http://viml.nchc.org.tw/home/ 6 | */ 7 | 8 | // STL Header 9 | #include 10 | 11 | // OpenNI Header 12 | #include 13 | 14 | // XnLib in OpenNI Source Code, use for threading 15 | #include "XnLib.h" 16 | 17 | // Virtual Device Header 18 | #include "..\..\VirtualDevice\VirtualDevice.h" 19 | 20 | // namespace 21 | using namespace std; 22 | using namespace openni; 23 | 24 | // global object 25 | bool bRunning = true; 26 | 27 | // The function to generate dummy frame 28 | XN_THREAD_PROC GenerateDummyFrame( XN_THREAD_PARAM pThreadParam ) 29 | { 30 | VideoStream* pVStream = (VideoStream*)pThreadParam; 31 | 32 | while( bRunning ) 33 | { 34 | if( pVStream->isValid() ) 35 | { 36 | // get a frame form virtual video stream 37 | OniFrame* pFrame = NULL; 38 | if( pVStream->invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame ) == openni::STATUS_OK ) 39 | { 40 | // type casting 41 | DepthPixel* pVirData = reinterpret_cast( pFrame->data ); 42 | 43 | // Fill dummy data 44 | for( int y = 0; y < pFrame->height; ++ y ) 45 | { 46 | for( int x = 0; x < pFrame->width; ++ x ) 47 | { 48 | int idx = x + y * pFrame->width; 49 | pVirData[idx] = 100; 50 | } 51 | } 52 | 53 | // write data to form virtual video stream 54 | pVStream->invoke( SET_VIRTUAL_STREAM_IMAGE, pFrame ); 55 | 56 | } 57 | } 58 | 59 | // sleep 60 | xnOSSleep(33); 61 | } 62 | 63 | XN_THREAD_PROC_RETURN(XN_STATUS_OK); 64 | } 65 | 66 | int main( int, char** ) 67 | { 68 | #pragma region OpenNI initialize 69 | // Initial OpenNI 70 | if( OpenNI::initialize() != STATUS_OK ) 71 | { 72 | cerr << "OpenNI Initial Error: " << OpenNI::getExtendedError() << endl; 73 | return -1; 74 | } 75 | 76 | // Open Virtual Device 77 | Device devVirDevice; 78 | if( devVirDevice.open( "\\OpenNI2\\VirtualDevice\\TEST" ) != STATUS_OK ) 79 | { 80 | cerr << "Can't create virtual device: " << OpenNI::getExtendedError() << endl; 81 | return -1; 82 | } 83 | 84 | // create virtual color video stream 85 | VideoStream vsVirDepth; 86 | if( vsVirDepth.create( devVirDevice, SENSOR_DEPTH ) == STATUS_OK ) 87 | { 88 | VideoMode mMode; 89 | mMode.setFps( 30 ); 90 | mMode.setResolution( 320, 240 ); 91 | mMode.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM ); 92 | vsVirDepth.setVideoMode( mMode ); 93 | } 94 | else 95 | { 96 | cerr << "Can't create depth stream on device: " << OpenNI::getExtendedError() << endl; 97 | return -1; 98 | } 99 | #pragma endregion 100 | 101 | #pragma region main loop 102 | // start data generate 103 | vsVirDepth.start(); 104 | 105 | // create a new thread to generate dummy data 106 | XN_THREAD_HANDLE mThreadHandle; 107 | xnOSCreateThread( GenerateDummyFrame, &vsVirDepth, &mThreadHandle ); 108 | 109 | // use for-loop to read 100 frames 110 | for( int i = 0; i < 100; ++ i ) 111 | { 112 | VideoFrameRef mFrame; 113 | if( vsVirDepth.readFrame( &mFrame ) == STATUS_OK ) 114 | { 115 | const DepthPixel* pData = reinterpret_cast( mFrame.getData() ); 116 | cout << pData[ mFrame.getWidth() / 2 + ( mFrame.getHeight() / 2 ) * mFrame.getWidth() ] << endl; 117 | } 118 | } 119 | 120 | // stop data generate 121 | bRunning = false; 122 | vsVirDepth.stop(); 123 | 124 | // close device 125 | vsVirDepth.destroy(); 126 | devVirDevice.close(); 127 | 128 | // shutdown 129 | OpenNI::shutdown(); 130 | 131 | #pragma endregion 132 | 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /Samples/NiTESample/VirtualDeviceHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // STL Header 4 | #include 5 | #include 6 | 7 | // OpenNI Header 8 | #include 9 | #include 10 | 11 | // definition of customized property 12 | #define GET_VIRTUAL_STREAM_IMAGE 100000 13 | #define SET_VIRTUAL_STREAM_IMAGE 100001 14 | 15 | class CFrameModifer : public openni::VideoStream::NewFrameListener 16 | { 17 | public: 18 | typedef std::function TCallback; 19 | 20 | public: 21 | CFrameModifer( openni::VideoStream& rStream, TCallback func ) : m_rVStream( rStream ) 22 | { 23 | m_funcProccess = func; 24 | } 25 | 26 | void onNewFrame( openni::VideoStream& rStream ) 27 | { 28 | openni::VideoFrameRef mFrame; 29 | if( rStream.readFrame( &mFrame ) == openni::STATUS_OK ) 30 | { 31 | OniFrame* pFrame = NULL; 32 | if( m_rVStream.invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame ) == openni::STATUS_OK ) 33 | { 34 | m_funcProccess( *(mFrame._getFrame()), *pFrame ); 35 | m_rVStream.invoke( SET_VIRTUAL_STREAM_IMAGE, pFrame ); 36 | } 37 | } 38 | } 39 | 40 | protected: 41 | openni::VideoStream& m_rVStream; 42 | TCallback m_funcProccess; 43 | 44 | CFrameModifer& operator=(const CFrameModifer&); 45 | }; 46 | 47 | openni::VideoStream* CreateVirtualStream( openni::Device& rVDevice, openni::VideoStream& rStream, CFrameModifer::TCallback func ) 48 | { 49 | openni::VideoStream* pStream = new openni::VideoStream(); 50 | if( rStream.isValid() ) 51 | { 52 | const openni::SensorInfo& rInfo = rStream.getSensorInfo(); 53 | if( pStream->create( rVDevice, rInfo.getSensorType() ) == openni::STATUS_OK ) 54 | { 55 | // Set configuration 56 | 57 | pStream->setProperty( ONI_STREAM_PROPERTY_VERTICAL_FOV, rStream.getVerticalFieldOfView() ); 58 | pStream->setProperty( ONI_STREAM_PROPERTY_HORIZONTAL_FOV, rStream.getHorizontalFieldOfView() ); 59 | pStream->setProperty( ONI_STREAM_PROPERTY_MIRRORING, rStream.getMirroringEnabled() ); 60 | 61 | if( rInfo.getSensorType() == openni::SENSOR_DEPTH ) 62 | { 63 | pStream->setProperty( ONI_STREAM_PROPERTY_MIN_VALUE, rStream.getMinPixelValue() ); 64 | pStream->setProperty( ONI_STREAM_PROPERTY_MAX_VALUE, rStream.getMaxPixelValue() ); 65 | 66 | std::map mapProperties; 67 | mapProperties[XN_STREAM_PROPERTY_CONST_SHIFT] = 8; 68 | mapProperties[XN_STREAM_PROPERTY_PARAM_COEFF] = 8; 69 | mapProperties[XN_STREAM_PROPERTY_SHIFT_SCALE] = 8; 70 | mapProperties[XN_STREAM_PROPERTY_MAX_SHIFT] = 8; 71 | mapProperties[XN_STREAM_PROPERTY_S2D_TABLE] = 4096; 72 | mapProperties[XN_STREAM_PROPERTY_D2S_TABLE] = 20002; 73 | mapProperties[XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE] = 8; 74 | mapProperties[XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE] = 8; 75 | mapProperties[XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE] = 8; 76 | 77 | for( auto itProp = mapProperties.begin(); itProp != mapProperties.end(); ++ itProp ) 78 | { 79 | int iSize = itProp->second; 80 | char* pData = new char[itProp->second]; 81 | if( rStream.getProperty( itProp->first, pData, &iSize ) == openni::STATUS_OK ) 82 | { 83 | pStream->setProperty( itProp->first, pData, iSize ); 84 | } 85 | else 86 | { 87 | std::cerr << "This VideoStream doesn't provide property [" << itProp->first << "], which is required for NiTE2" << std::endl; 88 | } 89 | delete [] pData; 90 | } 91 | } 92 | pStream->setVideoMode( rStream.getVideoMode() ); 93 | 94 | // add listener 95 | rStream.addNewFrameListener( new CFrameModifer( *pStream, func ) ); 96 | } 97 | } 98 | return pStream; 99 | } 100 | -------------------------------------------------------------------------------- /Samples/ExistedDeviceSample/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a simple example to show how to use the virtual device. 3 | * This sample will open an existed real device, read the depth frame with listener, 4 | * then copy to the virtual device. 5 | * 6 | * http://viml.nchc.org.tw/home/ 7 | */ 8 | 9 | // STL Header 10 | #include 11 | 12 | // OpenNI Header 13 | #include 14 | 15 | // Virtual Device Header 16 | #include "..\..\VirtualDevice\VirtualDevice.h" 17 | 18 | // namespace 19 | using namespace std; 20 | using namespace openni; 21 | 22 | // the NewFrameListener 23 | class CFrameModifer : public VideoStream::NewFrameListener 24 | { 25 | public: 26 | CFrameModifer( VideoStream& rStream ) : m_rVStream( rStream ) 27 | { 28 | } 29 | 30 | void onNewFrame( openni::VideoStream& rStream ) 31 | { 32 | openni::VideoFrameRef mFrame; 33 | // read frame from real video stream 34 | if( rStream.readFrame( &mFrame ) == openni::STATUS_OK ) 35 | { 36 | // get a frame form virtual video stream 37 | OniFrame* pFrame = NULL; 38 | if( m_rVStream.invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame ) == openni::STATUS_OK ) 39 | { 40 | // type casting 41 | const DepthPixel* pRealData = reinterpret_cast( mFrame.getData() ); 42 | DepthPixel* pVirData = reinterpret_cast( pFrame->data ); 43 | 44 | // read data from the frame of real sensor, and write to the frame of virtual sensor 45 | for( int y = 0; y < mFrame.getHeight(); ++ y ) 46 | { 47 | for( int x = 0; x < mFrame.getWidth(); ++ x ) 48 | { 49 | int idx = x + y * mFrame.getWidth(); 50 | pVirData[idx] = pRealData[idx]; 51 | } 52 | } 53 | 54 | // write data to form virtual video stream 55 | m_rVStream.invoke( SET_VIRTUAL_STREAM_IMAGE, pFrame ); 56 | } 57 | } 58 | } 59 | 60 | protected: 61 | openni::VideoStream& m_rVStream; 62 | 63 | CFrameModifer& operator=(const CFrameModifer&); 64 | }; 65 | 66 | int main( int, char** ) 67 | { 68 | #pragma region OpenNI initialize 69 | // Initial OpenNI 70 | if( OpenNI::initialize() != STATUS_OK ) 71 | { 72 | cerr << "OpenNI Initial Error: " << OpenNI::getExtendedError() << endl; 73 | return -1; 74 | } 75 | 76 | // Open a real device 77 | Device devRealSensor; 78 | if( devRealSensor.open( ANY_DEVICE ) != STATUS_OK ) 79 | { 80 | cerr << "Can't Open Device: " << OpenNI::getExtendedError() << endl; 81 | return -1; 82 | } 83 | 84 | // Create depth stream 85 | VideoStream vsRealDepth; 86 | if( devRealSensor.hasSensor( SENSOR_DEPTH ) ) 87 | { 88 | if( vsRealDepth.create( devRealSensor, SENSOR_DEPTH ) != STATUS_OK ) 89 | { 90 | cerr << "Can't create depth stream on device: " << OpenNI::getExtendedError() << endl; 91 | return -1; 92 | } 93 | } 94 | else 95 | { 96 | cerr << "ERROR: This device does not have depth sensor" << endl; 97 | return -1; 98 | } 99 | #pragma endregion 100 | 101 | #pragma region Virtual Device 102 | // Open Virtual Device 103 | Device devVirDevice; 104 | if( devVirDevice.open( "\\OpenNI2\\VirtualDevice\\TEST" ) != STATUS_OK ) 105 | { 106 | cerr << "Can't create virtual device: " << OpenNI::getExtendedError() << endl; 107 | return -1; 108 | } 109 | 110 | // create virtual color video stream 111 | VideoStream vsVirDepth; 112 | CFrameModifer mCopyDepth(vsVirDepth); 113 | if( vsVirDepth.create( devVirDevice, SENSOR_DEPTH ) == STATUS_OK ) 114 | { 115 | vsVirDepth.setVideoMode( vsRealDepth.getVideoMode() ); 116 | 117 | // add new frame listener to real video stream 118 | vsRealDepth.addNewFrameListener( &mCopyDepth ); 119 | } 120 | else 121 | { 122 | cerr << "Can't create depth stream on device: " << OpenNI::getExtendedError() << endl; 123 | return -1; 124 | } 125 | #pragma endregion 126 | 127 | #pragma region main loop 128 | // start data generate 129 | vsVirDepth.start(); 130 | vsRealDepth.start(); 131 | 132 | // use for-loop to read 100 frames 133 | for( int i = 0; i < 100; ++ i ) 134 | { 135 | VideoFrameRef mFrame; 136 | if( vsVirDepth.readFrame( &mFrame ) == STATUS_OK ) 137 | { 138 | const DepthPixel* pData = reinterpret_cast( mFrame.getData() ); 139 | cout << pData[ mFrame.getWidth() / 2 + ( mFrame.getHeight() / 2 ) * mFrame.getWidth() ] << endl; 140 | } 141 | } 142 | 143 | // remove listener 144 | vsRealDepth.removeNewFrameListener( &mCopyDepth ); 145 | 146 | // stop data generate 147 | vsVirDepth.stop(); 148 | vsRealDepth.stop(); 149 | 150 | // close device 151 | vsVirDepth.destroy(); 152 | vsRealDepth.destroy(); 153 | devVirDevice.close(); 154 | devRealSensor.close(); 155 | 156 | // shutdown 157 | OpenNI::shutdown(); 158 | 159 | #pragma endregion 160 | 161 | return 0; 162 | } 163 | -------------------------------------------------------------------------------- /Samples/DepthToWorldSample/OpenGLCamera.h: -------------------------------------------------------------------------------- 1 | // Basic vector and camera operation for OpenGL 3D 2 | // 3 | // by Heresy 4 | // http://kheresy.wordpress.com 5 | // 6 | // version 1.02 @2013/03/11 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | // glut Header 13 | #include 14 | 15 | class Vector3 16 | { 17 | public: 18 | float v[3]; 19 | 20 | public: 21 | Vector3() 22 | { 23 | v[0] = 0; 24 | v[1] = 0; 25 | v[2] = 0; 26 | } 27 | 28 | Vector3( float x, float y, float z ) 29 | { 30 | v[0] = x; 31 | v[1] = y; 32 | v[2] = z; 33 | } 34 | 35 | Vector3( const Vector3& rV ) 36 | { 37 | v[0] = rV.v[0]; 38 | v[1] = rV.v[1]; 39 | v[2] = rV.v[2]; 40 | } 41 | 42 | Vector3 operator+( const Vector3& rV2 ) const 43 | { 44 | return Vector3( v[0] + rV2.v[0], v[1] + rV2.v[1], v[2] + rV2.v[2] ); 45 | } 46 | 47 | Vector3 operator-( const Vector3& rV2 ) const 48 | { 49 | return Vector3( v[0] - rV2.v[0], v[1] - rV2.v[1], v[2] - rV2.v[2] ); 50 | } 51 | 52 | Vector3 operator*( float fScale ) const 53 | { 54 | return Vector3( v[0] * fScale, v[1] * fScale, v[2] * fScale ); 55 | } 56 | 57 | float Length() const 58 | { 59 | return sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] ); 60 | } 61 | 62 | Vector3 Normalize() const 63 | { 64 | float fLength = Length(); 65 | return Vector3( v[0] / fLength, v[1] / fLength, v[2] / fLength ); 66 | } 67 | 68 | Vector3 Cross( const Vector3& rV ) const 69 | { 70 | return Vector3( v[1] * rV.v[2] - v[2] * rV.v[1], 71 | v[2] * rV.v[0] - v[0] * rV.v[2], 72 | v[0] * rV.v[1] - v[1] * rV.v[0] ); 73 | } 74 | 75 | float Dot( const Vector3& rV ) const 76 | { 77 | return v[0] * rV.v[0] + v[1] * rV.v[1] + v[2] * rV.v[2]; 78 | } 79 | }; 80 | 81 | class Matrix3 82 | { 83 | public: 84 | float m[3][3]; 85 | 86 | public: 87 | Matrix3() 88 | { 89 | m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; 90 | m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; 91 | m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; 92 | } 93 | 94 | Matrix3( float w, float x, float y, float z ) 95 | { 96 | // normalize 97 | const float n = 1.0f / sqrt( x * x + y * y + z * z + w * w ); 98 | x *= n; 99 | y *= n; 100 | z *= n; 101 | w *= n; 102 | 103 | m[0][0] = 1 - 2 * y * y - 2 * z * z; 104 | m[0][1] = 2 * x * y - 2 * z * w; 105 | m[0][2] = 2 * x * z + 2 * y * w; 106 | m[1][0] = 2 * x * y + 2 * z * w; 107 | m[1][1] = 1 - 2 * x * x - 2 * z * z; 108 | m[1][2] = 2 * y * z - 2 * x * w; 109 | m[2][0] = 2 * x * z - 2 * y * w; 110 | m[2][1] = 2 * y * z + 2 * x * w; 111 | m[2][2] = 1 - 2 * x * x - 2 * y * y; 112 | } 113 | 114 | Vector3 operator*( const Vector3& rV ) const 115 | { 116 | return Vector3( m[0][0] * rV.v[0] + m[0][1] * rV.v[1] + m[0][2] * rV.v[2], 117 | m[1][0] * rV.v[0] + m[1][1] * rV.v[1] + m[1][2] * rV.v[2], 118 | m[2][0] * rV.v[0] + m[2][1] * rV.v[1] + m[2][2] * rV.v[2] ); 119 | } 120 | 121 | Matrix3 operator*( const Matrix3& rM ) const 122 | { 123 | Matrix3 mR; 124 | for( int y = 0; y < 3; ++ y ) 125 | { 126 | for( int x = 0; x < 3; ++ x ) 127 | { 128 | float v = 0; 129 | for( int i = 0; i < 3; ++ i ) 130 | v += m[y][i] * rM.m[i][x]; 131 | 132 | mR.m[x][y] = v; 133 | } 134 | } 135 | return mR; 136 | } 137 | }; 138 | 139 | // A class of simple camera control 140 | class SimpleCamera 141 | { 142 | public: 143 | Vector3 vPosition; 144 | Vector3 vCenter; 145 | Vector3 vLook; 146 | Vector3 vUpper; 147 | Vector3 vSide; 148 | 149 | void Update() 150 | { 151 | vLook = ( vCenter - vPosition ).Normalize(); 152 | vSide = vLook.Cross( vUpper ); 153 | vUpper = vSide.Cross( vLook ); 154 | } 155 | 156 | void SetCamera() 157 | { 158 | Update(); 159 | glMatrixMode( GL_MODELVIEW ); 160 | glLoadIdentity(); 161 | gluLookAt( vPosition.v[0], vPosition.v[1], vPosition.v[2], 162 | vCenter.v[0], vCenter.v[1], vCenter.v[2], 163 | vUpper.v[0], vUpper.v[1], vUpper.v[2] ); 164 | } 165 | 166 | void MoveSide( float fDistance ) 167 | { 168 | vPosition = vPosition + vSide * fDistance; 169 | vCenter = vCenter + vSide * fDistance; 170 | SetCamera(); 171 | } 172 | 173 | void MoveForward( float fDistance ) 174 | { 175 | vPosition = vPosition + vLook * fDistance; 176 | vCenter = vCenter + vLook * fDistance; 177 | SetCamera(); 178 | } 179 | 180 | void MoveUp( float fDistance ) 181 | { 182 | vPosition = vPosition + vUpper * fDistance; 183 | vCenter = vCenter + vUpper * fDistance; 184 | SetCamera(); 185 | } 186 | 187 | void RotateUp( float fR ) 188 | { 189 | fR *= ( vPosition - vCenter ).Length(); 190 | vCenter = vCenter + vUpper * fR; 191 | SetCamera(); 192 | } 193 | 194 | void RotateSide( float fR ) 195 | { 196 | fR *= ( vPosition - vCenter ).Length(); 197 | vCenter = vCenter + vSide * fR; 198 | SetCamera(); 199 | } 200 | }; 201 | -------------------------------------------------------------------------------- /VirtualDevice.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VirtualDevice", "VirtualDevice\VirtualDevice.vcxproj", "{DAFA5887-D67D-495F-8FC5-01CD24A70CE5}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{3720F158-247F-4FBB-A131-2D81599E794E}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NiTESample", "Samples\NiTESample\NiTESample.vcxproj", "{F6125DDF-7B0D-48C0-A0EC-D09780C438FA}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DepthToWorldSample", "Samples\DepthToWorldSample\DepthToWorld.vcxproj", "{F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExistedDeviceSample", "Samples\ExistedDeviceSample\ExistedDevice.vcxproj", "{9C80FE73-5990-4043-9A2C-EDF99C7BAF48}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicSample", "Samples\BasicSample\BasicSample.vcxproj", "{A368BED9-CE9B-4B1C-BD07-3647094A4099}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Win32 = Debug|Win32 19 | Debug|x64 = Debug|x64 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Debug|Win32.ActiveCfg = Debug|Win32 25 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Debug|Win32.Build.0 = Debug|Win32 26 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Debug|x64.ActiveCfg = Debug|x64 27 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Debug|x64.Build.0 = Debug|x64 28 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Release|Win32.ActiveCfg = Release|Win32 29 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Release|Win32.Build.0 = Release|Win32 30 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Release|x64.ActiveCfg = Release|x64 31 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5}.Release|x64.Build.0 = Release|x64 32 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Debug|Win32.Build.0 = Debug|Win32 34 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Debug|x64.ActiveCfg = Debug|x64 35 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Debug|x64.Build.0 = Debug|x64 36 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Release|Win32.ActiveCfg = Release|Win32 37 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Release|Win32.Build.0 = Release|Win32 38 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Release|x64.ActiveCfg = Release|x64 39 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA}.Release|x64.Build.0 = Release|x64 40 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Debug|Win32.Build.0 = Debug|Win32 42 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Debug|x64.ActiveCfg = Debug|x64 43 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Debug|x64.Build.0 = Debug|x64 44 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Release|Win32.ActiveCfg = Release|Win32 45 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Release|Win32.Build.0 = Release|Win32 46 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Release|x64.ActiveCfg = Release|x64 47 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E}.Release|x64.Build.0 = Release|x64 48 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Debug|Win32.ActiveCfg = Debug|Win32 49 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Debug|Win32.Build.0 = Debug|Win32 50 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Debug|x64.ActiveCfg = Debug|x64 51 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Debug|x64.Build.0 = Debug|x64 52 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Release|Win32.ActiveCfg = Release|Win32 53 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Release|Win32.Build.0 = Release|Win32 54 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Release|x64.ActiveCfg = Release|x64 55 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48}.Release|x64.Build.0 = Release|x64 56 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Debug|Win32.ActiveCfg = Debug|Win32 57 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Debug|Win32.Build.0 = Debug|Win32 58 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Debug|x64.ActiveCfg = Debug|x64 59 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Debug|x64.Build.0 = Debug|x64 60 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Release|Win32.ActiveCfg = Release|Win32 61 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Release|Win32.Build.0 = Release|Win32 62 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Release|x64.ActiveCfg = Release|x64 63 | {A368BED9-CE9B-4B1C-BD07-3647094A4099}.Release|x64.Build.0 = Release|x64 64 | EndGlobalSection 65 | GlobalSection(SolutionProperties) = preSolution 66 | HideSolutionNode = FALSE 67 | EndGlobalSection 68 | GlobalSection(NestedProjects) = preSolution 69 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA} = {3720F158-247F-4FBB-A131-2D81599E794E} 70 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E} = {3720F158-247F-4FBB-A131-2D81599E794E} 71 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48} = {3720F158-247F-4FBB-A131-2D81599E794E} 72 | {A368BED9-CE9B-4B1C-BD07-3647094A4099} = {3720F158-247F-4FBB-A131-2D81599E794E} 73 | EndGlobalSection 74 | EndGlobal 75 | -------------------------------------------------------------------------------- /Samples/NiTESample/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a simple example to show how to use the virtual device. 3 | * This sample will open an existed real device, read the depth frame with listener, 4 | * then copy to the virtual device. 5 | * 6 | * http://viml.nchc.org.tw/home/ 7 | */ 8 | 9 | // STL Header 10 | #include 11 | 12 | // OpenCV Header 13 | #include 14 | #include 15 | #include 16 | 17 | // NiTE Header 18 | #include 19 | 20 | #include "VirtualDeviceHelper.h" 21 | 22 | // namespace 23 | using namespace std; 24 | using namespace nite; 25 | 26 | int main( int, char** ) 27 | { 28 | openni::OpenNI::initialize(); 29 | openni::Device mDevice; 30 | mDevice.open( openni::ANY_DEVICE ); 31 | auto x = mDevice.getDeviceInfo(); 32 | 33 | openni::VideoStream vsDepth; 34 | vsDepth.create( mDevice, openni::SENSOR_DEPTH ); 35 | vsDepth.setMirroringEnabled(true); 36 | 37 | openni::Device virDevice; 38 | virDevice.open( "\\OpenNI2\\VirtualDevice\\Kinect" ); 39 | openni::VideoStream* virDepth = CreateVirtualStream( virDevice, vsDepth, []( const OniFrame& rF1,OniFrame& rF2 ){ 40 | openni::DepthPixel* pImg1 = reinterpret_cast(rF1.data); 41 | openni::DepthPixel* pImg2 = reinterpret_cast(rF2.data); 42 | 43 | for( int y = 0; y < rF2.height; ++ y ) 44 | { 45 | for( int x = 0; x < rF2.width; ++ x ) 46 | { 47 | int idx = x + y * rF2.width; 48 | const openni::DepthPixel& rDepth = pImg1[ idx ]; 49 | if( rDepth > 3000 ) 50 | pImg2[ idx ] = 0; 51 | else 52 | pImg2[ idx ] = rDepth; 53 | } 54 | } 55 | } ); 56 | 57 | vsDepth.start(); 58 | virDepth->start(); 59 | 60 | // Initial NiTE 61 | if( NiTE::initialize() != STATUS_OK ) 62 | { 63 | cerr << "NiTE initial error" << endl; 64 | return -1; 65 | } 66 | 67 | // create user tracker 68 | UserTracker mUserTracker; 69 | if( mUserTracker.create( &virDevice ) != STATUS_OK ) 70 | { 71 | cerr << "Can't create user tracker" << endl; 72 | return -1; 73 | } 74 | 75 | // create OpenCV Window 76 | cv::namedWindow( "User Image", CV_WINDOW_AUTOSIZE ); 77 | 78 | // start 79 | while( true ) 80 | { 81 | // get user frame 82 | UserTrackerFrameRef mUserFrame; 83 | if( mUserTracker.readFrame( &mUserFrame )== nite::STATUS_OK ) 84 | { 85 | // get depth data and convert to OpenCV format 86 | openni::VideoFrameRef vfDepthFrame = mUserFrame.getDepthFrame(); 87 | const cv::Mat mImageDepth( vfDepthFrame.getHeight(), vfDepthFrame.getWidth(), CV_16UC1, const_cast( vfDepthFrame.getData() ) ); 88 | // re-map depth data [0,Max] to [0,255] 89 | cv::Mat mScaledDepth; 90 | mImageDepth.convertTo( mScaledDepth, CV_8U, 255.0 / 10000 ); 91 | 92 | // convert gray-scale to color 93 | cv::Mat mImageBGR; 94 | cv::cvtColor( mScaledDepth, mImageBGR, CV_GRAY2BGR ); 95 | 96 | // get users data 97 | const nite::Array& aUsers = mUserFrame.getUsers(); 98 | for( int i = 0; i < aUsers.getSize(); ++ i ) 99 | { 100 | const UserData& rUser = aUsers[i]; 101 | 102 | // check user status 103 | if( rUser.isNew() ) 104 | { 105 | cout << "New User [" << rUser.getId() << "] found." << endl; 106 | // 5a. start tracking for new user 107 | mUserTracker.startSkeletonTracking( rUser.getId() ); 108 | } 109 | else if( rUser.isLost() ) 110 | { 111 | cout << "User [" << rUser.getId() << "] lost." << endl; 112 | } 113 | 114 | if( rUser.isVisible() ) 115 | { 116 | // get user skeleton 117 | const Skeleton& rSkeleton = rUser.getSkeleton(); 118 | if( rSkeleton.getState() == SKELETON_TRACKED ) 119 | { 120 | // build joints array 121 | nite::SkeletonJoint aJoints[15]; 122 | aJoints[ 0] = rSkeleton.getJoint( JOINT_HEAD ); 123 | aJoints[ 1] = rSkeleton.getJoint( JOINT_NECK ); 124 | aJoints[ 2] = rSkeleton.getJoint( JOINT_LEFT_SHOULDER ); 125 | aJoints[ 3] = rSkeleton.getJoint( JOINT_RIGHT_SHOULDER ); 126 | aJoints[ 4] = rSkeleton.getJoint( JOINT_LEFT_ELBOW ); 127 | aJoints[ 5] = rSkeleton.getJoint( JOINT_RIGHT_ELBOW ); 128 | aJoints[ 6] = rSkeleton.getJoint( JOINT_LEFT_HAND ); 129 | aJoints[ 7] = rSkeleton.getJoint( JOINT_RIGHT_HAND ); 130 | aJoints[ 8] = rSkeleton.getJoint( JOINT_TORSO ); 131 | aJoints[ 9] = rSkeleton.getJoint( JOINT_LEFT_HIP ); 132 | aJoints[10] = rSkeleton.getJoint( JOINT_RIGHT_HIP ); 133 | aJoints[11] = rSkeleton.getJoint( JOINT_LEFT_KNEE ); 134 | aJoints[12] = rSkeleton.getJoint( JOINT_RIGHT_KNEE ); 135 | aJoints[13] = rSkeleton.getJoint( JOINT_LEFT_FOOT ); 136 | aJoints[14] = rSkeleton.getJoint( JOINT_RIGHT_FOOT ); 137 | 138 | // convert joint position to image 139 | cv::Point2f aPoint[15]; 140 | for( int s = 0; s < 15; ++ s ) 141 | { 142 | const Point3f& rPos = aJoints[s].getPosition(); 143 | mUserTracker.convertJointCoordinatesToDepth( rPos.x, rPos.y, rPos.z, &(aPoint[s].x), &(aPoint[s].y) ); 144 | } 145 | 146 | // draw line 147 | cv::line( mImageBGR, aPoint[ 0], aPoint[ 1], cv::Scalar( 255, 0, 0 ), 3 ); 148 | cv::line( mImageBGR, aPoint[ 1], aPoint[ 2], cv::Scalar( 255, 0, 0 ), 3 ); 149 | cv::line( mImageBGR, aPoint[ 1], aPoint[ 3], cv::Scalar( 255, 0, 0 ), 3 ); 150 | cv::line( mImageBGR, aPoint[ 2], aPoint[ 4], cv::Scalar( 255, 0, 0 ), 3 ); 151 | cv::line( mImageBGR, aPoint[ 3], aPoint[ 5], cv::Scalar( 255, 0, 0 ), 3 ); 152 | cv::line( mImageBGR, aPoint[ 4], aPoint[ 6], cv::Scalar( 255, 0, 0 ), 3 ); 153 | cv::line( mImageBGR, aPoint[ 5], aPoint[ 7], cv::Scalar( 255, 0, 0 ), 3 ); 154 | cv::line( mImageBGR, aPoint[ 1], aPoint[ 8], cv::Scalar( 255, 0, 0 ), 3 ); 155 | cv::line( mImageBGR, aPoint[ 8], aPoint[ 9], cv::Scalar( 255, 0, 0 ), 3 ); 156 | cv::line( mImageBGR, aPoint[ 8], aPoint[10], cv::Scalar( 255, 0, 0 ), 3 ); 157 | cv::line( mImageBGR, aPoint[ 9], aPoint[11], cv::Scalar( 255, 0, 0 ), 3 ); 158 | cv::line( mImageBGR, aPoint[10], aPoint[12], cv::Scalar( 255, 0, 0 ), 3 ); 159 | cv::line( mImageBGR, aPoint[11], aPoint[13], cv::Scalar( 255, 0, 0 ), 3 ); 160 | cv::line( mImageBGR, aPoint[12], aPoint[14], cv::Scalar( 255, 0, 0 ), 3 ); 161 | 162 | // draw joint 163 | for( int s = 0; s < 15; ++ s ) 164 | { 165 | if( aJoints[s].getPositionConfidence() > 0.5 ) 166 | cv::circle( mImageBGR, aPoint[s], 3, cv::Scalar( 0, 0, 255 ), 2 ); 167 | else 168 | cv::circle( mImageBGR, aPoint[s], 3, cv::Scalar( 0, 255, 0 ), 2 ); 169 | } 170 | } 171 | } 172 | } 173 | 174 | // show image 175 | cv::imshow( "User Image", mImageBGR ); 176 | 177 | mUserFrame.release(); 178 | } 179 | else 180 | { 181 | cerr << "Can't get user frame" << endl; 182 | } 183 | 184 | // check keyboard 185 | if( cv::waitKey( 1 ) == 'q' ) 186 | break; 187 | } 188 | 189 | // stop 190 | mUserTracker.destroy(); 191 | virDepth->destroy(); 192 | vsDepth.destroy(); 193 | mDevice.close(); 194 | virDevice.close(); 195 | 196 | NiTE::shutdown(); 197 | openni::OpenNI::shutdown(); 198 | 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /Samples/ExistedDeviceSample/ExistedDevice.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {9C80FE73-5990-4043-9A2C-EDF99C7BAF48} 23 | SimpleViewer 24 | ExistedDeviceSample 25 | 26 | 27 | 28 | Application 29 | true 30 | MultiByte 31 | 32 | 33 | Application 34 | true 35 | MultiByte 36 | 37 | 38 | Application 39 | false 40 | true 41 | MultiByte 42 | 43 | 44 | Application 45 | false 46 | true 47 | MultiByte 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 67 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 68 | 69 | 70 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 71 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 72 | 73 | 74 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 75 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 79 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 80 | 81 | 82 | 83 | Disabled 84 | $(OPENNI2_INCLUDE) 85 | _WINDLL;%(PreprocessorDefinitions) 86 | Level4 87 | true 88 | false 89 | 90 | 91 | 92 | 93 | true 94 | OpenNI2.lib; 95 | $(OPENNI2_LIB); 96 | true 97 | 98 | 99 | 100 | 101 | Disabled 102 | $(OPENNI2_INCLUDE) 103 | _WINDLL;%(PreprocessorDefinitions) 104 | Level4 105 | true 106 | false 107 | 108 | 109 | 110 | 111 | true 112 | OpenNI2.lib; 113 | $(OPENNI2_LIB64); 114 | true 115 | 116 | 117 | 118 | 119 | Level4 120 | MaxSpeed 121 | true 122 | $(OPENNI2_INCLUDE) 123 | true 124 | AnySuitable 125 | Speed 126 | true 127 | true 128 | false 129 | StreamingSIMDExtensions2 130 | Fast 131 | false 132 | 133 | 134 | true 135 | true 136 | true 137 | OpenNI2.lib; 138 | $(OPENNI2_LIB); 139 | true 140 | 141 | 142 | 143 | 144 | Level4 145 | MaxSpeed 146 | true 147 | $(OPENNI2_INCLUDE) 148 | true 149 | AnySuitable 150 | Speed 151 | true 152 | true 153 | false 154 | StreamingSIMDExtensions2 155 | Fast 156 | false 157 | 158 | 159 | true 160 | true 161 | true 162 | OpenNI2.lib; 163 | $(OPENNI2_LIB64); 164 | true 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /Samples/DepthToWorldSample/DepthToWorld.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F9A3BCB8-4BFE-4DA7-A43C-8DAC09DFE03E} 23 | SimpleViewer 24 | DepthToWorldSample 25 | 26 | 27 | 28 | Application 29 | true 30 | MultiByte 31 | 32 | 33 | Application 34 | true 35 | MultiByte 36 | 37 | 38 | Application 39 | false 40 | true 41 | MultiByte 42 | 43 | 44 | Application 45 | false 46 | true 47 | MultiByte 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 71 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 72 | 73 | 74 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 75 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 79 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 80 | 81 | 82 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 83 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 84 | 85 | 86 | 87 | Disabled 88 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\GL\ 89 | _WINDLL;%(PreprocessorDefinitions) 90 | Level4 91 | true 92 | false 93 | 94 | 95 | 96 | 97 | true 98 | OpenNI2.lib;glut32.lib 99 | $(OPENNI2_LIB);$(OpenNI_SDK_Path)\ThirdParty\GL 100 | true 101 | 102 | 103 | 104 | 105 | Disabled 106 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\GL\ 107 | _WINDLL;%(PreprocessorDefinitions) 108 | Level4 109 | true 110 | false 111 | 112 | 113 | 114 | 115 | true 116 | OpenNI2.lib;glut64.lib 117 | $(OPENNI2_LIB64);$(OpenNI_SDK_Path)\ThirdParty\GL 118 | true 119 | 120 | 121 | 122 | 123 | Level4 124 | MaxSpeed 125 | true 126 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\GL\ 127 | true 128 | AnySuitable 129 | Speed 130 | true 131 | true 132 | false 133 | StreamingSIMDExtensions2 134 | Fast 135 | false 136 | 137 | 138 | true 139 | true 140 | true 141 | OpenNI2.lib;glut32.lib 142 | $(OPENNI2_LIB);$(OpenNI_SDK_Path)\ThirdParty\GL 143 | true 144 | 145 | 146 | 147 | 148 | Level4 149 | MaxSpeed 150 | true 151 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\GL\ 152 | true 153 | AnySuitable 154 | Speed 155 | true 156 | true 157 | false 158 | StreamingSIMDExtensions2 159 | Fast 160 | false 161 | 162 | 163 | true 164 | true 165 | true 166 | OpenNI2.lib;glut64.lib 167 | $(OPENNI2_LIB64);$(OpenNI_SDK_Path)\ThirdParty\GL 168 | true 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /Samples/DepthToWorldSample/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a simple example to show how to use the virtual device. 3 | * This sample will open an existed real device, read the depth frame with listener, 4 | * then copy to the virtual device. 5 | * 6 | * http://viml.nchc.org.tw/home/ 7 | */ 8 | 9 | // STL Header 10 | #include 11 | 12 | // glut Header 13 | #include 14 | 15 | // OpenNI Header 16 | #include 17 | 18 | #include "OpenGLCamera.h" 19 | 20 | // namespace 21 | using namespace std; 22 | using namespace openni; 23 | 24 | #pragma region global objects 25 | 26 | // global OpenNI object 27 | struct SDevice 28 | { 29 | Device devDevice; 30 | VideoStream vsDepth; 31 | VideoStream vsColor; 32 | } g_Device[2]; 33 | 34 | // global object 35 | SimpleCamera g_Camera; 36 | 37 | #pragma endregion 38 | 39 | #pragma region used for Virtual Device 40 | 41 | // Virtual Device Header 42 | #include "..\..\VirtualDevice\VirtualDevice.h" 43 | 44 | // The NewFrameListener to set the new frame of virtual device 45 | template 46 | class CCopyFrame : public VideoStream::NewFrameListener 47 | { 48 | public: 49 | CCopyFrame( VideoStream& rStream ) : m_rVStream( rStream ){} 50 | 51 | void onNewFrame( openni::VideoStream& rStream ) 52 | { 53 | openni::VideoFrameRef mFrame; 54 | // read frame from real video stream 55 | if( rStream.readFrame( &mFrame ) == openni::STATUS_OK ) 56 | { 57 | // get a frame form virtual video stream 58 | OniFrame* pFrame = NULL; 59 | if( m_rVStream.invoke( GET_VIRTUAL_STREAM_IMAGE, pFrame ) == openni::STATUS_OK ) 60 | { 61 | // type casting 62 | const PIXEL_TYPE* pRealData = reinterpret_cast( mFrame.getData() ); 63 | PIXEL_TYPE* pVirData = reinterpret_cast( pFrame->data ); 64 | 65 | // read data from the frame of real sensor, and write to the frame of virtual sensor 66 | int w = mFrame.getWidth(), h = mFrame.getHeight(); 67 | for( int y = 0; y < h; ++ y ) 68 | { 69 | for( int x = 0; x < w; ++ x ) 70 | { 71 | int idx = x + y * w; 72 | pVirData[idx] = pRealData[idx]; 73 | } 74 | } 75 | 76 | // write data to form virtual video stream 77 | m_rVStream.invoke( SET_VIRTUAL_STREAM_IMAGE, pFrame ); 78 | } 79 | } 80 | } 81 | 82 | protected: 83 | openni::VideoStream& m_rVStream; 84 | 85 | CCopyFrame& operator=(const CCopyFrame&); 86 | }; 87 | 88 | #pragma endregion 89 | 90 | #pragma region GLUT callback functions 91 | 92 | // glut display function(draw) 93 | void display() 94 | { 95 | // clear previous screen 96 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 97 | 98 | SDevice& virDevice = g_Device[1]; 99 | 100 | // get depth and color frame 101 | VideoFrameRef vfDepthFrame; 102 | VideoFrameRef vfColorFrame; 103 | if( virDevice.vsDepth.readFrame( &vfDepthFrame ) == STATUS_OK && 104 | virDevice.vsColor.readFrame( &vfColorFrame ) == STATUS_OK ) 105 | { 106 | // type cast 107 | const DepthPixel* pDepthArray = reinterpret_cast( vfDepthFrame.getData() ); 108 | const RGB888Pixel* pColorArray = reinterpret_cast( vfColorFrame.getData() ); 109 | 110 | int iW = vfDepthFrame.getWidth(), 111 | iH = vfDepthFrame.getHeight(); 112 | 113 | // draw point cloud 114 | glBegin( GL_POINTS ); 115 | float vPos[3]; 116 | for( int y = 0; y < iH; ++ y ) 117 | { 118 | for( int x = 0; x < iW; ++ x ) 119 | { 120 | int idx = x + y * iW; 121 | 122 | // update points array 123 | const DepthPixel& rDepth = pDepthArray[idx]; 124 | if( rDepth > 0 ) 125 | { 126 | // read color 127 | const RGB888Pixel& rColor = pColorArray[idx]; 128 | 129 | // convert coordinate 130 | CoordinateConverter::convertDepthToWorld( virDevice.vsDepth, x, y, rDepth, &vPos[0], &vPos[1], &vPos[2] ); 131 | 132 | // draw point 133 | glColor3ub( rColor.r, rColor.g, rColor.b ); 134 | glVertex3fv( vPos ); 135 | } 136 | } 137 | } 138 | glEnd(); 139 | } 140 | 141 | // swap buffer 142 | glutSwapBuffers(); 143 | } 144 | 145 | // glut idle function 146 | void idle() 147 | { 148 | glutPostRedisplay(); 149 | } 150 | 151 | // glut keyboard function 152 | void keyboard( unsigned char key, int, int ) 153 | { 154 | float fSpeed = 50.0f; 155 | switch( key ) 156 | { 157 | case 'q': 158 | // stop OpenNI 159 | g_Device[0].vsDepth.destroy(); 160 | g_Device[0].vsColor.destroy(); 161 | g_Device[1].vsDepth.destroy(); 162 | g_Device[1].vsColor.destroy(); 163 | 164 | g_Device[0].devDevice.close(); 165 | g_Device[1].devDevice.close(); 166 | 167 | OpenNI::shutdown(); 168 | exit( 0 ); 169 | 170 | case 's': 171 | g_Camera.MoveForward( -fSpeed ); 172 | break; 173 | 174 | case 'w': 175 | g_Camera.MoveForward( fSpeed ); 176 | break; 177 | 178 | case 'a': 179 | g_Camera.MoveSide( -fSpeed ); 180 | break; 181 | 182 | case 'd': 183 | g_Camera.MoveSide( fSpeed ); 184 | break; 185 | 186 | case 'z': 187 | g_Camera.MoveUp( -fSpeed ); 188 | break; 189 | 190 | case 'x': 191 | g_Camera.MoveUp( fSpeed ); 192 | break; 193 | 194 | case 'p': 195 | { 196 | static bool bPoly = true; 197 | if( bPoly ) 198 | { 199 | bPoly = false; 200 | glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 201 | } 202 | else 203 | { 204 | bPoly = true; 205 | glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); 206 | } 207 | } 208 | break; 209 | } 210 | } 211 | 212 | // glut special keyboard function 213 | void specialKey( int key, int, int ) 214 | { 215 | float fRotateScale = 0.01f; 216 | switch( key ) 217 | { 218 | case GLUT_KEY_DOWN: 219 | g_Camera.RotateUp( -fRotateScale ); 220 | break; 221 | 222 | case GLUT_KEY_UP: 223 | g_Camera.RotateUp( fRotateScale ); 224 | break; 225 | 226 | case GLUT_KEY_RIGHT: 227 | g_Camera.RotateSide( fRotateScale ); 228 | break; 229 | 230 | case GLUT_KEY_LEFT: 231 | g_Camera.RotateSide( -fRotateScale ); 232 | break; 233 | } 234 | } 235 | 236 | #pragma endregion 237 | 238 | int main( int argc, char** argv ) 239 | { 240 | #pragma region OpenNI initialize 241 | // Initial OpenNI 242 | if( OpenNI::initialize() != STATUS_OK ) 243 | { 244 | cerr << "OpenNI Initial Error: " << OpenNI::getExtendedError() << endl; 245 | return -1; 246 | } 247 | 248 | // Open Device 249 | SDevice& phyDevice = g_Device[0]; 250 | if( phyDevice.devDevice.open( ANY_DEVICE ) != STATUS_OK ) 251 | { 252 | cerr << "Can't Open Device: " << OpenNI::getExtendedError() << endl; 253 | return -1; 254 | } 255 | 256 | // Create depth stream 257 | if( phyDevice.devDevice.hasSensor( SENSOR_DEPTH ) ) 258 | { 259 | if( phyDevice.vsDepth.create( phyDevice.devDevice, SENSOR_DEPTH ) != STATUS_OK ) 260 | { 261 | cerr << "Can't create depth stream on device: " << OpenNI::getExtendedError() << endl; 262 | return -1; 263 | } 264 | } 265 | else 266 | { 267 | cerr << "ERROR: This device does not have depth sensor" << endl; 268 | return -1; 269 | } 270 | 271 | // Create color stream 272 | if( phyDevice.devDevice.hasSensor( SENSOR_COLOR ) ) 273 | { 274 | if( phyDevice.vsColor.create( phyDevice.devDevice, SENSOR_COLOR ) == STATUS_OK ) 275 | { 276 | // image registration 277 | if( phyDevice.devDevice.isImageRegistrationModeSupported( IMAGE_REGISTRATION_DEPTH_TO_COLOR ) ) 278 | { 279 | phyDevice.devDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR ); 280 | } 281 | else 282 | { 283 | cout << "This device doesn't support IMAGE_REGISTRATION_DEPTH_TO_COLOR, will use CoordinateConverter." << endl; 284 | } 285 | } 286 | else 287 | { 288 | cerr << "Can't create color stream on device: " << OpenNI::getExtendedError() << endl; 289 | } 290 | } 291 | else 292 | { 293 | cerr << "This device does not have depth sensor" << endl; 294 | return -1; 295 | } 296 | #pragma endregion 297 | 298 | #pragma region Virtual Device 299 | // Open Virtual Device 300 | SDevice& virDevice = g_Device[1]; 301 | if( virDevice.devDevice.open( "\\OpenNI2\\VirtualDevice\\TEST" ) != STATUS_OK ) 302 | { 303 | cerr << "Can't create virtual device: " << OpenNI::getExtendedError() << endl; 304 | return -1; 305 | } 306 | 307 | // create virtual depth video stream 308 | if( virDevice.vsDepth.create( virDevice.devDevice, SENSOR_DEPTH ) == STATUS_OK ) 309 | { 310 | // set the FOV for depth, which is required for 311 | virDevice.vsDepth.setProperty( ONI_STREAM_PROPERTY_VERTICAL_FOV, phyDevice.vsDepth.getVerticalFieldOfView() ); 312 | virDevice.vsDepth.setProperty( ONI_STREAM_PROPERTY_HORIZONTAL_FOV, phyDevice.vsDepth.getHorizontalFieldOfView() ); 313 | 314 | virDevice.vsDepth.setVideoMode( phyDevice.vsDepth.getVideoMode() ); 315 | 316 | phyDevice.vsDepth.addNewFrameListener( new CCopyFrame( virDevice.vsDepth ) ); 317 | } 318 | else 319 | { 320 | cerr << "Virtual Depth Stream Create error: " << OpenNI::getExtendedError() << endl; 321 | return -1; 322 | } 323 | 324 | // create virtual color video stream 325 | if( virDevice.vsColor.create( virDevice.devDevice, SENSOR_COLOR ) == STATUS_OK ) 326 | { 327 | virDevice.vsColor.setVideoMode( phyDevice.vsColor.getVideoMode() ); 328 | phyDevice.vsColor.addNewFrameListener( new CCopyFrame( virDevice.vsColor ) ); 329 | } 330 | #pragma endregion 331 | 332 | #pragma region OpenGL Initialize 333 | // initial glut 334 | glutInit(&argc, argv); 335 | glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB ); 336 | 337 | // create glut window 338 | glutInitWindowSize( 640, 480 ); 339 | glutCreateWindow( "OpenNI 3D Point Cloud" ); 340 | 341 | // set OpenGL environment 342 | glEnable( GL_DEPTH_TEST ); 343 | glDisable( GL_LIGHTING ); 344 | 345 | // OpenGL projection 346 | glMatrixMode( GL_PROJECTION ); 347 | gluPerspective( 40.0, 1.0, 100.0, 20000.0 ); // FOV, aspect ration, near, far 348 | g_Camera.vCenter = Vector3( 0.0, 0.0, 1000.0 ); 349 | g_Camera.vPosition = Vector3( 0.0, 0.0, -2000.0 ); 350 | g_Camera.vUpper = Vector3( 0.0, 1.0, 0.0 ); 351 | g_Camera.SetCamera(); 352 | 353 | // register glut callback functions 354 | glutDisplayFunc( display ); 355 | glutIdleFunc( idle ); 356 | glutKeyboardFunc( keyboard ); 357 | glutSpecialFunc( specialKey ); 358 | #pragma endregion 359 | 360 | // start 361 | if( phyDevice.vsDepth.start() == STATUS_OK ) 362 | { 363 | phyDevice.vsColor.start(); 364 | virDevice.vsDepth.start(); 365 | virDevice.vsColor.start(); 366 | 367 | glutMainLoop(); 368 | } 369 | else 370 | { 371 | cerr << "Stream start error: " << OpenNI::getExtendedError() << endl; 372 | return -1; 373 | } 374 | 375 | return 0; 376 | } 377 | -------------------------------------------------------------------------------- /Samples/BasicSample/BasicSample.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A368BED9-CE9B-4B1C-BD07-3647094A4099} 23 | SimpleViewer 24 | BasicSample 25 | 26 | 27 | 28 | Application 29 | true 30 | MultiByte 31 | 32 | 33 | Application 34 | true 35 | MultiByte 36 | 37 | 38 | Application 39 | false 40 | true 41 | MultiByte 42 | 43 | 44 | Application 45 | false 46 | true 47 | MultiByte 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 71 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 72 | 73 | 74 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 75 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 79 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 80 | 81 | 82 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 83 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 84 | 85 | 86 | 87 | Disabled 88 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 89 | _WINDLL;%(PreprocessorDefinitions) 90 | Level4 91 | true 92 | false 93 | 94 | 95 | 96 | 97 | true 98 | OpenNI2.lib;XnLib.lib 99 | $(OPENNI2_LIB);;$(OpenNI_SDK_Path)\Bin\$(Platform)-$(Configuration)\ 100 | true 101 | 102 | 103 | 104 | 105 | Disabled 106 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 107 | _WINDLL;%(PreprocessorDefinitions) 108 | Level4 109 | true 110 | false 111 | 112 | 113 | 114 | 115 | true 116 | OpenNI2.lib;XnLib.lib 117 | $(OPENNI2_LIB64);;$(OpenNI_SDK_Path)\Bin\$(Platform)-$(Configuration)\ 118 | true 119 | 120 | 121 | 122 | 123 | Level4 124 | MaxSpeed 125 | true 126 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 127 | true 128 | AnySuitable 129 | Speed 130 | true 131 | true 132 | false 133 | StreamingSIMDExtensions2 134 | Fast 135 | false 136 | 137 | 138 | true 139 | true 140 | true 141 | OpenNI2.lib;XnLib.lib 142 | $(OPENNI2_LIB);;$(OpenNI_SDK_Path)\Bin\$(Platform)-$(Configuration)\ 143 | true 144 | 145 | 146 | 147 | 148 | Level4 149 | MaxSpeed 150 | true 151 | $(OPENNI2_INCLUDE);$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 152 | true 153 | AnySuitable 154 | Speed 155 | true 156 | true 157 | false 158 | StreamingSIMDExtensions2 159 | Fast 160 | false 161 | 162 | 163 | true 164 | true 165 | true 166 | OpenNI2.lib;XnLib.lib 167 | $(OPENNI2_LIB64);;$(OpenNI_SDK_Path)\Bin\$(Platform)-$(Configuration)\ 168 | true 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Samples/NiTESample/NiTESample.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F6125DDF-7B0D-48C0-A0EC-D09780C438FA} 23 | SimpleViewer 24 | NiTESample 25 | 26 | 27 | 28 | Application 29 | true 30 | MultiByte 31 | 32 | 33 | Application 34 | true 35 | MultiByte 36 | 37 | 38 | Application 39 | false 40 | true 41 | MultiByte 42 | 43 | 44 | Application 45 | false 46 | true 47 | MultiByte 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 71 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 72 | 73 | 74 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 75 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 79 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 80 | 81 | 82 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 83 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 84 | 85 | 86 | 87 | Disabled 88 | $(OPENNI2_INCLUDE);$(NITE2_INCLUDE);$(OpenCV_Path)\build\include;%(AdditionalIncludeDirectories) 89 | _WINDLL;%(PreprocessorDefinitions) 90 | Level4 91 | true 92 | false 93 | 94 | 95 | 96 | 97 | true 98 | OpenNI2.lib;NiTE2.lib;$(OpenCV_Libs_Debug) 99 | $(OPENNI2_LIB);$(NITE2_LIB);$(OpenCV_Path)\build\x86\vc10\lib 100 | true 101 | 102 | 103 | 104 | 105 | Disabled 106 | $(OPENNI2_INCLUDE);$(NITE2_INCLUDE);$(OpenCV_Path)\build\include;%(AdditionalIncludeDirectories) 107 | _WINDLL;%(PreprocessorDefinitions) 108 | Level4 109 | true 110 | false 111 | 112 | 113 | 114 | 115 | true 116 | OpenNI2.lib;NiTE2.lib;$(OpenCV_Libs_Debug) 117 | $(OPENNI2_LIB64);$(NITE2_LIB64);$(OpenCV_Path)\build\x64\vc10\lib 118 | true 119 | 120 | 121 | 122 | 123 | Level4 124 | MaxSpeed 125 | true 126 | $(OPENNI2_INCLUDE);$(NITE2_INCLUDE);$(OpenCV_Path)\build\include;%(AdditionalIncludeDirectories) 127 | true 128 | AnySuitable 129 | Speed 130 | true 131 | true 132 | false 133 | StreamingSIMDExtensions2 134 | Fast 135 | false 136 | 137 | 138 | true 139 | true 140 | true 141 | OpenNI2.lib;NiTE2.lib;$(OpenCV_Libs_Release) 142 | $(OPENNI2_LIB);$(NITE2_LIB);$(OpenCV_Path)\build\x86\vc10\lib 143 | true 144 | 145 | 146 | 147 | 148 | Level4 149 | MaxSpeed 150 | true 151 | $(OPENNI2_INCLUDE);$(NITE2_INCLUDE);$(OpenCV_Path)\build\include;%(AdditionalIncludeDirectories) 152 | true 153 | AnySuitable 154 | Speed 155 | true 156 | true 157 | false 158 | StreamingSIMDExtensions2 159 | Fast 160 | false 161 | 162 | 163 | true 164 | true 165 | true 166 | OpenNI2.lib;NiTE2.lib;$(OpenCV_Libs_Release) 167 | $(OPENNI2_LIB64);$(NITE2_LIB64);$(OpenCV_Path)\build\x64\vc10\lib 168 | true 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /VirtualDevice/VirtualDevice.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {DAFA5887-D67D-495F-8FC5-01CD24A70CE5} 29 | TestDevice 30 | 31 | 32 | 33 | DynamicLibrary 34 | true 35 | MultiByte 36 | 37 | 38 | DynamicLibrary 39 | true 40 | MultiByte 41 | 42 | 43 | DynamicLibrary 44 | false 45 | true 46 | MultiByte 47 | 48 | 49 | DynamicLibrary 50 | false 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\OpenNI2\Drivers\ 76 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 77 | 78 | 79 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\OpenNI2\Drivers\ 80 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 81 | 82 | 83 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\OpenNI2\Drivers\ 84 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 85 | 86 | 87 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\OpenNI2\Drivers\ 88 | $(SolutionDir)Bin\Intermediate\$(Platform)-$(Configuration)\$(ProjectName)\ 89 | 90 | 91 | 92 | Disabled 93 | $(OpenNI_SDK_Path)\Include;$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 94 | _WINDLL;%(PreprocessorDefinitions);TestDevice2_EXPORT 95 | ProgramDatabase 96 | Level4 97 | false 98 | true 99 | MultiThreadedDebugDLL 100 | 101 | 102 | true 103 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 104 | %(AdditionalDependencies) 105 | 106 | 107 | 108 | 109 | Disabled 110 | $(OpenNI_SDK_Path)\Include;$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 111 | _WINDLL;%(PreprocessorDefinitions);TestDevice2_EXPORT 112 | ProgramDatabase 113 | Level4 114 | false 115 | true 116 | MultiThreadedDebugDLL 117 | 118 | 119 | true 120 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 121 | %(AdditionalDependencies) 122 | 123 | 124 | 125 | 126 | Level4 127 | MaxSpeed 128 | true 129 | _MBCS;%(PreprocessorDefinitions);TestDevice2_EXPORT 130 | $(OpenNI_SDK_Path)\Include;$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 131 | false 132 | true 133 | AnySuitable 134 | Speed 135 | true 136 | true 137 | false 138 | StreamingSIMDExtensions2 139 | Fast 140 | MultiThreadedDLL 141 | 142 | 143 | true 144 | true 145 | true 146 | %(AdditionalDependencies) 147 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 148 | 149 | 150 | 151 | 152 | Level4 153 | MaxSpeed 154 | true 155 | _MBCS;%(PreprocessorDefinitions);TestDevice2_EXPORT 156 | $(OpenNI_SDK_Path)\Include;$(OpenNI_SDK_Path)\ThirdParty\PSCommon\XnLib\Include 157 | false 158 | true 159 | AnySuitable 160 | Speed 161 | true 162 | true 163 | false 164 | StreamingSIMDExtensions2 165 | Fast 166 | MultiThreadedDLL 167 | 168 | 169 | true 170 | true 171 | true 172 | %(AdditionalDependencies) 173 | $(SolutionDir)Bin\$(Platform)-$(Configuration)\ 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /APACHE_LICENSE_2: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /VirtualDevice/VirtualDevice.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a virtual device driver module for OpenNI 2.2+ 3 | * 4 | * It doesn't map to any physical device, but a dummy device. 5 | * You can send the map you want to it, and it will let OpenNI to use it. 6 | * 7 | * It also provide a property pool to accept any property. 8 | * 9 | * http://viml.nchc.org.tw/home/ 10 | * 11 | * version 0.4 @2013/09/14 12 | */ 13 | 14 | // C Header 15 | #include 16 | 17 | // STL Header 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | // C Time header 24 | #include 25 | 26 | // for debug only 27 | #include 28 | 29 | // OpenNI Header 30 | #include "Driver/OniDriverAPI.h" 31 | #include "XnLib.h" 32 | 33 | // VirtualDevice command 34 | #include "VirtualDevice.h" 35 | 36 | #pragma region inline functions for propertry data 37 | template 38 | _T* PropertyConvert( oni::driver::DriverServices& rService, size_t uSize, void* pData ) 39 | { 40 | if( sizeof(_T) == uSize ) 41 | return reinterpret_cast<_T*>( pData ); 42 | 43 | rService.errorLoggerAppend( "The required property data size not match: %d != %d\n", uSize, sizeof(_T) ); 44 | return NULL; 45 | } 46 | 47 | template 48 | const _T* PropertyConvert( oni::driver::DriverServices& rService, size_t uSize, const void* pData ) 49 | { 50 | if( sizeof(_T) == uSize ) 51 | return reinterpret_cast( pData ); 52 | 53 | rService.errorLoggerAppend( "The required property data size not match: %d != %d\n", uSize, sizeof(const _T) ); 54 | return NULL; 55 | } 56 | 57 | template 58 | bool GetProperty( oni::driver::DriverServices& rService, size_t uSize, void* pData, _T& rValue ) 59 | { 60 | _T* pTData = PropertyConvert<_T>( rService, uSize, pData ); 61 | if( pTData != NULL ) 62 | { 63 | *pTData = rValue; 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | template 70 | bool SetProperty( oni::driver::DriverServices& rService, size_t uSize, const void* pData, _T& rValue ) 71 | { 72 | const _T* pTData = PropertyConvert<_T>( rService, uSize, pData ); 73 | if( pTData != NULL ) 74 | { 75 | rValue = *pTData; 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | #pragma endregion 82 | 83 | /** 84 | * This is a property pool to store any type of property 85 | */ 86 | class PropertyPool 87 | { 88 | public: 89 | std::map< int,std::vector > m_Data; 90 | 91 | public: 92 | PropertyPool( oni::driver::DriverServices& rService ) : m_Service( rService ) 93 | { 94 | } 95 | 96 | bool GetProperty( int propertyId, void* data, int* pDataSize ) 97 | { 98 | auto itData = m_Data.find( propertyId ); 99 | if( itData == m_Data.end() ) 100 | { 101 | //std::cout << "request unsaved property: " << propertyId << std::endl; 102 | m_Service.errorLoggerAppend( "Required property '%d' not set.", propertyId ); 103 | return false; 104 | } 105 | 106 | auto vData = itData->second; 107 | if( vData.size() == *pDataSize ) 108 | { 109 | memcpy( data, vData.data(), vData.size() ); 110 | return true; 111 | } 112 | 113 | m_Service.errorLoggerAppend( "Required property '%d' data size not match: '%d != '%d''.", propertyId, vData.size(), *pDataSize ); 114 | return false; 115 | } 116 | 117 | bool SetProperty( int propertyId, const void* data, int iSize ) 118 | { 119 | auto itData = m_Data.find( propertyId ); 120 | std::vector* pData = NULL; 121 | if( itData == m_Data.end() ) 122 | { 123 | pData = &(m_Data[propertyId]); 124 | pData->resize( iSize ); 125 | } 126 | else 127 | { 128 | m_Service.errorLoggerAppend( "Overwrite property '%d'", propertyId ); 129 | pData = &(itData->second); 130 | } 131 | 132 | if( pData->size() == iSize ) 133 | { 134 | memcpy( pData->data(), data, pData->size() ); 135 | return true; 136 | } 137 | 138 | m_Service.errorLoggerAppend( "Required property '%d' data size not match: '%d != '%d''.", propertyId, pData->size(), iSize ); 139 | return false; 140 | } 141 | 142 | protected: 143 | oni::driver::DriverServices& m_Service; 144 | 145 | private: 146 | void operator=( const PropertyPool&); 147 | }; 148 | 149 | /** 150 | * 151 | */ 152 | class OpenNIVirtualStream : public oni::driver::StreamBase 153 | { 154 | public: 155 | /** 156 | * Constructor 157 | */ 158 | OpenNIVirtualStream( OniSensorType eSeneorType, oni::driver::DriverServices& driverServices ) : oni::driver::StreamBase(), m_rDriverServices(driverServices), m_Properties(driverServices) 159 | { 160 | m_eSensorType = eSeneorType; 161 | m_bStarted = false; 162 | m_iFrameId = 0; 163 | 164 | m_bConfigDone = false; 165 | 166 | // default video mode 167 | m_mVideoMode.resolutionX = 320; 168 | m_mVideoMode.resolutionY = 240; 169 | m_mVideoMode.fps = 1; 170 | m_mVideoMode.pixelFormat = ONI_PIXEL_FORMAT_DEPTH_1_MM; 171 | 172 | // default cropping 173 | m_mCropping.enabled = false; 174 | m_mCropping.width = m_mVideoMode.resolutionX; 175 | m_mCropping.height = m_mVideoMode.resolutionY; 176 | m_mCropping.originX = 0; 177 | m_mCropping.originY = 0; 178 | } 179 | 180 | /** 181 | * Start load image 182 | */ 183 | OniStatus start() 184 | { 185 | if( m_bConfigDone ) 186 | { 187 | m_bStarted = true; 188 | return ONI_STATUS_OK; 189 | } 190 | m_rDriverServices.errorLoggerAppend( "Please assign VideoMode before start" ); 191 | return ONI_STATUS_ERROR; 192 | } 193 | 194 | /** 195 | * Stop load image 196 | */ 197 | void stop() 198 | { 199 | m_bStarted = false; 200 | } 201 | 202 | /** 203 | * Check if the property is supported 204 | */ 205 | OniBool isPropertySupported( int ) 206 | { 207 | return true; 208 | } 209 | 210 | /** 211 | * get property 212 | */ 213 | OniStatus getProperty( int propertyId, void* data, int* pDataSize ) 214 | { 215 | switch( propertyId ) 216 | { 217 | case ONI_STREAM_PROPERTY_VIDEO_MODE: 218 | if( GetProperty( m_rDriverServices, *pDataSize, data, m_mVideoMode ) ) 219 | return ONI_STATUS_OK; 220 | break; 221 | 222 | case ONI_STREAM_PROPERTY_CROPPING: 223 | if( GetProperty( m_rDriverServices, *pDataSize, data, m_mCropping ) ) 224 | return ONI_STATUS_OK; 225 | break; 226 | 227 | case ONI_STREAM_PROPERTY_STRIDE: 228 | { 229 | int iStride = int(m_uStride); 230 | if( GetProperty( m_rDriverServices, *pDataSize, data, iStride ) ) 231 | return ONI_STATUS_OK; 232 | } 233 | break; 234 | 235 | default: 236 | if( m_Properties.GetProperty( propertyId, data, pDataSize ) ) 237 | return ONI_STATUS_OK; 238 | } 239 | //std::cerr << " >>> Request Stream Property: " << propertyId << std::endl; 240 | return ONI_STATUS_ERROR; 241 | } 242 | 243 | /** 244 | * set property 245 | */ 246 | OniStatus setProperty( int propertyId, const void* data, int dataSize ) 247 | { 248 | switch( propertyId ) 249 | { 250 | case ONI_STREAM_PROPERTY_VIDEO_MODE: 251 | if( SetProperty( m_rDriverServices, dataSize, data, m_mVideoMode ) ) 252 | { 253 | switch( m_mVideoMode.pixelFormat ) 254 | { 255 | case ONI_PIXEL_FORMAT_RGB888: 256 | m_uStride = m_mVideoMode.resolutionX * sizeof( OniRGB888Pixel ); 257 | break; 258 | 259 | case ONI_PIXEL_FORMAT_DEPTH_1_MM: 260 | case ONI_PIXEL_FORMAT_DEPTH_100_UM: 261 | m_uStride = m_mVideoMode.resolutionX * sizeof( OniDepthPixel ); 262 | break; 263 | 264 | default: 265 | m_rDriverServices.errorLoggerAppend( "Unsupported pixel format: %d", m_mVideoMode.pixelFormat ); 266 | return ONI_STATUS_ERROR; 267 | } 268 | 269 | m_uDataSize = m_uStride * m_mVideoMode.resolutionY; 270 | 271 | m_bConfigDone = true; 272 | return ONI_STATUS_OK; 273 | } 274 | break; 275 | 276 | case ONI_STREAM_PROPERTY_CROPPING: 277 | if( SetProperty( m_rDriverServices, dataSize, data, m_mCropping ) ) 278 | return ONI_STATUS_OK; 279 | break; 280 | 281 | default: 282 | if( m_Properties.SetProperty( propertyId, data, dataSize ) ) 283 | return ONI_STATUS_OK; 284 | } 285 | return ONI_STATUS_ERROR; 286 | } 287 | 288 | OniStatus invoke( int commandId, void* data, int dataSize ) 289 | { 290 | switch( commandId ) 291 | { 292 | case GET_VIRTUAL_STREAM_IMAGE: 293 | if( m_bStarted ) 294 | { 295 | OniFrame** pFrame = PropertyConvert( m_rDriverServices, dataSize, data ); 296 | if( pFrame != NULL ) 297 | { 298 | *pFrame = CreateeNewFrame(); 299 | if( pFrame != NULL ) 300 | { 301 | (*pFrame)->croppingEnabled = m_mCropping.enabled; 302 | if (m_mCropping.enabled) 303 | { 304 | (*pFrame)->cropOriginX = m_mCropping.originX; 305 | (*pFrame)->cropOriginY = m_mCropping.originY; 306 | (*pFrame)->height = m_mCropping.height; 307 | (*pFrame)->width = m_mCropping.width; 308 | } 309 | 310 | return ONI_STATUS_OK; 311 | } 312 | } 313 | } 314 | else 315 | { 316 | return ONI_STATUS_ERROR; 317 | } 318 | break; 319 | 320 | case SET_VIRTUAL_STREAM_IMAGE: 321 | if( m_bStarted ) 322 | { 323 | OniFrame** pFrame = PropertyConvert( m_rDriverServices, dataSize, data ); 324 | if( pFrame != NULL ) 325 | { 326 | if( SendNewFrame( *pFrame ) ) 327 | return ONI_STATUS_OK; 328 | } 329 | } 330 | else 331 | { 332 | return ONI_STATUS_ERROR; 333 | } 334 | break; 335 | } 336 | return ONI_STATUS_NOT_IMPLEMENTED; 337 | } 338 | 339 | OniBool isCommandSupported( int commandId ) 340 | { 341 | switch( commandId ) 342 | { 343 | case GET_VIRTUAL_STREAM_IMAGE: 344 | case SET_VIRTUAL_STREAM_IMAGE: 345 | return true; 346 | break; 347 | } 348 | 349 | return FALSE; 350 | } 351 | 352 | void notifyAllProperties() 353 | { 354 | for( std::map< int,std::vector >::iterator itProp = m_Properties.m_Data.begin(); itProp != m_Properties.m_Data.end(); ++ itProp ) 355 | raisePropertyChanged( itProp->first, itProp->second.data(), itProp->second.size() ); 356 | } 357 | 358 | protected: 359 | OniFrame* CreateeNewFrame() 360 | { 361 | OniFrame* pFrame = getServices().acquireFrame(); 362 | if( pFrame != NULL ) 363 | { 364 | // update metadata 365 | pFrame->frameIndex = ++m_iFrameId; 366 | pFrame->videoMode = m_mVideoMode; 367 | pFrame->width = m_mVideoMode.resolutionX; 368 | pFrame->height = m_mVideoMode.resolutionY; 369 | pFrame->cropOriginX = pFrame->cropOriginY = 0; 370 | pFrame->croppingEnabled = FALSE; 371 | pFrame->sensorType = m_eSensorType; 372 | pFrame->stride = int( m_uStride ); 373 | 374 | time_t tNow; 375 | time( &tNow ); 376 | pFrame->timestamp = tNow; 377 | } 378 | return pFrame; 379 | } 380 | 381 | bool SendNewFrame( OniFrame* pFrame ) 382 | { 383 | if( pFrame->videoMode.pixelFormat == m_mVideoMode.pixelFormat && 384 | pFrame->videoMode.resolutionX == m_mVideoMode.resolutionX && 385 | pFrame->videoMode.resolutionY == m_mVideoMode.resolutionY ) 386 | { 387 | raiseNewFrame( pFrame ); 388 | getServices().releaseFrame( pFrame ); 389 | return true; 390 | } 391 | getServices().releaseFrame( pFrame ); 392 | return false; 393 | } 394 | 395 | protected: 396 | bool m_bStarted; 397 | bool m_bConfigDone; 398 | 399 | OniSensorType m_eSensorType; 400 | OniVideoMode m_mVideoMode; 401 | OniCropping m_mCropping; 402 | 403 | int m_iFrameId; 404 | size_t m_uDataSize; 405 | size_t m_uStride; 406 | 407 | oni::driver::DriverServices& m_rDriverServices; 408 | PropertyPool m_Properties; 409 | 410 | private: 411 | OpenNIVirtualStream( const OpenNIVirtualStream& ); 412 | void operator=( const OpenNIVirtualStream& ); 413 | }; 414 | 415 | /** 416 | * Device 417 | */ 418 | class OpenNIVirualDevice : public oni::driver::DeviceBase 419 | { 420 | public: 421 | /** 422 | * Constructor 423 | */ 424 | OpenNIVirualDevice( OniDeviceInfo* pInfo, oni::driver::DriverServices& driverServices ) : m_pInfo(pInfo), m_rDriverServices(driverServices) 425 | { 426 | m_bCreated = false; 427 | 428 | // set depth sensor 429 | m_aStream[0] = NULL; 430 | m_aSensor[0].sensorType = ONI_SENSOR_DEPTH; 431 | m_aSensor[0].numSupportedVideoModes = 1; 432 | // set dummy supported video mode 433 | m_aSensor[0].pSupportedVideoModes = new OniVideoMode[1]; 434 | m_aSensor[0].pSupportedVideoModes[0].resolutionX = 1; 435 | m_aSensor[0].pSupportedVideoModes[0].resolutionY = 1; 436 | m_aSensor[0].pSupportedVideoModes[0].fps = 1; 437 | m_aSensor[0].pSupportedVideoModes[0].pixelFormat = ONI_PIXEL_FORMAT_DEPTH_1_MM; 438 | 439 | // set depth sensor 440 | m_aStream[1] = NULL; 441 | m_aSensor[1].sensorType = ONI_SENSOR_COLOR; 442 | m_aSensor[1].numSupportedVideoModes = 1; 443 | // set dummy supported video mode 444 | m_aSensor[1].pSupportedVideoModes = new OniVideoMode[1]; 445 | m_aSensor[1].pSupportedVideoModes[0].resolutionX = 1; 446 | m_aSensor[1].pSupportedVideoModes[0].resolutionY = 1; 447 | m_aSensor[1].pSupportedVideoModes[0].fps = 1; 448 | m_aSensor[1].pSupportedVideoModes[0].pixelFormat = ONI_PIXEL_FORMAT_RGB888; 449 | 450 | m_bCreated = true; 451 | } 452 | 453 | /** 454 | * Destructor 455 | */ 456 | ~OpenNIVirualDevice(){} 457 | 458 | /** 459 | * getSensorInfoList 460 | */ 461 | OniStatus getSensorInfoList( OniSensorInfo** pSensors, int* numSensors ) 462 | { 463 | *numSensors = m_aSensor.size(); 464 | *pSensors = m_aSensor.data(); 465 | 466 | return ONI_STATUS_OK; 467 | } 468 | 469 | /** 470 | * create Stream 471 | */ 472 | oni::driver::StreamBase* createStream( OniSensorType sensorType ) 473 | { 474 | size_t idx = GetSensorIdx( sensorType ); 475 | if( idx < m_aStream.size() ) 476 | { 477 | if( m_aStream[idx] == NULL ) 478 | m_aStream[idx] = new OpenNIVirtualStream( sensorType, m_rDriverServices ); 479 | return m_aStream[idx]; 480 | } 481 | 482 | m_rDriverServices.errorLoggerAppend( "The given sensor type '%d' is not supported", sensorType ); 483 | return NULL; 484 | } 485 | 486 | /** 487 | * destroy Stream 488 | */ 489 | void destroyStream( oni::driver::StreamBase* pStream ) 490 | { 491 | for( auto itStream = m_aStream.begin(); itStream != m_aStream.end(); ++ itStream ) 492 | { 493 | if( *itStream == pStream ) 494 | { 495 | *itStream = NULL; 496 | delete pStream; 497 | break; 498 | } 499 | } 500 | } 501 | 502 | /** 503 | * get Property 504 | */ 505 | OniStatus getProperty( int propertyId, void* data, int* pDataSize ) 506 | { 507 | switch (propertyId) 508 | { 509 | case ONI_DEVICE_PROPERTY_DRIVER_VERSION: 510 | { 511 | OniVersion* pVersion = PropertyConvert( m_rDriverServices, *pDataSize, data ); 512 | if( pVersion != NULL ) 513 | { 514 | pVersion->major = 0; 515 | pVersion->minor = 1; 516 | pVersion->maintenance = 0; 517 | pVersion->build = 0; 518 | return ONI_STATUS_OK; 519 | } 520 | } 521 | break; 522 | 523 | default: 524 | m_rDriverServices.errorLoggerAppend( "Unknown property: %d\n", propertyId ); 525 | std::cerr << " >>> Request Device Property: " << propertyId << std::endl; 526 | return ONI_STATUS_NOT_IMPLEMENTED; 527 | } 528 | return ONI_STATUS_ERROR; 529 | } 530 | 531 | /** 532 | * make sure if this device is created 533 | */ 534 | bool Created() const 535 | { 536 | return m_bCreated; 537 | } 538 | 539 | protected: 540 | size_t GetSensorIdx( OniSensorType sensorType ) 541 | { 542 | switch( sensorType ) 543 | { 544 | case ONI_SENSOR_DEPTH: 545 | return 0; 546 | 547 | case ONI_SENSOR_COLOR: 548 | return 1; 549 | } 550 | return 100; 551 | } 552 | 553 | private: 554 | OpenNIVirualDevice( const OpenNIVirualDevice& ); 555 | void operator=( const OpenNIVirualDevice& ); 556 | 557 | bool m_bCreated; 558 | OniDeviceInfo* m_pInfo; 559 | std::array m_aSensor; 560 | std::array m_aStream; 561 | oni::driver::DriverServices& m_rDriverServices; 562 | }; 563 | 564 | /** 565 | * Driver 566 | */ 567 | class OpenNIVirtualDriver : public oni::driver::DriverBase 568 | { 569 | public: 570 | /** 571 | * Constructor 572 | */ 573 | OpenNIVirtualDriver( OniDriverServices* pDriverServices ) : DriverBase( pDriverServices ) 574 | { 575 | // default values 576 | m_sDeviceName = "\\OpenNI2\\VirtualDevice\\"; 577 | m_sVendorName = "OpenNI2 Virtual Device by Heresy"; 578 | } 579 | 580 | /** 581 | * Initialize 582 | */ 583 | OniStatus initialize( oni::driver::DeviceConnectedCallback connectedCallback, 584 | oni::driver::DeviceDisconnectedCallback disconnectedCallback, 585 | oni::driver::DeviceStateChangedCallback deviceStateChangedCallback, 586 | void* pCookie ) 587 | { 588 | return oni::driver::DriverBase::initialize( connectedCallback, disconnectedCallback, deviceStateChangedCallback, pCookie ); 589 | } 590 | 591 | /** 592 | * Open device 593 | */ 594 | oni::driver::DeviceBase* deviceOpen( const char* uri, const char* /*mode*/ ) 595 | { 596 | std::string sUri = uri; 597 | 598 | // find if the device is already in the list 599 | auto itDevice = m_mDevices.find( sUri ); 600 | if( itDevice != m_mDevices.end() ) 601 | { 602 | auto& rDeviceData = itDevice->second; 603 | if( rDeviceData.second == NULL ) 604 | { 605 | // create device if not created 606 | OpenNIVirualDevice* pDevice = new OpenNIVirualDevice( rDeviceData.first, getServices() ); 607 | if( pDevice->Created() ) 608 | { 609 | rDeviceData.second = pDevice; 610 | return pDevice; 611 | } 612 | else 613 | { 614 | getServices().errorLoggerAppend( "Device '%s' create error", uri ); 615 | delete pDevice; 616 | return NULL; 617 | } 618 | } 619 | else 620 | { 621 | // use created device directly 622 | return rDeviceData.second; 623 | } 624 | } 625 | 626 | getServices().errorLoggerAppend( "Can't find device: '%s'", uri ); 627 | return NULL; 628 | } 629 | 630 | /** 631 | * Close device 632 | */ 633 | void deviceClose( oni::driver::DeviceBase* pDevice ) 634 | { 635 | // find in device list 636 | for( auto itDevice = m_mDevices.begin(); itDevice != m_mDevices.end(); ++ itDevice ) 637 | { 638 | auto& rDeviceData = itDevice->second; 639 | if( rDeviceData.second == pDevice ) 640 | { 641 | rDeviceData.second = NULL; 642 | delete pDevice; 643 | return; 644 | } 645 | } 646 | } 647 | 648 | /** 649 | * Test given URI 650 | */ 651 | OniStatus tryDevice( const char* uri ) 652 | { 653 | std::string sUri = uri; 654 | 655 | // Find in list first 656 | auto itDevice = m_mDevices.find( sUri ); 657 | if( itDevice != m_mDevices.end() ) 658 | { 659 | return ONI_STATUS_OK; 660 | } 661 | else 662 | { 663 | // check if URI prefix is correct 664 | if( sUri.substr( 0, m_sDeviceName.length() ) == m_sDeviceName ) 665 | { 666 | // get id 667 | try 668 | { 669 | CreateDeviceInfo( sUri ); 670 | return ONI_STATUS_OK; 671 | } 672 | catch( ... ) 673 | { 674 | getServices().errorLoggerAppend( "given uri '%s' parsing error", uri ); 675 | return ONI_STATUS_ERROR; 676 | } 677 | } 678 | } 679 | 680 | return DriverBase::tryDevice(uri); 681 | } 682 | 683 | /** 684 | * Shutdown 685 | */ 686 | void shutdown() 687 | { 688 | for( auto itDevice = m_mDevices.begin(); itDevice != m_mDevices.end(); ++ itDevice ) 689 | { 690 | auto& rDeviceData = itDevice->second; 691 | delete rDeviceData.first; 692 | delete rDeviceData.second; 693 | } 694 | } 695 | 696 | protected: 697 | /** 698 | * prepare OniDeviceInfo and device list 699 | */ 700 | void CreateDeviceInfo( const std::string& sUri ) 701 | { 702 | // Construct OniDeviceInfo 703 | OniDeviceInfo* pInfo = new OniDeviceInfo(); 704 | strncpy( pInfo->vendor, m_sVendorName.c_str(), ONI_MAX_STR ); 705 | strncpy( pInfo->name, sUri.substr( m_sDeviceName.length() ).c_str(), ONI_MAX_STR ); 706 | strncpy( pInfo->uri, sUri.c_str(), ONI_MAX_STR ); 707 | 708 | // save device info 709 | m_mDevices[sUri] = std::make_pair( pInfo, (oni::driver::DeviceBase*)NULL ); 710 | deviceConnected( pInfo ); 711 | deviceStateChanged( pInfo, 0 ); 712 | } 713 | 714 | protected: 715 | std::string m_sDeviceName; 716 | std::string m_sVendorName; 717 | std::map< std::string,std::pair > m_mDevices; 718 | }; 719 | 720 | ONI_EXPORT_DRIVER(OpenNIVirtualDriver); 721 | --------------------------------------------------------------------------------