3#include <SDL2/SDL_rect.h>
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");
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) {
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);
24inline bool checkCollision(
const SDL_FRect& recA,
const SDL_Rect& recB) {
25 return checkCollision(recB, recA);
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) {
32 glm::vec3 paddedHalfSizeA = halfSizeA + glm::vec3(padding);
33 glm::vec3 paddedHalfSizeB = halfSizeB + glm::vec3(padding);
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);
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));
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) {
54 float denom = glm::dot(planeNormal, rayDirection);
57 if (std::abs(denom) < 1e-6) {
62 float t = glm::dot(planeNormal, planePoint - rayOrigin) / denom;
70 glm::vec3 intersectionPoint = rayOrigin + t * rayDirection;
73 if (intersectionPoint.x >= xMin && intersectionPoint.x <= xMax &&
74 intersectionPoint.y >= yMin && intersectionPoint.y <= yMax) {
82inline bool rayIntersectsSphere(
83 const glm::vec3& rayOrigin,
84 const glm::vec3& rayDirection,
85 const glm::vec3& sphereCenter,
89 glm::vec3 oc = rayOrigin - sphereCenter;
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;
95 float discriminant = B * B - 4 * A * C;
97 if (discriminant < 0) {
102 float sqrtDiscriminant = sqrt(discriminant);
103 float t0 = (-B - sqrtDiscriminant) / (2.0f * A);
104 float t1 = (-B + sqrtDiscriminant) / (2.0f * A);
107 t = rayOrigin + t0 * rayDirection;
111 t = rayOrigin + t1 * rayDirection;
118inline bool sphereIntersectsBox(
119 const glm::vec3& sphereCenter,
float sphereRadius,
120 const glm::vec3& boxMin,
const glm::vec3& boxMax,
121 glm::vec3& intersectionPoint)
123 glm::vec3 closestPoint = glm::clamp(sphereCenter, boxMin, boxMax);
125 intersectionPoint = closestPoint;
127 glm::vec3 diff = closestPoint - sphereCenter;
128 float distanceSquared = glm::dot(diff, diff);
130 return distanceSquared <= (sphereRadius * sphereRadius);
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,
141 float sphereRad = glm::distance(boxMin, boxMax)/ 2.0f;
146 for (
float t = 0.0f; t < m_maxT; t += sphereRad) {
147 glm::vec3 samplePoint = rayOrigin + t * rayDirection;
149 if (sphereIntersectsBox(
150 samplePoint, sphereRad,
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,
172 for (
float t = m_minT; t < m_maxT; t += m_sphereRad) {
173 m_sphereRad += 0.005f;
174 glm::vec3 samplePoint = rayOrigin + t * rayDirection;
176 glm::vec3 lineLength = segmentEnd - segmentStart;
178 glm::vec3 lineDir = glm::normalize(lineLength);
179 glm::vec3 t_temp(0.0f);
181 if (rayIntersectsSphere(segmentStart, lineDir, samplePoint, m_sphereRad, t_temp)) {
182 if(glm::distance(segmentStart, t_temp) < glm::distance(segmentEnd, segmentStart))
189inline bool checkCircleLineCollision(glm::vec2 center,
int circleRadius, glm::vec2 lineStartPoint, glm::vec2 lineEndPoint) {
190 float dist = pointLineDistance(center, lineStartPoint, lineEndPoint);
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);
197 t = std::max(0.0f, std::min(1.0f, t));
199 float closestX = lineStartPoint.x + t * dx;
200 float closestY = lineStartPoint.y + t * dy;
202 float distanceToCircle = std::sqrt((closestX - center.x) * (closestX - center.x) +
203 (closestY - center.y) * (closestY - center.y));
204 return distanceToCircle <= circleRadius;