mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-27 07:57:21 +00:00
118 lines
3.7 KiB
C++
118 lines
3.7 KiB
C++
|
#include "dpCollisionChecks.h"
|
||
|
#include "dpEntity.h"
|
||
|
#include "dpShapeBase.h"
|
||
|
#include "dpShapeSphere.h"
|
||
|
#include "dpShapeBox.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
#include <algorithm>
|
||
|
|
||
|
using namespace dpCollisionChecks;
|
||
|
|
||
|
bool dpCollisionChecks::AreColliding(dpEntity* a, dpEntity* b) {
|
||
|
auto shapeA = a->GetShape();
|
||
|
auto shapeB = b->GetShape();
|
||
|
|
||
|
//Sphere to sphere collision
|
||
|
if (shapeA->GetShapeType() == dpShapeType::Sphere && shapeB->GetShapeType() == dpShapeType::Sphere) {
|
||
|
return CheckSpheres(a, b);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool dpCollisionChecks::CheckSpheres(dpEntity* a, dpEntity* b) {
|
||
|
if (!a || !b) return false;
|
||
|
|
||
|
auto posA = a->GetPosition();
|
||
|
auto distance = Vector3::DistanceSquared(posA, b->GetPosition());
|
||
|
|
||
|
auto sphereA = static_cast<dpShapeSphere*>(a->GetShape());
|
||
|
auto sphereB = static_cast<dpShapeSphere*>(b->GetShape());
|
||
|
const auto radius = sphereA->GetRadius() + sphereB->GetRadius();
|
||
|
|
||
|
if (distance <= radius * radius)
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool dpCollisionChecks::CheckBoxes(dpEntity* a, dpEntity* b) {
|
||
|
if (!a || !b) return false;
|
||
|
|
||
|
auto boxA = static_cast<dpShapeBox*>(a->GetShape());
|
||
|
auto boxB = static_cast<dpShapeBox*>(b->GetShape());
|
||
|
|
||
|
const auto& posA = a->GetPosition();
|
||
|
const auto& posB = b->GetPosition();
|
||
|
|
||
|
for (const auto& vert : boxA->GetVertices()) {
|
||
|
if (boxB->IsVertInBox(vert))
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*//Check if we're overlapping on X/Z:
|
||
|
if ((boxA->GetMaxWidth() >= boxB->GetMinWidth()) && //If our max width is greater than starting X of b
|
||
|
(boxA->GetMinWidth() <= boxB->GetMaxWidth()) && //If our start x is less than b's max width
|
||
|
(boxA->GetMaxDepth() >= boxB->GetMinDepth()) &&
|
||
|
(boxA->GetMinDepth() <= boxB->GetMaxDepth())) {
|
||
|
|
||
|
//Check if we're in the right height
|
||
|
if (boxA->GetTop() <= boxB->GetTop() && boxA->GetTop() >= boxB->GetBottom() || //If our top Y is within their minY/maxY bounds
|
||
|
boxA->GetBottom() <= boxB->GetTop() && boxA->GetBottom() >= boxB->GetBottom()) //Or our bottom Y
|
||
|
return true; //We definitely are colliding.
|
||
|
}*/
|
||
|
|
||
|
/*//Check if we're overlapping on X/Z:
|
||
|
if ((boxA->GetMaxWidth() >= posB.x) && //If our max width is greater than starting X of b
|
||
|
(posA.x <= boxB->GetMaxWidth()) && //If our start x is less than b's max width
|
||
|
(boxA->GetMaxDepth() >= posB.z) &&
|
||
|
(posA.z <= boxB->GetMaxDepth())) {
|
||
|
|
||
|
//Check if we're in the right height
|
||
|
if (boxA->GetTop() <= boxB->GetTop() && boxA->GetTop() >= posB.y || //If our top Y is within their minY/maxY bounds
|
||
|
posA.y <= boxB->GetTop() && posA.y >= posB.y) //Or our bottom Y
|
||
|
return true; //We definitely are colliding.
|
||
|
}*/
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool dpCollisionChecks::CheckSphereBox(dpEntity* a, dpEntity* b) {
|
||
|
if (!a || !b) return false;
|
||
|
|
||
|
NiPoint3 boxPos;
|
||
|
dpShapeBox* box;
|
||
|
|
||
|
NiPoint3 spherePos;
|
||
|
dpShapeSphere* sphere;
|
||
|
|
||
|
//Figure out which is the box and which is the sphere
|
||
|
if (a->GetShape()->GetShapeType() == dpShapeType::Box) {
|
||
|
box = static_cast<dpShapeBox*>(a->GetShape());
|
||
|
sphere = static_cast<dpShapeSphere*>(b->GetShape());
|
||
|
boxPos = a->GetPosition();
|
||
|
spherePos = b->GetPosition();
|
||
|
}
|
||
|
else {
|
||
|
box = static_cast<dpShapeBox*>(b->GetShape());
|
||
|
sphere = static_cast<dpShapeSphere*>(a->GetShape());
|
||
|
boxPos = b->GetPosition();
|
||
|
spherePos = a->GetPosition();
|
||
|
}
|
||
|
|
||
|
//Get closest point from the box to the sphere center by clamping
|
||
|
float x = std::max(box->m_MinX, std::min(spherePos.x, box->m_MaxX));
|
||
|
float y = std::max(box->m_MinY, std::min(spherePos.y, box->m_MaxY));
|
||
|
float z = std::max(box->m_MinZ, std::min(spherePos.z, box->m_MaxZ));
|
||
|
|
||
|
//Check the distance between that point & our sphere
|
||
|
float dX = x - spherePos.x;
|
||
|
float dY = y - spherePos.y;
|
||
|
float dZ = z - spherePos.z;
|
||
|
float distanceSquared = (dX * dX) + (dY * dY) + (dZ * dZ);
|
||
|
const float radius = sphere->GetRadius();
|
||
|
|
||
|
return distanceSquared < radius * radius;
|
||
|
}
|