2#include <glm/gtx/component_wise.hpp>
5#include "../../graphics/components/Axis.h"
13 return NodeIndex{
static_cast<int>(nodes.size() - 1)};
16void BVH::build(std::vector<Physics::PhysicsBody*> bodies) {
18 if (bodies.empty())
return;
19 nodes.reserve(bodies.size() * 2);
28 if (end.
val - start.
val == 1) {
33 std::unique_ptr<Physics::Bounding::ICollider> worldCollider =
36 glm::vec3 minCorner = worldCollider->getAABBMin();
37 glm::vec3 maxCorner = worldCollider->getAABBMax();
39 glm::vec3 center = (minCorner + maxCorner) * 0.5f;
40 glm::vec3 halfExtents = (maxCorner - minCorner) * 0.5f;
50 for (
int i = start.
val + 1; i < end.
val; i++) {
52 centroidMin = glm::min(centroidMin, pos);
53 centroidMax = glm::max(centroidMax, pos);
57 glm::vec3 extent = centroidMax - centroidMin;
59 if (extent.y > extent.x) splitAxis =
Axis::Y;
60 if (extent.z > extent[splitAxis]) splitAxis =
Axis::Z;
63 int mid = start.
val + (end.
val - start.
val) / 2;
65 bodies.begin() + start.
val,
67 bodies.begin() + end.
val,
69 return a->getPosition(BodyLock::NOLOCK)[splitAxis] <
70 b->getPosition(BodyLock::NOLOCK)[splitAxis];
76 mergedBound.expand(nodes[rightIdx.val].bounds);
79 node = nodes[nodeIdx.
val];
81 node.
right = rightIdx;
89 std::vector<std::pair<Physics::PhysicsBody*, Physics::PhysicsBody*>> potentialCollisions;
94 std::vector<std::pair<NodeIndex, NodeIndex>> stack;
98 while (!stack.empty()) {
99 auto [idxA, idxB] = stack.back();
102 const BVHNode& a = nodes[idxA.val];
103 const BVHNode& b = nodes[idxB.val];
106 if (idxA.val == idxB.val) {
123 potentialCollisions.emplace_back(a.
body, b.
body);
136 splitA = glm::compMul(extentA) > glm::compMul(extentB);
144 stack.emplace_back(a.
left, idxB);
147 stack.emplace_back(a.
right, idxB);
154 stack.emplace_back(idxA, b.
left);
157 stack.emplace_back(idxA, b.
right);
162 return potentialCollisions;
Axis
Cardinal axes for handle orientation.
std::vector< std::pair< Physics::PhysicsBody *, Physics::PhysicsBody * > > getPotentialCollisions() const
bool intersectsAABB(const AABB &other) const
glm::vec3 getAABBMin() const override
Gets the minimum, maximum corner of the axis-aligned bounding box (AABB) that contains this collider.
glm::vec3 getAABBMax() const override
Abstract base class for collision volumes in the physics engine.
virtual std::unique_ptr< ICollider > getTransformed(const glm::mat4 &modelMatrix) const =0
Creates a transformed copy of this collider in world space.
glm::mat4 getWorldTransform(BodyLock lock) const
glm::vec3 getPosition(BodyLock lock) const
virtual Bounding::ICollider * getCollider() const
Physics::PhysicsBody * body
Physics::Bounding::AABB bounds
static NodeIndex rootIndex()