summaryrefslogtreecommitdiffstats
path: root/src/Runtime/Source/foundation/Qt3DSBounds3.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Runtime/Source/foundation/Qt3DSBounds3.h')
-rw-r--r--src/Runtime/Source/foundation/Qt3DSBounds3.h443
1 files changed, 443 insertions, 0 deletions
diff --git a/src/Runtime/Source/foundation/Qt3DSBounds3.h b/src/Runtime/Source/foundation/Qt3DSBounds3.h
new file mode 100644
index 00000000..fda4a6d4
--- /dev/null
+++ b/src/Runtime/Source/foundation/Qt3DSBounds3.h
@@ -0,0 +1,443 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_FOUNDATION_QT3DS_BOUNDS3_H
+#define QT3DS_FOUNDATION_QT3DS_BOUNDS3_H
+
+/** \addtogroup foundation
+@{
+*/
+
+#include "foundation/Qt3DSTransform.h"
+#include "foundation/Qt3DSMat33.h"
+#include "foundation/Qt3DSMat44.h"
+
+#ifndef QT3DS_DOXYGEN
+namespace qt3ds {
+#endif
+
+typedef QT3DSVec3 TNVBounds2BoxPoints[8];
+
+/**
+\brief Class representing 3D range or axis aligned bounding box.
+
+Stored as minimum and maximum extent corners. Alternate representation
+would be center and dimensions.
+May be empty or nonempty. If not empty, minimum <= maximum has to hold.
+*/
+class NVBounds3
+{
+public:
+ /**
+ \brief Default constructor, not performing any initialization for performance reason.
+ \remark Use empty() function below to construct empty bounds.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3() {}
+
+ /**
+ \brief Construct from two bounding points
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3(const QT3DSVec3 &minimum, const QT3DSVec3 &maximum);
+
+ /**
+ \brief Return empty bounds.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 empty();
+
+ /**
+ \brief returns the AABB containing v0 and v1.
+ \param v0 first point included in the AABB.
+ \param v1 second point included in the AABB.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 boundsOfPoints(const QT3DSVec3 &v0,
+ const QT3DSVec3 &v1);
+
+ /**
+ \brief returns the AABB from center and extents vectors.
+ \param center Center vector
+ \param extent Extents vector
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 centerExtents(const QT3DSVec3 &center,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief Construct from center, extent, and (not necessarily orthogonal) basis
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 basisExtent(const QT3DSVec3 &center,
+ const QT3DSMat33 &basis,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief Construct from pose and extent
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 poseExtent(const NVTransform &pose,
+ const QT3DSVec3 &extent);
+
+ /**
+ \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
+ \param[in] matrix Transform to apply, can contain scaling as well
+ \param[in] bounds The bounds to transform.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 transform(const QT3DSMat33 &matrix,
+ const NVBounds3 &bounds);
+
+ /**
+ \brief gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
+ \param[in] transform Transform to apply, can contain scaling as well
+ \param[in] bounds The bounds to transform.
+ */
+ static QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 transform(const NVTransform &transform,
+ const NVBounds3 &bounds);
+
+ /**
+ \brief Sets empty to true
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void setEmpty();
+
+ /**
+ \brief Sets infinite bounds
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void setInfinite();
+
+ /**
+ \brief expands the volume to include v
+ \param v Point to expand to.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void include(const QT3DSVec3 &v);
+
+ /**
+ \brief expands the volume to include b.
+ \param b Bounds to perform union with.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void include(const NVBounds3 &b);
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isEmpty() const;
+
+ /**
+ \brief indicates whether the intersection of this and b is empty or not.
+ \param b Bounds to test for intersection.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool intersects(const NVBounds3 &b) const;
+
+ /**
+ \brief computes the 1D-intersection between two AABBs, on a given axis.
+ \param a the other AABB
+ \param axis the axis (0, 1, 2)
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool intersects1D(const NVBounds3 &a, QT3DSU32 axis) const;
+
+ /**
+ \brief indicates if these bounds contain v.
+ \param v Point to test against bounds.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool contains(const QT3DSVec3 &v) const;
+
+ /**
+ \brief checks a box is inside another box.
+ \param box the other AABB
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isInside(const NVBounds3 &box) const;
+
+ /**
+ \brief returns the center of this axis aligned box.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getCenter() const;
+
+ /**
+ \brief get component of the box's center along a given axis
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float getCenter(QT3DSU32 axis) const;
+
+ /**
+ \brief get component of the box's extents along a given axis
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float getExtents(QT3DSU32 axis) const;
+
+ /**
+ \brief returns the dimensions (width/height/depth) of this axis aligned box.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getDimensions() const;
+
+ /**
+ \brief returns the extents, which are half of the width/height/depth.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 getExtents() const;
+
+ /**
+ \brief scales the AABB.
+ \param scale Factor to scale AABB by.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void scale(QT3DSF32 scale);
+
+ /**
+ fattens the AABB in all 3 dimensions by the given distance.
+ */
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void fatten(NVReal distance);
+
+ /**
+ checks that the AABB values are not NaN
+ */
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool isFinite() const;
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void expand(TNVBounds2BoxPoints &outPoints) const;
+
+ QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void transform(const QT3DSMat44 &inMatrix);
+
+ QT3DSVec3 minimum, maximum;
+};
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3::NVBounds3(const QT3DSVec3 &minimum, const QT3DSVec3 &maximum)
+ : minimum(minimum)
+ , maximum(maximum)
+{
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::empty()
+{
+ return NVBounds3(QT3DSVec3(QT3DS_MAX_REAL), QT3DSVec3(-QT3DS_MAX_REAL));
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isFinite() const
+{
+ return minimum.isFinite() && maximum.isFinite();
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::boundsOfPoints(const QT3DSVec3 &v0,
+ const QT3DSVec3 &v1)
+{
+ return NVBounds3(v0.minimum(v1), v0.maximum(v1));
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE NVBounds3 NVBounds3::centerExtents(const QT3DSVec3 &center,
+ const QT3DSVec3 &extent)
+{
+ return NVBounds3(center - extent, center + extent);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::basisExtent(const QT3DSVec3 &center,
+ const QT3DSMat33 &basis,
+ const QT3DSVec3 &extent)
+{
+ // extended basis vectors
+ QT3DSVec3 c0 = basis.column0 * extent.x;
+ QT3DSVec3 c1 = basis.column1 * extent.y;
+ QT3DSVec3 c2 = basis.column2 * extent.z;
+
+ QT3DSVec3 w;
+ // find combination of base vectors that produces max. distance for each component = sum of
+ // abs()
+ w.x = NVAbs(c0.x) + NVAbs(c1.x) + NVAbs(c2.x);
+ w.y = NVAbs(c0.y) + NVAbs(c1.y) + NVAbs(c2.y);
+ w.z = NVAbs(c0.z) + NVAbs(c1.z) + NVAbs(c2.z);
+
+ return NVBounds3(center - w, center + w);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::poseExtent(const NVTransform &pose,
+ const QT3DSVec3 &extent)
+{
+ return basisExtent(pose.p, QT3DSMat33(pose.q), extent);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::setEmpty()
+{
+ minimum = QT3DSVec3(QT3DS_MAX_REAL);
+ maximum = QT3DSVec3(-QT3DS_MAX_REAL);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::setInfinite()
+{
+ minimum = QT3DSVec3(-QT3DS_MAX_REAL);
+ maximum = QT3DSVec3(QT3DS_MAX_REAL);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::include(const QT3DSVec3 &v)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum = minimum.minimum(v);
+ maximum = maximum.maximum(v);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::include(const NVBounds3 &b)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum = minimum.minimum(b.minimum);
+ maximum = maximum.maximum(b.maximum);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isEmpty() const
+{
+ QT3DS_ASSERT(isFinite());
+ // Consistency condition for (Min, Max) boxes: minimum < maximum
+ return minimum.x > maximum.x || minimum.y > maximum.y || minimum.z > maximum.z;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::intersects(const NVBounds3 &b) const
+{
+ QT3DS_ASSERT(isFinite() && b.isFinite());
+ return !(b.minimum.x > maximum.x || minimum.x > b.maximum.x || b.minimum.y > maximum.y
+ || minimum.y > b.maximum.y || b.minimum.z > maximum.z || minimum.z > b.maximum.z);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::intersects1D(const NVBounds3 &a, QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite() && a.isFinite());
+ return maximum[axis] >= a.minimum[axis] && a.maximum[axis] >= minimum[axis];
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::contains(const QT3DSVec3 &v) const
+{
+ QT3DS_ASSERT(isFinite());
+
+ return !(v.x < minimum.x || v.x > maximum.x || v.y < minimum.y || v.y > maximum.y
+ || v.z < minimum.z || v.z > maximum.z);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE bool NVBounds3::isInside(const NVBounds3 &box) const
+{
+ QT3DS_ASSERT(isFinite() && box.isFinite());
+ if (box.minimum.x > minimum.x)
+ return false;
+ if (box.minimum.y > minimum.y)
+ return false;
+ if (box.minimum.z > minimum.z)
+ return false;
+ if (box.maximum.x < maximum.x)
+ return false;
+ if (box.maximum.y < maximum.y)
+ return false;
+ if (box.maximum.z < maximum.z)
+ return false;
+ return true;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getCenter() const
+{
+ QT3DS_ASSERT(isFinite());
+ return (minimum + maximum) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVBounds3::getCenter(QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite());
+ return (minimum[axis] + maximum[axis]) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE float NVBounds3::getExtents(QT3DSU32 axis) const
+{
+ QT3DS_ASSERT(isFinite());
+ return (maximum[axis] - minimum[axis]) * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getDimensions() const
+{
+ QT3DS_ASSERT(isFinite());
+ return maximum - minimum;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE QT3DSVec3 NVBounds3::getExtents() const
+{
+ QT3DS_ASSERT(isFinite());
+ return getDimensions() * NVReal(0.5);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::scale(QT3DSF32 scale)
+{
+ QT3DS_ASSERT(isFinite());
+ *this = centerExtents(getCenter(), getExtents() * scale);
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::fatten(NVReal distance)
+{
+ QT3DS_ASSERT(isFinite());
+ minimum.x -= distance;
+ minimum.y -= distance;
+ minimum.z -= distance;
+
+ maximum.x += distance;
+ maximum.y += distance;
+ maximum.z += distance;
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::transform(const QT3DSMat33 &matrix,
+ const NVBounds3 &bounds)
+{
+ QT3DS_ASSERT(bounds.isFinite());
+ return bounds.isEmpty() ? bounds : NVBounds3::basisExtent(matrix * bounds.getCenter(), matrix,
+ bounds.getExtents());
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_INLINE NVBounds3 NVBounds3::transform(const NVTransform &transform,
+ const NVBounds3 &bounds)
+{
+ QT3DS_ASSERT(bounds.isFinite());
+ return bounds.isEmpty() ? bounds
+ : NVBounds3::basisExtent(transform.transform(bounds.getCenter()),
+ QT3DSMat33(transform.q), bounds.getExtents());
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::expand(TNVBounds2BoxPoints &outPoints) const
+{
+ if (isEmpty()) {
+ for (QT3DSU32 idx = 0; idx < 8; ++idx)
+ outPoints[idx] = QT3DSVec3(0, 0, 0);
+ } else {
+ // Min corner of box
+ outPoints[0] = QT3DSVec3(minimum[0], minimum[1], minimum[2]);
+ outPoints[1] = QT3DSVec3(maximum[0], minimum[1], minimum[2]);
+ outPoints[2] = QT3DSVec3(minimum[0], maximum[1], minimum[2]);
+ outPoints[3] = QT3DSVec3(minimum[0], minimum[1], maximum[2]);
+
+ // Max corner of box
+ outPoints[4] = QT3DSVec3(maximum[0], maximum[1], maximum[2]);
+ outPoints[5] = QT3DSVec3(minimum[0], maximum[1], maximum[2]);
+ outPoints[6] = QT3DSVec3(maximum[0], minimum[1], maximum[2]);
+ outPoints[7] = QT3DSVec3(maximum[0], maximum[1], minimum[2]);
+ }
+}
+
+QT3DS_CUDA_CALLABLE QT3DS_FORCE_INLINE void NVBounds3::transform(const QT3DSMat44 &inMatrix)
+{
+ if (!isEmpty()) {
+ TNVBounds2BoxPoints thePoints;
+ expand(thePoints);
+ setEmpty();
+ for (QT3DSU32 idx = 0; idx < 8; ++idx)
+ include(inMatrix.transform(thePoints[idx]));
+ }
+}
+
+#ifndef QT3DS_DOXYGEN
+} // namespace qt3ds
+#endif
+
+/** @} */
+#endif // QT3DS_FOUNDATION_QT3DS_BOUNDS3_H