You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

133 lines
4.8 KiB

namespace UnityEngine.Rendering
{
internal static class ProbeVolumePositioning
{
internal static Vector3[] m_Axes = new Vector3[6];
internal static Vector3[] m_AABBCorners = new Vector3[8];
public static bool OBBIntersect(in ProbeReferenceVolume.Volume a, in ProbeReferenceVolume.Volume b)
{
// First we test if the bounding spheres intersects, in which case we case do the more complex OBB test
a.CalculateCenterAndSize(out var aCenter, out var aSize);
b.CalculateCenterAndSize(out var bCenter, out var bSize);
var aRadius = aSize.sqrMagnitude / 2.0f;
var bRadius = bSize.sqrMagnitude / 2.0f;
if (Vector3.SqrMagnitude(aCenter - bCenter) > aRadius + bRadius)
return false;
m_Axes[0] = a.X.normalized;
m_Axes[1] = a.Y.normalized;
m_Axes[2] = a.Z.normalized;
m_Axes[3] = b.X.normalized;
m_Axes[4] = b.Y.normalized;
m_Axes[5] = b.Z.normalized;
for (int i = 0; i < 6; i++)
{
Vector2 aProj = ProjectOBB(in a, m_Axes[i]);
Vector2 bProj = ProjectOBB(in b, m_Axes[i]);
if (aProj.y < bProj.x || bProj.y < aProj.x)
{
return false;
}
}
return true;
}
public static bool OBBContains(in ProbeReferenceVolume.Volume obb, Vector3 point)
{
float lenX2 = obb.X.sqrMagnitude;
float lenY2 = obb.Y.sqrMagnitude;
float lenZ2 = obb.Z.sqrMagnitude;
// Project in OBB space
point -= obb.corner;
point = new Vector3(Vector3.Dot(point, obb.X), Vector3.Dot(point, obb.Y), Vector3.Dot(point, obb.Z));
return (0.0f < point.x && point.x < lenX2) && (0.0f < point.y && point.y < lenY2) && (0.0f < point.z && point.z < lenZ2);
}
// Test between a OBB and an AABB. The AABB of the OBB is requested to avoid recalculating it
public static bool OBBAABBIntersect(in ProbeReferenceVolume.Volume a, in Bounds b, in Bounds aAABB)
{
// First perform fast AABB test
if (!aAABB.Intersects(b))
return false;
// Perform complex OBB test
Vector3 boundsMin = b.min, boundsMax = b.max;
m_AABBCorners[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMin.z);
m_AABBCorners[1] = new Vector3(boundsMax.x, boundsMin.y, boundsMin.z);
m_AABBCorners[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMin.z);
m_AABBCorners[3] = new Vector3(boundsMin.x, boundsMax.y, boundsMin.z);
m_AABBCorners[4] = new Vector3(boundsMin.x, boundsMin.y, boundsMax.z);
m_AABBCorners[5] = new Vector3(boundsMax.x, boundsMin.y, boundsMax.z);
m_AABBCorners[6] = new Vector3(boundsMax.x, boundsMax.y, boundsMax.z);
m_AABBCorners[7] = new Vector3(boundsMin.x, boundsMax.y, boundsMax.z);
m_Axes[0] = a.X.normalized;
m_Axes[1] = a.Y.normalized;
m_Axes[2] = a.Z.normalized;
for (int i = 0; i < 3; i++)
{
Vector2 aProj = ProjectOBB(in a, m_Axes[i]);
Vector2 bProj = ProjectAABB(m_AABBCorners, m_Axes[i]);
if (aProj.y < bProj.x || bProj.y < aProj.x)
{
return false;
}
}
return true;
}
static Vector2 ProjectOBB(in ProbeReferenceVolume.Volume a, Vector3 axis)
{
float min = Vector3.Dot(axis, a.corner);
float max = min;
for (int x = 0; x < 2; x++)
{
for (int y = 0; y < 2; y++)
{
for (int z = 0; z < 2; z++)
{
Vector3 vert = a.corner + a.X * x + a.Y * y + a.Z * z;
float proj = Vector3.Dot(axis, vert);
if (proj < min)
{
min = proj;
}
else if (proj > max)
{
max = proj;
}
}
}
}
return new Vector2(min, max);
}
static Vector2 ProjectAABB(in Vector3[] corners, Vector3 axis)
{
float min = Vector3.Dot(axis, corners[0]);
float max = min;
for (int i = 1; i < 8; i++)
{
float proj = Vector3.Dot(axis, corners[i]);
if (proj < min) min = proj;
else if (proj > max) max = proj;
}
return new Vector2(min, max);
}
}
}