protected override void Apply(HandDataAsset handDataAsset) { if (!handDataAsset.IsTracked) { return; } Profiler.BeginSample($"{nameof(OneEuroFilterRotationHand)}." + $"{nameof(OneEuroFilterRotationHand.Apply)}"); if (Time.frameCount > _lastFrameUpdated) { _lastFrameUpdated = Time.frameCount; ApplyFilters(handDataAsset); _lastFiltered.CopyFrom(handDataAsset); } else { handDataAsset.CopyFrom(_lastFiltered); } handDataAsset.RootPoseOrigin = PoseOrigin.FilteredTrackedPose; Profiler.EndSample(); }
protected override void Apply(HandDataAsset data) { if (!data.IsDataValid) { return; } if (_capturedDataVersion != ModifyDataFromSource.CurrentDataVersion) { _capturedDataVersion = ModifyDataFromSource.CurrentDataVersion; _historyIndex = (_historyIndex + 1) % _historyLength; for (int i = 0; i < _jointHistory.Length; i++) { _jointHistory[i][_historyIndex] = data.Joints[i]; } } _historyOffset = Mathf.Clamp(_historyOffset, 0, _historyLength); int index = (_historyIndex + _historyLength - _historyOffset) % _historyLength; for (int i = 0; i < _jointHistory.Length; i++) { data.Joints[i] = _jointHistory[i][index]; } }
private void UpdateAllLocalPoses(HandDataAsset data) { for (int i = 0; i < Constants.NUM_HAND_JOINTS; ++i) { HandSkeletonJoint originalJoint = _originalJoints[i]; _localPoses[i].position = originalJoint.pose.position; _localPoses[i].rotation = data.Joints[i]; } }
protected override void Apply(HandDataAsset data) { Pose rootToPointer = PoseUtils.RelativeOffset(data.PointerPose, data.Root); rootToPointer.position = (rootToPointer.position / data.HandScale) * _scale; PoseUtils.Multiply(data.Root, rootToPointer, ref data.PointerPose); data.HandScale = _scale; }
protected override void Start() { base.Start(); InitFingerJointFilters(); _lastFrameUpdated = 0; _lastFiltered = new HandDataAsset(); _wristFilter = OneEuroFilter.CreateQuaternion(); }
public void Update(HandDataAsset data, int dataVersion) { _dirtyWorldJoints = _dirtyWristJoints = (1 << (int)HandJointId.HandEnd) - 1; //set all dirty if (!data.IsDataValidAndConnected) { return; } LocalDataVersion = dataVersion; UpdateAllLocalPoses(data); }
private void ApplyFilters(HandDataAsset handDataAsset) { if (_wristFilterEnabled) { Pose rootPose = handDataAsset.Root; _wristFilter.SetProperties(_wristFilterProperties); rootPose.rotation = _wristFilter.Step(rootPose.rotation, Time.fixedDeltaTime); handDataAsset.Root = rootPose; } if (_fingerFiltersEnabled) { foreach (var joint in _fingerJointFilters) { joint.Filter.SetProperties(_fingerFilterProperties); handDataAsset.Joints[(int)joint.JointId] = joint.Filter.Step(handDataAsset.Joints[(int)joint.JointId], Time.fixedDeltaTime); } } }
protected override void Apply(HandDataAsset handDataAsset) { if (!handDataAsset.IsTracked) { return; } Profiler.BeginSample($"{nameof(OneEuroFilterPositionHand)}." + $"{nameof(OneEuroFilterPositionHand.Apply)}"); if (Time.frameCount > _lastFrameUpdated) { _lastFrameUpdated = Time.frameCount; _lastSmoothedPose = ApplyFilter(handDataAsset.Root); } handDataAsset.Root = _lastSmoothedPose; handDataAsset.RootPoseOrigin = PoseOrigin.FilteredTrackedPose; Profiler.EndSample(); }
protected override void Apply(HandDataAsset data) { if (!data.IsDataValid || !data.IsTracked || !data.IsHighConfidence) { data.IsConnected = false; data.RootPoseOrigin = PoseOrigin.None; _hasConnectedData = false; return; } UpdateRequired.Invoke(); _lastStates.CopyFrom(data); if (!_hasConnectedData) { _constrainedWristPose.CopyFrom(data.Root); _hasConnectedData = true; } UpdateJointsRotation(data); UpdateRootPose(ref data.Root); data.RootPoseOrigin = PoseOrigin.SyntheticPose; }
/// <summary> /// Updates the rotation of the joints in the hand /// using the visual provided values. Sometimes this /// might require lerping between the tracked pose /// and the provided ones to improve the movement of the fingers /// without worrying about when the overwrite values were written. /// /// During this update the modifier also ensures that fingers that disallow /// some movement (locked or constrained) have their values properly set, and /// when there is an unlock event the finger values are smoothly animated back to /// their tracked rotations. /// </summary> /// <param name="data">The entire hand data structure to read and write the joints rotations from</param> private void UpdateJointsRotation(HandDataAsset data) { float extraRotationAllowance = 0f; Quaternion[] jointRotations = data.Joints; for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; ++i) { JointFreedom freedomLevel = _jointsFreedomLevels[i]; Quaternion desiredRotation = _desiredJointsRotation[i]; float overrideFactor = _jointsOverrideFactor[i]; int rawJointIndex = (int)FingersMetadata.HAND_JOINT_IDS[i]; if (freedomLevel == JointFreedom.Free) { //nothing to do, we move the finger freely } else if (freedomLevel == JointFreedom.Locked) { jointRotations[rawJointIndex] = Quaternion.Slerp( jointRotations[rawJointIndex], desiredRotation, overrideFactor); } else if (freedomLevel == JointFreedom.Constrained) { bool jointCanSpread = false; if (FingersMetadata.HAND_JOINT_CAN_SPREAD[i]) { jointCanSpread = true; extraRotationAllowance = 0f; } Quaternion maxRotation = desiredRotation * Quaternion.Euler(0f, 0f, -90f * extraRotationAllowance); float overRotation = OverFlex(jointRotations[rawJointIndex], maxRotation); extraRotationAllowance = Mathf.Max(extraRotationAllowance, overRotation); if (overRotation < 0f) { jointRotations[rawJointIndex] = Quaternion.Slerp( jointRotations[rawJointIndex], maxRotation, overrideFactor); } else if (jointCanSpread) { Quaternion trackedRotation = jointRotations[rawJointIndex]; float spreadAngle = Vector3.SignedAngle( trackedRotation * Vector3.forward, maxRotation * Vector3.forward, trackedRotation * Vector3.up); float spreadFactor = 1f - Mathf.Clamp01(overRotation * _spreadAllowance); trackedRotation = trackedRotation * Quaternion.Euler(0f, spreadAngle * spreadFactor, 0f); jointRotations[rawJointIndex] = trackedRotation; } } float smoothFactor = _jointsFreedomLevels[i] == JointFreedom.Free ? _jointUnlockProgressCurves[i].Progress() : _jointLockProgressCurves[i].Progress(); jointRotations[rawJointIndex] = Quaternion.Slerp( _constrainedJointRotations[i], jointRotations[rawJointIndex], smoothFactor); _lastSyntheticRotation[i] = jointRotations[rawJointIndex]; } }