/************************************************************************ * * * NuiSkeleton.h -- This module defines the APIs for the Natural * * User Interface(NUI) skeleton services. * * * * Copyright (c) Microsoft Corp. All rights reserved. * * * ************************************************************************/ #pragma once #ifndef NUIAPI #error "You must include nuiapi.h rather than including nuiskeleton.h directly" #endif #ifdef __cplusplus extern "C" { #endif #ifndef FLT_EPSILON #define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */ #endif #ifndef _Matrix4_ #define _Matrix4_ typedef struct _Matrix4 { FLOAT M11; FLOAT M12; FLOAT M13; FLOAT M14; FLOAT M21; FLOAT M22; FLOAT M23; FLOAT M24; FLOAT M31; FLOAT M32; FLOAT M33; FLOAT M34; FLOAT M41; FLOAT M42; FLOAT M43; FLOAT M44; } Matrix4; #endif #ifndef __NuiSensor_h__ #ifndef _Vector4_ #define _Vector4_ typedef struct _Vector4 { FLOAT x; FLOAT y; FLOAT z; FLOAT w; } Vector4; #endif #ifdef __XNAMATH_H__ #ifndef _Vector4_Functions_ #define _Vector4_Functions_ inline XMVECTOR XMVectorFromVector4(const Vector4& vec4) { return XMVectorSet(vec4.x, vec4.y, vec4.z, vec4.w); } inline Vector4 XMVectorToVector4(FXMVECTOR V) { Vector4 vec4 = { XMVectorGetX(V), XMVectorGetY(V), XMVectorGetZ(V), XMVectorGetW(V) }; return vec4; } #endif #endif typedef enum _NUI_SKELETON_POSITION_INDEX { NUI_SKELETON_POSITION_HIP_CENTER = 0, NUI_SKELETON_POSITION_SPINE, NUI_SKELETON_POSITION_SHOULDER_CENTER, NUI_SKELETON_POSITION_HEAD, NUI_SKELETON_POSITION_SHOULDER_LEFT, NUI_SKELETON_POSITION_ELBOW_LEFT, NUI_SKELETON_POSITION_WRIST_LEFT, NUI_SKELETON_POSITION_HAND_LEFT, NUI_SKELETON_POSITION_SHOULDER_RIGHT, NUI_SKELETON_POSITION_ELBOW_RIGHT, NUI_SKELETON_POSITION_WRIST_RIGHT, NUI_SKELETON_POSITION_HAND_RIGHT, NUI_SKELETON_POSITION_HIP_LEFT, NUI_SKELETON_POSITION_KNEE_LEFT, NUI_SKELETON_POSITION_ANKLE_LEFT, NUI_SKELETON_POSITION_FOOT_LEFT, NUI_SKELETON_POSITION_HIP_RIGHT, NUI_SKELETON_POSITION_KNEE_RIGHT, NUI_SKELETON_POSITION_ANKLE_RIGHT, NUI_SKELETON_POSITION_FOOT_RIGHT, NUI_SKELETON_POSITION_COUNT } NUI_SKELETON_POSITION_INDEX; // // Number of NUI_SKELETON_DATA elements in NUI_SKELETON_FRAME // #define NUI_SKELETON_COUNT 6 #endif // __NuiSensor_h__ // // Number of NUI_SKELETON_DATA elements that can be in the NUI_SKELETON_TRACKED state // #define NUI_SKELETON_MAX_TRACKED_COUNT 2 // // Tracking IDs start at 1 // #define NUI_SKELETON_INVALID_TRACKING_ID 0 #ifndef __NuiSensor_h__ typedef enum _NUI_SKELETON_POSITION_TRACKING_STATE { NUI_SKELETON_POSITION_NOT_TRACKED = 0, NUI_SKELETON_POSITION_INFERRED, NUI_SKELETON_POSITION_TRACKED } NUI_SKELETON_POSITION_TRACKING_STATE; typedef enum _NUI_SKELETON_TRACKING_STATE { NUI_SKELETON_NOT_TRACKED = 0, NUI_SKELETON_POSITION_ONLY, NUI_SKELETON_TRACKED } NUI_SKELETON_TRACKING_STATE; typedef struct _NUI_SKELETON_DATA { NUI_SKELETON_TRACKING_STATE eTrackingState; DWORD dwTrackingID; DWORD dwEnrollmentIndex; DWORD dwUserIndex; Vector4 Position; Vector4 SkeletonPositions[NUI_SKELETON_POSITION_COUNT]; NUI_SKELETON_POSITION_TRACKING_STATE eSkeletonPositionTrackingState[NUI_SKELETON_POSITION_COUNT]; DWORD dwQualityFlags; } NUI_SKELETON_DATA; #endif // __NuiSensor_h__ // // Force a link error if the size of NUI_SKELETON_DATA is different // between the static library and the header included by the title. // __declspec(selectany) DWORD NuiSkeletonDataSize = sizeof(NUI_SKELETON_DATA); #define NUI_SKELETON_QUALITY_CLIPPED_RIGHT 0x00000001 #define NUI_SKELETON_QUALITY_CLIPPED_LEFT 0x00000002 #define NUI_SKELETON_QUALITY_CLIPPED_TOP 0x00000004 #define NUI_SKELETON_QUALITY_CLIPPED_BOTTOM 0x00000008 #ifndef __NuiSensor_h__ #pragma pack(push, 16) typedef struct _NUI_SKELETON_FRAME { LARGE_INTEGER liTimeStamp; DWORD dwFrameNumber; DWORD dwFlags; Vector4 vFloorClipPlane; Vector4 vNormalToGravity; NUI_SKELETON_DATA SkeletonData[NUI_SKELETON_COUNT]; } NUI_SKELETON_FRAME; #pragma pack(pop) typedef struct _NUI_TRANSFORM_SMOOTH_PARAMETERS { FLOAT fSmoothing; // [0..1], lower values closer to raw data FLOAT fCorrection; // [0..1], lower values slower to correct towards the raw data FLOAT fPrediction; // [0..n], the number of frames to predict into the future FLOAT fJitterRadius; // The radius in meters for jitter reduction FLOAT fMaxDeviationRadius; // The maximum radius in meters that filtered positions are allowed to deviate from raw data } NUI_TRANSFORM_SMOOTH_PARAMETERS; #endif // __NuiSensor_h__ // Flags returned by NuiSkeletonGetNextFrame in the dwFlags field of the NUI_SKELETON_FRAME structure #define NUI_SKELETON_FRAME_FLAG_SEATED_SUPPORT_ENABLED 0x00000008 // Flags for use with the NuiSkeletonTrackingEnable function #define NUI_SKELETON_TRACKING_FLAG_SUPPRESS_NO_FRAME_DATA 0x00000001 #define NUI_SKELETON_TRACKING_FLAG_TITLE_SETS_TRACKED_SKELETONS 0x00000002 #define NUI_SKELETON_TRACKING_FLAG_ENABLE_SEATED_SUPPORT 0x00000004 #define NUI_SKELETON_TRACKING_FLAG_ENABLE_IN_NEAR_RANGE 0x00000008 #ifndef __NuiSensor_h__ typedef struct _NUI_SKELETON_BONE_ROTATION { Matrix4 rotationMatrix; Vector4 rotationQuaternion; } NUI_SKELETON_BONE_ROTATION; typedef struct _NUI_SKELETON_BONE_ORIENTATION { NUI_SKELETON_POSITION_INDEX endJoint; NUI_SKELETON_POSITION_INDEX startJoint; NUI_SKELETON_BONE_ROTATION hierarchicalRotation; NUI_SKELETON_BONE_ROTATION absoluteRotation; } NUI_SKELETON_BONE_ORIENTATION; #endif // __NuiSensor_h__ /// /// Enables skeleton tracking. /// /// /// A handle to an application-allocated, manual reset event that will be set whenever a new frame /// of skeleton data is available, and will be reset whenever the latest frame data is returned. /// This can be NULL. /// /// /// Flags that control skeleton tracking, as a bitwise-OR combination NUI_SKELETON_TRACKING values. /// /// /// Returns S_OK if successful; otherwise, returns one of the following failure codes: /// /// /// Error code /// Description /// /// /// __HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION) /// The device is uninitialized or the sensor is not initialized with the NUI_INITIALIZE_FLAG_USES_SKELETON flag. . /// /// /// E_INVALIDARG /// The parameter includes invalid flags. /// /// /// E_OUTOFMEMORY /// Allocation failed. /// /// /// /// /// The following flags are supported: /// /// /// NUI_SKELETON_TRACKING_FLAG_SUPPRESS_NO_FRAME_DATA /// Prevents NuiSkeletonGetNextFrame from returning E_NUI_FRAME_NO_DATA errors. Instead, calls to NuiSkeletonGetNextFrame block until data is available or the timeout period passes. /// /// /// NUI_SKELETON_TRACKING_FLAG_TITLE_SETS_TRACKED_SKELETONS /// Disables the default player selection mode and enables the title to manage which players have tracked skeletons. /// /// /// NUI_SKELETON_TRACKING_FLAG_ENABLE_SEATED_SUPPORT /// Uses seated skeleton tracking mode. The 10 lower-body joints of each skeleton will not be tracked. /// /// /// _Check_return_ HRESULT NUIAPI NuiSkeletonTrackingEnable( _In_opt_ HANDLE hNextFrameEvent, _In_ DWORD dwFlags ); /// /// Disables skeleton tracking. /// /// /// Returns S_OK if successful; otherwise, returns one of the following error codes: /// /// /// Error code /// Description /// /// /// __HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION) /// The device is uninitialized or the sensor is not initialized with the NUI_INITIALIZE_FLAG_USES_SKELETON flag. . /// /// /// _Check_return_ HRESULT NUIAPI NuiSkeletonTrackingDisable( ); /// /// Gets the next frame of data from the skeleton stream. /// /// The timeout (in milliseconds) before returning without a new frame. /// /// A pointer to a NUI_SKELETON_FRAME structure that receives the next image frame in the skeleton /// stream. This must not be NULL. /// /// /// Returns S_OK if successful; otherwise, returns one of the following error codes: /// /// /// Error code /// Description /// /// /// S_FALSE /// The wait timeout expired before a new frame was available and NuiSkeletonTrackingEnable was passed the NUI_SKELETON_TRACKING_FLAG_TITLE_SETS_TRACKED_SKELETONS flag. /// /// /// E_NUI_FRAME_NO_DATA /// The wait timeout expired before a new frame was available. /// /// /// E_POINTER /// The parameter is NULL. /// /// /// /// _Check_return_ HRESULT NUIAPI NuiSkeletonGetNextFrame( _In_ DWORD dwMillisecondsToWait, _Inout_ NUI_SKELETON_FRAME *pSkeletonFrame ); /// /// Sets an array of IDs for skeletal tracking. /// /// A pointer to the first DWORD in an array of tracking IDs, one for each skeleton. /// /// Returns S_OK if successful; otherwise, returns one of the following error codes: /// /// /// Error code /// Description /// /// /// E_INVALIDARG /// The parameter is NULL. /// /// /// E_NUI_STREAM_NOT_ENABLED /// The device is uninitialized or the sensor is not initialized with the NUI_INITIALIZE_FLAG_USES_SKELETON flag. . /// /// /// E_NUI_FEATURE_NOT_INITIALIZED /// Skeletal tracking is not enabled with the NUI_SKELETON_TRACKING_FLAG_TITLE_SETS_TRACKED_SKELETONS flag. /// /// /// _Check_return_ HRESULT NUIAPI NuiSkeletonSetTrackedSkeletons( _In_count_c_(NUI_SKELETON_MAX_TRACKED_COUNT) DWORD TrackingIDs[NUI_SKELETON_MAX_TRACKED_COUNT] ); #ifdef __cplusplus } //close extern "C" // Assuming a pixel resolution of 320x240 // x_meters = (x_pixelcoord - 160) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * z_meters; // y_meters = (y_pixelcoord - 120) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * z_meters; #define NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 (NUI_CAMERA_DEPTH_NOMINAL_INVERSE_FOCAL_LENGTH_IN_PIXELS) // Assuming a pixel resolution of 320x240 // x_pixelcoord = (x_meters) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / z_meters + 160; // y_pixelcoord = (y_meters) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / z_meters + 120; #define NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 (NUI_CAMERA_DEPTH_NOMINAL_FOCAL_LENGTH_IN_PIXELS) /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// /// The point to transform, in skeleton space coordinates. This point must have a valid depth value. /// /// /// A pointer to a FLOAT that receives the X coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a FLOAT that receives the Y coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a USHORT that receives the depth value of the point in depth space. This /// pointer must be non-NULL when you call the function. If this is a NULL pointer, this function /// returns without doing anything. /// /// The format of this value is the same as that for points in other depth images: the least /// significant three bits contain a player index that is always zero, and the remaining bits are /// the depth value, in millimeters. This value is suitable for comparison with values from an /// image from any of the depth streams, provided that the player index information is masked /// appropriately from the other image. /// /// /// A NUI_IMAGE_RESOLUTION value that specifies the resolution of the depth image. /// /// /// You can use this function to place virtual objects into the color image with depth-based /// occlusion. Call this function to determine which skeleton-space vertices of a virtual object /// are in front of, or behind, real objects that are visible in the depth map image. After /// occluded parts of the virtual objects have been culled, use the /// NuiImageGetColorPixelCoordinatesFromDepthPixel function to overlay the virtual object's /// vertices into color image pixel coordinates for rendering. /// inline VOID NuiTransformSkeletonToDepthImage( _In_ Vector4 vPoint, _Out_ LONG *plDepthX, _Out_ LONG *plDepthY, _Out_ USHORT *pusDepthValue, _In_ NUI_IMAGE_RESOLUTION eResolution ) { if((plDepthX == NULL) || (plDepthY == NULL) || (pusDepthValue == NULL)) { return; } // // Requires a valid depth value. // if(vPoint.z > FLT_EPSILON) { DWORD width; DWORD height; NuiImageResolutionToSize( eResolution, width, height ); // // Center of depth sensor is at (0,0,0) in skeleton space, and // and (width/2,height/2) in depth image coordinates. Note that positive Y // is up in skeleton space and down in image coordinates. // // The 0.5f is to correct for casting to int truncating, not rounding *plDepthX = static_cast( width / 2 + vPoint.x * (width/320.f) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / vPoint.z + 0.5f); *plDepthY = static_cast( height / 2 - vPoint.y * (height/240.f) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / vPoint.z + 0.5f); // // Depth is in meters in skeleton space. // The depth image pixel format has depth in millimeters shifted left by 3. // *pusDepthValue = static_cast(vPoint.z *1000) << 3; } else { *plDepthX = 0; *plDepthY = 0; *pusDepthValue = 0; } } /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// /// The point to transform, in skeleton space coordinates. This point must have a valid depth value. /// /// /// A pointer to a FLOAT that receives the X coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a FLOAT that receives the Y coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a USHORT that receives the depth value of the point in depth space. This /// pointer must be non-NULL when you call the function. If this is a NULL pointer, this function /// returns without doing anything. /// /// The format of this value is the same as that for points in other depth images: the least /// significant three bits contain a player index that is always zero, and the remaining bits are /// the depth value, in millimeters. This value is suitable for comparison with values from an /// image from any of the depth streams, provided that the player index information is masked /// appropriately from the other image. /// /// /// You can use this function to place virtual objects into the color image with depth-based /// occlusion. Call this function to determine which skeleton-space vertices of a virtual object /// are in front of, or behind, real objects that are visible in the depth map image. After /// occluded parts of the virtual objects have been culled, use the /// NuiImageGetColorPixelCoordinatesFromDepthPixel function to overlay the virtual object's /// vertices into color image pixel coordinates for rendering. /// inline VOID NuiTransformSkeletonToDepthImage( _In_ Vector4 vPoint, _Out_ LONG *plDepthX, _Out_ LONG *plDepthY, _Out_ USHORT *pusDepthValue ) { NuiTransformSkeletonToDepthImage( vPoint, plDepthX, plDepthY, pusDepthValue, NUI_IMAGE_RESOLUTION_320x240); } /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// /// The point to transform, in skeleton space coordinates. This point must have a valid depth value. /// /// /// A pointer to a FLOAT that receives the X coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a FLOAT that receives the Y coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A NUI_IMAGE_RESOLUTION value that specifies the resolution of the depth image. /// /// /// You can use this function to place virtual objects into the color image with depth-based /// occlusion. Call this function to determine which skeleton-space vertices of a virtual object /// are in front of, or behind, real objects that are visible in the depth map image. After /// occluded parts of the virtual objects have been culled, use the /// NuiImageGetColorPixelCoordinatesFromDepthPixel function to overlay the virtual object's /// vertices into color image pixel coordinates for rendering. /// inline VOID NuiTransformSkeletonToDepthImage( _In_ Vector4 vPoint, _Out_ FLOAT *pfDepthX, _Out_ FLOAT *pfDepthY, _In_ NUI_IMAGE_RESOLUTION eResolution ) { if((pfDepthX == NULL) || (pfDepthY == NULL)) { return; } // // Requires a valid depth value. // if(vPoint.z > FLT_EPSILON) { DWORD width; DWORD height; NuiImageResolutionToSize( eResolution, width, height ); // // Center of depth sensor is at (0,0,0) in skeleton space, and // and (width/2,height/2) in depth image coordinates. Note that positive Y // is up in skeleton space and down in image coordinates. // *pfDepthX = width / 2 + vPoint.x * (width/320.f) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / vPoint.z; *pfDepthY = height / 2 - vPoint.y * (height/240.f) * NUI_CAMERA_SKELETON_TO_DEPTH_IMAGE_MULTIPLIER_320x240 / vPoint.z; } else { *pfDepthX = 0.0f; *pfDepthY = 0.0f; } } /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// /// The point to transform, in skeleton space coordinates. This point must have a valid depth value. /// /// /// A pointer to a FLOAT that receives the X coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// A pointer to a FLOAT that receives the Y coordinate of the point in depth space. This pointer /// must be non-NULL when you call the function. If this is a NULL pointer, this function returns /// without doing anything. /// /// /// You can use this function to place virtual objects into the color image with depth-based /// occlusion. Call this function to determine which skeleton-space vertices of a virtual object /// are in front of, or behind, real objects that are visible in the depth map image. After /// occluded parts of the virtual objects have been culled, use the /// NuiImageGetColorPixelCoordinatesFromDepthPixel function to overlay the virtual object's /// vertices into color image pixel coordinates for rendering. /// inline VOID NuiTransformSkeletonToDepthImage( _In_ Vector4 vPoint, _Out_ FLOAT *pfDepthX, _Out_ FLOAT *pfDepthY ) { NuiTransformSkeletonToDepthImage(vPoint, pfDepthX, pfDepthY, NUI_IMAGE_RESOLUTION_320x240); } /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// The X coordinate of the depth pixel. /// The Y coordinate of the depth pixel. /// /// The depth value (in millimeters) of the depth image pixel, shifted left by three bits. The left /// shift enables you to pass the value from the depth image directly into this function. /// /// /// A NUI_IMAGE_RESOLUTION value that specifies the resolution of the depth image. /// /// /// Returns the skeleton space coordinates of the given depth image pixel (in meters). /// inline Vector4 NuiTransformDepthImageToSkeleton( _In_ LONG lDepthX, _In_ LONG lDepthY, _In_ USHORT usDepthValue, _In_ NUI_IMAGE_RESOLUTION eResolution ) { DWORD width; DWORD height; NuiImageResolutionToSize( eResolution, width, height ); // // Depth is in meters in skeleton space. // The depth image pixel format has depth in millimeters shifted left by 3. // FLOAT fSkeletonZ = static_cast(usDepthValue >> 3) / 1000.0f; // // Center of depth sensor is at (0,0,0) in skeleton space, and // and (width/2,height/2) in depth image coordinates. Note that positive Y // is up in skeleton space and down in image coordinates. // FLOAT fSkeletonX = (lDepthX - width/2.0f) * (320.0f/width) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * fSkeletonZ; FLOAT fSkeletonY = -(lDepthY - height/2.0f) * (240.0f/height) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * fSkeletonZ; // // Return the result as a vector. // Vector4 v4; v4.x = fSkeletonX; v4.y = fSkeletonY; v4.z = fSkeletonZ; v4.w = 1.0f; return v4; } /// /// Returns the depth space coordinates of the specified point in skeleton space. /// /// The X coordinate of the depth pixel. /// The Y coordinate of the depth pixel. /// /// The depth value (in millimeters) of the depth image pixel, shifted left by three bits. The left /// shift enables you to pass the value from the depth image directly into this function. /// /// /// Returns the skeleton space coordinates of the given depth image pixel (in meters). /// inline Vector4 NuiTransformDepthImageToSkeleton( _In_ LONG lDepthX, _In_ LONG lDepthY, _In_ USHORT usDepthValue ) { return NuiTransformDepthImageToSkeleton(lDepthX, lDepthY, usDepthValue, NUI_IMAGE_RESOLUTION_320x240); } #endif #ifdef __cplusplus extern "C" { #endif /// /// Filters skeleton positions to reduce jitter between frames. /// /// /// On entry, points to a NUI_SKELETON_FRAME structure that contains the skeleton data to be /// smoothed. On exit, the skeleton data in the structure has been replaced by smoothed data. If /// this function does not return S_OK, this data is unchanged. /// /// /// The parameters for the smoothing function. See the NUI_TRANSFORM_SMOOTH_PARAMETERS structure /// for a description of the parameters. /// /// /// Returns S_OK if successful; otherwise, returns one of the following error codes: /// /// /// Error code /// Description /// /// /// E_OUTOFMEMORY /// Failed allocation. /// /// /// E_POINTER /// The parameter is NULL. /// /// /// /// /// The filter used is based on the Holt Double Exponential Smoothing method used for statistical /// analysis of economic data, which provides smoothing with less latency than other smoothing /// filter algorithms. A single call of this function updates all currently-tracked skeletons. /// _Check_return_ HRESULT NUIAPI NuiTransformSmooth( _Inout_ NUI_SKELETON_FRAME *pSkeletonFrame, _In_opt_ CONST NUI_TRANSFORM_SMOOTH_PARAMETERS *pSmoothingParams ); /// /// Calculate bone orientations for a skeleton. /// /// /// Pointer to the skeleton data to calculate joint angles for. /// /// /// Pointer to an array of NUI_SKELETON_BONE_ORIENTATION of dimension NUI_SKELETON_POSITION_COUNT (20). /// This array must be allocated by the user before calling this function. /// /// /// Returns S_OK if successful; otherwise, returns one of the following error codes: /// /// /// Error code /// Description /// /// /// E_INVALIDARG /// The parameter is NULL. /// /// /// E_POINTER /// The parameter is NULL. /// /// /// /// S_FALSE /// The joints required to calculate the skeleton root are not visible. Hierarchical bone rotations are set to Identity. /// /// /// /// /// The function calculates hierarchical and absolute joint angles for the skeleton, which can /// be used in animating an avatar (Avateering). The HipCenter joint is the root of the hierarchy, /// and describes an absolute rotation in the right-hand camera coordinate system. All other /// joints describe rotations relative to their parent joint orientation. The angles are returned /// in the same order as the joints are defined. /// _Check_return_ STDMETHODIMP NuiSkeletonCalculateBoneOrientations( _In_ const NUI_SKELETON_DATA *pSkeletonData, _Out_cap_c_(NUI_SKELETON_POSITION_COUNT) NUI_SKELETON_BONE_ORIENTATION *pBoneOrientations); #ifdef __cplusplus } //close extern "C" #endif