// initialize a roll joint data for the given joint as parent private void JoinRollJoint(string rollJointName, Omek.JointID parentJointID) { TransformWrapper tw = m_hierarchyList.Find((a) => { return(a.m_jointID == parentJointID); }); RollJointWrapper rjw = m_rollJointsList.Find((a) => { return(a.m_name == rollJointName); }); tw.m_rollJoint = rjw; rjw.m_parentWrapper = tw; if (tw.m_transform != null) { rjw.m_originalParentRotation = tw.m_transform.localRotation; rjw.m_inverseOriginalParentRotation = Quaternion.Inverse(rjw.m_originalParentRotation); } }
// return the reflected joint of a given joint private static Omek.JointID GetReflectedJointID(Omek.JointID jointID) { switch (jointID) { case Omek.JointID.leftCollar: return(Omek.JointID.rightCollar); case Omek.JointID.rightCollar: return(Omek.JointID.leftCollar); case Omek.JointID.leftShoulder: return(Omek.JointID.rightShoulder); case Omek.JointID.rightShoulder: return(Omek.JointID.leftShoulder); case Omek.JointID.leftElbow: return(Omek.JointID.rightElbow); case Omek.JointID.rightElbow: return(Omek.JointID.leftElbow); case Omek.JointID.leftFingerTip: return(Omek.JointID.rightFingerTip); case Omek.JointID.rightFingerTip: return(Omek.JointID.leftFingerTip); case Omek.JointID.leftHip: return(Omek.JointID.rightHip); case Omek.JointID.rightHip: return(Omek.JointID.leftHip); case Omek.JointID.leftKnee: return(Omek.JointID.rightKnee); case Omek.JointID.rightKnee: return(Omek.JointID.leftKnee); case Omek.JointID.rightFoot: return(Omek.JointID.leftFoot); case Omek.JointID.leftFoot: return(Omek.JointID.rightFoot); default: return(jointID); } }
/// <summary> /// Set specific joint be active so it will play the animation /// </summary> /// <param name="jointID">the joint id to effect</param> /// <param name="isActive">should the joint be activate or deactivate</param> /// <param name="applyForAllChildren">should the joint children state be changed as well</param> public void SetJointActive(Omek.JointID jointID, bool isActive, bool applyForAllChildren = false) { foreach (TransformWrapper tw in m_hierarchyList) { if (tw.m_jointID == jointID) { if (applyForAllChildren) { SetJointActiveForChildren(tw.m_transform, isActive); } else { tw.m_active = isActive; } break; } } }
// update the confidence for a joint private void UpdateConfidence(ConfidanceParams confidanceParams, Omek.JointID jointID) { if (m_lastPersonIndex < 0) { return; } BeckonData.Persons[(uint)m_lastPersonIndex].Skeleton[(Omek.JointID)jointID].Confidence.Get(out confidanceParams.m_currentConfidence); // do we have good confidence for this frame bool isConfidant = (confidanceParams.m_currentConfidence >= 70); // initialize if this the first time if (confidanceParams.m_confidenceWeight == -1) { confidanceParams.m_lastFrameConfidence = isConfidant; confidanceParams.m_lastCurrentStateTime = Time.realtimeSinceStartup; confidanceParams.m_confidenceWeight = isConfidant ? 1 : 0; return; } // if there is a difference from last value and enough time passed since the last change if (isConfidant != confidanceParams.m_lastFrameConfidence && Time.realtimeSinceStartup >= confidanceParams.m_lastCurrentStateTime + m_confidenceChangeSafetyTime) { confidanceParams.m_lastFrameConfidence = isConfidant; confidanceParams.m_lastCurrentStateTime = Time.realtimeSinceStartup; } else if (isConfidant == confidanceParams.m_lastFrameConfidence) // we have the same value as before - update last known time { confidanceParams.m_lastCurrentStateTime = Time.realtimeSinceStartup; } // move the real confidenceWeight towards 1 or 0 according to the current value if (confidanceParams.m_lastFrameConfidence) { confidanceParams.m_confidenceWeight = Mathf.MoveTowards(confidanceParams.m_confidenceWeight, 1, Time.deltaTime * m_confidenceChangeRate); } else { confidanceParams.m_confidenceWeight = Mathf.MoveTowards(confidanceParams.m_confidenceWeight, 0, Time.deltaTime * m_confidenceChangeRate); } }
public TransformWrapper(Omek.JointID jointID, bool mandatory) { m_jointID = jointID; m_mandatory = mandatory; }
// We use LateUpdate so the transforms will be updated by all other animation. // We'll compute the transform of the tracking animation and blend them together void LateUpdate() { CheckForPersonChange(); if (m_initalized) { m_weight = calcualteCurrentWeight(); if (m_weight > 0) { OMKStatus rc = OMKStatus.OMK_ERROR_SKELETON_NOT_FOUND; if (m_useRetargetSkeleton) { rc = BeckonManager.BeckonInstance.PersonAnalyzer.getRetargetedSkeleton(m_characterName, ref m_currentSkeleton); } else { Omek.IPerson person; rc = BeckonManager.BeckonInstance.PersonAnalyzer.getPerson((uint)m_lastPersonIndex, out person); if (rc == OMKStatus.OMK_SUCCESS) { rc = person.copySkeleton(m_currentSkeleton); } } if (rc != OMKStatus.OMK_SUCCESS) { return; } Quaternion baseRotation = m_transform.rotation; m_transform.rotation = Quaternion.identity; float[] beckonQuat = new float[4]; foreach (TransformWrapper transformWrapper in m_hierarchyList) { if (!transformWrapper.m_active || transformWrapper.m_transform == null) { continue; } Omek.JointID jointID = transformWrapper.m_jointID; if (m_mirror) { jointID = GetReflectedJointID(jointID); } rc = m_currentSkeleton.getJointOrientation((JointID)jointID, true, beckonQuat); if (rc == OMKStatus.OMK_SUCCESS) { // fixing quaternion handness Quaternion quat = UnityConverter.ToUnityQuaternion(beckonQuat); if (m_mirror) { quat.x = -quat.x; quat.w = -quat.w; } // add the original base T-pose rotation to the current rotation. quat = quat * transformWrapper.m_originalRotation; //Smoothly rotate towards the new quaternion based on the confidence UpdateConfidence(transformWrapper.m_confidanceParams, jointID); if (transformWrapper.m_confidanceParams.m_currentConfidence >= 70) { if (m_useSmoothing == true) { quat = RotateTowards(transformWrapper.m_lastRotation, quat, Time.deltaTime * m_animationSmoothing); } } else { quat = transformWrapper.m_lastRotation; } // save the current rotation for next frame transformWrapper.m_lastRotation = quat; // smoothly blend in, the orientation from tracking with the transform orientation from all other animations base on animation weight transformWrapper.m_transform.rotation = Quaternion.Slerp(transformWrapper.m_transform.rotation, quat, m_weight * transformWrapper.m_confidanceParams.m_confidenceWeight); if (transformWrapper.m_rollJoint != null && transformWrapper.m_rollJoint.m_transform != null && transformWrapper.m_rollJoint.m_active) { rollRotation(transformWrapper.m_rollJoint); } } } m_transform.rotation = baseRotation; } } }