/// <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, SteamVR_Input_Sources inputSource) { // only allow this function to run once per frame if (poseUpdatedThisFrame) { return; } poseUpdatedThisFrame = true; if (skeletonAction.activeBinding) { // 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 == SteamVR_Input_Sources.RightHand) { blendedSnapshotR = snap; } if (inputSource == SteamVR_Input_Sources.LeftHand) { blendedSnapshotL = snap; } }
public void UpdateAdditiveAnimation(SteamVR_Action_Skeleton skeletonAction, SteamVR_Input_Sources inputSource) { if (skeletonAction.GetSkeletalTrackingLevel() == EVRSkeletalTrackingLevel.VRSkeletalTracking_Estimated) { //do not apply additive animation on low fidelity controllers, eg. Vive Wands and Touch return; } SteamVR_Skeleton_PoseSnapshot snapshot = GetHandSnapshot(inputSource); SteamVR_Skeleton_Pose_Hand poseHand = pose.GetHand(inputSource); for (int boneIndex = 0; boneIndex < snapshotL.bonePositions.Length; boneIndex++) { int fingerIndex = SteamVR_Skeleton_JointIndexes.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]); } } }
public void UpdateAdditiveAnimation(SteamVR_Action_Skeleton skeletonAction, SteamVR_Input_Sources inputSource) { SteamVR_Skeleton_PoseSnapshot snapshot = GetHandSnapshot(inputSource); SteamVR_Skeleton_Pose_Hand poseHand = pose.GetHand(inputSource); for (int boneIndex = 0; boneIndex < snapshotL.bonePositions.Length; boneIndex++) { int fingerIndex = SteamVR_Skeleton_JointIndexes.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]); } } }
protected virtual void UpdateSkeleton() { if (skeletonAction == null) { return; } if (updatePose) { UpdatePose(); } if (blendPoser != null && skeletonBlend < 1) { if (blendSnapshot == null) { blendSnapshot = blendPoser.GetBlendedPose(this); } 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(); } }
/// <summary> /// Init based on an existing Skeleton_Pose /// </summary> public SkeletonBlendablePose(SteamVR_Skeleton_Pose p) { pose = p; snapshotR = new SteamVR_Skeleton_PoseSnapshot(p.rightHand.bonePositions.Length, SteamVR_Input_Sources.RightHand); snapshotL = new SteamVR_Skeleton_PoseSnapshot(p.leftHand.bonePositions.Length, SteamVR_Input_Sources.LeftHand); }
/// <summary> /// Blend from the current skeletonBlend amount to full bone data. (skeletonBlend = 1) /// </summary> /// <param name="overTime">How long you want the blend to take (in seconds)</param> public void BlendToSkeleton(float overTime = 0.1f) { if (blendPoser != null) { blendSnapshot = blendPoser.GetBlendedPose(this); } blendPoser = null; BlendTo(1, overTime); }
/// <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]; } }
public void UpdateAdditiveAnimation(SteamVR_Action_Skeleton skeletonAction, SteamVR_Input_Sources 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++) { int fingerIndex = SteamVR_Skeleton_JointIndexes.GetFingerForBone(boneIndex); SteamVR_Skeleton_FingerExtensionTypes extensionType = poseHand.GetMovementTypeForBone(boneIndex); //do target pose mirroring on left hand if (inputSource == SteamVR_Input_Sources.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]); } } }
/// <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 boneIndex = 0; boneIndex < bonePositions.Length; boneIndex++) { bonePositions[boneIndex] = source.bonePositions[boneIndex]; boneRotations[boneIndex] = source.boneRotations[boneIndex]; } }
/// <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_PoseSnapshot snapshot, SkeletonBlendablePose[] blendPoses, SteamVR_Input_Sources inputSource) { SteamVR_Skeleton_PoseSnapshot 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_JointIndexes.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); } } }
/// <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, SteamVR_Input_Sources inputSource) { // only allow this function to run once per frame if (poseUpdatedThisFrame) { return; } poseUpdatedThisFrame = true; if (skeletonAction.activeBinding) { // 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 == SteamVR_Input_Sources.RightHand) { blendedSnapshotR = snap; } if (inputSource == SteamVR_Input_Sources.LeftHand) { blendedSnapshotL = snap; } // ebaender - adjust rotation to cover angle if (coverMapping != null && pageMapping != null) { blendedSnapshotL.rotation *= Quaternion.Euler(0f, (177f / 180f - coverMapping.value) * 200f * pageMapping.value, 0f); // Debug.Log((177f / 180f - coverMapping.value) * 200f * pageMapping.value); } }
protected void ApplyBlenderBehaviours(SteamVR_Action_Skeleton skeletonAction, SteamVR_Input_Sources inputSource, SteamVR_Skeleton_PoseSnapshot 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); } } }
protected void Awake() { if (previewLeftInstance != null) { DestroyImmediate(previewLeftInstance); } if (previewRightInstance != null) { DestroyImmediate(previewRightInstance); } blendPoses = new SkeletonBlendablePose[skeletonAdditionalPoses.Count + 1]; for (int i = 0; i < blendPoseCount; i++) { blendPoses[i] = new SkeletonBlendablePose(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_PoseSnapshot(boneCount, SteamVR_Input_Sources.LeftHand); blendedSnapshotR = new SteamVR_Skeleton_PoseSnapshot(boneCount, SteamVR_Input_Sources.RightHand); }
protected void Awake() { if (previewLeftInstance != null) { DestroyImmediate(previewLeftInstance); } if (previewRightInstance != null) { DestroyImmediate(previewRightInstance); } blendPoses = new SkeletonBlendablePose[skeletonAdditionalPoses.Count + 1]; for (int i = 0; i < blendPoseCount; i++) { SteamVR_Skeleton_Pose iterPose = GetPoseByIndex(i); // ValheimVR Mod Edit: Potentially need to initialize here // to workaround serialized data not traveling with AssetBundle if (iterPose.leftHand.bonePositions == null) { Debug.Log("Initializing Left Hand Pose Data for index : " + i); HandResourceInitializer.Initialize_SteamVR_Skeleton_Pose_Hand(ref iterPose.leftHand, i, HandResourceInitializer.LEFT_HAND); } if (iterPose.rightHand.bonePositions == null) { Debug.Log("Initializing Right Hand Pose Data for index : " + i); HandResourceInitializer.Initialize_SteamVR_Skeleton_Pose_Hand(ref iterPose.rightHand, i, HandResourceInitializer.RIGHT_HAND); } blendPoses[i] = new SkeletonBlendablePose(iterPose); blendPoses[i].PoseToSnapshots(); } boneCount = skeletonMainPose.leftHand.bonePositions.Length; // NOTE: Is there a better way to get the bone count? idk blendedSnapshotL = new SteamVR_Skeleton_PoseSnapshot(boneCount, SteamVR_Input_Sources.LeftHand); blendedSnapshotR = new SteamVR_Skeleton_PoseSnapshot(boneCount, SteamVR_Input_Sources.RightHand); }