1. 程式人生 > >AABB包圍盒演算法

AABB包圍盒演算法

因為用到了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;
}