AABB包围盒算法

时间:2022-02-06 15:16:46

因为用到了Ogre的Vector3,所以首先需要配置Ogre的环境,在这里不再赘述。

下面这是AABB头文件: aabb.h

#ifndef AABB3_H
#define AABB3_H

#include "OgreOde_Core.h"
#include "OgreOde_Prefab.h"
#include "OgreOde_Loader.h"

class cAABB3
{
public:
Ogre::Vector3 min,max;
public:
//query for dimentions
Ogre::Vector3 size() const {return max - min;}
Ogre::Real x_size() {return max.x - min.x;}
Ogre::Real y_size() {return max.y - min.y;}
Ogre::Real z_size() {return max.z - min.z;}
Ogre::Vector3 center() const {return (min + max)*0.5f;}
//返回8个顶点中的一个
Ogre::Vector3 corner(int i) const;

//清空包围盒
void empty();

//add a point to the box
void add(const Ogre::Vector3 &p);
//add an AABB to the box
void add(const cAABB3 &box);
//return true if the box is empty
bool is_empty() const;
//return true if the box contains a point
bool contains(const Ogre::Vector3 &p) const;
//return the clostet point on this box to another point
Ogre::Vector3 clostet_point_to(const Ogre::Vector3 &p) const;
};
#endif

下面是AABB的实现:aabb.cpp

#include "aabb.h"

//Empty the box, by setting the values to really large/small numbers
void cAABB3::empty()
{
const Ogre::Real big_number = 1e37f;
min.x = min.y = min.z = big_number;
max.x = max.y = max.z = -big_number;
}
//Add a point to the box
void cAABB3::add(const Ogre::Vector3 &p)
{
//expand the box as necessary to contain the point
if(p.x < min.x)
min.x = p.x;
if(p.x > max.x)
max.x = p.x;
if(p.y < min.y)
min.y = p.y;
if(p.y > max.y)
max.y = p.y;
if(p.z < min.z)
min.z = p.z;
if(p.z > max.z)
max.z = p.z;
}
//return one of the 8 corner points.
//Bit 0 selects min.x vs max.x
//bit 1 selects min.y vs max.y
//bit 2 selects min.z vs max.z
Ogre::Vector3 cAABB3::corner(int i) const
{
assert(i >= 0 && i <= 7); //make sure index is in range
return Ogre::Vector3((i&1)?max.x:min.y,
(i&2)?max.y:min.y,(i&4)?max.z:min.z);
}
//add an AABB to the box
void cAABB3::add(const cAABB3 &box)
{
//expand the box as necessary
if(box.min.x < min.x)
min.x = box.min.x;
if(box.max.x > max.x)
max.x = box.max.x;
if(box.min.y < min.y)
min.y = box.min.y;
if(box.max.y > max.y)
max.y = box.max.y;
if(box.min.z < min.z)
min.z = box.min.z;
if(box.max.z > max.z)
max.z = box.max.z;
}
//return true if the box is empty
bool cAABB3::is_empty() const
{
//check if we're inverted on any axis
return (min.x>max.x)||(min.y>max.y)||(min.z>max.z);
}
//return true if the box contains a point
bool cAABB3::contains(const Ogre::Vector3 &p) const
{
//check for overlap on each axis
return (p.x>=min.x)&&(p.x<=max.x)&&(p.y>=min.y)&&
(p.y<=max.y)&&(p.z>=min.z)&&(p.z<=max.z);
}
//return the closest point on this box to another point
Ogre::Vector3 cAABB3::clostet_point_to(const Ogre::Vector3 &p) const
{
//push p into the box, on each dimension
Ogre::Vector3 r;
if(p.x < min.x)
r.x = min.x;
else if(p.x > max.x)
r.x = max.x;
else
r.x = p.x;

if(p.y < min.y)
r.y = min.y;
else if(p.y > max.y)
r.y = max.y;
else
r.y = p.y;

if(p.z < min.z)
r.z = min.z;
else if(p.z > max.z)
r.z = max.z;
else
r.z = p.z;

return r;
}


下面是主函数:main.cpp

#include <iostream>

#include "aabb.h"

int main()
{
const int N = 10;
Ogre::Vector3 list[N] = {Ogre::Vector3(0,0,0),Ogre::Vector3(1,0,0),Ogre::Vector3(2,0,0),
Ogre::Vector3(3,0,0),Ogre::Vector3(4,0,0),Ogre::Vector3(10,10,10),
Ogre::Vector3(10,0,10),Ogre::Vector3(0,0,10),Ogre::Vector3(0,10,0),
Ogre::Vector3(0,10,10)};
cAABB3 box;
box.empty();

for(int i = 0; i != N; i++)
{
box.add(list[i]);
}
std::cout<<"box size: "<<box.size()<<std::endl;
std::cout<<"box x_size: "<<box.x_size()<<std::endl;
std::cout<<"box y_size: "<<box.y_size()<<std::endl;
std::cout<<"box z_size: "<<box.z_size()<<std::endl;
std::cout<<"box center: "<<box.center()<<std::endl;

std::cout<<"box corner 0: "<<box.corner(0)<<std::endl;
std::cout<<"box corner 1: "<<box.corner(1)<<std::endl;
std::cout<<"box corner 2: "<<box.corner(2)<<std::endl;
std::cout<<"box corner 3: "<<box.corner(3)<<std::endl;
std::cout<<"box corner 4: "<<box.corner(4)<<std::endl;
std::cout<<"box corner 5: "<<box.corner(5)<<std::endl;
std::cout<<"box corner 6: "<<box.corner(6)<<std::endl;
std::cout<<"box corner 7: "<<box.corner(7)<<std::endl;

std::cout<<"box is empty: "<<(box.is_empty()?"true":"false")<<std::endl;
std::cout<<"box contains p? "<<(box.contains(Ogre::Vector3(-1,-2,-3))?"true":"false")<<std::endl;
std::cout<<"box contains p? "<<(box.contains(Ogre::Vector3(1,2,3))?"true":"false")<<std::endl;
std::cout<<"box contains p? "<<(box.contains(Ogre::Vector3(11,12,13))?"true":"false")<<std::endl;

std::cout<<"box clostet to point p: "<<box.clostet_point_to(Ogre::Vector3(-1,-2,-3))<<std::endl;
std::cout<<"box clostet to point p: "<<box.clostet_point_to(Ogre::Vector3(1,2,3))<<std::endl;
std::cout<<"box clostet to point p: "<<box.clostet_point_to(Ogre::Vector3(11,12,13))<<std::endl;
return 0;
}