Added a (temp) collision solver for Axis-Aligned rectangles

This commit is contained in:
Bram Verhulst
2024-03-12 12:21:17 +01:00
parent e474a7815a
commit d0781db9f0
11 changed files with 252 additions and 38 deletions

View File

@@ -686,9 +686,87 @@ bool utils::IntersectRectLine(const Rectf& r, const Point2f& p1, const Point2f&
intersectMax = tMax;
return true;
}
bool utils::IsRectInRect(const Rectf& r1, const Rectf& r2) {
// the origin of both rectangles is in bottom left
return (r1.left < r2.left + r2.width && r1.left + r1.width > r2.left && r1.bottom < r2.bottom + r2.height && r1.bottom + r1.height > r2.bottom);
}
bool utils::RayVsRect(const Point2f& rayOrigin, const Point2f& rayDir, const Rectf& target,
Point2f& contactPoint, Point2f& contactNormal, float& t_hit_near) {
Point2f t_near = Point2f{(target.BottomLeft() - rayOrigin).x / rayDir.x, (target.BottomLeft() - rayOrigin).y / rayDir.y};
Point2f t_far = Point2f{(target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).x / rayDir.x, (target.BottomLeft() + Point2f{target.width, target.height} - rayOrigin).y / rayDir.y};
if(std::isnan(t_far.y) || std::isnan(t_far.x)) return false;
if(std::isnan(t_near.y) || std::isnan(t_near.x)) return false;
if (t_near.x > t_far.x) std::swap(t_near.x, t_far.x);
if (t_near.y > t_far.y) std::swap(t_near.y, t_far.y);
if (t_near.x > t_far.y || t_near.y > t_far.x) return false;
t_hit_near = std::max(t_near.x, t_near.y);
float t_hit_far = std::min(t_far.x, t_far.y);
if (t_hit_far < 0) return false;
contactPoint = rayOrigin + rayDir * t_hit_near;
if(t_near.x > t_near.y) {
if(rayDir.x < 0) {
contactNormal = Point2f{1, 0};
}else {
contactNormal = Point2f{-1, 0};
}
} else if(t_near.x < t_near.y) {
if(rayDir.y < 0) {
contactNormal = Point2f{0, 1};
}else {
contactNormal = Point2f{0, -1};
}
}
return true;
}
bool utils::DynamicRectVsRect(const MovingRectf& in, const Rectf& target, Point2f& contactPoint, Point2f& contactNormal, float& contactTime, float dt) {
if(in.velocity.x == 0 && in.velocity.y == 0) return false;
Rectf expanded_target{};
expanded_target.left = target.left - in.width / 2;
expanded_target.bottom = target.bottom - in.height / 2;
expanded_target.width = target.width + in.width;
expanded_target.height = target.height + in.height;
if(RayVsRect(Point2f{in.bottomLeft.x + in.width / 2, in.bottomLeft.y + in.height / 2}, in.velocity * dt, expanded_target, contactPoint, contactNormal, contactTime)) {
if(contactTime <= 1.0f && contactTime >= 0.0f) {
return true;
}
}
return false;
}
float utils::DotProduct(const Point2f& a, const Point2f& b) {
return a.x * b.x + a.y * b.y;
}
#pragma endregion CollisionFunctionality
int utils::randRange(int min, int max) {
return min + rand() % (( max + 1 ) - min);
}
bool utils::isKeyDown(int keycode) {
const Uint8* pStates = SDL_GetKeyboardState(nullptr);
if (pStates != nullptr)
{
if(pStates[keycode]) {
return true;
}
}
return false;
}
bool utils::isMouseDown(int button) {
const Uint32 pStates = SDL_GetMouseState(nullptr, nullptr);
if (pStates & SDL_BUTTON(button)) {
return true;
}
return false;
}