#include <limits>
+//! Base class for BVH_Box (CRTP idiom is used).
+//! @tparam T Numeric data type
+//! @tparam N Vector dimension
+//! @tparam TheDerivedBox Template of derived class that defined axis aligned bounding box.
+template <class T, int N, template <class /*T*/, int /*N*/> class TheDerivedBox>
+class BVH_BaseBox {};
+
+// forward declaration
+template <class T, int N> class BVH_Box;
+
+//! Partial template specialization for BVH_Box when N = 3.
+template <class T>
+class BVH_BaseBox<T, 3, BVH_Box>
+{
+public:
+
+ //! Transforms this box with given transformation.
+ void Transform (const NCollection_Mat4<T>& theTransform)
+ {
+ if (theTransform.IsIdentity())
+ {
+ return;
+ }
+
+ BVH_Box<T, 3> *aThis = static_cast<BVH_Box<T, 3>*>(this);
+ if (!aThis->IsValid())
+ {
+ return;
+ }
+
+ BVH_Box<T, 3> aBox = Transformed (theTransform);
+
+ aThis->CornerMin() = aBox.CornerMin();
+ aThis->CornerMax() = aBox.CornerMax();
+ }
+
+ //! Returns a box which is the result of applying the
+ //! given transformation to this box.
+ BVH_Box<T, 3> Transformed (const NCollection_Mat4<T>& theTransform) const
+ {
+ BVH_Box<T, 3> aResultBox;
+
+ if (theTransform.IsIdentity())
+ {
+ return aResultBox;
+ }
+
+ const BVH_Box<T, 3> *aThis = static_cast<const BVH_Box<T, 3>*>(this);
+ if (!aThis->IsValid())
+ {
+ return aResultBox;
+ }
+
+ for (size_t aX = 0; aX <= 1; ++aX)
+ {
+ for (size_t aY = 0; aY <= 1; ++aY)
+ {
+ for (size_t aZ = 0; aZ <= 1; ++aZ)
+ {
+ typename BVH::VectorType<T, 4>::Type aPnt =
+ theTransform * typename BVH::VectorType<T, 4>::Type (aX ? aThis->CornerMax().x() : aThis->CornerMin().x(),
+ aY ? aThis->CornerMax().y() : aThis->CornerMin().y(),
+ aZ ? aThis->CornerMax().z() : aThis->CornerMin().z(),
+ static_cast<T> (1.0));
+
+ aResultBox.Add (aPnt.xyz());
+ }
+ }
+ }
+ return aResultBox;
+ }
+};
+
//! Defines axis aligned bounding box (AABB) based on BVH vectors.
//! \tparam T Numeric data type
//! \tparam N Vector dimension
template<class T, int N>
-class BVH_Box
+class BVH_Box : public BVH_BaseBox<T, N, BVH_Box>
{
public:
--- /dev/null
+// Created by: Olga Suryaninova
+// Created on: 2019-11-25
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BVH_Ray_Header
+#define _BVH_Ray_Header
+
+//! Describes a ray based on BVH vectors.
+template<class T, int N>
+class BVH_Ray
+{
+public:
+
+ typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
+
+public:
+
+ BVH_VecNt Origin;
+ BVH_VecNt Direct;
+
+public:
+
+ BVH_Ray (const BVH_VecNt& theOrigin,
+ const BVH_VecNt& theDirect) : Origin (theOrigin),
+ Direct (theDirect) { }
+};
+
+#endif // _BVH_Ray_Header
#define _BVH_Tools_Header
#include <BVH_Box.hxx>
+#include <BVH_Ray.hxx>
#include <BVH_Types.hxx>
//! Defines a set of static methods operating with points and bounding boxes.
static T BoxBoxSquareDistance (const BVH_Box<T, N>& theBox1,
const BVH_Box<T, N>& theBox2)
{
+ if (!theBox1.IsValid() || !theBox2.IsValid())
+ {
+ return static_cast<T>(0);
+ }
return BoxBoxSquareDistance (theBox1.CornerMin(), theBox1.CornerMax(),
theBox2.CornerMin(), theBox2.CornerMax());
}
static T PointBoxSquareDistance (const BVH_VecNt& thePoint,
const BVH_Box<T, N>& theBox)
{
+ if (!theBox.IsValid())
+ {
+ return static_cast<T>(0);
+ }
return PointBoxSquareDistance (thePoint,
theBox.CornerMin(),
theBox.CornerMax());
return aDist;
}
+public: //! @name Point-Box projection
+
+ //! Computes projection of point on bounding box
+ static BVH_VecNt PointBoxProjection (const BVH_VecNt& thePoint,
+ const BVH_Box<T, N>& theBox)
+ {
+ if (!theBox.IsValid())
+ {
+ return thePoint;
+ }
+ return PointBoxProjection (thePoint,
+ theBox.CornerMin(),
+ theBox.CornerMax());
+ }
+
+ //! Computes projection of point on bounding box
+ static BVH_VecNt PointBoxProjection (const BVH_VecNt& thePoint,
+ const BVH_VecNt& theCMin,
+ const BVH_VecNt& theCMax)
+ {
+ return thePoint.cwiseMax (theCMin).cwiseMin (theCMax);
+ }
+
public: //! @name Point-Triangle Square distance
//! Computes square distance between point and triangle
return (aDirect.Dot(aDirect));
}
+public: //! @name Ray-Box Intersection
+
+ //! Computes hit time of ray-box intersection
+ static Standard_Boolean RayBoxIntersection (const BVH_Ray<T, N>& theRay,
+ const BVH_Box<T, N>& theBox,
+ T& theTimeEnter,
+ T& theTimeLeave)
+ {
+ if (!theBox.IsValid())
+ {
+ return Standard_False;
+ }
+ return RayBoxIntersection (theRay, theBox.CornerMin(), theBox.CornerMax(), theTimeEnter, theTimeLeave);
+ }
+
+ //! Computes hit time of ray-box intersection
+ static Standard_Boolean RayBoxIntersection (const BVH_Ray<T, N>& theRay,
+ const BVH_VecNt& theBoxCMin,
+ const BVH_VecNt& theBoxCMax,
+ T& theTimeEnter,
+ T& theTimeLeave)
+ {
+ return RayBoxIntersection (theRay.Origin, theRay.Direct,
+ theBoxCMin, theBoxCMax, theTimeEnter, theTimeLeave);
+ }
+
+ //! Computes hit time of ray-box intersection
+ static Standard_Boolean RayBoxIntersection (const BVH_VecNt& theRayOrigin,
+ const BVH_VecNt& theRayDirection,
+ const BVH_Box<T, N>& theBox,
+ T& theTimeEnter,
+ T& theTimeLeave)
+ {
+ if (!theBox.IsValid())
+ {
+ return Standard_False;
+ }
+ return RayBoxIntersection (theRayOrigin, theRayDirection,
+ theBox.CornerMin(), theBox.CornerMax(),
+ theTimeEnter, theTimeLeave);
+ }
+
+ //! Computes hit time of ray-box intersection
+ static Standard_Boolean RayBoxIntersection (const BVH_VecNt& theRayOrigin,
+ const BVH_VecNt& theRayDirection,
+ const BVH_VecNt& theBoxCMin,
+ const BVH_VecNt& theBoxCMax,
+ T& theTimeEnter,
+ T& theTimeLeave)
+ {
+ BVH_VecNt aNodeMin, aNodeMax;
+ for (int i = 0; i < N; ++i)
+ {
+ if (theRayDirection[i] == 0)
+ {
+ aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) < 0 ?
+ (std::numeric_limits<T>::min)() : (std::numeric_limits<T>::max)();
+ aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) < 0 ?
+ (std::numeric_limits<T>::min)() : (std::numeric_limits<T>::max)();
+ }
+ else
+ {
+ aNodeMin[i] = (theBoxCMin[i] - theRayOrigin[i]) / theRayDirection[i];
+ aNodeMax[i] = (theBoxCMax[i] - theRayOrigin[i]) / theRayDirection[i];
+ }
+ }
+
+ BVH_VecNt aTimeMin, aTimeMax;
+ for (int i = 0; i < N; ++i)
+ {
+ aTimeMin[i] = Min (aNodeMin[i], aNodeMax[i]);
+ aTimeMax[i] = Max (aNodeMin[i], aNodeMax[i]);
+ }
+
+ T aTimeEnter = Max (aTimeMin[0], Max (aTimeMin[1], aTimeMin[2]));
+ T aTimeLeave = Min (aTimeMax[0], Min (aTimeMax[1], aTimeMax[2]));
+
+ Standard_Boolean hasIntersection = aTimeEnter < aTimeLeave && aTimeLeave > 0;
+ if (hasIntersection)
+ {
+ theTimeEnter = aTimeEnter;
+ theTimeLeave = aTimeLeave;
+ }
+
+ return hasIntersection;
+ }
};
#endif
\ No newline at end of file