八叉树碰撞检测是一种在三维空间中高效处理物体碰撞检测的算法,其原理可以类比为一个管理三维空间物体的智能系统。这个示例包含两个部分:八叉树部分用于宏观检测,AABB用于微观检测。AABB可以更换为均值或节点检测来提高检测精度。
#include
#include
#include
// 定义三维向量结构体
struct Vec3 {
float x, y, z;
Vec3(float x = 0, float y = 0, float z = 0) : x(x), y(y), z(z) {}
};
// 定义 AABB 结构体
struct AABB {
Vec3 min;
Vec3 max;
AABB(const Vec3& min, const Vec3& max) : min(min), max(max) {}
// 判断两个 AABB 是否相交
bool intersects(const AABB& other) const {
return (min.x <= other.max.x && max.x >= other.min.x) &&
(min.y <= other.max.y && max.y >= other.min.y) &&
(min.z <= other.max.z && max.z >= other.min.z);
}
};
// 定义八叉树节点类
class OctreeNode {
public:
AABB bounds;
std::vector<AABB> objects;
std::vector<std::unique_ptr<OctreeNode>> children;
OctreeNode(const AABB& bounds) : bounds(bounds) {}
// 插入 AABB 到节点中
void insert(const AABB& object) {
if (children.empty()) {
if (objects.size() < 8) {
objects.push_back(object);
} else {
split();
insert(object);
}
} else {
for (auto& child : children) {
if (child->bounds.intersects(object)) {
child->insert(object);
}
}
}
}
// 分割节点
void split() {
Vec3 center((bounds.min.x + bounds.max.x) / 2, (bounds.min.y + bounds.max.y) / 2, (bounds.min.z + bounds.max.z) / 2);
children.resize(8);
children[0] = std::make_unique<OctreeNode>(AABB(bounds.min, center));
children[1] = std::make_unique<OctreeNode>(AABB(Vec3(center.x, bounds.min.y, bounds.min.z), Vec3(bounds.max.x, center.y, center.z)));
children[2] = std::make_unique<OctreeNode>(AABB(Vec3(bounds.min.x, center.y, bounds.min.z), Vec3(center.x, bounds.max.y, center.z)));
children[3] = std::make_unique<OctreeNode>(AABB(Vec3(center.x, center.y, bounds.min.z), Vec3(bounds.max.x, bounds.max.y, center.z)));
children[4] = std::make_unique<OctreeNode>(AABB(Vec3(bounds.min.x, bounds.min.y, center.z), Vec3(center.x, center.y, bounds.max.z)));
children[5] = std::make_unique<OctreeNode>(AABB(Vec3(center.x, bounds.min.y, center.z), Vec3(bounds.max.x, center.y, bounds.max.z)));
children[6] = std::make_unique<OctreeNode>(AABB(Vec3(bounds.min.x, center.y, center.z), Vec3(center.x, bounds.max.y, bounds.max.z)));
children[7] = std::make_unique<OctreeNode>(AABB(center, bounds.max));
for (const auto& object : objects) {
for (auto& child : children) {
if (child->bounds.intersects(object)) {
child->insert(object);
}
}
}
objects.clear();
}
// 检测与指定 AABB 的碰撞
void query(const AABB& object, std::vector<AABB>& result) const {
if (bounds.intersects(object)) {
for (const auto& obj : objects) {
if (obj.intersects(object)) {
result.push_back(obj);
}
}
for (const auto& child : children) {
child->query(object, result);
}
}
}
};
// 定义八叉树类
class Octree {
public:
std::unique_ptr<OctreeNode> root;
Octree(const AABB& bounds) : root(std::make_unique<OctreeNode>(bounds)) {}
// 插入 AABB 到八叉树中
void insert(const AABB& object) {
root->insert(object);
}
// 检测与指定 AABB 的碰撞
std::vector<AABB> query(const AABB& object) const {
std::vector<AABB> result;
root->query(object, result);
return result;
}
};
// 示例使用
int main() {
// 定义八叉树的边界
AABB octreeBounds(Vec3(0, 0, 0), Vec3(100, 100, 100));
Octree octree(octreeBounds);
// 插入一些 AABB
octree.insert(AABB(Vec3(10, 10, 10), Vec3(20, 20, 20)));
octree.insert(AABB(Vec3(30, 30, 30), Vec3(40, 40, 40)));
// 定义一个查询的 AABB
AABB queryAABB(Vec3(15, 15, 15), Vec3(25, 25, 25));
// 进行碰撞检测
std::vector<AABB> collisions = octree.query(queryAABB);
// 输出碰撞结果
std::cout << "Collisions found: " << collisions.size() << std::endl;
for (const auto& collision : collisions) {
std::cout << "Collision: min(" << collision.min.x << ", " << collision.min.y << ", " << collision.min.z << "), max("
<< collision.max.x << ", " << collision.max.y << ", " << collision.max.z << ")" << std::endl;
}
return 0;
}