Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/maths/BoundingBoxAligned.cpp
/* Copyright (C) 2012 Wildfire Games. | /* Copyright (C) 2019 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
* GNU General Public License for more details. | * GNU General Public License for more details. | ||||
* | * | ||||
* You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
/* | /* | ||||
* Axis-aligned bounding box | * Axis-aligned bounding box | ||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "BoundingBoxAligned.h" | #include "BoundingBoxAligned.h" | ||||
#include "lib/ogl.h" | |||||
#include <float.h> | |||||
#include "graphics/Frustum.h" | #include "graphics/Frustum.h" | ||||
#include "graphics/ShaderProgram.h" | #include "graphics/ShaderProgram.h" | ||||
#include "lib/ogl.h" | |||||
#include "maths/BoundingBoxOriented.h" | #include "maths/BoundingBoxOriented.h" | ||||
#include "maths/Brush.h" | #include "maths/Brush.h" | ||||
#include "maths/Matrix3D.h" | #include "maths/Matrix3D.h" | ||||
#include <limits> | |||||
const CBoundingBoxAligned CBoundingBoxAligned::EMPTY = CBoundingBoxAligned(); // initializes to an empty bound | const CBoundingBoxAligned CBoundingBoxAligned::EMPTY = CBoundingBoxAligned(); // initializes to an empty bound | ||||
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||
// RayIntersect: intersect ray with this bound; return true | // RayIntersect: intersect ray with this bound; return true | ||||
// if ray hits (and store entry and exit times), or false | // if ray hits (and store entry and exit times), or false | ||||
// otherwise | // otherwise | ||||
// note: incoming ray direction must be normalised | // note: incoming ray direction must be normalised | ||||
bool CBoundingBoxAligned::RayIntersect(const CVector3D& origin,const CVector3D& dir, | bool CBoundingBoxAligned::RayIntersect( | ||||
float& tmin,float& tmax) const | const CVector3D& origin, const CVector3D& dir, float& tmin, float& tmax) const | ||||
{ | { | ||||
float t1,t2; | float t1, t2; | ||||
float tnear,tfar; | float tnear, tfar; | ||||
if (dir[0]==0) { | if (dir[0] == 0) | ||||
{ | |||||
if (origin[0]<m_Data[0][0] || origin[0]>m_Data[1][0]) | if (origin[0] < m_Data[0][0] || origin[0] > m_Data[1][0]) | ||||
return false; | return false; | ||||
else { | else | ||||
tnear=(float) -FLT_MAX; | { | ||||
tfar=(float) FLT_MAX; | tnear = -std::numeric_limits<float>::max(); | ||||
tfar = std::numeric_limits<float>::max(); | |||||
} | |||||
} | } | ||||
} else { | else | ||||
{ | |||||
t1=(m_Data[0][0]-origin[0])/dir[0]; | t1 = (m_Data[0][0] - origin[0]) / dir[0]; | ||||
t2=(m_Data[1][0]-origin[0])/dir[0]; | t2 = (m_Data[1][0] - origin[0]) / dir[0]; | ||||
if (dir[0]<0) { | if (dir[0] < 0) | ||||
{ | |||||
tnear = t2; | tnear = t2; | ||||
tfar = t1; | tfar = t1; | ||||
} else { | } | ||||
else | |||||
{ | |||||
tnear = t1; | tnear = t1; | ||||
tfar = t2; | tfar = t2; | ||||
} | } | ||||
if (tfar<0) | if (tfar < 0) | ||||
return false; | return false; | ||||
} | } | ||||
if (dir[1]==0 && (origin[1]<m_Data[0][1] || origin[1]>m_Data[1][1])) | if (dir[1] == 0 && (origin[1] < m_Data[0][1] || origin[1] > m_Data[1][1])) | ||||
return false; | return false; | ||||
else { | else | ||||
{ | |||||
t1=(m_Data[0][1]-origin[1])/dir[1]; | t1 = (m_Data[0][1] - origin[1]) / dir[1]; | ||||
t2=(m_Data[1][1]-origin[1])/dir[1]; | t2 = (m_Data[1][1] - origin[1]) / dir[1]; | ||||
if (dir[1]<0) { | if (dir[1] < 0) | ||||
{ | |||||
if (t2>tnear) | if (t2 > tnear) | ||||
tnear = t2; | tnear = t2; | ||||
if (t1<tfar) | if (t1 < tfar) | ||||
tfar = t1; | tfar = t1; | ||||
} else { | } | ||||
else | |||||
{ | |||||
if (t1>tnear) | if (t1 > tnear) | ||||
tnear = t1; | tnear = t1; | ||||
if (t2<tfar) | if (t2 < tfar) | ||||
tfar = t2; | tfar = t2; | ||||
} | } | ||||
if (tnear>tfar || tfar<0) | if (tnear > tfar || tfar < 0) | ||||
return false; | return false; | ||||
} | } | ||||
if (dir[2]==0 && (origin[2]<m_Data[0][2] || origin[2]>m_Data[1][2])) | if (dir[2] == 0 && (origin[2] < m_Data[0][2] || origin[2] > m_Data[1][2])) | ||||
return false; | return false; | ||||
else { | else | ||||
{ | |||||
t1=(m_Data[0][2]-origin[2])/dir[2]; | t1 = (m_Data[0][2] - origin[2]) / dir[2]; | ||||
t2=(m_Data[1][2]-origin[2])/dir[2]; | t2 = (m_Data[1][2] - origin[2]) / dir[2]; | ||||
if (dir[2]<0) { | if (dir[2] < 0) | ||||
{ | |||||
if (t2>tnear) | if (t2 > tnear) | ||||
tnear = t2; | tnear = t2; | ||||
if (t1<tfar) | if (t1 < tfar) | ||||
tfar = t1; | tfar = t1; | ||||
} else { | } | ||||
else | |||||
{ | |||||
if (t1>tnear) | if (t1 > tnear) | ||||
tnear = t1; | tnear = t1; | ||||
if (t2<tfar) | if (t2 < tfar) | ||||
tfar = t2; | tfar = t2; | ||||
} | } | ||||
if (tnear>tfar || tfar<0) | if (tnear > tfar || tfar < 0) | ||||
return false; | return false; | ||||
} | } | ||||
tmin=tnear; | tmin = tnear; | ||||
tmax=tfar; | tmax = tfar; | ||||
return true; | return true; | ||||
} | } | ||||
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||
// SetEmpty: initialise this bound as empty | // SetEmpty: initialise this bound as empty | ||||
void CBoundingBoxAligned::SetEmpty() | void CBoundingBoxAligned::SetEmpty() | ||||
{ | { | ||||
m_Data[0]=CVector3D( FLT_MAX, FLT_MAX, FLT_MAX); | m_Data[0] = CVector3D::Max(); | ||||
m_Data[1]=CVector3D(-FLT_MAX,-FLT_MAX,-FLT_MAX); | m_Data[1] = CVector3D::Min(); | ||||
} | } | ||||
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||
// IsEmpty: tests whether this bound is empty | // IsEmpty: tests whether this bound is empty | ||||
bool CBoundingBoxAligned::IsEmpty() const | bool CBoundingBoxAligned::IsEmpty() const | ||||
{ | { | ||||
return (m_Data[0].X == FLT_MAX && m_Data[0].Y == FLT_MAX && m_Data[0].Z == FLT_MAX | return m_Data[0] == CVector3D::Max() && m_Data[1] == CVector3D::Min(); | ||||
&& m_Data[1].X == -FLT_MAX && m_Data[1].Y == -FLT_MAX && m_Data[1].Z == -FLT_MAX); | |||||
} | } | ||||
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||
// Transform: transform this bound by given matrix; return transformed bound | // Transform: transform this bound by given matrix; return transformed bound | ||||
// in 'result' parameter - slightly modified version of code in Graphic Gems | // in 'result' parameter - slightly modified version of code in Graphic Gems | ||||
// (can't remember which one it was, though) | // (can't remember which one it was, though) | ||||
void CBoundingBoxAligned::Transform(const CMatrix3D& m, CBoundingBoxAligned& result) const | void CBoundingBoxAligned::Transform(const CMatrix3D& m, CBoundingBoxAligned& result) const | ||||
{ | { | ||||
ENSURE(this!=&result); | ENSURE(this != &result); | ||||
for (int i=0;i<3;++i) { | for (int i = 0; i < 3; ++i) | ||||
{ | |||||
// handle translation | // handle translation | ||||
result[0][i]=result[1][i]=m(i,3); | result[0][i] = result[1][i] = m(i, 3); | ||||
// Now find the extreme points by considering the product of the | // Now find the extreme points by considering the product of the | ||||
// min and max with each component of matrix | // min and max with each component of matrix | ||||
for(int j=0;j<3;j++) { | for (int j = 0; j < 3; ++j) | ||||
{ | |||||
float a=m(i,j)*m_Data[0][j]; | float a = m(i, j) * m_Data[0][j]; | ||||
float b=m(i,j)*m_Data[1][j]; | float b = m(i, j) * m_Data[1][j]; | ||||
if (a<b) { | if (a >= b) | ||||
std::swap(a, b); | |||||
result[0][i]+=a; | result[0][i] += a; | ||||
result[1][i]+=b; | result[1][i] += b; | ||||
} else { | |||||
result[0][i]+=b; | |||||
result[1][i]+=a; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
void CBoundingBoxAligned::Transform(const CMatrix3D& transform, CBoundingBoxOriented& result) const | void CBoundingBoxAligned::Transform(const CMatrix3D& transform, CBoundingBoxOriented& result) const | ||||
{ | { | ||||
const CVector3D& pMin = m_Data[0]; | const CVector3D& pMin = m_Data[0]; | ||||
const CVector3D& pMax = m_Data[1]; | const CVector3D& pMax = m_Data[1]; | ||||
▲ Show 20 Lines • Show All 152 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator