Fichier source en cours : FW - AABB.cpp






Voici le code source cpp :




	#include "Framework.h"

using namespace fw;

AABB::AABB() :
m_minEdge(-1.0f, -1.0f, -1.0f),
m_maxEdge(1.0f, 1.0f, 1.0f)
{
}

AABB::AABB(const D3DXVECTOR3& min, const D3DXVECTOR3& max) :
m_minEdge(min),
m_maxEdge(max)
{
}

AABB::~AABB()
{
}

D3DXVECTOR3 AABB::GetCenter()
{
	return (m_minEdge + m_maxEdge) / 2;
}

void AABB::AddInternalPoint(const D3DXVECTOR3& p)
{
	AddInternalPoint(p.x, p.y, p.z);
}

void AABB::AddInternalPoint(float x, float y, float z)
{
	if (x > m_maxEdge.x) m_maxEdge.x = x;
	if (y > m_maxEdge.y) m_maxEdge.y = y;
	if (z > m_maxEdge.z) m_maxEdge.z = z;

	if (x < m_minEdge.x) m_minEdge.x = x;
	if (y < m_minEdge.y) m_minEdge.y = y;
	if (z < m_minEdge.z) m_minEdge.z = z;
}

void AABB::Reset(float x, float y, float z)
{
	m_maxEdge = D3DXVECTOR3(x, y, z);
	m_minEdge = m_maxEdge;
}

void AABB::Reset(const D3DXVECTOR3& initValue)
{
	m_maxEdge = initValue;
	m_minEdge = initValue;
}

void AABB::GetEdges(std::vector<D3DXVECTOR3>& edges) 
{
	const D3DXVECTOR3 middle = GetCenter();
	const D3DXVECTOR3 diag = middle - m_maxEdge;

	/*
	Edges are stored in this way:
                   /3--------/7
                  / |       / |
                 /  |      /  |
                1---------5   |
                |  /2- - -|- -6
                | /       |  /
                |/        | /
                0---------4/
	*/

	edges.clear();

	edges.push_back(D3DXVECTOR3(middle.x + diag.x, middle.y + diag.y, middle.z + diag.z));
	edges.push_back(D3DXVECTOR3(middle.x + diag.x, middle.y - diag.y, middle.z + diag.z));
	edges.push_back(D3DXVECTOR3(middle.x + diag.x, middle.y + diag.y, middle.z - diag.z));
	edges.push_back(D3DXVECTOR3(middle.x + diag.x, middle.y - diag.y, middle.z - diag.z));
	edges.push_back(D3DXVECTOR3(middle.x - diag.x, middle.y + diag.y, middle.z + diag.z));
	edges.push_back(D3DXVECTOR3(middle.x - diag.x, middle.y - diag.y, middle.z + diag.z));
	edges.push_back(D3DXVECTOR3(middle.x - diag.x, middle.y + diag.y, middle.z - diag.z));
	edges.push_back(D3DXVECTOR3(middle.x - diag.x, middle.y - diag.y, middle.z - diag.z));
}

D3DXVECTOR3 AABB::GetExtent() const
{
	return m_maxEdge - m_minEdge;
}

float AABB::GetVolume()
{
	D3DXVECTOR3 e = GetExtent();
	return e.x * e.y * e.z;
}
 
const D3DXVECTOR3& AABB::GetMin() const
{
	return m_minEdge;
}

const D3DXVECTOR3& AABB::GetMax() const
{
	return m_maxEdge;
}

void AABB::Translate(const D3DXVECTOR3& translate)
{
	D3DXMATRIX transform;

	D3DXMatrixTranslation(&transform, translate.x, translate.y, translate.z);

	Transform(transform);

	Repair();
}

void AABB::Scale(const D3DXVECTOR3& scale)
{
	D3DXMATRIX transform;

	D3DXMatrixScaling(&transform, scale.x, scale.y, scale.z);
	
	Transform(transform);

	Repair();
}

/* Utilise l'algortihme d'intersection Slab */
bool AABB::Intersects(const Ray& r)
{
	double t1 = (m_minEdge.x - r.x0.x) * r.n_inv.x;
	double t2 = (m_maxEdge.x - r.x0.x) * r.n_inv.x;

	double tmin = min(t1, t2);
	double tmax = max(t1, t2);

	t1 = (m_minEdge.y - r.x0.y) * r.n_inv.y;
	t2 = (m_maxEdge.y - r.x0.y) * r.n_inv.y;

	tmin = max(tmin, min(t1, t2));
	tmax = min(tmax, max(t1, t2));

	t1 = (m_minEdge.z - r.x0.z) * r.n_inv.z;
	t2 = (m_maxEdge.z - r.x0.z) * r.n_inv.z;

	tmin = max(tmin, min(t1, t2));
	tmax = min(tmax, max(t1, t2));

	return tmax > max(tmin, 0.0);
}

void AABB::Repair()
{
	float t;

	if (m_minEdge.x > m_maxEdge.x)
	{
		t = m_minEdge.x; m_minEdge.x = m_maxEdge.x; m_maxEdge.x = t;
	}
	if (m_minEdge.y > m_maxEdge.y)
	{
		t = m_minEdge.y; m_minEdge.y = m_maxEdge.y; m_maxEdge.y = t;
	}
	if (m_minEdge.z > m_maxEdge.z)
	{
		t = m_minEdge.z; m_minEdge.z = m_maxEdge.z; m_maxEdge.z = t;
	}
}

void AABB::Transform(const D3DXMATRIX& mat)
{
	D3DXVECTOR3 oldMin, oldMax, currentCorner;

	// Getting the old values so that we can use the existing merge method.
	oldMin = m_minEdge;
	oldMax = m_maxEdge;

	// reset
	Reset(0.0f, 0.0f, 0.0f);

	// We sequentially compute the corners in the following order :
	// 0, 6, 5, 1, 2, 4 ,7 , 3
	// This sequence allows us to only change one member at a time to get at all corners.

	// For each one, we transform it using the matrix
	// Which gives the resulting point and AddInternalPoint the resulting point.

	// First corner 
	// min min min
	currentCorner = oldMin;
	D3DXVECTOR3 tmpVec;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// min,min,max
	currentCorner.z = oldMax.z;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// min max max
	currentCorner.y = oldMax.y;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// min max min
	currentCorner.z = oldMin.z;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// max max min
	currentCorner.x = oldMax.x;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// max max max
	currentCorner.z = oldMax.z;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// max min max
	currentCorner.y = oldMin.y;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);

	// max min min
	currentCorner.z = oldMin.z;
	D3DXVec3TransformCoord(&tmpVec, &currentCorner, &mat);
	AddInternalPoint(tmpVec);
}

bool AABB::Contains(const AABB& other)
{
	return m_minEdge.x <= other.m_minEdge.x &&
		m_minEdge.y <= other.m_minEdge.y &&
		m_minEdge.z <= other.m_minEdge.z &&
		other.m_maxEdge.x <= m_maxEdge.x &&
		other.m_maxEdge.y <= m_maxEdge.y &&
		other.m_maxEdge.z <= m_maxEdge.z;
}