A game about forced loneliness, made by TACStudios
at master 133 lines 4.9 kB view raw
1namespace UnityEngine.Rendering 2{ 3 internal static class ProbeVolumePositioning 4 { 5 internal static Vector3[] m_Axes = new Vector3[6]; 6 internal static Vector3[] m_AABBCorners = new Vector3[8]; 7 8 public static bool OBBIntersect(in ProbeReferenceVolume.Volume a, in ProbeReferenceVolume.Volume b) 9 { 10 // First we test if the bounding spheres intersects, in which case we case do the more complex OBB test 11 a.CalculateCenterAndSize(out var aCenter, out var aSize); 12 b.CalculateCenterAndSize(out var bCenter, out var bSize); 13 14 var aRadius = aSize.sqrMagnitude / 2.0f; 15 var bRadius = bSize.sqrMagnitude / 2.0f; 16 if (Vector3.SqrMagnitude(aCenter - bCenter) > aRadius + bRadius) 17 return false; 18 19 m_Axes[0] = a.X.normalized; 20 m_Axes[1] = a.Y.normalized; 21 m_Axes[2] = a.Z.normalized; 22 m_Axes[3] = b.X.normalized; 23 m_Axes[4] = b.Y.normalized; 24 m_Axes[5] = b.Z.normalized; 25 26 for (int i = 0; i < 6; i++) 27 { 28 Vector2 aProj = ProjectOBB(in a, m_Axes[i]); 29 Vector2 bProj = ProjectOBB(in b, m_Axes[i]); 30 31 if (aProj.y < bProj.x || bProj.y < aProj.x) 32 { 33 return false; 34 } 35 } 36 37 return true; 38 } 39 40 public static bool OBBContains(in ProbeReferenceVolume.Volume obb, Vector3 point) 41 { 42 float lenX2 = obb.X.sqrMagnitude; 43 float lenY2 = obb.Y.sqrMagnitude; 44 float lenZ2 = obb.Z.sqrMagnitude; 45 46 // Project in OBB space 47 point -= obb.corner; 48 point = new Vector3(Vector3.Dot(point, obb.X), Vector3.Dot(point, obb.Y), Vector3.Dot(point, obb.Z)); 49 50 return (0.0f < point.x && point.x < lenX2) && (0.0f < point.y && point.y < lenY2) && (0.0f < point.z && point.z < lenZ2); 51 } 52 53 // Test between a OBB and an AABB. The AABB of the OBB is requested to avoid recalculating it 54 public static bool OBBAABBIntersect(in ProbeReferenceVolume.Volume a, in Bounds b, in Bounds aAABB) 55 { 56 // First perform fast AABB test 57 if (!aAABB.Intersects(b)) 58 return false; 59 60 // Perform complex OBB test 61 Vector3 boundsMin = b.min, boundsMax = b.max; 62 m_AABBCorners[0] = new Vector3(boundsMin.x, boundsMin.y, boundsMin.z); 63 m_AABBCorners[1] = new Vector3(boundsMax.x, boundsMin.y, boundsMin.z); 64 m_AABBCorners[2] = new Vector3(boundsMax.x, boundsMax.y, boundsMin.z); 65 m_AABBCorners[3] = new Vector3(boundsMin.x, boundsMax.y, boundsMin.z); 66 m_AABBCorners[4] = new Vector3(boundsMin.x, boundsMin.y, boundsMax.z); 67 m_AABBCorners[5] = new Vector3(boundsMax.x, boundsMin.y, boundsMax.z); 68 m_AABBCorners[6] = new Vector3(boundsMax.x, boundsMax.y, boundsMax.z); 69 m_AABBCorners[7] = new Vector3(boundsMin.x, boundsMax.y, boundsMax.z); 70 71 m_Axes[0] = a.X.normalized; 72 m_Axes[1] = a.Y.normalized; 73 m_Axes[2] = a.Z.normalized; 74 75 for (int i = 0; i < 3; i++) 76 { 77 Vector2 aProj = ProjectOBB(in a, m_Axes[i]); 78 Vector2 bProj = ProjectAABB(m_AABBCorners, m_Axes[i]); 79 80 if (aProj.y < bProj.x || bProj.y < aProj.x) 81 { 82 return false; 83 } 84 } 85 86 return true; 87 } 88 89 static Vector2 ProjectOBB(in ProbeReferenceVolume.Volume a, Vector3 axis) 90 { 91 float min = Vector3.Dot(axis, a.corner); 92 float max = min; 93 94 for (int x = 0; x < 2; x++) 95 { 96 for (int y = 0; y < 2; y++) 97 { 98 for (int z = 0; z < 2; z++) 99 { 100 Vector3 vert = a.corner + a.X * x + a.Y * y + a.Z * z; 101 102 float proj = Vector3.Dot(axis, vert); 103 104 if (proj < min) 105 { 106 min = proj; 107 } 108 else if (proj > max) 109 { 110 max = proj; 111 } 112 } 113 } 114 } 115 116 return new Vector2(min, max); 117 } 118 119 static Vector2 ProjectAABB(in Vector3[] corners, Vector3 axis) 120 { 121 float min = Vector3.Dot(axis, corners[0]); 122 float max = min; 123 for (int i = 1; i < 8; i++) 124 { 125 float proj = Vector3.Dot(axis, corners[i]); 126 if (proj < min) min = proj; 127 else if (proj > max) max = proj; 128 } 129 130 return new Vector2(min, max); 131 } 132 } 133}