#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, ¤tCorner, &mat); AddInternalPoint(tmpVec); // min,min,max currentCorner.z = oldMax.z; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // min max max currentCorner.y = oldMax.y; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // min max min currentCorner.z = oldMin.z; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // max max min currentCorner.x = oldMax.x; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // max max max currentCorner.z = oldMax.z; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // max min max currentCorner.y = oldMin.y; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &mat); AddInternalPoint(tmpVec); // max min min currentCorner.z = oldMin.z; D3DXVec3TransformCoord(&tmpVec, ¤tCorner, &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; }