Kinnect中AvatarController脚本翻译

AvatarController脚本翻译

using UnityEngine;
//using Windows.Kinect;

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Text; 


/// <summary>
/// Avatar controller is the component that transfers the captured user motion to a humanoid model (avatar).
/// </summary>
[RequireComponent(typeof(Animator))]
public class AvatarController : MonoBehaviour
{   
    [Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")]
    //索引
    public int playerIndex = 0;

    [Tooltip("Whether the avatar is facing the player or not.")]
    //人物是否面对玩家
    public bool mirroredMovement = false;

    [Tooltip("Whether the avatar is allowed to move vertically or not.")]
    //人物是否允许呗垂直移动
    public bool verticalMovement = false;

    [Tooltip("Whether the avatar's root motion is applied by other component or script.")]
    //人物的根动作是否适用于其他组件或脚本。
    public bool externalRootMotion = false;

    [Tooltip("Whether the head rotation is controlled externally (e.g. by VR-headset)" )]
    //头部旋转是否由外部控制(例如,由vr-耳机)
    public bool externalHeadRotation = false;

    [Tooltip("Whether the finger orientations are allowed or not.")]
    //手指朝向是否允许。
    public bool fingerOrientations = false;

    [Tooltip("Rate at which the avatar will move through the scene.")]
    //人物在镜头中的移动速度
    public float moveRate = 1f;

    [Tooltip("Smooth factor used for avatar movements and joint rotations.")]
    //用于人物运动和关节旋转的平滑因子
    public float smoothFactor = 10f;

    [Tooltip("Game object this transform is relative to (optional).")]
    //这个转换是相对于(可选的)。随人物的变换而变换
    public GameObject offsetNode;

    [Tooltip("If enabled, makes the avatar position relative to this camera to be the same as the player's position to the sensor.")]
    //如果启用,则使化身相对于该摄像机的位置与玩家对传感器的位置相同。
    public Camera posRelativeToCamera;

    [Tooltip("Whether the avatar's position should match the color image (in Pos-rel-to-camera mode only).")]
    //人物的位置是否应该与彩色图像相匹配(仅在相机-镜头模式下)。
    public bool posRelOverlayColor = false;

    [Tooltip("Whether z-axis movement needs to be inverted (Pos-Relative mode only).")]
    //z轴运动是否需要反转(仅是相对模式)
    public bool posRelInvertedZ = false;

    [Tooltip("Whether the avatar's feet must stick to the ground.")]
    //人物的脚是否必须贴在地面上。
    public bool groundedFeet = false;

    [Tooltip("Whether to apply the humanoid muscle limits or not.")]
    //是否适用于人类的肌肉限制。
    public bool applyMuscleLimits = false;

    [Tooltip("Whether to flip left and right, relative to the sensor.")]
    //相对于传感器,是否要翻转左和右。
    public bool flipLeftRight = false;


    [Tooltip("Vertical offset of the avatar with respect to the position of user's spine-base.")]
    //在用户的脊柱基础上,对化身的垂直偏移量。
    [Range(-0.5f, 0.5f)]
    public float verticalOffset = 0f;

    [Tooltip("Forward (Z) offset of the avatar with respect to the position of user's spine-base.")]
    //向前(Z)在用户的脊柱基础上的位置偏移。
    [Range(-0.5f, 0.5f)]
    public float forwardOffset = 0f;

    // userId of the player
    [NonSerialized]
    //人物Id
    public Int64 playerId = 0;


    // The body root node
    //人物根节点
    protected Transform bodyRoot;

    // Variable to hold all them bones. It will initialize the same size as initialRotations.
    //把所有的骨头都固定住,将初始化与初始旋转相同的大小。
    protected Transform[] bones;

    // Rotations of the bones when the Kinect tracking starts.
    //当Kinect追踪开始时,骨头的旋转。
    protected Quaternion[] initialRotations;
    protected Quaternion[] localRotations;
    protected bool[] isBoneDisabled;

    // Local rotations of finger bones
    //手指骨局部旋转
    protected Dictionary<HumanBodyBones, Quaternion> fingerBoneLocalRotations = new Dictionary<HumanBodyBones, Quaternion>();
    protected Dictionary<HumanBodyBones, Vector3> fingerBoneLocalAxes = new Dictionary<HumanBodyBones, Vector3>();

    // Initial position and rotation of the transform
    //转换的初始位置和旋转
    protected Vector3 initialPosition;
    protected Quaternion initialRotation;
    protected Vector3 initialHipsPosition;//初始化臀部位置
    protected Quaternion initialHipsRotation;//初始化臀部旋转角度

    protected Vector3 offsetNodePos;
    protected Quaternion offsetNodeRot;
    protected Vector3 bodyRootPosition;

    // Calibration Offset Variables for Character Position.
    //对字符位置的校正偏置变量。
    [NonSerialized]
    public bool offsetCalibrated = false;
    protected Vector3 offsetPos = Vector3.zero;
    //protected float xOffset, yOffset, zOffset;
    //private Quaternion originalRotation;

    private Animator animatorComponent = null;
    private HumanPoseHandler humanPoseHandler = null;
    private HumanPose humanPose = new HumanPose();

    // whether the parent transform obeys physics
    //父变换是否遵循物理
    protected bool isRigidBody = false;

    // private instance of the KinectManager
    //KinectManager的私有实例
    protected KinectManager kinectManager;

    // last hand events
    //最后手事件
    private InteractionManager.HandEventType lastLeftHandEvent = InteractionManager.HandEventType.Release;
    private InteractionManager.HandEventType lastRightHandEvent = InteractionManager.HandEventType.Release;

    // fist states
    private bool bLeftFistDone = false;
    private bool bRightFistDone = false;

    // grounder constants and variables
    //滚地球常量和变量
    private const int raycastLayers = ~2;  // Ignore Raycast//忽略Raycast
    private const float maxFootDistanceGround = 0.02f;  // maximum distance from lower foot to the ground//从下脚到地面的最大距离
    private const float maxFootDistanceTime = 0.2f; // 1.0f;  // maximum allowed time, the lower foot to be distant from the ground//最大允许时间,下脚距离地面较远
    private Transform leftFoot, rightFoot;

    private float fFootDistanceInitial = 0f;
    private float fFootDistance = 0f;
    private float fFootDistanceTime = 0f;


    /// <summary>
    /// Gets the number of bone transforms (array length).
    /// 得到骨转换的数量(数组长度)。
    /// </summary>
    /// <returns>The number of bone transforms.</returns>
    public int GetBoneTransformCount()
    {
        return bones != null ? bones.Length : 0;
    }

    /// <summary>
    /// Gets the bone transform by index.
    /// 通过索引来得到骨头的变化。
    /// </summary>
    /// <returns>The bone transform.</returns>
    /// <param name="index">Index</param>
    public Transform GetBoneTransform(int index)
    {
        if(index >= 0 && index < bones.Length)
        {
            return bones[index];
        }

        return null;
    }

    /// <summary>
    /// Get joint position with respect of player world and kinect offsets   ( //!!still some problems with accurate Y pos, probably connected with kinect sensor height estimation ) 
    /// 得到在世界坐标上准确的关节位置和kinect偏移量(//!!!还有一些问题是精确的Y pos,可能与kinect传感器高度评估有关)
    /// </summary>
    /// <param name="jointType"></param>
    /// <returns></returns>
    public Vector3 GetJointWorldPos( KinectInterop.JointType jointType )
    {
        if( !kinectManager )
        {
            return Vector3.zero;
        }

        Vector3 jointPosition = kinectManager.GetJointPosition( playerId, (int)jointType );
        Vector3 worldPosition = new Vector3(
            jointPosition.x - offsetPos.x, 
//            jointPosition.y - offsetPos.y + kinectManager.sensorHeight,  //!! this should be better investigated .. 
            jointPosition.y + offsetPos.y - kinectManager.sensorHeight,  //!! this workds better on my example 
            !mirroredMovement && !posRelativeToCamera ? (-jointPosition.z - offsetPos.z) : (jointPosition.z - offsetPos.z));

        Quaternion posRotation = mirroredMovement ? Quaternion.Euler (0f, 180f, 0f) * initialRotation : initialRotation;
        worldPosition = posRotation * worldPosition;

        return bodyRootPosition + worldPosition;
    }

    /// <summary>
    /// Disables the bone and optionally resets its orientation.
    /// 禁用骨头,并可选择重新设置其方向。
    /// </summary>
    /// <param name="index">Bone index.</param>
    /// <param name="resetBone">If set to <c>true</c> resets bone orientation.</param>
    public void DisableBone(int index, bool resetBone)
    {
        if(index >= 0 && index < bones.Length)
        {
            isBoneDisabled[index] = true;

            if (resetBone && bones[index] != null) 
            {
                bones[index].rotation = localRotations[index];
            }
        }
    }

    /// <summary>
    /// Enables the bone, so AvatarController could update its orientation.
    /// 骨骼是否激活,因此,它可以更新它的方向。
    /// </summary>
    /// <param name="index">Bone index.</param>
    public void EnableBone(int index)
    {
        if(index >= 0 && index < bones.Length)
        {
            isBoneDisabled[index] = false;
        }
    }

    /// <summary>
    /// Determines whether the bone orientation update is enabled or not.
    /// 确定是否启用了骨定位更新。
    /// </summary>
    /// <returns><c>true</c> if the bone update is enabled; otherwise, <c>false</c>.</returns>
    /// <param name="index">Bone index.</param>
    public bool IsBoneEnabled(int index)
    {
        if(index >= 0 && index < bones.Length)
        {
            return !isBoneDisabled[index];
        }

        return false;
    }

    /// <summary>
    /// Gets the bone index by joint type.
    /// 通过关节类型得到骨骼索引。
    /// </summary>
    /// <returns>The bone index.</returns>
    /// <param name="joint">Joint type</param>
    /// <param name="bMirrored">If set to <c>true</c> gets the mirrored joint index.</param>
    public int GetBoneIndexByJoint(KinectInterop.JointType joint, bool bMirrored)
    {
        int boneIndex = -1;

        if(jointMap2boneIndex.ContainsKey(joint))
        {
            boneIndex = !bMirrored ? jointMap2boneIndex[joint] : mirrorJointMap2boneIndex[joint];
        }

        return boneIndex;
    }

    /// <summary>
    /// Gets the special index by two joint types.
    /// 通过两种关节类型得到特殊的索引。
    /// </summary>
    /// <returns>The spec index by joint.</returns>
    /// <param name="joint1">Joint 1 type.</param>
    /// <param name="joint2">Joint 2 type.</param>
    /// <param name="bMirrored">If set to <c>true</c> gets the mirrored joint index.</param>
    public int GetSpecIndexByJoint(KinectInterop.JointType joint1, KinectInterop.JointType joint2, bool bMirrored)
    {
        int boneIndex = -1;

        if((joint1 == KinectInterop.JointType.ShoulderLeft && joint2 == KinectInterop.JointType.SpineShoulder) ||
           (joint2 == KinectInterop.JointType.ShoulderLeft && joint1 == KinectInterop.JointType.SpineShoulder))
        {
            return (!bMirrored ? 25 : 26);
        }
        else if((joint1 == KinectInterop.JointType.ShoulderRight && joint2 == KinectInterop.JointType.SpineShoulder) ||
                (joint2 == KinectInterop.JointType.ShoulderRight && joint1 == KinectInterop.JointType.SpineShoulder))
        {
            return (!bMirrored ? 26 : 25);
        }
        else if((joint1 == KinectInterop.JointType.HandTipLeft && joint2 == KinectInterop.JointType.HandLeft) ||
                (joint2 == KinectInterop.JointType.HandTipLeft && joint1 == KinectInterop.JointType.HandLeft))
        {
            return (!bMirrored ? 27 : 28);
        }
        else if((joint1 == KinectInterop.JointType.HandTipRight && joint2 == KinectInterop.JointType.HandRight) ||
                (joint2 == KinectInterop.JointType.HandTipRight && joint1 == KinectInterop.JointType.HandRight))
        {
            return (!bMirrored ? 28 : 27);
        }
        else if((joint1 == KinectInterop.JointType.ThumbLeft && joint2 == KinectInterop.JointType.HandLeft) ||
                (joint2 == KinectInterop.JointType.ThumbLeft && joint1 == KinectInterop.JointType.HandLeft))
        {
            return (!bMirrored ? 29 : 30);
        }
        else if((joint1 == KinectInterop.JointType.ThumbRight && joint2 == KinectInterop.JointType.HandRight) ||
                (joint2 == KinectInterop.JointType.ThumbRight && joint1 == KinectInterop.JointType.HandRight))
        {
            return (!bMirrored ? 30 : 29);
        }

        return boneIndex;
    }


    // transform caching gives performance boost since Unity calls GetComponent<Transform>() each time you call transform 
    //转换缓存提供了性能提升,因为每次调用转换时都调用GetComponent的GetComponent()
    private Transform _transformCache;
    public new Transform transform
    {
        get
        {
            if (!_transformCache) 
            {
                _transformCache = base.transform;
            }

            return _transformCache;
        }
    }


    public void Awake()
    {   
        // check for double start
        if(bones != null)
            return;
        if(!gameObject.activeInHierarchy) 
            return;

        // inits the bones array
        //初始化骨头数组
        bones = new Transform[31];

        // get the animator reference
        //得到动画组件
        animatorComponent = GetComponent<Animator>();

        // Map bones to the points the Kinect tracks
        //将骨头映射到Kinect追踪的点
        MapBones();

        // Set model's arms to be in T-pose, if needed
        //如果需要,将模型的手臂设置为t型
        SetModelArmsInTpose();

        // Initial rotations and directions of the bones.
        //最初的旋转和骨骼的方向。
        initialRotations = new Quaternion[bones.Length];
        localRotations = new Quaternion[bones.Length];
        isBoneDisabled = new bool[bones.Length];

        // Get initial bone rotations
        //得到初始骨旋转
        GetInitialRotations();

        // enable all bones
        //不激活所有的骨骼
        for(int i = 0; i < bones.Length; i++)
        {
            isBoneDisabled[i] = false;
        }

        // get initial distance to ground
        //到达地面的初始距离
        fFootDistanceInitial = GetDistanceToGround();
        fFootDistance = 0f;
        fFootDistanceTime = 0f;

        // if parent transform uses physics
        //如果父变换使用物理
        isRigidBody = (gameObject.GetComponent<Rigidbody>() != null);

        // get the pose handler reference
        //获取姿势处理程序引用
        if (animatorComponent && animatorComponent.avatar && animatorComponent.avatar.isHuman) 
        {
            //Transform hipsTransform = animator.GetBoneTransform(HumanBodyBones.Hips);
            //Transform rootTransform = hipsTransform.parent;
            Transform rootTransform = transform;

            humanPoseHandler = new HumanPoseHandler(animatorComponent.avatar, rootTransform);
            humanPoseHandler.GetHumanPose(ref humanPose);
        }
    }


    // applies the muscle limits for humanoid avatar
    //适用于类人的肌力限制
    private void CheckMuscleLimits()
    {
        if (humanPoseHandler == null)
            return;

        humanPoseHandler.GetHumanPose(ref humanPose);

        //Debug.Log(playerId + " - Trans: " + transform.position + ", body: " + humanPose.bodyPosition);

        bool isPoseChanged = false;

        float muscleMin = -1f;
        float muscleMax = 1f;

        for (int i = 0; i < humanPose.muscles.Length; i++) 
        {
            if (float.IsNaN(humanPose.muscles[i])) 
            {
                //humanPose.muscles[i] = 0f;
                continue;
            }

            if (humanPose.muscles[i] < muscleMin) 
            {
                humanPose.muscles[i] = muscleMin;
                isPoseChanged = true;
            }
            else if (humanPose.muscles[i] > muscleMax) 
            {
                humanPose.muscles[i] = muscleMax;
                isPoseChanged = true;
            }
        }

        if (isPoseChanged) 
        {
            Quaternion localBodyRot = Quaternion.Inverse(transform.rotation) * humanPose.bodyRotation;

            // recover the body position & orientation
            //humanPose.bodyPosition = Vector3.zero;
            //humanPose.bodyPosition.y = initialHipsPosition.y;
            humanPose.bodyPosition = initialHipsPosition;
            humanPose.bodyRotation = localBodyRot; // Quaternion.identity;

            humanPoseHandler.SetHumanPose(ref humanPose);
            //Debug.Log("  Human pose updated.");
        }

    }


    /// <summary>
    /// Updates the avatar each frame.
    /// 更新化身每一帧。
    /// </summary>
    /// <param name="UserID">User ID</param>
    public void UpdateAvatar(Int64 UserID)
    {   
        if(!gameObject.activeInHierarchy) 
            return;

        // Get the KinectManager instance
        if(kinectManager == null)
        {
            kinectManager = KinectManager.Instance;
        }

        // move the avatar to its Kinect position
        //将化身移动到它的Kinect位置
        if (!externalRootMotion)
        {
            MoveAvatar(UserID);
        }

        // get the left hand state and event
        //得到左边的状态和事件
        if (kinectManager && kinectManager.GetJointTrackingState(UserID, (int)KinectInterop.JointType.HandLeft) != KinectInterop.TrackingState.NotTracked)
        {
            KinectInterop.HandState leftHandState = kinectManager.GetLeftHandState(UserID);
            InteractionManager.HandEventType leftHandEvent = InteractionManager.HandStateToEvent(leftHandState, lastLeftHandEvent);

            if(leftHandEvent != InteractionManager.HandEventType.None)
            {
                lastLeftHandEvent = leftHandEvent;
            }
        }

        // get the right hand state and event
        //得到正确的手状态和事件
        if (kinectManager && kinectManager.GetJointTrackingState(UserID, (int)KinectInterop.JointType.HandRight) != KinectInterop.TrackingState.NotTracked)
        {
            KinectInterop.HandState rightHandState = kinectManager.GetRightHandState(UserID);
            InteractionManager.HandEventType rightHandEvent = InteractionManager.HandStateToEvent(rightHandState, lastRightHandEvent);

            if(rightHandEvent != InteractionManager.HandEventType.None)
            {
                lastRightHandEvent = rightHandEvent;
            }
        }

        // rotate the avatar bones
        //旋转人物的骨头
        for (var boneIndex = 0; boneIndex < bones.Length; boneIndex++)
        {
            if (!bones[boneIndex] || isBoneDisabled[boneIndex]) 
                continue;

            if(boneIndex2JointMap.ContainsKey(boneIndex))
            {
                KinectInterop.JointType joint = !(mirroredMovement ^ flipLeftRight) ? 
                    boneIndex2JointMap[boneIndex] : boneIndex2MirrorJointMap[boneIndex];

                if( externalHeadRotation && joint == KinectInterop.JointType.Head)   // skip head if moved externally如果移动到外部,就跳过头
                {
                    continue;
                }

                TransformBone(UserID, joint, boneIndex, !(mirroredMovement ^ flipLeftRight));
            }
            else if(specIndex2JointMap.ContainsKey(boneIndex))
            {
                // special bones (clavicles)
                //特殊的骨头(锁骨)
                List<KinectInterop.JointType> alJoints = !(mirroredMovement ^ flipLeftRight) ? 
                    specIndex2JointMap[boneIndex] : specIndex2MirrorMap[boneIndex];

                if(alJoints.Count >= 2)
                {
                    //Debug.Log(alJoints[0].ToString());
                    Vector3 baseDir = alJoints[0].ToString().EndsWith("Left") ? Vector3.left : Vector3.right;
                    TransformSpecialBone(UserID, alJoints[0], alJoints[1], boneIndex, baseDir, !(mirroredMovement ^ flipLeftRight));
                }
            }
        }

        if (applyMuscleLimits && kinectManager && kinectManager.IsUserTracked(UserID)) 
        {
            // check for limits
            //检查限制
            CheckMuscleLimits();
        }
    }

    /// <summary>
    /// Resets bones to their initial positions and rotations. This also releases avatar control from KM, by settings playerId to 0 
    /// 将骨头重新设置为最初的位置和旋转。这也会从KM的设置中释放出阿凡达的控制,将playerId设置为0
    /// </summary>
    public virtual void ResetToInitialPosition()
    {
        playerId = 0;

        if(bones == null)
            return;

        // For each bone that was defined, reset to initial position.
        //对于每一个被定义的骨头,重置为初始位置。
        transform.rotation = Quaternion.identity;

        for(int pass = 0; pass < 2; pass++)  // 2 passes because clavicles are at the end因为锁骨在末端
        {
            for(int i = 0; i < bones.Length; i++)
            {
                if(bones[i] != null)
                {
                    bones[i].rotation = initialRotations[i];
                }
            }
        }

        // reset finger bones to initial position
        //将手指骨复位到初始位置
        //Animator animatorComponent = GetComponent<Animator>();
        foreach (HumanBodyBones bone in fingerBoneLocalRotations.Keys)
        {
            Transform boneTransform = animatorComponent ? animatorComponent.GetBoneTransform(bone) : null;

            if(boneTransform)
            {
                boneTransform.localRotation = fingerBoneLocalRotations[bone];
            }
        }

        //      if(bodyRoot != null)
        //      {
        //          bodyRoot.localPosition = Vector3.zero;
        //          bodyRoot.localRotation = Quaternion.identity;
        //      }

        // Restore the offset's position and rotation
        //恢复偏移位置和旋转
        if (offsetNode != null)
        {
            offsetNode.transform.position = offsetNodePos;
            offsetNode.transform.rotation = offsetNodeRot;
        }

        transform.position = initialPosition;
        transform.rotation = initialRotation;

        if (bones[0]) 
        {
            bones[0].localPosition = initialHipsPosition;
            bones[0].localRotation = initialHipsRotation;
        }
    }

    /// <summary>
    /// Invoked on the successful calibration of the player.
    /// 在玩家成功的校准上被调用。
    /// </summary>
    /// <param name="userId">User identifier.</param>
    public virtual void SuccessfulCalibration(Int64 userId, bool resetInitialTransform)
    {
        playerId = userId;

        // reset the models position
        //重置模型位置
        if(offsetNode != null)
        {
            offsetNode.transform.position = offsetNodePos;
            offsetNode.transform.rotation = offsetNodeRot;
        }

        // reset initial position / rotation if needed 
        //如果需要,重置初始位置/旋转
        if (resetInitialTransform)
        {
            bodyRootPosition = transform.position;
            initialPosition = transform.position;
            initialRotation = transform.rotation;
        }

        transform.position = initialPosition;
        transform.rotation = initialRotation;

        //      // enable all bones
        //      for(int i = 0; i < bones.Length; i++)
        //      {
        //          isBoneDisabled[i] = false;
        //      }

        // re-calibrate the position offset
        //校准的位置偏移
        offsetCalibrated = false;
    }

    /// <summary>
    /// Moves the avatar to its initial/base position 
    /// 将化身移动到它的初始/基础位置
    /// </summary>
    /// <param name="position"> world position </param>
    /// <param name="rotation"> rotation offset </param>
    public void resetInitialTransform( Vector3 position, Vector3 rotation )
    {
        bodyRootPosition = position;
        initialPosition = position;
        initialRotation = Quaternion.Euler( rotation );

        transform.position = initialPosition;
        transform.rotation = initialRotation;

        offsetCalibrated = false;       // this cause also calibrating kinect offset in moveAvatar function 这个原因也可以在move化身函数中校正kinect的偏移量
    }

    // Apply the rotations tracked by kinect to the joints.
    //将kinect追踪的旋转应用到关节处。
    protected void TransformBone(Int64 userId, KinectInterop.JointType joint, int boneIndex, bool flip)
    {
        Transform boneTransform = bones[boneIndex];
        if(boneTransform == null || kinectManager == null)
            return;

        int iJoint = (int)joint;
        if(iJoint < 0 || !kinectManager.IsJointTracked(userId, iJoint))
            return;

        // Get Kinect joint orientation
        //得到Kinect关节定位
        Quaternion jointRotation = kinectManager.GetJointOrientation(userId, iJoint, flip);
        if(jointRotation == Quaternion.identity)
            return;

        // calculate the new orientation
        //计算的新方向
        Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex);

        if(externalRootMotion)
        {
            newRotation = transform.rotation * newRotation;
        }

        // Smoothly transition to the new rotation
        //平稳过渡到新的旋转
        if (smoothFactor != 0f)
            boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime);
        else
            boneTransform.rotation = newRotation;
    }

    // Apply the rotations tracked by kinect to a special joint
    //将kinect跟踪的旋转应用到一个特殊的关节
    protected void TransformSpecialBone(Int64 userId, KinectInterop.JointType joint, KinectInterop.JointType jointParent, int boneIndex, Vector3 baseDir, bool flip)
    {
        Transform boneTransform = bones[boneIndex];
        if(boneTransform == null || kinectManager == null)
            return;

        if(!kinectManager.IsJointTracked(userId, (int)joint) || 
           !kinectManager.IsJointTracked(userId, (int)jointParent))
        {
            return;
        }

        if(boneIndex >= 27 && boneIndex <= 30)
        {
            // fingers or thumbs
            if(fingerOrientations)
            {
                TransformSpecialBoneFingers(userId, (int)joint, boneIndex, flip);
            }

            return;
        }

        Vector3 jointDir = kinectManager.GetJointDirection(userId, (int)joint, false, true);
        Quaternion jointRotation = jointDir != Vector3.zero ? Quaternion.FromToRotation(baseDir, jointDir) : Quaternion.identity;

        if(!flip)
        {
            Vector3 mirroredAngles = jointRotation.eulerAngles;
            mirroredAngles.y = -mirroredAngles.y;
            mirroredAngles.z = -mirroredAngles.z;

            jointRotation = Quaternion.Euler(mirroredAngles);
        }

        if(jointRotation != Quaternion.identity)
        {
            // Smoothly transition to the new rotation
            //平稳过渡到新的旋转
            Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex);

            if(externalRootMotion)
            {
                newRotation = transform.rotation * newRotation;
            }

            if(smoothFactor != 0f)
                boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime);
            else
                boneTransform.rotation = newRotation;
        }

    }

    // Apply the rotations tracked by kinect to fingers (one joint = multiple bones)
    //将kinect追踪的旋转应用到手指(一个关节=多个骨头)
    protected void TransformSpecialBoneFingers(Int64 userId, int joint, int boneIndex, bool flip)
    {
        // check for hand grips
        //检查手握
        if (joint == (int)KinectInterop.JointType.HandTipLeft || joint == (int)KinectInterop.JointType.ThumbLeft)
        {
            if(lastLeftHandEvent == InteractionManager.HandEventType.Grip)
            {
                if(!bLeftFistDone)
                {
                    float angleSign = !mirroredMovement /**(boneIndex == 27 || boneIndex == 29)*/ ? -1f : -1f;
                    float angleRot = angleSign * 60f;

                    TransformSpecialBoneFist(boneIndex, angleRot);
                    bLeftFistDone = (boneIndex >= 29);
                }

                return;
            }
            else if(bLeftFistDone && lastLeftHandEvent == InteractionManager.HandEventType.Release)
            {
                TransformSpecialBoneUnfist(boneIndex);
                bLeftFistDone = !(boneIndex >= 29);
            }
        }
        else if(joint == (int)KinectInterop.JointType.HandTipRight || joint == (int)KinectInterop.JointType.ThumbRight)
        {
            if(lastRightHandEvent == InteractionManager.HandEventType.Grip)
            {
                if(!bRightFistDone)
                {
                    float angleSign = !mirroredMovement /**(boneIndex == 27 || boneIndex == 29)*/ ? -1f : -1f;
                    float angleRot = angleSign * 60f;

                    TransformSpecialBoneFist(boneIndex, angleRot);
                    bRightFistDone = (boneIndex >= 29);
                }

                return;
            }
            else if(bRightFistDone && lastRightHandEvent == InteractionManager.HandEventType.Release)
            {
                TransformSpecialBoneUnfist(boneIndex);
                bRightFistDone = !(boneIndex >= 29);
            }
        }

        // get the animator component
        //Animator animatorComponent = GetComponent<Animator>();
        if(!animatorComponent)
            return;

        // Get Kinect joint orientation
        //得到Kinect联合定位
        Quaternion jointRotation = kinectManager.GetJointOrientation(userId, joint, flip);
        if(jointRotation == Quaternion.identity)
            return;

        // calculate the new orientation
        //计算的新方向
        Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex);

        if(externalRootMotion)
        {
            newRotation = transform.rotation * newRotation;
        }

        // get the list of bones
        //List<HumanBodyBones> alBones = flip ? specialIndex2MultiBoneMap[boneIndex] : specialIndex2MirrorBoneMap[boneIndex];
        List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex];

        // Smoothly transition to the new rotation
        //平稳过渡到新的旋转
        for (int i = 0; i < alBones.Count; i++)
        {
            Transform boneTransform = animatorComponent.GetBoneTransform(alBones[i]);
            if(!boneTransform)
                continue;

            if(smoothFactor != 0f)
                boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime);
            else
                boneTransform.rotation = newRotation;
        }
    }

    // Apply the rotations needed to transform fingers to fist
    //将手指旋转到拳头的转动
    protected void TransformSpecialBoneFist(int boneIndex, float angle)
    {
        //      // do fist only for fingers
       //       //只做手指
        //      if(boneIndex != 27 && boneIndex != 28)
        //          return;

        // get the animator component
        //Animator animatorComponent = GetComponent<Animator>();
        if (!animatorComponent)
            return;

        // get the list of bones
        List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex];

        for(int i = 0; i < alBones.Count; i++)
        {
            if(i < 1 && (boneIndex == 29 || boneIndex == 30))  // skip the first two thumb bones
                continue;

            HumanBodyBones bone = alBones[i];
            Transform boneTransform = animatorComponent.GetBoneTransform(bone);

            // set the fist rotation
            if(boneTransform && fingerBoneLocalAxes[bone] != Vector3.zero)
            {
                Quaternion qRotFinger = Quaternion.AngleAxis(angle, fingerBoneLocalAxes[bone]);
                boneTransform.localRotation = fingerBoneLocalRotations[bone] * qRotFinger;
            }
        }

    }

    // Apply the initial rotations fingers
    //初始旋转手指
    protected void TransformSpecialBoneUnfist(int boneIndex)
    {
//      // do fist only for fingers
//      if(boneIndex != 27 && boneIndex != 28)
//          return;

        // get the animator component
        //Animator animatorComponent = GetComponent<Animator>();
        if(!animatorComponent)
            return;

        // get the list of bones
        List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex];

        for(int i = 0; i < alBones.Count; i++)
        {
            HumanBodyBones bone = alBones[i];
            Transform boneTransform = animatorComponent.GetBoneTransform(bone);

            // set the initial rotation
            if(boneTransform)
            {
                boneTransform.localRotation = fingerBoneLocalRotations[bone];
            }
        }
    }

    // Moves the avatar - gets the tracked position of the user and applies it to avatar.
    //移动化身-获得用户的追踪位置并将其应用到人物。
    protected void MoveAvatar(Int64 UserID)
    {
        if((moveRate == 0f) || !kinectManager ||
           !kinectManager.IsJointTracked(UserID, (int)KinectInterop.JointType.SpineBase))
        {
            return;
        }

        // get the position of user's spine base
        Vector3 trans = kinectManager.GetUserPosition(UserID);
        if(flipLeftRight)
            trans.x = -trans.x;

        // use the color overlay position if needed
        if(posRelativeToCamera && posRelOverlayColor)
        {
            Rect backgroundRect = posRelativeToCamera.pixelRect;
            PortraitBackground portraitBack = PortraitBackground.Instance;

            if(portraitBack && portraitBack.enabled)
            {
                backgroundRect = portraitBack.GetBackgroundRect();
            }

            trans = kinectManager.GetJointPosColorOverlay(UserID, (int)KinectInterop.JointType.SpineBase, posRelativeToCamera, backgroundRect);
            if(flipLeftRight)
                trans.x = -trans.x;
        }

        // invert the z-coordinate, if needed
        //如果需要的话,对z坐标求逆
        if (posRelativeToCamera && posRelInvertedZ)
        {
            trans.z = -trans.z;
        }

        if(!offsetCalibrated)
        {
            offsetCalibrated = true;

            offsetPos.x = trans.x;  // !mirroredMovement ? trans.x * moveRate : -trans.x * moveRate;
            offsetPos.y = trans.y;  // trans.y * moveRate;
            offsetPos.z = !mirroredMovement && !posRelativeToCamera ? -trans.z : trans.z;  // -trans.z * moveRate;

            if(posRelativeToCamera)
            {
                Vector3 cameraPos = posRelativeToCamera.transform.position;
                Vector3 bodyRootPos = bodyRoot != null ? bodyRoot.position : transform.position;
                Vector3 hipCenterPos = bodyRoot != null ? bodyRoot.position : (bones != null && bones.Length > 0 && bones[0] != null ? bones[0].position : Vector3.zero);

                float yRelToAvatar = 0f;
                if(verticalMovement)
                {
                    yRelToAvatar = (trans.y - cameraPos.y) - (hipCenterPos - bodyRootPos).magnitude;
                }
                else
                {
                    yRelToAvatar = bodyRootPos.y - cameraPos.y;
                }

                Vector3 relativePos = new Vector3(trans.x, yRelToAvatar, trans.z);
                Vector3 newBodyRootPos = cameraPos + relativePos;

//              if(offsetNode != null)
//              {
//                  newBodyRootPos += offsetNode.transform.position;
//              }

                if(bodyRoot != null)
                {
                    bodyRoot.position = newBodyRootPos;
                }
                else
                {
                    transform.position = newBodyRootPos;
                }

                bodyRootPosition = newBodyRootPos;
            }
        }

        // transition to the new position
        //移动到新的位置
        Vector3 targetPos = bodyRootPosition + Kinect2AvatarPos(trans, verticalMovement);

        if(isRigidBody && !verticalMovement)
        {
            // workaround for obeying the physics (e.g. gravity falling)
            //解决物理问题的方法(如重力下降)
            targetPos.y = bodyRoot != null ? bodyRoot.position.y : transform.position.y;
        }

        if (verticalMovement && verticalOffset != 0f && 
            bones[0] != null && bones[3] != null) 
        {
            Vector3 dirSpine = bones[3].position - bones[0].position;
            targetPos += dirSpine.normalized * verticalOffset;
        }

        if (forwardOffset != 0f && 
            bones[0] != null && bones[3] != null && bones[5] != null && bones[11] != null) 
        {
            Vector3 dirSpine = (bones[3].position - bones[0].position).normalized;
            Vector3 dirShoulders = (bones[11].position - bones[5].position).normalized;
            Vector3 dirForward = Vector3.Cross(dirShoulders, dirSpine).normalized;

            targetPos += dirForward * forwardOffset;
        }

        if(groundedFeet)
        {
            // keep the current correction
            //保持当前的修正
            float fLastTgtY = targetPos.y;
            targetPos.y += fFootDistance;

            float fNewDistance = GetDistanceToGround();
            float fNewDistanceTime = Time.time;

//          Debug.Log(string.Format("PosY: {0:F2}, LastY: {1:F2},  TgrY: {2:F2}, NewDist: {3:F2}, Corr: {4:F2}, Time: {5:F2}", bodyRoot != null ? bodyRoot.position.y : transform.position.y,
//              fLastTgtY, targetPos.y, fNewDistance, fFootDistance, fNewDistanceTime));

            if(Mathf.Abs(fNewDistance) >= 0.01f && Mathf.Abs(fNewDistance - fFootDistanceInitial) >= maxFootDistanceGround)
            {
                if((fNewDistanceTime - fFootDistanceTime) >= maxFootDistanceTime)
                {
                    fFootDistance += (fNewDistance - fFootDistanceInitial);
                    fFootDistanceTime = fNewDistanceTime;

                    targetPos.y = fLastTgtY + fFootDistance;

//                  Debug.Log(string.Format("   >> change({0:F2})! - Corr: {1:F2}, LastY: {2:F2},  TgrY: {3:F2} at time {4:F2}", 
//                              (fNewDistance - fFootDistanceInitial), fFootDistance, fLastTgtY, targetPos.y, fFootDistanceTime));
                }
            }
            else
            {
                fFootDistanceTime = fNewDistanceTime;
            }
        }

        if(bodyRoot != null)
        {
            bodyRoot.position = smoothFactor != 0f ? 
                Vector3.Lerp(bodyRoot.position, targetPos, smoothFactor * Time.deltaTime) : targetPos;
        }
        else
        {
            transform.position = smoothFactor != 0f ? 
                Vector3.Lerp(transform.position, targetPos, smoothFactor * Time.deltaTime) : targetPos;
        }
    }

    // Set model's arms to be in T-pose
    //将模型的手臂放在t形上
    protected void SetModelArmsInTpose()
    {
        Vector3 vTposeLeftDir = transform.TransformDirection(Vector3.left);
        Vector3 vTposeRightDir = transform.TransformDirection(Vector3.right);

        Transform transLeftUarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ShoulderLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
        Transform transLeftLarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ElbowLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        Transform transLeftHand = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.WristLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftHand);

        if(transLeftUarm != null && transLeftLarm != null)
        {
            Vector3 vUarmLeftDir = transLeftLarm.position - transLeftUarm.position;
            float fUarmLeftAngle = Vector3.Angle(vUarmLeftDir, vTposeLeftDir);

            if(Mathf.Abs(fUarmLeftAngle) >= 5f)
            {
                Quaternion vFixRotation = Quaternion.FromToRotation(vUarmLeftDir, vTposeLeftDir);
                transLeftUarm.rotation = vFixRotation * transLeftUarm.rotation;
            }

            if(transLeftHand != null)
            {
                Vector3 vLarmLeftDir = transLeftHand.position - transLeftLarm.position;
                float fLarmLeftAngle = Vector3.Angle(vLarmLeftDir, vTposeLeftDir);

                if(Mathf.Abs(fLarmLeftAngle) >= 5f)
                {
                    Quaternion vFixRotation = Quaternion.FromToRotation(vLarmLeftDir, vTposeLeftDir);
                    transLeftLarm.rotation = vFixRotation * transLeftLarm.rotation;
                }
            }
        }

        Transform transRightUarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ShoulderRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
        Transform transRightLarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ElbowRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
        Transform transRightHand = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.WristRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightHand);

        if(transRightUarm != null && transRightLarm != null)
        {
            Vector3 vUarmRightDir = transRightLarm.position - transRightUarm.position;
            float fUarmRightAngle = Vector3.Angle(vUarmRightDir, vTposeRightDir);

            if(Mathf.Abs(fUarmRightAngle) >= 5f)
            {
                Quaternion vFixRotation = Quaternion.FromToRotation(vUarmRightDir, vTposeRightDir);
                transRightUarm.rotation = vFixRotation * transRightUarm.rotation;
            }

            if(transRightHand != null)
            {
                Vector3 vLarmRightDir = transRightHand.position - transRightLarm.position;
                float fLarmRightAngle = Vector3.Angle(vLarmRightDir, vTposeRightDir);

                if(Mathf.Abs(fLarmRightAngle) >= 5f)
                {
                    Quaternion vFixRotation = Quaternion.FromToRotation(vLarmRightDir, vTposeRightDir);
                    transRightLarm.rotation = vFixRotation * transRightLarm.rotation;
                }
            }
        }

    }

    // If the bones to be mapped have been declared, map that bone to the model.
    //如果要映射的骨头已经被声明了,那就把骨头映射到模型上。
    protected virtual void MapBones()
    {
//      // make OffsetNode as a parent of model transform.
//      offsetNode = new GameObject(name + "Ctrl") { layer = transform.gameObject.layer, tag = transform.gameObject.tag };
//      offsetNode.transform.position = transform.position;
//      offsetNode.transform.rotation = transform.rotation;
//      offsetNode.transform.parent = transform.parent;

//      // take model transform as body root
//      transform.parent = offsetNode.transform;
//      transform.localPosition = Vector3.zero;
//      transform.localRotation = Quaternion.identity;

        //bodyRoot = transform;

        // get bone transforms from the animator component
        //Animator animatorComponent = GetComponent<Animator>();

        for (int boneIndex = 0; boneIndex < bones.Length; boneIndex++)
        {
            if (!boneIndex2MecanimMap.ContainsKey(boneIndex)) 
                continue;

            bones[boneIndex] = animatorComponent ? animatorComponent.GetBoneTransform(boneIndex2MecanimMap[boneIndex]) : null;
        }
    }

    // Capture the initial rotations of the bones
    protected void GetInitialRotations()
    {
        // save the initial rotation
        if(offsetNode != null)
        {
            offsetNodePos = offsetNode.transform.position;
            offsetNodeRot = offsetNode.transform.rotation;
        }

        initialPosition = transform.position;
        initialRotation = transform.rotation;

        initialHipsPosition = bones[0] ? bones[0].localPosition : Vector3.zero;
        initialHipsRotation = bones[0] ? bones[0].localRotation : Quaternion.identity;

//      if(offsetNode != null)
//      {
//          initialRotation = Quaternion.Inverse(offsetNodeRot) * initialRotation;
//      }

        transform.rotation = Quaternion.identity;

        // save the body root initial position
        if(bodyRoot != null)
        {
            bodyRootPosition = bodyRoot.position;
        }
        else
        {
            bodyRootPosition = transform.position;
        }

        if(offsetNode != null)
        {
            bodyRootPosition = bodyRootPosition - offsetNodePos;
        }

        // save the initial bone rotations
        for (int i = 0; i < bones.Length; i++)
        {
            if (bones[i] != null)
            {
                initialRotations[i] = bones[i].rotation;
                localRotations[i] = bones[i].localRotation;
            }
        }

        // get finger bones' local rotations
        //Animator animatorComponent = GetComponent<Animator>();
        foreach(int boneIndex in specialIndex2MultiBoneMap.Keys)
        {
            List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex];
            //Transform handTransform = animatorComponent.GetBoneTransform((boneIndex == 27 || boneIndex == 29) ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand);

            for(int b = 0; b < alBones.Count; b++)
            {
                HumanBodyBones bone = alBones[b];
                Transform boneTransform = animatorComponent ? animatorComponent.GetBoneTransform(bone) : null;

                // get the finger's 1st transform
                Transform fingerBaseTransform = animatorComponent ? animatorComponent.GetBoneTransform(alBones[b - (b % 3)]) : null;
                //Vector3 vBoneDirParent = handTransform && fingerBaseTransform ? (handTransform.position - fingerBaseTransform.position).normalized : Vector3.zero;

                // get the finger's 2nd transform
                Transform baseChildTransform = fingerBaseTransform && fingerBaseTransform.childCount > 0 ? fingerBaseTransform.GetChild(0) : null;
                Vector3 vBoneDirChild = baseChildTransform && fingerBaseTransform ? (baseChildTransform.position - fingerBaseTransform.position).normalized : Vector3.zero;
                Vector3 vOrthoDirChild = Vector3.Cross(vBoneDirChild, Vector3.up).normalized;

                if(boneTransform)
                {
                    fingerBoneLocalRotations[bone] = boneTransform.localRotation;

                    if (vBoneDirChild != Vector3.zero) 
                    {
                        fingerBoneLocalAxes[bone] = boneTransform.InverseTransformDirection(vOrthoDirChild).normalized;
                    } 
                    else 
                    {
                        fingerBoneLocalAxes [bone] = Vector3.zero;
                    }

//                  Transform bparTransform = boneTransform ? boneTransform.parent : null;
//                  Transform bchildTransform = boneTransform && boneTransform.childCount > 0 ? boneTransform.GetChild(0) : null;
//
//                  // get the finger base transform (1st joint)
//                  Transform fingerBaseTransform = animatorComponent.GetBoneTransform(alBones[b - (b % 3)]);
//                  Vector3 vBoneDir2 = (handTransform.position - fingerBaseTransform.position).normalized;
//
//                  // set the fist rotation
//                  if(boneTransform && fingerBaseTransform && handTransform)
//                  {
//                      Vector3 vBoneDir = bchildTransform ? (bchildTransform.position - boneTransform.position).normalized :
//                          (bparTransform ? (boneTransform.position - bparTransform.position).normalized : Vector3.zero);
//
//                      Vector3 vOrthoDir = Vector3.Cross(vBoneDir2, vBoneDir).normalized;
//                      fingerBoneLocalAxes[bone] = boneTransform.InverseTransformDirection(vOrthoDir);
//                  }
                }
            }
        }

        // Restore the initial rotation
        transform.rotation = initialRotation;
    }

    // Converts kinect joint rotation to avatar joint rotation, depending on joint initial rotation and offset rotation
    protected Quaternion Kinect2AvatarRot(Quaternion jointRotation, int boneIndex)
    {
        Quaternion newRotation = jointRotation * initialRotations[boneIndex];
        //newRotation = initialRotation * newRotation;

//      if(offsetNode != null)
//      {
//          newRotation = offsetNode.transform.rotation * newRotation;
//      }
//      else
        {
            newRotation = initialRotation * newRotation;
        }

        return newRotation;
    }

    // Converts Kinect position to avatar skeleton position, depending on initial position, mirroring and move rate
    protected Vector3 Kinect2AvatarPos(Vector3 jointPosition, bool bMoveVertically)
    {
        float xPos = (jointPosition.x - offsetPos.x) * moveRate;
        float yPos = (jointPosition.y - offsetPos.y) * moveRate;
        float zPos = !mirroredMovement && !posRelativeToCamera ? (-jointPosition.z - offsetPos.z) * moveRate : (jointPosition.z - offsetPos.z) * moveRate;

        Vector3 newPosition = new Vector3(xPos, bMoveVertically ? yPos : 0f, zPos);

        Quaternion posRotation = mirroredMovement ? Quaternion.Euler (0f, 180f, 0f) * initialRotation : initialRotation;
        newPosition = posRotation * newPosition;

        if(offsetNode != null)
        {
            //newPosition += offsetNode.transform.position;
            newPosition = offsetNode.transform.position;
        }

        return newPosition;
    }

    // returns distance from the given transform to the underlying object. The player must be in IgnoreRaycast layer.
    //返回从给定转换到底层对象的距离。玩家必须在无知的层中。
    protected virtual float GetTransformDistanceToGround(Transform trans)
    {
        if(!trans)
            return 0f;

//      RaycastHit hit;
//      if(Physics.Raycast(trans.position, Vector3.down, out hit, 2f, raycastLayers))
//      {
//          return -hit.distance;
//      }
//      else if(Physics.Raycast(trans.position, Vector3.up, out hit, 2f, raycastLayers))
//      {
//          return hit.distance;
//      }
//      else
//      {
//          if (trans.position.y < 0)
//              return -trans.position.y;
//          else
//              return 1000f;
//      }

        return -trans.position.y;
    }

    // returns the lower distance distance from left or right foot to the ground, or 1000f if no LF/RF transforms are found
    //如果没有发现f/rf变换,则返回从左或右到地面的较低距离距离,或1000 f。
    protected virtual float GetDistanceToGround()
    {
        if(leftFoot == null && rightFoot == null)
        {
//          Animator animatorComponent = GetComponent<Animator>();
//
//          if(animatorComponent)
//          {
//              leftFoot = animatorComponent.GetBoneTransform(HumanBodyBones.LeftFoot);
//              rightFoot = animatorComponent.GetBoneTransform(HumanBodyBones.RightFoot);
//          }

            leftFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.FootLeft, false));
            rightFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.FootRight, false));

            if (leftFoot == null || rightFoot == null) 
            {
                leftFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.AnkleLeft, false));
                rightFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.AnkleRight, false));
            }
        }

        float fDistMin = 1000f;
        float fDistLeft = leftFoot ? GetTransformDistanceToGround(leftFoot) : fDistMin;
        float fDistRight = rightFoot ? GetTransformDistanceToGround(rightFoot) : fDistMin;
        fDistMin = Mathf.Abs(fDistLeft) < Mathf.Abs(fDistRight) ? fDistLeft : fDistRight;

        if(fDistMin == 1000f)
        {
            fDistMin = 0f; // fFootDistanceInitial;
        }

