// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#include <Standard_Assert.hxx>
-
#ifdef HAVE_TBB
// On Windows, function TryEnterCriticalSection has appeared in Windows NT
// and is surrounded by #ifdef in MS VC++ 7.1 headers.
- // Thus to use it we need to define appropriate macro saying that we wil
+ // Thus to use it we need to define appropriate macro saying that we will
// run on Windows NT 4.0 at least
- #if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT))
+ #if defined(_WIN32) && !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0501
#endif
#include <OpenGl_SceneGeometry.hxx>
-//! Use this macro to output BVH profiling info
-//#define BVH_PRINT_INFO
+#include <OpenGl_ArbTexBindless.hxx>
+#include <OpenGl_PrimitiveArray.hxx>
+#include <OpenGl_Structure.hxx>
+#include <OSD_Timer.hxx>
+#include <Standard_Assert.hxx>
-#ifdef BVH_PRINT_INFO
- #include <OSD_Timer.hxx>
-#endif
+//! Use this macro to output BVH profiling info
+// #define RAY_TRACE_PRINT_INFO
namespace
{
//! Useful constant for null floating-point 4D vector.
static const BVH_Vec4f ZERO_VEC_4F;
-};
+}
// =======================================================================
// function : OpenGl_RaytraceMaterial
//
}
+// =======================================================================
+// function : Center
+// purpose : Returns centroid position along the given axis
+// =======================================================================
+Standard_ShortReal OpenGl_TriangleSet::Center (
+ const Standard_Integer theIndex, const Standard_Integer theAxis) const
+{
+ // Note: Experiments show that the use of the box centroid (instead
+ // of the triangle centroid) increases render performance up to 12%
+
+ const BVH_Vec4i& aTriangle = Elements[theIndex];
+
+ const Standard_ShortReal aVertex0 =
+ BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.x()], theAxis);
+ const Standard_ShortReal aVertex1 =
+ BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.y()], theAxis);
+ const Standard_ShortReal aVertex2 =
+ BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.z()], theAxis);
+
+ return (Min (Min (aVertex0, aVertex1), aVertex2) +
+ Max (Max (aVertex0, aVertex1), aVertex2)) * 0.5f;
+}
+
+// =======================================================================
+// function : Box
+// purpose : Returns AABB of primitive set
+// =======================================================================
+OpenGl_TriangleSet::BVH_BoxNt OpenGl_TriangleSet::Box() const
+{
+ const BVH_Transform<Standard_ShortReal, 4>* aTransform =
+ dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (Properties().operator->());
+
+ BVH_BoxNt aBox = BVH_PrimitiveSet<Standard_ShortReal, 3>::Box();
+
+ if (aTransform != NULL)
+ {
+ BVH_BoxNt aTransformedBox;
+
+ for (Standard_Integer aX = 0; aX <= 1; ++aX)
+ {
+ for (Standard_Integer aY = 0; aY <= 1; ++aY)
+ {
+ for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
+ {
+ BVH_Vec4f aCorner = aTransform->Transform() * BVH_Vec4f (
+ aX == 0 ? aBox.CornerMin().x() : aBox.CornerMax().x(),
+ aY == 0 ? aBox.CornerMin().y() : aBox.CornerMax().y(),
+ aZ == 0 ? aBox.CornerMin().z() : aBox.CornerMax().z(),
+ 1.f);
+
+ aTransformedBox.Add (reinterpret_cast<BVH_Vec3f&> (aCorner));
+ }
+ }
+ }
+
+ return aTransformedBox;
+ }
+
+ return aBox;
+}
+
// =======================================================================
// function : Clear
// purpose : Clears ray-tracing geometry
// =======================================================================
void OpenGl_RaytraceGeometry::Clear()
{
- BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear();
+ BVH_Geometry<Standard_ShortReal, 3>::BVH_Geometry::Clear();
std::vector<OpenGl_RaytraceLight,
NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources;
struct OpenGL_BVHParallelBuilder
{
- BVH_ObjectSet<Standard_ShortReal, 4>* Set;
+ BVH_ObjectSet<Standard_ShortReal, 3>* Set;
- OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet)
+ OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 3>* theSet)
: Set (theSet)
{
//
// =======================================================================
Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
{
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
OSD_Timer aTimer;
#endif
MarkDirty(); // force BVH rebuilding
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
aTimer.Reset();
aTimer.Start();
#endif
myBottomLevelTreeDepth = Max (myBottomLevelTreeDepth, aTriangleSet->BVH()->Depth());
}
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
aTimer.Stop();
std::cout << "Updating bottom-level BVHs (sec): " <<
aTimer.ElapsedTime() << std::endl;
#endif
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
aTimer.Reset();
aTimer.Start();
#endif
- NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH();
+ NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> > aBVH = BVH();
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
aTimer.Stop();
std::cout << "Updating high-level BVH (sec): " <<
Standard_Integer aVerticesOffset = 0;
Standard_Integer aElementsOffset = 0;
- Standard_Integer aBVHNodesOffset = 0;
+ Standard_Integer aBVHNodesOffset = BVH()->Length();
for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
{
// =======================================================================
Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer theNodeIdx)
{
- const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+ const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
return INVALID_OFFSET;
// =======================================================================
Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNodeIdx)
{
- const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+ const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
return INVALID_OFFSET;
// =======================================================================
Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNodeIdx)
{
- const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+ const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
return INVALID_OFFSET;
// =======================================================================
OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNodeIdx)
{
- const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+ const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
return NULL;
aBVH->NodeInfoBuffer().at (theNodeIdx).x() - 1).operator->());
}
+// =======================================================================
+// function : AcquireTextures
+// purpose : Makes the OpenGL texture handles resident
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_Context)& theContext) const
+{
+ if (theContext->arbTexBindless == NULL)
+ {
+ return Standard_True;
+ }
+
+#if !defined(GL_ES_VERSION_2_0)
+ for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+ {
+ theContext->arbTexBindless->glMakeTextureHandleResidentARB (myTextureHandles[anIdx]);
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to make OpenGL texture resident" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
+#endif
+
+ return Standard_True;
+}
+
+// =======================================================================
+// function : ReleaseTextures
+// purpose : Makes the OpenGL texture handles non-resident
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::ReleaseTextures (const Handle(OpenGl_Context)& theContext) const
+{
+ if (theContext->arbTexBindless == NULL)
+ {
+ return Standard_True;
+ }
+
+#if !defined(GL_ES_VERSION_2_0)
+ for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+ {
+ theContext->arbTexBindless->glMakeTextureHandleNonResidentARB (myTextureHandles[anIdx]);
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to make OpenGL texture non-resident" << std::endl;
+#endif
+ return Standard_False;
+ }
+ }
+#endif
+
+ return Standard_True;
+}
+
+// =======================================================================
+// function : AddTexture
+// purpose : Adds new OpenGL texture to the scene and returns its index
+// =======================================================================
+Standard_Integer OpenGl_RaytraceGeometry::AddTexture (const Handle(OpenGl_Texture)& theTexture)
+{
+ NCollection_Vector<Handle (OpenGl_Texture)>::iterator anIter =
+ std::find (myTextures.begin(), myTextures.end(), theTexture);
+
+ if (anIter == myTextures.end())
+ {
+ if (myTextures.Size() >= MAX_TEX_NUMBER)
+ {
+ return -1;
+ }
+
+ myTextures.Append (theTexture);
+ }
+
+ return static_cast<Standard_Integer> (anIter - myTextures.begin());
+}
+
+// =======================================================================
+// function : UpdateTextureHandles
+// purpose : Updates unique 64-bit texture handles to use in shaders
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(OpenGl_Context)& theContext)
+{
+ if (theContext->arbTexBindless == NULL)
+ {
+ return Standard_False;
+ }
+
+ myTextureHandles.clear();
+
+#if !defined(GL_ES_VERSION_2_0)
+ for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+ {
+ const GLuint64 aHandle = theContext->arbTexBindless->glGetTextureHandleARB (
+ myTextures.Value (anIdx)->TextureId());
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+#ifdef RAY_TRACE_PRINT_INFO
+ std::cout << "Error: Failed to get 64-bit handle of OpenGL texture" << std::endl;
+#endif
+ return Standard_False;
+ }
+
+ myTextureHandles.push_back (aHandle);
+ }
+#endif
+
+ return Standard_True;
+}
+
namespace OpenGl_Raytrace
{
// =======================================================================
// =======================================================================
Standard_Boolean IsRaytracedElement (const OpenGl_ElementNode* theNode)
{
- OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem);
+ OpenGl_PrimitiveArray* anArray = dynamic_cast<OpenGl_PrimitiveArray*> (theNode->elem);
+ return anArray != NULL
+ && anArray->DrawMode() >= GL_TRIANGLES;
+ }
+
+ // =======================================================================
+ // function : IsRaytracedElement
+ // purpose : Checks to see if the element contains ray-trace geometry
+ // =======================================================================
+ Standard_Boolean IsRaytracedElement (const OpenGl_Element* theElement)
+ {
+ const OpenGl_PrimitiveArray* anArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
return anArray != NULL
&& anArray->DrawMode() >= GL_TRIANGLES;
}