using System.Collections.Generic; using UnityEngine; namespace UDE_HAND_INTERACTION { public interface ISurface { Transform Transform { get; } bool Raycast(in Ray ray, out SurfaceHit hit, float maxDistance = 0); bool ClosestSurfacePoint(in Vector3 point, out SurfaceHit hit, float maxDistance = 0); } public struct SurfaceHit { public Vector3 Point { get; set; } public Vector3 Normal { get; set; } public float Distance { get; set; } } public interface ISurfacePatch : ISurface { ISurface BackingSurface { get; } } public static class SurfaceUtils { public static float ComputeDistanceAbove(ISurfacePatch surfacePatch, Vector3 point, float radius) { surfacePatch.BackingSurface.ClosestSurfacePoint(point, out SurfaceHit hit); Vector3 surfaceToPoint = point - hit.Point; return Vector3.Dot(surfaceToPoint, hit.Normal) - radius; } public static float ComputeTangentDistance(ISurfacePatch surfacePatch, Vector3 point, float radius) { surfacePatch.ClosestSurfacePoint(point, out SurfaceHit patchHit); surfacePatch.BackingSurface.ClosestSurfacePoint(point, out SurfaceHit backingHit); Vector3 proximityToPoint = point - patchHit.Point; Vector3 projOnNormal = Vector3.Dot(proximityToPoint, backingHit.Normal) * backingHit.Normal; Vector3 lateralVec = proximityToPoint - projOnNormal; return lateralVec.magnitude - radius; } public static float ComputeDepth(ISurfacePatch surfacePatch, Vector3 point, float radius) { return Mathf.Max(0f, -ComputeDistanceAbove(surfacePatch, point, radius)); } public static float ComputeDistanceFrom(ISurfacePatch surfacePatch, Vector3 point, float radius) { surfacePatch.ClosestSurfacePoint(point, out SurfaceHit hit); Vector3 surfaceToPoint = point - hit.Point; return surfaceToPoint.magnitude - radius; } public static bool Clip(this Bounds bounds, in Bounds clipper, out Bounds result) { result = new Bounds(); Vector3 min = Vector3.Max(bounds.min, clipper.min); Vector3 max = Vector3.Min(bounds.max, clipper.max); if (min.x > max.x || min.y > max.y || min.z > max.z) { return false; } result.SetMinMax(min, max); return true; } } public interface IBounds { Bounds Bounds { get; } } public interface IBoundsClipper { public bool GetLocalBounds(Transform localTo, out Bounds bounds); } public interface IClippedSurface : ISurfacePatch { IEnumerable GetClippers(); } }