diff --git a/include/mitsuba/core/aabb.h b/include/mitsuba/core/aabb.h index 5a6c0d50..b0b66094 100644 --- a/include/mitsuba/core/aabb.h +++ b/include/mitsuba/core/aabb.h @@ -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) + */ +template 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::infinity()); + max = PointType(-std::numeric_limits::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 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 max[i]) + return false; + return true; + } + + /// Axis-aligned bounding box overlap test + inline bool overlaps(const TAABB &aabb) const { + for (int i=0; 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 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 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 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 { 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() { } /// Unserialize a bounding box from a binary data stream - inline AABB(Stream *stream) { - min = Point(stream); - max = Point(stream); - } - + inline AABB(Stream *stream) : TAABB(stream) { } + /// Create a collapsed AABB from a single point - inline AABB(const Point &p) - : min(p), max(p) { } + inline AABB(const Point &p) : TAABB(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::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(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 diff --git a/include/mitsuba/core/point.h b/include/mitsuba/core/point.h index ddf27755..cd2d43c7 100644 --- a/include/mitsuba/core/point.h +++ b/include/mitsuba/core/point.h @@ -28,6 +28,9 @@ MTS_NAMESPACE_BEGIN * \brief Parameterizable two-dimensional point data structure */ template struct TPoint2 { + typedef T ValueType; + typedef TVector2 VectorType; + T x, y; /** \brief Construct a new point without initializing it. @@ -171,6 +174,9 @@ template struct TPoint2 { stream->writeElement(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 &TPoint2::operator/=(int s) { * \brief Parameterizable three-dimensional point data structure */ template struct TPoint3 { + typedef T ValueType; + typedef TVector3 VectorType; + T x, y, z; /** \brief Construct a new point without initializing it. @@ -359,6 +368,9 @@ template struct TPoint3 { stream->writeElement(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 &TPoint3::operator/=(int s) { * \brief Parameterizable four-dimensional point data structure */ template struct TPoint4 { + typedef T ValueType; + typedef TVector4 VectorType; + T x, y, z, w; /** \brief Construct a new point without initializing it. @@ -550,6 +565,9 @@ template struct TPoint4 { stream->writeElement(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; diff --git a/include/mitsuba/core/vector.h b/include/mitsuba/core/vector.h index ad97a949..dcac0c37 100644 --- a/include/mitsuba/core/vector.h +++ b/include/mitsuba/core/vector.h @@ -28,7 +28,9 @@ MTS_NAMESPACE_BEGIN * \brief Parameterizable two-dimensional vector data structure */ template struct TVector2 { -public: + typedef T ValueType; + typedef TPoint2 PointType; + T x, y; /** \brief Construct a new vector without initializing it. @@ -166,6 +168,9 @@ public: stream->writeElement(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 &TVector2::operator/=(int s) { * \brief Parameterizable three-dimensional vector data structure */ template struct TVector3 { -public: + typedef T ValueType; + typedef TPoint3 PointType; + T x, y, z; /** \brief Construct a new vector without initializing it. @@ -354,6 +361,9 @@ public: stream->writeElement(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 &TVector3::operator/=(int s) { * \brief Parameterizable four-dimensional vector data structure */ template struct TVector4 { -public: + typedef T ValueType; + typedef TPoint4 PointType; + T x, y, z, w; /** \brief Construct a new vector without initializing it. @@ -555,6 +567,9 @@ public: stream->writeElement(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; diff --git a/src/libcore/aabb.cpp b/src/libcore/aabb.cpp index 03abbdd3..976c236c 100644 --- a/src/libcore/aabb.cpp +++ b/src/libcore/aabb.cpp @@ -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 diff --git a/src/librender/scene.cpp b/src/librender/scene.cpp index dad53b5c..18bb469c 100644 --- a/src/librender/scene.cpp +++ b/src/librender/scene.cpp @@ -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 (PluginManager::getInstance()->createObject(Camera::m_theClass, props));