VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.interaction/Runtime/Scripts/Grab/SnapSurfaces/GrabPoseHelper.cs
IonutMocanu d7aba243a2 Main
2025-09-08 11:04:02 +03:00

130 lines
6.2 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.Grab
{
public static class GrabPoseHelper
{
public delegate Pose PoseCalculator(in Pose desiredPose, Transform relativeTo);
/// <summary>
/// Finds the best pose comparing the one that requires the minimum rotation
/// and minimum translation.
/// </summary>
/// <param name="desiredPose">Root pose to measure from.</param>
/// <param name="offset">The offset from the root for accurate scoring</param>
/// <param name="bestPose">Nearest pose to the desired one at the hand grab pose.</param>
/// <param name="scoringModifier">Modifiers for the score based in rotation and distance.</param>
/// <param name="relativeTo">The reference transform to apply the calculators to</param>
/// <param name="minimalTranslationPoseCalculator">Delegate to calculate the nearest, by position, pose at a hand grab pose.</param>
/// <param name="minimalRotationPoseCalculator">Delegate to calculate the nearest, by rotation, pose at a hand grab pose.</param>
/// <returns>The score, normalized, of the best pose.</returns>
public static GrabPoseScore CalculateBestPoseAtSurface(in Pose desiredPose, in Pose offset, out Pose bestPose,
in PoseMeasureParameters scoringModifier, Transform relativeTo,
PoseCalculator minimalTranslationPoseCalculator, PoseCalculator minimalRotationPoseCalculator)
{
if (scoringModifier.PositionRotationWeight == 1f)
{
bestPose = minimalRotationPoseCalculator(desiredPose, relativeTo);
return new GrabPoseScore(desiredPose, bestPose, offset, scoringModifier);
}
if (scoringModifier.PositionRotationWeight == 0f)
{
bestPose = minimalTranslationPoseCalculator(desiredPose, relativeTo);
return new GrabPoseScore(desiredPose, bestPose, offset, scoringModifier);
}
Pose minimalTranslationPose = minimalTranslationPoseCalculator(desiredPose, relativeTo);
Pose minimalRotationPose = minimalRotationPoseCalculator(desiredPose, relativeTo);
bestPose = SelectBestPose(minimalRotationPose, minimalTranslationPose,
desiredPose, offset, scoringModifier,
out GrabPoseScore bestScore);
return bestScore;
}
/// <summary>
/// Compares two poses to a reference and returns the most similar one
/// </summary>
/// <param name="poseA">First root Pose to compare with the reference.</param>
/// <param name="poseB">Second root Pose to compare with the reference.</param>
/// <param name="reference">Reference pose to measure from.</param>
/// <param name="offset">The offset from the roots, for accurate scoring</param>
/// <param name="scoringModifier">Modifiers for the score based in rotation and distance.</param>
/// <param name="bestScore">Out value with the score of the best pose.</param>
/// <returns>The most similar pose to reference out of the poses</returns>
public static Pose SelectBestPose(in Pose poseA, in Pose poseB, in Pose reference, in Pose offset,
PoseMeasureParameters scoringModifier, out GrabPoseScore bestScore)
{
GrabPoseScore poseAScore = new GrabPoseScore(reference, poseA, offset, scoringModifier);
GrabPoseScore poseBScore = new GrabPoseScore(reference, poseB, offset, scoringModifier);
if (poseAScore.IsBetterThan(poseBScore))
{
bestScore = poseAScore;
return poseA;
}
else
{
bestScore = poseBScore;
return poseB;
}
}
/// <summary>
/// Calculates the score from a point to a set of colliders.
/// When the point is outside the colliders the further from their surface means the
/// lower the score.
/// When the point is inside any of the colliders the score is always higher.
/// </summary>
/// <param name="position">Position to measure against the colliders</param>
/// <param name="colliders">Group of colliders to measure the score</param>
/// <param name="hitPoint">Output point in the surface or inside the colliders that is near the position</param>
/// <returns>A GrabPoseScore value containing the score of the position in reference to the colliders</returns>
public static GrabPoseScore CollidersScore(Vector3 position, Collider[] colliders,
out Vector3 hitPoint)
{
GrabPoseScore bestScore = GrabPoseScore.Max;
GrabPoseScore score;
hitPoint = position;
foreach (Collider collider in colliders)
{
bool isPointInsideCollider = Collisions.IsPointWithinCollider(position, collider);
Vector3 measuringPoint = isPointInsideCollider ? collider.bounds.center
: collider.ClosestPoint(position);
score = new GrabPoseScore(position, measuringPoint,
isPointInsideCollider);
if (score.IsBetterThan(bestScore))
{
hitPoint = isPointInsideCollider ? position : measuringPoint;
bestScore = score;
}
}
return bestScore;
}
}
}