AABB包囲ボックスアルゴリズム

3852 ワード

OgreのVector 3が使用されているので、まず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 

#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<