A game about forced loneliness, made by TACStudios
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}