using UnityEngine; using System.Collections; using com.rfilkov.kinect; namespace com.rfilkov.components { /// /// Avatar scaler is the component that scales avatar's body, according to the user's body and bone sizes. /// [RequireComponent(typeof(Animator))] public class AvatarScaler : 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 mirroredAvatar = false; [Tooltip("Minimum distance to the user.")] public float minUserDistance = 1.0f; [Tooltip("Body scale factor (incl. arms and legs) that may be used for fine tuning of model-scale.")] [Range(0.0f, 2.0f)] public float bodyScaleFactor = 1f; [Tooltip("Body width scale factor that may be used for fine tuning of model-width scale.")] [Range(0.0f, 2.0f)] public float bodyWidthFactor = 0f; [Tooltip("Additional scale factor for arms that may be used for fine tuning of model arm-scale.")] [Range(0.0f, 2.0f)] public float armScaleFactor = 0f; [Tooltip("Additional scale factor for legs that may be used for fine tuning of model leg-scale.")] [Range(0.0f, 2.0f)] public float legScaleFactor = 0f; [Tooltip("Whether the scale is updated continuously or just after the calibration pose.")] public bool continuousScaling = true; [Tooltip("Scale smoothing factor used in case of continuous scaling.")] public float smoothFactor = 5f; [Tooltip("Camera used to overlay the model over the background.")] public Camera foregroundCamera; [Tooltip("Plane used to render the color camera background.")] private Transform backgroundPlane = null; [Tooltip("Index of the depth sensor that generates the color camera background. 0 is the 1st one, 1 - the 2nd one, etc.")] private int sensorIndex = 0; // [Tooltip("Whether to put the clothing model hip and shoulder joints where the user joints are.")] // public bool fixModelHipsAndShoulders = false; [Tooltip("UI-Text to display the avatar-scaler debug messages.")] public UnityEngine.UI.Text debugText; // used by category selector [System.NonSerialized] public ulong currentUserId = 0; // used by category selector [System.NonSerialized] public bool scalerInited = false; // class references private KinectManager kinectManager = null; private AvatarController avtController = null; // model transforms for scaling private Transform bodyScaleTransform; //private Transform bodyHipsTransform; private Transform leftShoulderScaleTransform; private Transform leftElbowScaleTransform; private Transform rightShoulderScaleTransform; private Transform rightElbowScaleTransform; private Transform leftHipScaleTransform; private Transform leftKneeScaleTransform; private Transform rightHipScaleTransform; private Transform rightKneeScaleTransform; private Vector3 modelBodyScale = Vector3.one; private Vector3 modelLeftShoulderScale = Vector3.one; private Vector3 modelLeftElbowScale = Vector3.one; private Vector3 modelRightShoulderScale = Vector3.one; private Vector3 modelRightElbowScale = Vector3.one; private Vector3 modelLeftHipScale = Vector3.one; private Vector3 modelLeftKneeScale = Vector3.one; private Vector3 modelRightHipScale = Vector3.one; private Vector3 modelRightKneeScale = Vector3.one; // model bone sizes and original scales private float modelBodyHeight = 0f; private float modelBodyWidth = 0f; private float modelLeftUpperArmLength = 0f; private float modelLeftLowerArmLength = 0f; private float modelRightUpperArmLength = 0f; private float modelRightLowerArmLength = 0f; private float modelLeftUpperLegLength = 0f; private float modelLeftLowerLegLength = 0f; private float modelRightUpperLegLength = 0f; private float modelRightLowerLegLength = 0f; // user bone sizes private float userBodyHeight = 0f; private float userBodyWidth = 0f; private float leftUpperArmLength = 0f; private float leftLowerArmLength = 0f; private float rightUpperArmLength = 0f; private float rightLowerArmLength = 0f; private float leftUpperLegLength = 0f; private float leftLowerLegLength = 0f; private float rightUpperLegLength = 0f; private float rightLowerLegLength = 0f; // user bone scale factors private float fScaleBodyHeight = 0f; private float fScaleBodyWidth = 0f; private float fScaleLeftUpperArm = 0f; private float fScaleLeftLowerArm = 0f; private float fScaleRightUpperArm = 0f; private float fScaleRightLowerArm = 0f; private float fScaleLeftUpperLeg = 0f; private float fScaleLeftLowerLeg = 0f; private float fScaleRightUpperLeg = 0f; private float fScaleRightLowerLeg = 0f; // background plane rectangle private Rect planeRect = new Rect(); private bool planeRectSet = false; // user body lengths private bool gotUserBodySize = false; private bool gotUserArmsSize = false; private bool gotUserLegsSize = false; // mesh renderer private SkinnedMeshRenderer meshRenderer = null; public void Start() { // get references to other components kinectManager = KinectManager.Instance; avtController = gameObject.GetComponent(); // get model transforms Animator animatorComponent = GetComponent(); AvatarController avatarController = GetComponent(); // get mesh renderer meshRenderer = GetComponentInChildren(); // use the root transform for body scale bodyScaleTransform = transform; if (animatorComponent && animatorComponent.GetBoneTransform(HumanBodyBones.Hips)) { //bodyHipsTransform = animatorComponent.GetBoneTransform (HumanBodyBones.Hips); leftShoulderScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperArm); leftElbowScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.LeftLowerArm); rightShoulderScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperArm); rightElbowScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.RightLowerArm); leftHipScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperLeg); leftKneeScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.LeftLowerLeg); rightHipScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperLeg); rightKneeScaleTransform = animatorComponent.GetBoneTransform(HumanBodyBones.RightLowerLeg); } else if (avatarController) { //bodyHipsTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.SpineBase, false)); leftShoulderScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ShoulderLeft, false)); leftElbowScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ElbowLeft, false)); rightShoulderScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ShoulderRight, false)); rightElbowScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ElbowRight, false)); leftHipScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.HipLeft, false)); leftKneeScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.KneeLeft, false)); rightHipScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.HipRight, false)); rightKneeScaleTransform = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.KneeRight, false)); } else { // needed transforms could not be found return; } // get model bone scales modelBodyScale = bodyScaleTransform ? bodyScaleTransform.localScale : Vector3.one; modelLeftShoulderScale = leftShoulderScaleTransform ? leftShoulderScaleTransform.localScale : Vector3.one; modelLeftElbowScale = leftElbowScaleTransform ? leftElbowScaleTransform.localScale : Vector3.one; modelRightShoulderScale = rightShoulderScaleTransform ? rightShoulderScaleTransform.localScale : Vector3.one; modelRightElbowScale = rightElbowScaleTransform ? rightElbowScaleTransform.localScale : Vector3.one; modelLeftHipScale = leftHipScaleTransform ? leftHipScaleTransform.localScale : Vector3.one; modelLeftKneeScale = leftKneeScaleTransform ? leftKneeScaleTransform.localScale : Vector3.one; modelRightHipScale = rightHipScaleTransform ? rightHipScaleTransform.localScale : Vector3.one; modelRightKneeScale = rightKneeScaleTransform ? rightKneeScaleTransform.localScale : Vector3.one; if (animatorComponent && animatorComponent.GetBoneTransform(HumanBodyBones.Hips)) { GetModelBodyHeight(animatorComponent, ref modelBodyHeight, ref modelBodyWidth); //Debug.Log (string.Format("MW: {0:F3}, MH: {1:F3}", modelBodyWidth, modelBodyHeight)); GetModelBoneLength(animatorComponent, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, ref modelLeftUpperArmLength); GetModelBoneLength(animatorComponent, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, ref modelLeftLowerArmLength); GetModelBoneLength(animatorComponent, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, ref modelRightUpperArmLength); GetModelBoneLength(animatorComponent, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, ref modelRightLowerArmLength); GetModelBoneLength(animatorComponent, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, ref modelLeftUpperLegLength); GetModelBoneLength(animatorComponent, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, ref modelLeftLowerLegLength); GetModelBoneLength(animatorComponent, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, ref modelRightUpperLegLength); GetModelBoneLength(animatorComponent, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, ref modelRightLowerLegLength); scalerInited = true; } else if (avatarController) { GetModelBodyHeight(avatarController, ref modelBodyHeight, ref modelBodyWidth); //Debug.Log (string.Format("MW: {0:F3}, MH: {1:F3}", modelBodyWidth, modelBodyHeight)); GetModelBoneLength(avatarController, KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.ElbowLeft, ref modelLeftUpperArmLength); GetModelBoneLength(avatarController, KinectInterop.JointType.ElbowLeft, KinectInterop.JointType.WristLeft, ref modelLeftLowerArmLength); GetModelBoneLength(avatarController, KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.ElbowRight, ref modelRightUpperArmLength); GetModelBoneLength(avatarController, KinectInterop.JointType.ElbowRight, KinectInterop.JointType.WristRight, ref modelRightLowerArmLength); GetModelBoneLength(avatarController, KinectInterop.JointType.HipLeft, KinectInterop.JointType.KneeLeft, ref modelLeftUpperLegLength); GetModelBoneLength(avatarController, KinectInterop.JointType.KneeLeft, KinectInterop.JointType.AnkleLeft, ref modelLeftLowerLegLength); GetModelBoneLength(avatarController, KinectInterop.JointType.HipRight, KinectInterop.JointType.KneeRight, ref modelRightUpperLegLength); GetModelBoneLength(avatarController, KinectInterop.JointType.KneeRight, KinectInterop.JointType.AnkleRight, ref modelRightLowerLegLength); scalerInited = true; } // update the scale immediately Update(); } public void Update() { if (scalerInited && kinectManager && kinectManager.IsInitialized()) { // get the plane rectangle to be used for object overlay if (backgroundPlane && !planeRectSet) { planeRectSet = true; planeRect.width = 10f * Mathf.Abs(backgroundPlane.localScale.x); planeRect.height = 10f * Mathf.Abs(backgroundPlane.localScale.z); planeRect.x = backgroundPlane.position.x - planeRect.width / 2f; planeRect.y = backgroundPlane.position.y - planeRect.height / 2f; } ulong userId = kinectManager.GetUserIdByIndex(playerIndex); // check user distance and hand positions if (userId != 0 && minUserDistance > 0f) { Vector3 userPos = kinectManager.GetUserPosition(userId); //bool lHandTracked = kinectManager.IsJointTracked(userId, (int)KinectInterop.JointType.WristLeft); //Vector3 lHandPos = lHandTracked ? kinectManager.GetJointPosition(userId, (int)KinectInterop.JointType.WristLeft) : Vector3.zero; //bool rHandTracked = kinectManager.IsJointTracked(userId, (int)KinectInterop.JointType.WristRight); //Vector3 rHandPos = rHandTracked ? kinectManager.GetJointPosition(userId, (int)KinectInterop.JointType.WristRight) : Vector3.zero; if (userPos.z < minUserDistance) // || //!lHandTracked || (lHandPos.z - userPos.z) <= -0.3f || //!rHandTracked || (rHandPos.z - userPos.z) <= -0.3f) { // don't scale the model userId = 0; //Debug.Log ("Avatar scaling skipped."); } } if (userId != currentUserId) { currentUserId = userId; if (userId != 0) { GetUserBodySize(true, true, true); if (gotUserBodySize) { // show the mesh if (meshRenderer && !meshRenderer.gameObject.activeSelf) meshRenderer.gameObject.SetActive(true); // scale avatar initially ScaleAvatar(0f, true); } else { // hide the mesh if (meshRenderer && meshRenderer.gameObject.activeSelf) meshRenderer.gameObject.SetActive(false); // consider the user as not tracked currentUserId = 0; } } else { // user not tracked gotUserBodySize = gotUserArmsSize = gotUserLegsSize = false; } } } if (currentUserId != 0 && continuousScaling) { // scale avatar continuously GetUserBodySize(true, true, true); ScaleAvatar(smoothFactor, false); } } // gets the the actual sizes of the user bones public void GetUserBodySize(bool bBody, bool bArms, bool bLegs) { //KinectManager kinectManager = KinectManager.Instance; if (kinectManager == null) return; if (bBody) { gotUserBodySize = GetUserBodyHeight(kinectManager, bodyScaleFactor, bodyWidthFactor, ref userBodyHeight, ref userBodyWidth); } if (bArms) { bool gotLeftArmSize = GetUserBoneLength(kinectManager, KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.ElbowLeft, armScaleFactor, ref leftUpperArmLength); gotLeftArmSize &= GetUserBoneLength(kinectManager, KinectInterop.JointType.ElbowLeft, KinectInterop.JointType.WristLeft, armScaleFactor, ref leftLowerArmLength); bool gotRightArmSize = GetUserBoneLength(kinectManager, KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.ElbowRight, armScaleFactor, ref rightUpperArmLength); gotRightArmSize &= GetUserBoneLength(kinectManager, KinectInterop.JointType.ElbowRight, KinectInterop.JointType.WristRight, armScaleFactor, ref rightLowerArmLength); gotUserArmsSize = gotLeftArmSize | gotRightArmSize; if(gotUserArmsSize) { EqualizeBoneLength(ref leftUpperArmLength, ref rightUpperArmLength); EqualizeBoneLength(ref leftLowerArmLength, ref rightLowerArmLength); } } if (bLegs) { bool gotLeftLegSize = GetUserBoneLength(kinectManager, KinectInterop.JointType.HipLeft, KinectInterop.JointType.KneeLeft, legScaleFactor, ref leftUpperLegLength); gotLeftLegSize &= GetUserBoneLength(kinectManager, KinectInterop.JointType.KneeLeft, KinectInterop.JointType.AnkleLeft, legScaleFactor, ref leftLowerLegLength); bool gotRightLegSize = GetUserBoneLength(kinectManager, KinectInterop.JointType.HipRight, KinectInterop.JointType.KneeRight, legScaleFactor, ref rightUpperLegLength); gotRightLegSize &= GetUserBoneLength(kinectManager, KinectInterop.JointType.KneeRight, KinectInterop.JointType.AnkleRight, legScaleFactor, ref rightLowerLegLength); gotUserLegsSize = gotLeftLegSize | gotRightLegSize; if(gotUserLegsSize) { EqualizeBoneLength(ref leftUpperLegLength, ref rightUpperLegLength); EqualizeBoneLength(ref leftLowerLegLength, ref rightLowerLegLength); } } } // scales the avatar as needed public void ScaleAvatar(float fSmooth, bool bInitialScale) { // scale body if (bodyScaleFactor > 0f && gotUserBodySize) { SetupBodyScale(bodyScaleTransform, modelBodyScale, modelBodyHeight, modelBodyWidth, userBodyHeight, userBodyWidth, fSmooth, ref fScaleBodyHeight, ref fScaleBodyWidth); if (avtController) { // recalibrate avatar position due to transform scale change avtController.offsetCalibrated = false; // set AC smooth-factor to 0 to prevent flickering (r618-issue) if (avtController.smoothFactor != 0f) { avtController.smoothFactor = 0f; } } } // scale arms if (/**bInitialScale &&*/ armScaleFactor > 0f && gotUserArmsSize) { float fLeftUpperArmLength = !mirroredAvatar ? leftUpperArmLength : rightUpperArmLength; SetupBoneScale(leftShoulderScaleTransform, modelLeftShoulderScale, modelLeftUpperArmLength, fLeftUpperArmLength, fScaleBodyHeight, fSmooth, ref fScaleLeftUpperArm); float fLeftLowerArmLength = !mirroredAvatar ? leftLowerArmLength : rightLowerArmLength; SetupBoneScale(leftElbowScaleTransform, modelLeftElbowScale, modelLeftLowerArmLength, fLeftLowerArmLength, fScaleLeftUpperArm, fSmooth, ref fScaleLeftLowerArm); float fRightUpperArmLength = !mirroredAvatar ? rightUpperArmLength : leftUpperArmLength; SetupBoneScale(rightShoulderScaleTransform, modelRightShoulderScale, modelRightUpperArmLength, fRightUpperArmLength, fScaleBodyHeight, fSmooth, ref fScaleRightUpperArm); float fRightLowerArmLength = !mirroredAvatar ? rightLowerArmLength : leftLowerArmLength; SetupBoneScale(rightElbowScaleTransform, modelRightElbowScale, modelLeftLowerArmLength, fRightLowerArmLength, fScaleRightUpperArm, fSmooth, ref fScaleRightLowerArm); } // scale legs if (/**bInitialScale &&*/ legScaleFactor > 0 && gotUserLegsSize) { float fLeftUpperLegLength = !mirroredAvatar ? leftUpperLegLength : rightUpperLegLength; SetupBoneScale(leftHipScaleTransform, modelLeftHipScale, modelLeftUpperLegLength, fLeftUpperLegLength, fScaleBodyHeight, fSmooth, ref fScaleLeftUpperLeg); float fLeftLowerLegLength = !mirroredAvatar ? leftLowerLegLength : rightLowerLegLength; SetupBoneScale(leftKneeScaleTransform, modelLeftKneeScale, modelLeftLowerLegLength, fLeftLowerLegLength, fScaleLeftUpperLeg, fSmooth, ref fScaleLeftLowerLeg); float fRightUpperLegLength = !mirroredAvatar ? rightUpperLegLength : leftUpperLegLength; SetupBoneScale(rightHipScaleTransform, modelRightHipScale, modelRightUpperLegLength, fRightUpperLegLength, fScaleBodyHeight, fSmooth, ref fScaleRightUpperLeg); float fRightLowerLegLength = !mirroredAvatar ? rightLowerLegLength : leftLowerLegLength; SetupBoneScale(rightKneeScaleTransform, modelRightKneeScale, modelRightLowerLegLength, fRightLowerLegLength, fScaleRightUpperLeg, fSmooth, ref fScaleRightLowerLeg); } if (debugText != null) { string sDebug = string.Format("BW: {0:F2}/{1:F3}, BH: {2:F2}/{3:F3}\nLUA: {4:F3}, LLA: {5:F3}; RUA: {6:F3}, RLA: {7:F3}\nLUL: {8:F3}, LLL: {9:F3}; RUL: {10:F3}, RLL: {11:F3}", userBodyWidth, fScaleBodyWidth, userBodyHeight, fScaleBodyHeight, fScaleLeftUpperArm, fScaleLeftLowerArm, fScaleRightUpperArm, fScaleRightLowerArm, fScaleLeftUpperLeg, fScaleLeftLowerLeg, fScaleRightUpperLeg, fScaleRightLowerLeg); debugText.text = sDebug; } } private bool GetModelBodyHeight(Animator animatorComponent, ref float height, ref float width) { height = 0f; if (animatorComponent) { //Transform hipCenter = animatorComponent.GetBoneTransform(HumanBodyBones.Hips); Transform leftUpperArm = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperArm); Transform rightUpperArm = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperArm); Transform leftUpperLeg = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperLeg); Transform rightUpperLeg = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperLeg); if (leftUpperArm && rightUpperArm && leftUpperLeg && rightUpperLeg) { Vector3 posShoulderCenter = (leftUpperArm.position + rightUpperArm.position) / 2f; Vector3 posHipCenter = (leftUpperLeg.position + rightUpperLeg.position) / 2f; // hipCenter.position //height = (posShoulderCenter.y - posHipCenter.y); height = (posShoulderCenter - posHipCenter).magnitude; width = (rightUpperArm.position - leftUpperArm.position).magnitude; return true; } } return false; } private bool GetModelBodyHeight(AvatarController avatarController, ref float height, ref float width) { height = 0f; if (avatarController) { Transform leftUpperArm = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ShoulderLeft, false)); Transform rightUpperArm = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.ShoulderRight, false)); Transform leftUpperLeg = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.HipLeft, false)); Transform rightUpperLeg = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(KinectInterop.JointType.HipRight, false)); if (leftUpperArm && rightUpperArm && leftUpperLeg && rightUpperLeg) { Vector3 posShoulderCenter = (leftUpperArm.position + rightUpperArm.position) / 2f; Vector3 posHipCenter = (leftUpperLeg.position + rightUpperLeg.position) / 2f; // hipCenter.position //height = (posShoulderCenter.y - posHipCenter.y); height = (posShoulderCenter - posHipCenter).magnitude; width = (rightUpperArm.position - leftUpperArm.position).magnitude; return true; } } return false; } private bool GetModelBoneLength(Animator animatorComponent, HumanBodyBones baseJoint, HumanBodyBones endJoint, ref float length) { length = 0f; if (animatorComponent) { Transform joint1 = animatorComponent.GetBoneTransform(baseJoint); Transform joint2 = animatorComponent.GetBoneTransform(endJoint); if (joint1 && joint2) { length = (joint2.position - joint1.position).magnitude; return true; } } return false; } private bool GetModelBoneLength(AvatarController avatarController, KinectInterop.JointType baseJoint, KinectInterop.JointType endJoint, ref float length) { length = 0f; if (avatarController) { Transform joint1 = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(baseJoint, false)); Transform joint2 = avatarController.GetBoneTransform(avatarController.GetBoneIndexByJoint(endJoint, false)); if (joint1 && joint2) { length = (joint2.position - joint1.position).magnitude; return true; } } return false; } private bool GetUserBodyHeight(KinectManager manager, float scaleFactor, float widthFactor, ref float height, ref float width) { height = 0f; width = 0f; Vector3 posHipLeft = GetJointPosition(manager, (int)KinectInterop.JointType.HipLeft); Vector3 posHipRight = GetJointPosition(manager, (int)KinectInterop.JointType.HipRight); Vector3 posShoulderLeft = GetJointPosition(manager, (int)KinectInterop.JointType.ShoulderLeft); Vector3 posShoulderRight = GetJointPosition(manager, (int)KinectInterop.JointType.ShoulderRight); if (posHipLeft != Vector3.zero && posHipRight != Vector3.zero && posShoulderLeft != Vector3.zero && posShoulderRight != Vector3.zero) { Vector3 posHipCenter = (posHipLeft + posHipRight) / 2f; Vector3 posShoulderCenter = (posShoulderLeft + posShoulderRight) / 2f; //height = (posShoulderCenter.y - posHipCenter.y) * scaleFactor; height = (posShoulderCenter - posHipCenter).magnitude * scaleFactor; width = (posShoulderRight - posShoulderLeft).magnitude * widthFactor; return true; } return false; } private bool GetUserBoneLength(KinectManager manager, KinectInterop.JointType baseJoint, KinectInterop.JointType endJoint, float scaleFactor, ref float length) { length = 0f; Vector3 vPos1 = GetJointPosition(manager, (int)baseJoint); Vector3 vPos2 = GetJointPosition(manager, (int)endJoint); if (vPos1 != Vector3.zero && vPos2 != Vector3.zero) { length = (vPos2 - vPos1).magnitude * scaleFactor; return true; } return false; } private void EqualizeBoneLength(ref float boneLen1, ref float boneLen2) { if (boneLen1 < boneLen2) { boneLen1 = boneLen2; } else { boneLen2 = boneLen1; } } private bool SetupBodyScale(Transform scaleTrans, Vector3 modelBodyScale, float modelHeight, float modelWidth, float userHeight, float userWidth, float fSmooth, ref float heightScale, ref float widthScale) { if (modelHeight > 0f && userHeight > 0f) { heightScale = userHeight / modelHeight; } if (modelWidth > 0f && userWidth > 0f) { widthScale = userWidth / modelWidth; } else { widthScale = heightScale; } if (scaleTrans && heightScale > 0f && widthScale > 0f) { float depthScale = heightScale; // (heightScale + widthScale) / 2f; Vector3 newLocalScale = new Vector3(modelBodyScale.x * widthScale, modelBodyScale.y * heightScale, modelBodyScale.z * depthScale); if (fSmooth != 0f) scaleTrans.localScale = Vector3.Lerp(scaleTrans.localScale, newLocalScale, fSmooth * Time.deltaTime); else scaleTrans.localScale = newLocalScale; return true; } return false; } private bool SetupBoneScale(Transform scaleTrans, Vector3 modelBoneScale, float modelBoneLen, float userBoneLen, float parentScale, float fSmooth, ref float boneScale) { if (modelBoneLen > 0f && userBoneLen > 0f) { boneScale = userBoneLen / modelBoneLen; } float localScale = boneScale; if (boneScale > 0f && parentScale > 0f) { localScale = boneScale / parentScale; } if (scaleTrans && localScale > 0f) { if (fSmooth != 0f) scaleTrans.localScale = Vector3.Lerp(scaleTrans.localScale, modelBoneScale * localScale, fSmooth * Time.deltaTime); else scaleTrans.localScale = modelBoneScale * localScale; return true; } return false; } public bool FixJointsBeforeScale() { Animator animatorComponent = GetComponent(); KinectManager manager = KinectManager.Instance; if (animatorComponent && modelBodyHeight > 0f && userBodyHeight > 0f) { Transform hipCenter = animatorComponent.GetBoneTransform(HumanBodyBones.Hips); if ((hipCenter.localScale - Vector3.one).magnitude > 0.01f) return false; Transform leftUpperLeg = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperLeg); Transform rightUpperLeg = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperLeg); Transform leftUpperArm = animatorComponent.GetBoneTransform(HumanBodyBones.LeftUpperArm); Transform rightUpperArm = animatorComponent.GetBoneTransform(HumanBodyBones.RightUpperArm); if (leftUpperArm && rightUpperArm && leftUpperLeg && rightUpperLeg) { Vector3 posHipCenter = GetJointPosition(manager, (int)KinectInterop.JointType.Pelvis); Vector3 posHipLeft = GetJointPosition(manager, (int)KinectInterop.JointType.HipLeft); Vector3 posHipRight = GetJointPosition(manager, (int)KinectInterop.JointType.HipRight); Vector3 posShoulderLeft = GetJointPosition(manager, (int)KinectInterop.JointType.ShoulderLeft); Vector3 posShoulderRight = GetJointPosition(manager, (int)KinectInterop.JointType.ShoulderRight); if (posHipCenter != Vector3.zero && posHipLeft != Vector3.zero && posHipRight != Vector3.zero && posShoulderLeft != Vector3.zero && posShoulderRight != Vector3.zero) { SetupUnscaledJoint(hipCenter, leftUpperLeg, posHipCenter, (!mirroredAvatar ? posHipLeft : posHipRight), modelBodyHeight, userBodyHeight); SetupUnscaledJoint(hipCenter, rightUpperLeg, posHipCenter, (!mirroredAvatar ? posHipRight : posHipLeft), modelBodyHeight, userBodyHeight); SetupUnscaledJoint(hipCenter, leftUpperArm, posHipCenter, (!mirroredAvatar ? posShoulderLeft : posShoulderRight), modelBodyHeight, userBodyHeight); SetupUnscaledJoint(hipCenter, rightUpperArm, posHipCenter, (!mirroredAvatar ? posShoulderRight : posShoulderLeft), modelBodyHeight, userBodyHeight); // recalculate model joints Start(); return true; } } } return false; } // gets the joint position in space private Vector3 GetJointPosition(KinectManager manager, int joint) { Vector3 vPosJoint = Vector3.zero; if (manager.IsJointTracked(currentUserId, joint)) { if (backgroundPlane && planeRectSet) { // get the plane overlay position vPosJoint = manager.GetJointPosColorOverlay(currentUserId, joint, sensorIndex, planeRect); vPosJoint.z = backgroundPlane.position.z; } else if (foregroundCamera) { // get the background rectangle (use the portrait background, if available) Rect backgroundRect = foregroundCamera.pixelRect; PortraitBackground portraitBack = PortraitBackground.Instance; if (portraitBack && portraitBack.enabled) { backgroundRect = portraitBack.GetBackgroundRect(); } // get the color overlay position vPosJoint = manager.GetJointPosColorOverlay(currentUserId, joint, sensorIndex, foregroundCamera, backgroundRect); } // else if (vPosJoint == Vector3.zero) { vPosJoint = manager.GetJointPosition(currentUserId, joint); } } return vPosJoint; } // sets the joint position before scaling private bool SetupUnscaledJoint(Transform hipCenter, Transform joint, Vector3 posHipCenter, Vector3 posJoint, float modelBoneLen, float userBoneLen) { float boneScale = 0f; if (modelBoneLen > 0f && userBoneLen > 0f) { boneScale = userBoneLen / modelBoneLen; //boneScale = 1f; } if (boneScale > 0f) { Vector3 posDiff = (posJoint - posHipCenter) / boneScale; if (foregroundCamera == null && backgroundPlane == null) posDiff.z = 0f; // ignore difference in z (non-overlay mode) Vector3 posJointNew = hipCenter.position + posDiff; joint.position = posJointNew; return true; } return false; } } }