Make the AABB class more general

metadata
Wenzel Jakob 2010-11-09 14:45:12 +01:00
parent 437169e4b4
commit fee7a12934
5 changed files with 272 additions and 234 deletions

View File

@ -23,103 +23,255 @@
MTS_NAMESPACE_BEGIN
/**
* \brief Generic multi-dimensional bounding box data structure
*
* Maintains a component-wise minimum and maximum position and provides
* various convenience functions to query or change them.
*
* \tparam T Underlying point data type (e.g. \ref TPoint3<float>)
*/
template <typename T> struct TAABB {
typedef T PointType;
typedef typename T::ValueType ValueType;
typedef typename T::VectorType VectorType;
/**
* \brief Create a new invalid bounding box
*
* Initializes the components of the minimum
* and maximum position to \f$\infty\f$ and \f$-\infty\f$,
* respectively.
*/
inline TAABB() {
reset();
}
/// Unserialize a bounding box from a binary data stream
inline TAABB(Stream *stream) {
min = PointType(stream);
max = PointType(stream);
}
/// Create a collapsed AABB from a single point
inline TAABB(const PointType &p)
: min(p), max(p) { }
/// Create a bounding box from two positions
inline TAABB(const PointType &min, const PointType &max)
: min(min), max(max) {
#if defined(MTS_DEBUG)
for (int i=0; i<PointType::dim(); ++i)
SAssert(min[i] <= max[i]);
#endif
}
/// Equality test
inline bool operator==(const TAABB &aabb) const {
return min == aabb.min && max == aabb.max;
}
/// Inequality test
inline bool operator!=(const TAABB &aabb) const {
return min != aabb.min || max != aabb.max;
}
/// Clip to another bounding box
inline void clip(const TAABB &aabb) {
for (int i=0; i<PointType::dim(); ++i) {
min[i] = std::max(min[i], aabb.min[i]);
max[i] = std::min(max[i], aabb.max[i]);
}
}
/**
* \brief Mark the bounding box as invalid.
*
* This operation sets the components of the minimum
* and maximum position to \f$\infty\f$ and \f$-\infty\f$,
* respectively.
*/
inline void reset() {
min = PointType( std::numeric_limits<ValueType>::infinity());
max = PointType(-std::numeric_limits<ValueType>::infinity());
}
/// Calculate the n-dimensional volume of the bounding box
inline ValueType getVolume() const {
ValueType result = 0;
for (int i=0; i<3; ++i) {
ValueType tmp = max[i] - min[i];
result += tmp*tmp;
}
return result;
}
/// Return the center point
inline PointType getCenter() const {
return (max + min) * (ValueType) 0.5;
}
/// Check whether a point lies on or inside the bounding box
inline bool contains(const PointType &vec) const {
for (int i=0; i<PointType::dim(); ++i)
if (vec[i] < min[i] || vec[i] > max[i])
return false;
return true;
}
/// Check whether a given bounding box is contained within this one
inline bool contains(const TAABB &aabb) const {
if (!isValid())
return false;
for (int i=0; i<PointType::dim(); ++i)
if (aabb.min[i] < min[i] || aabb.max[i] > max[i])
return false;
return true;
}
/// Axis-aligned bounding box overlap test
inline bool overlaps(const TAABB &aabb) const {
for (int i=0; i<PointType::dim(); ++i)
if (max[i] < aabb.min[i] || min[i] > aabb.max[i])
return false;
return true;
}
/// Expand the bounding box to contain another point
inline void expandBy(const PointType &p) {
for (int i=0; i<PointType::dim(); ++i) {
min[i] = std::min(min[i], p[i]);
max[i] = std::max(max[i], p[i]);
}
}
/// Expand the bounding box to contain another bounding box
inline void expandBy(const TAABB &aabb) {
for (int i=0; i<PointType::dim(); ++i) {
min[i] = std::min(min[i], aabb.min[i]);
max[i] = std::max(max[i], aabb.max[i]);
}
}
/// Calculate the point-AABB distance
inline ValueType distanceTo(const PointType &p) const {
ValueType result = 0;
for (int i=0; i<PointType::dim(); ++i) {
ValueType value = 0;
if (p[i] < min[i])
value = min[i] - p[i];
if (p[i] > max[i])
value = p[i] - max[i];
result += value*value;
}
return std::sqrt(result);
}
/// Return whether this bounding box is valid
inline bool isValid() const {
for (int i=0; i<PointType::dim(); ++i)
if (max[i] < min[i])
return false;
return true;
}
/**
* \brief Return whether or not this bounding box
* covers anything at all.
*
* A bounding box which only covers a single point
* is considered nonempty.
*/
inline bool isEmpty() const {
for (int i=0; i<PointType::dim(); ++i) {
if (max[i] > min[i])
return false;
}
return true;
}
/// Return the axis index with the largest associated side length
inline int getLargestAxis() const {
Vector d = max - min;
int largest = 0;
for (int i=1; i<PointType::dim(); ++i)
if (d[i] > d[largest])
largest = i;
return largest;
}
/// Return the axis index with the shortest associated side length
inline int getShortestAxis() const {
Vector d = max - min;
int shortest = 0;
for (int i=1; i<PointType::dim(); ++i)
if (d[i] < d[shortest])
shortest = i;
return shortest;
}
/**
* \brief Calculate the bounding box extents
* \return max-min
*/
inline VectorType getExtents() const {
return max - min;
}
/// Serialize this bounding box to a binary data stream
inline void serialize(Stream *stream) const {
min.serialize(stream);
max.serialize(stream);
}
/// Return a string representation of the bounding box
std::string toString() const {
std::ostringstream oss;
oss << "AABB[";
if (!isValid()) {
oss << "invalid";
} else {
oss << "min=" << min.toString()
<< ", max=" << max.toString();
}
oss << "]";
return oss.str();
}
PointType min; ///< Component-wise minimum
PointType max; ///< Component-wise maximum
};
/**
* \brief Axis-aligned bounding box data structure in three dimensions
*
* Maintains a component-wise minimum and maximum position and provides
* various convenience functions to query or change them.
*/
struct MTS_EXPORT_CORE AABB {
struct MTS_EXPORT_CORE AABB : public TAABB<Point> {
public:
Point min; ///< Component-wise minimum
Point max; ///< Component-wise maximum
/**
* \brief Construct an invalid bounding box
* \brief Create a new invalid bounding box
*
* The minimum and maximum positions will be
* initialized to \f$(\infty,\infty,\infty)\f$
* and \f$(-\infty, -\infty, -\infty)\f$, respectively.
* Initializes the components of the minimum
* and maximum position to \f$\infty\f$ and \f$-\infty\f$,
* respectively.
*/
inline AABB() {
reset();
}
inline AABB() : TAABB<Point>() { }
/// Unserialize a bounding box from a binary data stream
inline AABB(Stream *stream) {
min = Point(stream);
max = Point(stream);
}
inline AABB(Stream *stream) : TAABB<Point>(stream) { }
/// Create a collapsed AABB from a single point
inline AABB(const Point &p)
: min(p), max(p) { }
inline AABB(const Point &p) : TAABB<Point>(p) { }
/// Create a bounding box from two 3D positions
inline AABB(const Point &min, const Point &max)
: min(min), max(max) {
SAssert(min.x <= max.x
&& min.y <= max.y
&& min.z <= max.z);
}
/// Copy-constructor
inline AABB(const AABB &aabb)
: min(aabb.min), max(aabb.max) {
}
/// Assignment operator
inline AABB &operator=(const AABB &aabb) {
min = aabb.min;
max = aabb.max;
return *this;
}
/// Equality test
inline bool operator==(const AABB &aabb) const {
return min == aabb.min && max == aabb.max;
}
/// Inequality test
inline bool operator!=(const AABB &aabb) const {
return min != aabb.min || max != aabb.max;
}
/**
* \brief Mark the bounding box as invalid.
*
* This operation sets the
* minimum position to \f$(\infty,\infty,\infty)\f$ and the
* maximum position to \f$(-\infty, -\infty, -\infty)\f$.
*/
inline void reset() {
const Float inf = std::numeric_limits<Float>::infinity();
min = Point(inf, inf, inf);
max = Point(-inf, -inf, -inf);
}
/// Clip to another bounding box
inline void clip(const AABB &aabb) {
min.x = std::max(min.x, aabb.min.x);
min.y = std::max(min.y, aabb.min.y);
min.z = std::max(min.z, aabb.min.z);
max.x = std::min(max.x, aabb.max.x);
max.y = std::min(max.y, aabb.max.y);
max.z = std::min(max.z, aabb.max.z);
}
/// Return the center point
inline Point getCenter() const {
return (max + min) * (Float) 0.5;
}
/// Calculate the volume of the bounding box
inline Float getVolume() const {
Float x = max.x - min.x;
Float y = max.y - min.y;
Float z = max.z - min.z;
return x*x + y*y + z*z;
/// Create a bounding box from two positions
inline AABB(const PointType &min, const PointType &max)
: TAABB<Point>(min, max) {
}
/// Calculate the surface area of the bounding box
@ -128,74 +280,12 @@ public:
return (Float) 2.0 * (d.x*d.y + d.x*d.z + d.y*d.z);
}
/**
* \brief Calculate the bounding box extents
* \return max-min
*/
inline Vector getExtents() const {
return max - min;
}
/// Return the axis index with the largest associated side length
inline int getLargestAxis() const {
Vector d = max - min;
if (d.x >= d.y && d.x >= d.z)
return 0;
else if (d.y >= d.z)
return 1;
else
return 2;
}
/// Return the axis index with the smallest associated side length
inline int getSmallestAxis() const {
Vector d = max - min;
if (d.x <= d.y && d.x <= d.z)
return 0;
else if (d.y <= d.z)
return 1;
else
return 2;
}
/// Return whether this bounding box is valid
inline bool isValid() const {
return max.x >= min.x && max.y >= min.y && max.z >= min.z;
}
/**
* \brief Return whether or not this bounding box covers a
* nonzero amount of space
*/
inline bool isEmpty() const {
return max.x <= min.x
&& max.y <= min.y
&& max.z <= min.z;
}
/// Return the component-wise minimum point of the bounding box
inline const Point &getMinimum() const {
return min;
}
/// Return the component-wise maximum point of the bounding box
inline const Point &getMaximum() const {
return max;
}
/**
* \brief Return the position of a bounding box corner
* \param corner Requested corner index (0..7)
*/
Point getCorner(uint8_t corner) const;
/// Check whether a point lies on or inside the bounding box
bool contains(const Point &vec) const;
/// Check whether a given bounding box is contained within this one
bool contains(const AABB &aabb) const;
/**
* \brief Bounding sphere-box overlap test
*
@ -205,18 +295,6 @@ public:
*/
bool overlaps(const BSphere &sphere) const;
/// Axis-aligned bounding box overlap test
bool overlaps(const AABB &saabb) const;
/// Expand the bounding box to contain another point
void expandBy(const Point &vec);
/// Expand the bounding box to contain another bounding box
void expandBy(const AABB &aabb);
/// Calculate the point-AABB distance
Float distanceTo(const Point &p) const;
/** \brief Calculate the near and far ray-AABB intersection
* points (if they exist).
*/
@ -265,15 +343,6 @@ public:
/// Create a bounding sphere, which contains the axis-aligned box
BSphere getBSphere() const;
/// Serialize this bounding box to a binary data stream
inline void serialize(Stream *stream) const {
min.serialize(stream);
max.serialize(stream);
}
/// Return a string representation of the bounding box
std::string toString() const;
};
MTS_NAMESPACE_END

View File

@ -28,6 +28,9 @@ MTS_NAMESPACE_BEGIN
* \brief Parameterizable two-dimensional point data structure
*/
template <typename T> struct TPoint2 {
typedef T ValueType;
typedef TVector2<T> VectorType;
T x, y;
/** \brief Construct a new point without initializing it.
@ -171,6 +174,9 @@ template <typename T> struct TPoint2 {
stream->writeElement<T>(y);
}
/// Return the number of dimensions
inline static int dim() { return 2; }
/// Return a readable string representation of this point
std::string toString() const {
std::ostringstream oss;
@ -214,6 +220,9 @@ template <> inline TPoint2<int> &TPoint2<int>::operator/=(int s) {
* \brief Parameterizable three-dimensional point data structure
*/
template <typename T> struct TPoint3 {
typedef T ValueType;
typedef TVector3<T> VectorType;
T x, y, z;
/** \brief Construct a new point without initializing it.
@ -359,6 +368,9 @@ template <typename T> struct TPoint3 {
stream->writeElement<T>(z);
}
/// Return the number of dimensions
inline static int dim() { return 3; }
/// Return a readable string representation of this point
std::string toString() const {
std::ostringstream oss;
@ -403,6 +415,9 @@ template <> inline TPoint3<int> &TPoint3<int>::operator/=(int s) {
* \brief Parameterizable four-dimensional point data structure
*/
template <typename T> struct TPoint4 {
typedef T ValueType;
typedef TVector4<T> VectorType;
T x, y, z, w;
/** \brief Construct a new point without initializing it.
@ -550,6 +565,9 @@ template <typename T> struct TPoint4 {
stream->writeElement<T>(w);
}
/// Return the number of dimensions
inline static int dim() { return 4; }
/// Return a readable string representation of this point
std::string toString() const {
std::ostringstream oss;

View File

@ -28,7 +28,9 @@ MTS_NAMESPACE_BEGIN
* \brief Parameterizable two-dimensional vector data structure
*/
template <typename T> struct TVector2 {
public:
typedef T ValueType;
typedef TPoint2<T> PointType;
T x, y;
/** \brief Construct a new vector without initializing it.
@ -166,6 +168,9 @@ public:
stream->writeElement<T>(y);
}
/// Return the number of dimensions
inline static int dim() { return 2; }
/// Return a readable string representation of this vector
std::string toString() const {
std::ostringstream oss;
@ -214,7 +219,9 @@ template <> inline TVector2<int> &TVector2<int>::operator/=(int s) {
* \brief Parameterizable three-dimensional vector data structure
*/
template <typename T> struct TVector3 {
public:
typedef T ValueType;
typedef TPoint3<T> PointType;
T x, y, z;
/** \brief Construct a new vector without initializing it.
@ -354,6 +361,9 @@ public:
stream->writeElement<T>(z);
}
/// Return the number of dimensions
inline static int dim() { return 3; }
/// Return a readable string representation of this vector
std::string toString() const {
std::ostringstream oss;
@ -413,7 +423,9 @@ template <> inline TVector3<int> &TVector3<int>::operator/=(int s) {
* \brief Parameterizable four-dimensional vector data structure
*/
template <typename T> struct TVector4 {
public:
typedef T ValueType;
typedef TPoint4<T> PointType;
T x, y, z, w;
/** \brief Construct a new vector without initializing it.
@ -555,6 +567,9 @@ public:
stream->writeElement<T>(w);
}
/// Return the number of dimensions
inline static int dim() { return 4; }
/// Return a readable string representation of this vector
std::string toString() const {
std::ostringstream oss;

View File

@ -26,57 +26,6 @@ Point AABB::getCorner(uint8_t corner) const {
corner & 4 ? max.z : min.z);
}
bool AABB::contains(const Point &vec) const {
return isValid() &&
vec.x >= min.x && vec.x <= max.x &&
vec.y >= min.y && vec.y <= max.y &&
vec.z >= min.z && vec.z <= max.z;
}
bool AABB::contains(const AABB &aabb) const {
return isValid() &&
min.x <= aabb.min.x && max.x >= aabb.max.x &&
min.y <= aabb.min.y && max.y >= aabb.max.y &&
min.z <= aabb.min.z && max.z >= aabb.max.z;
}
void AABB::expandBy(const Point &vec) {
min.x = std::min(min.x, vec.x);
min.y = std::min(min.y, vec.y);
min.z = std::min(min.z, vec.z);
max.x = std::max(max.x, vec.x);
max.y = std::max(max.y, vec.y);
max.z = std::max(max.z, vec.z);
}
void AABB::expandBy(const AABB &aabb) {
min.x = std::min(min.x, aabb.min.x);
min.y = std::min(min.y, aabb.min.y);
min.z = std::min(min.z, aabb.min.z);
max.x = std::max(max.x, aabb.max.x);
max.y = std::max(max.y, aabb.max.y);
max.z = std::max(max.z, aabb.max.z);
}
Float AABB::distanceTo(const Point &p) const {
Float result = 0;
for (int i=0; i<3; ++i) {
Float value = 0;
if (p[i] < min[i])
value = min[i] - p[i];
if (p[i] > max[i])
value = p[i] - max[i];
result += value*value;
}
return std::sqrt(result);
}
bool AABB::overlaps(const AABB &aabb) const {
for (int i=0; i<3; ++i)
if (max[i] < aabb.min[i] || min[i] > aabb.max[i])
return false;
return true;
}
bool AABB::overlaps(const BSphere &sphere) const {
Float distance = 0;
@ -97,17 +46,4 @@ BSphere AABB::getBSphere() const {
return BSphere(center, (center - max).length());
}
std::string AABB::toString() const {
std::ostringstream oss;
oss << "AABB[";
if (!isValid()) {
oss << "invalid";
} else {
oss << "min=" << min.toString()
<< ", max=" << max.toString();
}
oss << "]";
return oss.str();
}
MTS_NAMESPACE_END

View File

@ -239,7 +239,7 @@ void Scene::configure() {
Float maxExtents = std::max(extents.x, extents.y);
Float distance = maxExtents/(2.0f * std::tan(45 * .5f * M_PI/180));
props.setTransform("toWorld", Transform::translate(Vector(center.x, center.y, aabb.getMinimum().z - distance)));
props.setTransform("toWorld", Transform::translate(Vector(center.x, center.y, aabb.min.z - distance)));
props.setFloat("fov", 45.0f);
m_camera = static_cast<Camera *> (PluginManager::getInstance()->createObject(Camera::m_theClass, props));