//      Debug.Log (string.Format ("LFootY: {0:F2}, Dist: {1:F2}, RFootY: {2:F2}, Dist: {3:F2}, Min: {4:F2}", leftFoot ? leftFoot.position.y : 0f, fDistLeft,
//                      rightFoot ? rightFoot.position.y : 0f, fDistRight, fDistMin));

        return fDistMin;
    }

//  protected void OnCollisionEnter(Collision col)
//  {
//      Debug.Log("Collision entered");
//  }
//
//  protected void OnCollisionExit(Collision col)
//  {
//      Debug.Log("Collision exited");
//  }

    // dictionaries to speed up bones' processing
    // the author of the terrific idea for kinect-joints to mecanim-bones mapping
    // along with its initial implementation, including following dictionary is
    // Mikhail Korchun (korchoon@gmail.com). Big thanks to this guy!
    //字典加速骨的处理
//他是关于关节-骨映射的极好方法的作者
//连同它的初始实现,包括以下字典
//米哈伊尔Korchun(korchoon @gmail.com)。感谢这个家伙!
    protected static readonly Dictionary<int, HumanBodyBones> boneIndex2MecanimMap = new Dictionary<int, HumanBodyBones>
    {
        {0, HumanBodyBones.Hips},
        {1, HumanBodyBones.Spine},
//        {2, HumanBodyBones.Chest},
        {3, HumanBodyBones.Neck},
//      {4, HumanBodyBones.Head},

        {5, HumanBodyBones.LeftUpperArm},
        {6, HumanBodyBones.LeftLowerArm},
        {7, HumanBodyBones.LeftHand},
//      {8, HumanBodyBones.LeftIndexProximal},
//      {9, HumanBodyBones.LeftIndexIntermediate},
//      {10, HumanBodyBones.LeftThumbProximal},

        {11, HumanBodyBones.RightUpperArm},
        {12, HumanBodyBones.RightLowerArm},
        {13, HumanBodyBones.RightHand},
//      {14, HumanBodyBones.RightIndexProximal},
//      {15, HumanBodyBones.RightIndexIntermediate},
//      {16, HumanBodyBones.RightThumbProximal},

        {17, HumanBodyBones.LeftUpperLeg},
        {18, HumanBodyBones.LeftLowerLeg},
        {19, HumanBodyBones.LeftFoot},
//      {20, HumanBodyBones.LeftToes},

        {21, HumanBodyBones.RightUpperLeg},
        {22, HumanBodyBones.RightLowerLeg},
        {23, HumanBodyBones.RightFoot},
//      {24, HumanBodyBones.RightToes},

        {25, HumanBodyBones.LeftShoulder},
        {26, HumanBodyBones.RightShoulder},
        {27, HumanBodyBones.LeftIndexProximal},
        {28, HumanBodyBones.RightIndexProximal},
        {29, HumanBodyBones.LeftThumbProximal},
        {30, HumanBodyBones.RightThumbProximal},
    };

    protected static readonly Dictionary<int, KinectInterop.JointType> boneIndex2JointMap = new Dictionary<int, KinectInterop.JointType>
    {
        {0, KinectInterop.JointType.SpineBase},
        {1, KinectInterop.JointType.SpineMid},
        {2, KinectInterop.JointType.SpineShoulder},
        {3, KinectInterop.JointType.Neck},
        {4, KinectInterop.JointType.Head},

        {5, KinectInterop.JointType.ShoulderLeft},
        {6, KinectInterop.JointType.ElbowLeft},
        {7, KinectInterop.JointType.WristLeft},
        {8, KinectInterop.JointType.HandLeft},

        {9, KinectInterop.JointType.HandTipLeft},
        {10, KinectInterop.JointType.ThumbLeft},

        {11, KinectInterop.JointType.ShoulderRight},
        {12, KinectInterop.JointType.ElbowRight},
        {13, KinectInterop.JointType.WristRight},
        {14, KinectInterop.JointType.HandRight},

        {15, KinectInterop.JointType.HandTipRight},
        {16, KinectInterop.JointType.ThumbRight},

        {17, KinectInterop.JointType.HipLeft},
        {18, KinectInterop.JointType.KneeLeft},
        {19, KinectInterop.JointType.AnkleLeft},
        {20, KinectInterop.JointType.FootLeft},

        {21, KinectInterop.JointType.HipRight},
        {22, KinectInterop.JointType.KneeRight},
        {23, KinectInterop.JointType.AnkleRight},
        {24, KinectInterop.JointType.FootRight},
    };

    protected static readonly Dictionary<int, List<KinectInterop.JointType>> specIndex2JointMap = new Dictionary<int, List<KinectInterop.JointType>>
    {
        {25, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.SpineShoulder} },
        {26, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.SpineShoulder} },
        {27, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipLeft, KinectInterop.JointType.HandLeft} },
        {28, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipRight, KinectInterop.JointType.HandRight} },
        {29, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbLeft, KinectInterop.JointType.HandLeft} },
        {30, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbRight, KinectInterop.JointType.HandRight} },
    };

    protected static readonly Dictionary<int, KinectInterop.JointType> boneIndex2MirrorJointMap = new Dictionary<int, KinectInterop.JointType>
    {
        {0, KinectInterop.JointType.SpineBase},
        {1, KinectInterop.JointType.SpineMid},
        {2, KinectInterop.JointType.SpineShoulder},
        {3, KinectInterop.JointType.Neck},
        {4, KinectInterop.JointType.Head},

        {5, KinectInterop.JointType.ShoulderRight},
        {6, KinectInterop.JointType.ElbowRight},
        {7, KinectInterop.JointType.WristRight},
        {8, KinectInterop.JointType.HandRight},

        {9, KinectInterop.JointType.HandTipRight},
        {10, KinectInterop.JointType.ThumbRight},

        {11, KinectInterop.JointType.ShoulderLeft},
        {12, KinectInterop.JointType.ElbowLeft},
        {13, KinectInterop.JointType.WristLeft},
        {14, KinectInterop.JointType.HandLeft},

        {15, KinectInterop.JointType.HandTipLeft},
        {16, KinectInterop.JointType.ThumbLeft},

        {17, KinectInterop.JointType.HipRight},
        {18, KinectInterop.JointType.KneeRight},
        {19, KinectInterop.JointType.AnkleRight},
        {20, KinectInterop.JointType.FootRight},

        {21, KinectInterop.JointType.HipLeft},
        {22, KinectInterop.JointType.KneeLeft},
        {23, KinectInterop.JointType.AnkleLeft},
        {24, KinectInterop.JointType.FootLeft},
    };

    protected static readonly Dictionary<int, List<KinectInterop.JointType>> specIndex2MirrorMap = new Dictionary<int, List<KinectInterop.JointType>>
    {
        {25, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.SpineShoulder} },
        {26, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.SpineShoulder} },
        {27, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipRight, KinectInterop.JointType.HandRight} },
        {28, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipLeft, KinectInterop.JointType.HandLeft} },
        {29, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbRight, KinectInterop.JointType.HandRight} },
        {30, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbLeft, KinectInterop.JointType.HandLeft} },
    };

    protected static readonly Dictionary<KinectInterop.JointType, int> jointMap2boneIndex = new Dictionary<KinectInterop.JointType, int>
    {
        {KinectInterop.JointType.SpineBase, 0},
        {KinectInterop.JointType.SpineMid, 1},
        {KinectInterop.JointType.SpineShoulder, 2},
        {KinectInterop.JointType.Neck, 3},
        {KinectInterop.JointType.Head, 4},

        {KinectInterop.JointType.ShoulderLeft, 5},
        {KinectInterop.JointType.ElbowLeft, 6},
        {KinectInterop.JointType.WristLeft, 7},
        {KinectInterop.JointType.HandLeft, 8},

        {KinectInterop.JointType.HandTipLeft, 9},
        {KinectInterop.JointType.ThumbLeft, 10},

        {KinectInterop.JointType.ShoulderRight, 11},
        {KinectInterop.JointType.ElbowRight, 12},
        {KinectInterop.JointType.WristRight, 13},
        {KinectInterop.JointType.HandRight, 14},

        {KinectInterop.JointType.HandTipRight, 15},
        {KinectInterop.JointType.ThumbRight, 16},

        {KinectInterop.JointType.HipLeft, 17},
        {KinectInterop.JointType.KneeLeft, 18},
        {KinectInterop.JointType.AnkleLeft, 19},
        {KinectInterop.JointType.FootLeft, 20},

        {KinectInterop.JointType.HipRight, 21},
        {KinectInterop.JointType.KneeRight, 22},
        {KinectInterop.JointType.AnkleRight, 23},
        {KinectInterop.JointType.FootRight, 24},
    };

    protected static readonly Dictionary<KinectInterop.JointType, int> mirrorJointMap2boneIndex = new Dictionary<KinectInterop.JointType, int>
    {
        {KinectInterop.JointType.SpineBase, 0},
        {KinectInterop.JointType.SpineMid, 1},
        {KinectInterop.JointType.SpineShoulder, 2},
        {KinectInterop.JointType.Neck, 3},
        {KinectInterop.JointType.Head, 4},

        {KinectInterop.JointType.ShoulderRight, 5},
        {KinectInterop.JointType.ElbowRight, 6},
        {KinectInterop.JointType.WristRight, 7},
        {KinectInterop.JointType.HandRight, 8},

        {KinectInterop.JointType.HandTipRight, 9},
        {KinectInterop.JointType.ThumbRight, 10},

        {KinectInterop.JointType.ShoulderLeft, 11},
        {KinectInterop.JointType.ElbowLeft, 12},
        {KinectInterop.JointType.WristLeft, 13},
        {KinectInterop.JointType.HandLeft, 14},

        {KinectInterop.JointType.HandTipLeft, 15},
        {KinectInterop.JointType.ThumbLeft, 16},

        {KinectInterop.JointType.HipRight, 17},
        {KinectInterop.JointType.KneeRight, 18},
        {KinectInterop.JointType.AnkleRight, 19},
        {KinectInterop.JointType.FootRight, 20},

        {KinectInterop.JointType.HipLeft, 21},
        {KinectInterop.JointType.KneeLeft, 22},
        {KinectInterop.JointType.AnkleLeft, 23},
        {KinectInterop.JointType.FootLeft, 24},
    };


    protected static readonly Dictionary<int, List<HumanBodyBones>> specialIndex2MultiBoneMap = new Dictionary<int, List<HumanBodyBones>>
    {
        {27, new List<HumanBodyBones> {  // left fingers
                HumanBodyBones.LeftIndexProximal,
                HumanBodyBones.LeftIndexIntermediate,
                HumanBodyBones.LeftIndexDistal,
                HumanBodyBones.LeftMiddleProximal,
                HumanBodyBones.LeftMiddleIntermediate,
                HumanBodyBones.LeftMiddleDistal,
                HumanBodyBones.LeftRingProximal,
                HumanBodyBones.LeftRingIntermediate,
                HumanBodyBones.LeftRingDistal,
                HumanBodyBones.LeftLittleProximal,
                HumanBodyBones.LeftLittleIntermediate,
                HumanBodyBones.LeftLittleDistal,
            }},
        {28, new List<HumanBodyBones> {  // right fingers
                HumanBodyBones.RightIndexProximal,
                HumanBodyBones.RightIndexIntermediate,
                HumanBodyBones.RightIndexDistal,
                HumanBodyBones.RightMiddleProximal,
                HumanBodyBones.RightMiddleIntermediate,
                HumanBodyBones.RightMiddleDistal,
                HumanBodyBones.RightRingProximal,
                HumanBodyBones.RightRingIntermediate,
                HumanBodyBones.RightRingDistal,
                HumanBodyBones.RightLittleProximal,
                HumanBodyBones.RightLittleIntermediate,
                HumanBodyBones.RightLittleDistal,
            }},
        {29, new List<HumanBodyBones> {  // left thumb
                HumanBodyBones.LeftThumbProximal,
                HumanBodyBones.LeftThumbIntermediate,
                HumanBodyBones.LeftThumbDistal,
            }},
        {30, new List<HumanBodyBones> {  // right thumb
                HumanBodyBones.RightThumbProximal,
                HumanBodyBones.RightThumbIntermediate,
                HumanBodyBones.RightThumbDistal,
            }},
    };

}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值