您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
115 行
4.0 KiB
115 行
4.0 KiB
using System.Runtime.CompilerServices;
|
|
using Unity.Properties;
|
|
using UnityEngine;
|
|
using static Unity.Mathematics.math;
|
|
namespace CollisionLib
|
|
{
|
|
using Unity.Mathematics;
|
|
using Primitives;
|
|
|
|
public static partial class coll
|
|
{
|
|
public static bool RayCast(sphere sphere, ray ray, float rayDist, float rayRadius)
|
|
{
|
|
var rayEnd = ray.origin + ray.direction * rayDist;
|
|
var closestPointOnRay = ClosestPointOnLineSegment(ray.origin, rayEnd, sphere.center);
|
|
var dist = distance(closestPointOnRay, sphere.center);
|
|
return dist < rayRadius + sphere.radius;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static void ProjectPointToLineSegment(float3 lineStart, float3 lineEnd, float3 point, out float t)
|
|
{
|
|
var v = lineStart - lineEnd;
|
|
t = dot(point - lineStart, v) / dot(v, v);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static float3 closest(lineseg lineseg, float3 point)
|
|
{
|
|
return ClosestPointOnLineSegment(lineseg.start, lineseg.end, point);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static float3 ClosestPointOnLineSegment(float3 lineStart, float3 lineEnd, float3 point)
|
|
{
|
|
var v = lineEnd - lineStart;
|
|
var t = dot(point - lineStart, v) / dot(v, v);
|
|
t = max(t, 0.0f);
|
|
t = min(t, 1.0f);
|
|
return lineStart + v * t;
|
|
}
|
|
|
|
public static float DistanceToSegment(float3 lineStart, float3 lineEnd, float3 point, out float3 closest)
|
|
{
|
|
closest = ClosestPointOnLineSegment(lineStart, lineEnd, point);
|
|
return distance(point, closest);
|
|
}
|
|
|
|
public static bool OverlapCapsuleAABB(capsule capsule, box AABB)
|
|
{
|
|
var closestOnCapsule = ClosestPointOnLineSegment(capsule.p1, capsule.p2, AABB.center);
|
|
|
|
float sqDist;
|
|
float3 closestInBox;
|
|
CalculateClosestPointInBox(closestOnCapsule, AABB, out closestInBox, out sqDist);
|
|
return math.sqrt(sqDist) < capsule.radius;
|
|
}
|
|
|
|
public static bool OverlapCapsuleBox(capsule capsule, box box)
|
|
{
|
|
// Transform capsule into box space
|
|
var rayCapsule = capsule;
|
|
var invBoxRot = math.inverse(box.rotation);
|
|
var invBoxPos = -math.mul(invBoxRot, box.center);
|
|
rayCapsule = primlib.transform(rayCapsule, invBoxPos, invBoxRot);
|
|
|
|
var primLocalSpace = box;
|
|
primLocalSpace.center = float3.zero;
|
|
primLocalSpace.rotation = Quaternion.identity;
|
|
|
|
var hit = coll.OverlapCapsuleAABB(rayCapsule, primLocalSpace);
|
|
return hit;
|
|
}
|
|
|
|
public static void CalculateClosestPointInBox(float3 point, box AABB, out float3 outPoint, out float outSqrDistance)
|
|
{
|
|
// compute coordinates of point in box coordinate system
|
|
float3 closest = point - AABB.center;
|
|
|
|
float3 halfSize = AABB.size * 0.5f;
|
|
// project test point onto box
|
|
float fSqrDistance = 0.0f;
|
|
float fDelta;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if (closest[i] < -halfSize[i])
|
|
{
|
|
fDelta = closest[i] + halfSize[i];
|
|
fSqrDistance += fDelta * fDelta;
|
|
closest[i] = -halfSize[i];
|
|
}
|
|
else if (closest[i] > halfSize[i])
|
|
{
|
|
fDelta = closest[i] - halfSize[i];
|
|
fSqrDistance += fDelta * fDelta;
|
|
closest[i] = halfSize[i];
|
|
}
|
|
}
|
|
|
|
// Inside
|
|
if (fSqrDistance == 0.0F)
|
|
{
|
|
outPoint = point;
|
|
outSqrDistance = 0.0F;
|
|
}
|
|
// Outside
|
|
else
|
|
{
|
|
outPoint = closest + AABB.center;
|
|
outSqrDistance = fSqrDistance;
|
|
}
|
|
}
|
|
}
|
|
}
|