protected virtual void UpdateSkeleton() { if (skeletonAction == null || skeletonAction.active == false) { return; } if (updatePose) { UpdatePose(); } if (blendPoser != null && skeletonBlend < 1) { blendSnapshot = blendPoser.GetBlendedPose(this); } if (rangeOfMotionBlendRoutine == null) { if (temporaryRangeOfMotion != null) { skeletonAction.SetRangeOfMotion(temporaryRangeOfMotion.Value); } else { skeletonAction.SetRangeOfMotion(rangeOfMotion); //this may be a frame behind } UpdateSkeletonTransforms(); } }
public void UpdateAdditiveAnimation(SteamVR_Action_Skeleton0 skeletonAction, SteamVR_Input_Sources inputSource) { SteamVR_Skeleton_PoseSnapshot0 snapshot = GetHandSnapshot(inputSource); SteamVR_Skeleton_Pose_Hand0 poseHand = pose.GetHand(inputSource); for (int boneIndex = 0; boneIndex < snapshotL.bonePositions.Length; boneIndex++) { int fingerIndex = SteamVR_Skeleton_JointIndexes0.GetFingerForBone(boneIndex); SteamVR_Skeleton_FingerExtensionTypes extensionType = poseHand.GetMovementTypeForBone(boneIndex); if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Free) { snapshot.bonePositions[boneIndex] = skeletonAction.bonePositions[boneIndex]; snapshot.boneRotations[boneIndex] = skeletonAction.boneRotations[boneIndex]; } if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Extend) { // lerp to open pose by fingercurl snapshot.bonePositions[boneIndex] = Vector3.Lerp(poseHand.bonePositions[boneIndex], skeletonAction.bonePositions[boneIndex], 1 - skeletonAction.fingerCurls[fingerIndex]); snapshot.boneRotations[boneIndex] = Quaternion.Lerp(poseHand.boneRotations[boneIndex], skeletonAction.boneRotations[boneIndex], 1 - skeletonAction.fingerCurls[fingerIndex]); } if (extensionType == SteamVR_Skeleton_FingerExtensionTypes.Contract) { // lerp to closed pose by fingercurl snapshot.bonePositions[boneIndex] = Vector3.Lerp(poseHand.bonePositions[boneIndex], skeletonAction.bonePositions[boneIndex], skeletonAction.fingerCurls[fingerIndex]); snapshot.boneRotations[boneIndex] = Quaternion.Lerp(poseHand.boneRotations[boneIndex], skeletonAction.boneRotations[boneIndex], skeletonAction.fingerCurls[fingerIndex]); } } }
/// <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_Skeleton0 skeletonAction, SteamVR_Input_Sources 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_PoseSnapshot0 snap = GetHandSnapshot(inputSource); snap.CopyFrom(blendPoses[0].GetHandSnapshot(inputSource)); ApplyBlenderBehaviours(skeletonAction, inputSource, snap); if (inputSource == SteamVR_Input_Sources.RightHand) { blendedSnapshotR = snap; } if (inputSource == SteamVR_Input_Sources.LeftHand) { blendedSnapshotL = snap; } }
/// <summary> /// Perform a deep copy from one poseSnapshot to another. /// </summary> public void CopyFrom(SteamVR_Skeleton_PoseSnapshot0 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> /// Apply blending to this behaviour's pose to an existing snapshot. /// </summary> /// <param name="snapshot">Snapshot to modify</param> /// <param name="blendPoses">List of blend poses to get the target pose</param> /// <param name="inputSource">Which hand to receive input from</param> public void ApplyBlending(SteamVR_Skeleton_PoseSnapshot0 snapshot, SkeletonBlendablePose0[] blendPoses, SteamVR_Input_Sources inputSource) { SteamVR_Skeleton_PoseSnapshot0 targetSnapshot = blendPoses[pose].GetHandSnapshot(inputSource); if (mask.GetFinger(0) || useMask == false) { snapshot.position = Vector3.Lerp(snapshot.position, targetSnapshot.position, influence * value); snapshot.rotation = Quaternion.Slerp(snapshot.rotation, targetSnapshot.rotation, influence * value); } for (int boneIndex = 0; boneIndex < snapshot.bonePositions.Length; boneIndex++) { // verify the current finger is enabled in the mask, or if no mask is used. if (mask.GetFinger(SteamVR_Skeleton_JointIndexes0.GetFingerForBone(boneIndex) + 1) || useMask == false) { snapshot.bonePositions[boneIndex] = Vector3.Lerp(snapshot.bonePositions[boneIndex], targetSnapshot.bonePositions[boneIndex], influence * value); snapshot.boneRotations[boneIndex] = Quaternion.Slerp(snapshot.boneRotations[boneIndex], targetSnapshot.boneRotations[boneIndex], influence * value); } } }
protected void Awake() { if (previewLeftInstance != null) { DestroyImmediate(previewLeftInstance); } if (previewRightInstance != null) { DestroyImmediate(previewRightInstance); } blendPoses = new SkeletonBlendablePose0[skeletonAdditionalPoses.Count + 1]; for (int i = 0; i < blendPoseCount; i++) { blendPoses[i] = new SkeletonBlendablePose0(GetPoseByIndex(i)); blendPoses[i].PoseToSnapshots(); } boneCount = skeletonMainPose.leftHand.bonePositions.Length; // NOTE: Is there a better way to get the bone count? idk blendedSnapshotL = new SteamVR_Skeleton_PoseSnapshot0(boneCount, SteamVR_Input_Sources.LeftHand); blendedSnapshotR = new SteamVR_Skeleton_PoseSnapshot0(boneCount, SteamVR_Input_Sources.RightHand); }
/// <summary> /// Init based on an existing Skeleton_Pose /// </summary> public SkeletonBlendablePose0(SteamVR_Skeleton_Pose0 p) { pose = p; snapshotR = new SteamVR_Skeleton_PoseSnapshot0(p.rightHand.bonePositions.Length, SteamVR_Input_Sources.RightHand); snapshotL = new SteamVR_Skeleton_PoseSnapshot0(p.leftHand.bonePositions.Length, SteamVR_Input_Sources.LeftHand); }
protected void ApplyBlenderBehaviours(SteamVR_Action_Skeleton0 skeletonAction, SteamVR_Input_Sources inputSource, SteamVR_Skeleton_PoseSnapshot0 snapshot) { // apply blending for each behaviour for (int behaviourIndex = 0; behaviourIndex < blendingBehaviours.Count; behaviourIndex++) { blendingBehaviours[behaviourIndex].Update(Time.deltaTime, inputSource); // if disabled or very low influence, skip for perf if (blendingBehaviours[behaviourIndex].enabled && blendingBehaviours[behaviourIndex].influence * blendingBehaviours[behaviourIndex].value > 0.01f) { if (blendingBehaviours[behaviourIndex].pose != 0) { // update additive animation only as needed blendPoses[blendingBehaviours[behaviourIndex].pose].UpdateAdditiveAnimation(skeletonAction, inputSource); } blendingBehaviours[behaviourIndex].ApplyBlending(snapshot, blendPoses, inputSource); } } }