/// <summary> /// Updates all pose animation and blending. Can be called from different places without performance concerns, as it will only let itself run once per frame. /// </summary> public void UpdatePose(SteamVR_Action_Skeleton skeletonAction, HandType inputSource) { // only allow this function to run once per frame if (poseUpdatedThisFrame) { return; } poseUpdatedThisFrame = true; // always do additive animation on main pose // blendPoses[0].UpdateAdditiveAnimation(skeletonAction, inputSource); //copy from main pose as a base SteamVR_Skeleton_PoseSnapshot snap = GetHandSnapshot(inputSource); // snap.CopyFrom(blendPoses[0].GetHandSnapshot(inputSource)); ApplyBlenderBehaviours(skeletonAction, inputSource, snap); if (inputSource == HandType.RightHand) { blendedSnapshotR = snap; } else if (inputSource == HandType.LeftHand) { blendedSnapshotL = snap; } }
/// <summary> /// Performs smoothing based on deltaTime parameter. /// </summary> public void Update(float deltaTime, HandType inputSource, float smoothSpeed) { if (targetBehaviour.type == SteamVR_Skeleton_PoserBehavior.PoseBlendingBehaviour.BlenderTypes.AnalogAction) { targetValue = targetBehaviour.action_single.GetAxis(inputSource); // if (targetBehaviour.smoothingSpeed == 0) // value = targetBehaviour.action_single.GetAxis(inputSource); // else // value = Mathf.Lerp(value, targetBehaviour.action_single.GetAxis(inputSource), deltaTime * targetBehaviour.smoothingSpeed); } if (targetBehaviour.type == SteamVR_Skeleton_PoserBehavior.PoseBlendingBehaviour.BlenderTypes.BooleanAction) { targetValue = targetBehaviour.action_bool.GetState(inputSource) ? 1 : 0; // if (targetBehaviour.smoothingSpeed == 0) // value = targetBehaviour.action_bool.GetState(inputSource) ? 1 : 0; // else // value = Mathf.Lerp(value, targetBehaviour.action_bool.GetState(inputSource) ? 1 : 0, deltaTime * targetBehaviour.smoothingSpeed); } if (smoothSpeed == 0) { value = targetValue; } else { value = Mathf.Lerp(value, targetValue, deltaTime * smoothSpeed); } }
public SteamVR_Skeleton_PoseSnapshot(int boneCount, HandType source) { inputSource = source; bonePositions = new Vector3[boneCount]; boneRotations = new Quaternion[boneCount]; // position = Vector3.zero; // rotation = Quaternion.identity; }
/// <summary> /// Perform a deep copy from one poseSnapshot to another. /// </summary> public void CopyFrom(SteamVR_Skeleton_PoseSnapshot source) { inputSource = source.inputSource; // position = source.position; // rotation = source.rotation; for (int i = 0; i < bonePositions.Length; i++) { bonePositions[i] = source.bonePositions[i]; boneRotations[i] = source.boneRotations[i]; } }
/// <summary> /// Get the snapshot of this pose with effects such as additive finger animation applied. /// </summary> public SteamVR_Skeleton_PoseSnapshot GetHandSnapshot(HandType inputSource) { if (inputSource == HandType.LeftHand) { return(snapshotL); } else { return(snapshotR); } }
private SteamVR_Skeleton_PoseSnapshot GetHandSnapshot(HandType inputSource) { if (inputSource == HandType.LeftHand) { return(blendedSnapshotL); } else { return(blendedSnapshotR); } }
public void ApplyBlending(SteamVR_Skeleton_PoseSnapshot snapshot, SkeletonBlendablePose[] blendPoses, HandType inputSource, float t) { // targetBehaviour.ApplyBlending(snapshot, blendPoses, inputSource, value); // float t = targetBehaviour.influence * value; // if (t == 0) // return; SteamVR_Skeleton_PoseSnapshot targetSnapshot = blendPoses[targetBehaviour.pose].GetHandSnapshot(inputSource); // SteamVR_Skeleton_PoseSnapshot targetSnapshot = targetBehaviour.pose.GetHandSnapshot(inputSource); // if (targetBehaviour.mask.GetFinger(0) || targetBehaviour.useMask == false) if (t >= 1) { // snapshot.position = targetSnapshot.position; // snapshot.rotation = targetSnapshot.rotation; } else { // snapshot.position = Vector3.Lerp(snapshot.position, targetSnapshot.position, t); // snapshot.rotation = Quaternion.Slerp(snapshot.rotation, targetSnapshot.rotation, t); } for (int boneIndex = 0; boneIndex < snapshot.bonePositions.Length; boneIndex++) { // if ((boneIndex == 1) || (boneIndex == 0)) // continue; // verify the current finger is enabled in the mask, or if no mask is used. // if (targetBehaviour.mask.GetFinger(SteamVR_Skeleton_JointIndexes.GetFingerForBone(boneIndex) + 1) || targetBehaviour.useMask == false) { if (t >= 1) { snapshot.bonePositions[boneIndex] = targetSnapshot.bonePositions[boneIndex]; snapshot.boneRotations[boneIndex] = targetSnapshot.boneRotations[boneIndex]; } else { snapshot.bonePositions[boneIndex] = Vector3.Lerp(snapshot.bonePositions[boneIndex], targetSnapshot.bonePositions[boneIndex], t); snapshot.boneRotations[boneIndex] = Quaternion.Slerp(snapshot.boneRotations[boneIndex], targetSnapshot.boneRotations[boneIndex], t); } } } }
public void UpdateAdditiveAnimation(SteamVR_Action_Skeleton skeletonAction, HandType inputSource) { SteamVR_Skeleton_PoseSnapshot snapshot = GetHandSnapshot(inputSource); SteamVR_Skeleton_Pose_Hand poseHand = pose.GetHand(inputSource); //setup mirrored pose buffers if (additivePositionBuffer == null) { additivePositionBuffer = new Vector3[skeletonAction.boneCount]; } if (additiveRotationBuffer == null) { additiveRotationBuffer = new Quaternion[skeletonAction.boneCount]; } for (int boneIndex = 0; boneIndex < snapshotL.bonePositions.Length; boneIndex++) { // if ((boneIndex == 1) || (boneIndex == 0)) // continue; int fingerIndex = SteamVR_Skeleton_JointIndexes.GetFingerForBone(boneIndex); SteamVR_Skeleton_FingerExtensionTypes extensionType = poseHand.GetMovementTypeForBone(boneIndex); //do target pose mirroring on left hand if (inputSource == HandType.LeftHand) { SteamVR_Behaviour_Skeleton.MirrorBonePosition(ref skeletonAction.bonePositions[boneIndex], ref additivePositionBuffer[boneIndex], boneIndex); SteamVR_Behaviour_Skeleton.MirrorBoneRotation(ref skeletonAction.boneRotations[boneIndex], ref additiveRotationBuffer[boneIndex], boneIndex); } else { additivePositionBuffer[boneIndex] = skeletonAction.bonePositions[boneIndex]; additiveRotationBuffer[boneIndex] = skeletonAction.boneRotations[boneIndex]; } if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Free) { snapshot.bonePositions[boneIndex] = additivePositionBuffer[boneIndex]; snapshot.boneRotations[boneIndex] = additiveRotationBuffer[boneIndex]; } else if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Extend) { // lerp to open pose by fingercurl snapshot.bonePositions[boneIndex] = Vector3.Lerp(poseHand.bonePositions[boneIndex], additivePositionBuffer[boneIndex], 1 - skeletonAction.fingerCurls[fingerIndex]); snapshot.boneRotations[boneIndex] = Quaternion.Lerp(poseHand.boneRotations[boneIndex], additiveRotationBuffer[boneIndex], 1 - skeletonAction.fingerCurls[fingerIndex]); } else if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Contract) { // lerp to closed pose by fingercurl snapshot.bonePositions[boneIndex] = Vector3.Lerp(poseHand.bonePositions[boneIndex], additivePositionBuffer[boneIndex], skeletonAction.fingerCurls[fingerIndex]); snapshot.boneRotations[boneIndex] = Quaternion.Lerp(poseHand.boneRotations[boneIndex], additiveRotationBuffer[boneIndex], skeletonAction.fingerCurls[fingerIndex]); } } }
protected void ApplyBlenderBehaviours(SteamVR_Action_Skeleton skeletonAction, HandType inputSource, SteamVR_Skeleton_PoseSnapshot snapshot) { // apply blending for each behaviour for (int behaviourIndex = 0; behaviourIndex < blendingBehaviours.Count; behaviourIndex++) { PoseBlendingBehaviour blending = blendingBehaviours[behaviourIndex]; blending.Update(Time.deltaTime, inputSource, smoothSpeed); // if disabled or very low influence, skip for perf // float t = blending.targetBehaviour.influence * blending.GetValue(); float t = behaviourIndex == 0 ? 1 : blending.GetValue(); bool isManual = blending.targetBehaviour.type == SteamVR_Skeleton_PoserBehavior.PoseBlendingBehaviour.BlenderTypes.Manual; if ((blending.enabled || isManual || behaviourIndex == 0) && t > 0.01f) { // if (blending.targetBehaviour.pose != 0) // { // update additive animation only as needed blendPoses[blending.targetBehaviour.pose].UpdateAdditiveAnimation(skeletonAction, inputSource); // } blending.ApplyBlending(snapshot, blendPoses, inputSource, t); } } }
/// <summary> /// Retrieve the final animated pose, to be applied to a hand skeleton /// </summary> /// <param name="forAction">The skeleton action you want to blend between</param> /// <param name="handType">If this is for the left or right hand</param> public SteamVR_Skeleton_PoseSnapshot GetBlendedPose(SteamVR_Action_Skeleton skeletonAction, HandType handType) { UpdatePose(skeletonAction, handType); return(GetHandSnapshot(handType)); }