TazGraph Project v0.1.0
Loading...
Searching...
No Matches
AABB.h
1#pragma once
2#include <glm/glm.hpp>
3#include <SDL2/SDL_rect.h>
4#include <type_traits>
5
6template<typename RectType>
7inline bool checkCollision(const RectType& recA, const RectType& recB) {
8 static_assert(std::is_same<RectType, SDL_Rect>::value || std::is_same<RectType, SDL_FRect>::value,
9 "checkCollision: RectType must be either SDL_Rect or SDL_FRect");
10
11 if (recA.x >= recB.x + recB.w || recA.x + recA.w <= recB.x ||
12 recA.y >= recB.y + recB.h || recA.y + recA.h <= recB.y) {
13 return false; // no collision
14 }
15 return true;
16}
17
18inline bool checkCollision(const SDL_Rect& recA, const SDL_FRect& recB) {
19 SDL_FRect convertedA = { static_cast<float>(recA.x), static_cast<float>(recA.y),
20 static_cast<float>(recA.w), static_cast<float>(recA.h) };
21 return checkCollision(convertedA, recB);
22}
23
24inline bool checkCollision(const SDL_FRect& recA, const SDL_Rect& recB) {
25 return checkCollision(recB, recA);
26}
27
28inline bool checkCollision3D(const glm::vec3& centerA, const glm::vec3& halfSizeA,
29 const glm::vec3& centerB, const glm::vec3& halfSizeB,
30 float padding = 0.0f) {
31
32 glm::vec3 paddedHalfSizeA = halfSizeA + glm::vec3(padding);
33 glm::vec3 paddedHalfSizeB = halfSizeB + glm::vec3(padding);
34
35
36 return !(centerA.x + paddedHalfSizeA.x <= centerB.x - paddedHalfSizeB.x ||
37 centerA.x - paddedHalfSizeA.x >= centerB.x + paddedHalfSizeB.x ||
38 centerA.y + paddedHalfSizeA.y <= centerB.y - paddedHalfSizeB.y ||
39 centerA.y - paddedHalfSizeA.y >= centerB.y + paddedHalfSizeB.y ||
40 centerA.z + paddedHalfSizeA.z <= centerB.z - paddedHalfSizeB.z ||
41 centerA.z - paddedHalfSizeA.z >= centerB.z + paddedHalfSizeB.z);
42}
43
44inline float pointLineDistance(glm::vec2 point, glm::vec2 lineStartPoint, glm::vec2 lineEndPoint) {
45 float num = std::abs((lineEndPoint.y - lineStartPoint.y) * point.x - (lineEndPoint.x - lineStartPoint.x) * point.y + lineEndPoint.x * lineStartPoint.y - lineEndPoint.y * lineStartPoint.x);
46 float den = std::sqrt((lineEndPoint.y - lineStartPoint.y) * (lineEndPoint.y - lineStartPoint.y) + (lineEndPoint.x - lineStartPoint.x) * (lineEndPoint.x - lineStartPoint.x));
47 return num / den;
48}
49
50inline bool rayIntersectsRectangle(const glm::vec3& rayOrigin, const glm::vec3& rayDirection,
51 const glm::vec3& planePoint, const glm::vec3& planeNormal,
52 float xMin, float xMax, float yMin, float yMax) {
53 // Step 1: Check if the ray intersects the plane
54 float denom = glm::dot(planeNormal, rayDirection);
55
56 // If denom == 0, the ray is parallel to the plane
57 if (std::abs(denom) < 1e-6) {
58 return false; // No intersection
59 }
60
61 // Calculate t
62 float t = glm::dot(planeNormal, planePoint - rayOrigin) / denom;
63
64 // If t < 0, the intersection is behind the ray origin
65 if (t < 0) {
66 return false;
67 }
68
69 // Calculate the intersection point
70 glm::vec3 intersectionPoint = rayOrigin + t * rayDirection;
71
72 // Step 2: Check if the intersection point lies within the rectangle bounds
73 if (intersectionPoint.x >= xMin && intersectionPoint.x <= xMax &&
74 intersectionPoint.y >= yMin && intersectionPoint.y <= yMax) {
75 return true; // Intersection point is within the rectangle
76 }
77
78 return false; // Intersection point is outside the rectangle
79}
80
81
82inline bool rayIntersectsSphere(
83 const glm::vec3& rayOrigin,
84 const glm::vec3& rayDirection,
85 const glm::vec3& sphereCenter,
86 float radius,
87 glm::vec3& t
88) {
89 glm::vec3 oc = rayOrigin - sphereCenter;
90
91 float A = glm::dot(rayDirection, rayDirection);
92 float B = 2.0f * glm::dot(oc, rayDirection);
93 float C = glm::dot(oc, oc) - radius * radius;
94
95 float discriminant = B * B - 4 * A * C;
96
97 if (discriminant < 0) {
98 return false; // No intersection
99 }
100
101 // Compute the closest valid t value
102 float sqrtDiscriminant = sqrt(discriminant);
103 float t0 = (-B - sqrtDiscriminant) / (2.0f * A);
104 float t1 = (-B + sqrtDiscriminant) / (2.0f * A);
105
106 if (t0 >= 0) {
107 t = rayOrigin + t0 * rayDirection; // Closest intersection point
108 return true;
109 }
110 else if (t1 >= 0) {
111 t = rayOrigin + t1 * rayDirection; // Intersection behind the ray origin
112 return true;
113 }
114
115 return false;
116}
117
118inline bool sphereIntersectsBox(
119 const glm::vec3& sphereCenter, float sphereRadius,
120 const glm::vec3& boxMin, const glm::vec3& boxMax,
121 glm::vec3& intersectionPoint)
122{
123 glm::vec3 closestPoint = glm::clamp(sphereCenter, boxMin, boxMax);
124
125 intersectionPoint = closestPoint;
126
127 glm::vec3 diff = closestPoint - sphereCenter;
128 float distanceSquared = glm::dot(diff, diff);
129
130 return distanceSquared <= (sphereRadius * sphereRadius);
131}
132
133inline bool rayIntersectsBox(
134 const glm::vec3& rayOrigin,
135 const glm::vec3& rayDirection,
136 const glm::vec3& boxMin, const glm::vec3& boxMax,
137 glm::vec3& intersectionPoint,
138 float m_maxT
139) {
140
141 float sphereRad = glm::distance(boxMin, boxMax)/ 2.0f;
142
143
144
145
146 for (float t = 0.0f; t < m_maxT; t += sphereRad) {
147 glm::vec3 samplePoint = rayOrigin + t * rayDirection;
148
149 if (sphereIntersectsBox(
150 samplePoint, sphereRad,
151 boxMin, boxMax,
152 intersectionPoint
153 )) {
154 return true;
155 }
156 }
157 return false;
158
159}
160
161
162inline bool rayIntersectsLineSegment(
163 const glm::vec3& rayOrigin,
164 const glm::vec3& rayDirection,
165 const glm::vec3& segmentStart,
166 const glm::vec3& segmentEnd,
167 glm::vec3& intersectionPoint,
168 float m_minT,
169 float m_maxT,
170 float m_sphereRad
171) {
172 for (float t = m_minT; t < m_maxT; t += m_sphereRad) {
173 m_sphereRad += 0.005f;
174 glm::vec3 samplePoint = rayOrigin + t * rayDirection;
175
176 glm::vec3 lineLength = segmentEnd - segmentStart;
177
178 glm::vec3 lineDir = glm::normalize(lineLength);
179 glm::vec3 t_temp(0.0f);
180
181 if (rayIntersectsSphere(segmentStart, lineDir, samplePoint, m_sphereRad, t_temp)) {
182 if(glm::distance(segmentStart, t_temp) < glm::distance(segmentEnd, segmentStart))
183 return true;
184 }
185 }
186 return false;
187}
188
189inline bool checkCircleLineCollision(glm::vec2 center, int circleRadius, glm::vec2 lineStartPoint, glm::vec2 lineEndPoint) {
190 float dist = pointLineDistance(center, lineStartPoint, lineEndPoint);
191
192 if (dist <= circleRadius) {
193 float dx = lineEndPoint.x - lineStartPoint.x;
194 float dy = lineEndPoint.y - lineStartPoint.y;
195 float t = ((center.x - lineStartPoint.x) * dx + (center.y - lineStartPoint.y) * dy) / (dx * dx + dy * dy);
196
197 t = std::max(0.0f, std::min(1.0f, t));
198
199 float closestX = lineStartPoint.x + t * dx;
200 float closestY = lineStartPoint.y + t * dy;
201
202 float distanceToCircle = std::sqrt((closestX - center.x) * (closestX - center.x) +
203 (closestY - center.y) * (closestY - center.y));
204 return distanceToCircle <= circleRadius;
205 }
206
207 return false;
208}