1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00

0028760: Visualization, TKOpenGl - avoid excessive frustum culling traverse within extra OIT rendering pass

Culling traverse is no more called implicitly within OpenGl_Layer::Render().
Instead, all layers are traversed at onces within OpenGl_View::render() beforehand.

OpenGl_BVHTreeSelector methods have been renamed to better reflect their meaning.
Non-persistent culling options has been moved to dedicated structure OpenGl_BVHTreeSelector::CullingContext
so that OpenGl_BVHTreeSelector instance can be used for different Layers without modifying its state.
This commit is contained in:
kgv 2017-11-08 09:44:27 +03:00
parent daf73ab7c9
commit 2b8832bb0e
9 changed files with 202 additions and 168 deletions

View File

@ -26,9 +26,7 @@
OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector() OpenGl_BVHTreeSelector::OpenGl_BVHTreeSelector()
: myIsProjectionParallel (Standard_True), : myIsProjectionParallel (Standard_True),
myCamScaleInv (1.0), myCamScaleInv (1.0),
myDistCull (-1.0), myPixelSize (1.0)
myPixelSize (1.0),
mySizeCull2 (-1.0)
{ {
// //
} }
@ -166,14 +164,15 @@ Standard_Real OpenGl_BVHTreeSelector::SignedPlanePointDistance (const OpenGl_Vec
// function : SetCullingDistance // function : SetCullingDistance
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_BVHTreeSelector::SetCullingDistance (Standard_Real theDistance) void OpenGl_BVHTreeSelector::SetCullingDistance (CullingContext& theCtx,
Standard_Real theDistance) const
{ {
myDistCull = -1.0; theCtx.DistCull = -1.0;
if (!myIsProjectionParallel) if (!myIsProjectionParallel)
{ {
myDistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance) theCtx.DistCull = theDistance > 0.0 && !Precision::IsInfinite (theDistance)
? theDistance ? theDistance
: -1.0; : -1.0;
} }
} }
@ -181,13 +180,14 @@ void OpenGl_BVHTreeSelector::SetCullingDistance (Standard_Real theDistance)
// function : SetCullingSize // function : SetCullingSize
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_BVHTreeSelector::SetCullingSize (Standard_Real theSize) void OpenGl_BVHTreeSelector::SetCullingSize (CullingContext& theCtx,
Standard_Real theSize) const
{ {
mySizeCull2 = -1.0; theCtx.SizeCull2 = -1.0;
if (theSize > 0.0 && !Precision::IsInfinite (theSize)) if (theSize > 0.0 && !Precision::IsInfinite (theSize))
{ {
mySizeCull2 = (myPixelSize * theSize) / myCamScaleInv; theCtx.SizeCull2 = (myPixelSize * theSize) / myCamScaleInv;
mySizeCull2 *= mySizeCull2; theCtx.SizeCull2 *= theCtx.SizeCull2;
} }
} }
@ -233,84 +233,3 @@ void OpenGl_BVHTreeSelector::CacheClipPtsProjections()
myMinOrthoProjectionPts[aDim] = aMinProj; myMinOrthoProjectionPts[aDim] = aMinProj;
} }
} }
// =======================================================================
// function : Intersect
// purpose : Detects if AABB overlaps view volume using separating axis theorem (SAT)
// =======================================================================
Standard_Boolean OpenGl_BVHTreeSelector::Intersect (const OpenGl_Vec3d& theMinPt,
const OpenGl_Vec3d& theMaxPt) const
{
// E1
// |_ E0
// /
// E2
// E0 test
if (theMinPt.x() > myMaxOrthoProjectionPts[0]
|| theMaxPt.x() < myMinOrthoProjectionPts[0])
{
return Standard_False;
}
// E1 test
if (theMinPt.y() > myMaxOrthoProjectionPts[1]
|| theMaxPt.y() < myMinOrthoProjectionPts[1])
{
return Standard_False;
}
// E2 test
if (theMinPt.z() > myMaxOrthoProjectionPts[2]
|| theMaxPt.z() < myMinOrthoProjectionPts[2])
{
return Standard_False;
}
Standard_Real aBoxProjMax = 0.0, aBoxProjMin = 0.0;
const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
{
OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
aBoxProjMax = (aPlane.x() > 0.0 ? (aPlane.x() * theMaxPt.x()) : aPlane.x() * theMinPt.x())
+ (aPlane.y() > 0.0 ? (aPlane.y() * theMaxPt.y()) : aPlane.y() * theMinPt.y())
+ (aPlane.z() > 0.0 ? (aPlane.z() * theMaxPt.z()) : aPlane.z() * theMinPt.z());
if (aBoxProjMax > myMinClipProjectionPts[aPlaneIter]
&& aBoxProjMax < myMaxClipProjectionPts[aPlaneIter])
{
continue;
}
aBoxProjMin = (aPlane.x() < 0.0 ? aPlane.x() * theMaxPt.x() : aPlane.x() * theMinPt.x())
+ (aPlane.y() < 0.0 ? aPlane.y() * theMaxPt.y() : aPlane.y() * theMinPt.y())
+ (aPlane.z() < 0.0 ? aPlane.z() * theMaxPt.z() : aPlane.z() * theMinPt.z());
if (aBoxProjMin > myMaxClipProjectionPts[aPlaneIter]
|| aBoxProjMax < myMinClipProjectionPts[aPlaneIter])
{
return Standard_False;
}
}
// distance culling - discard node if distance to it's bounding box from camera eye is less than specified culling distance
if (myDistCull > 0.0)
{
// check distance to the bounding sphere as fast approximation
const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5;
const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5;
if ((aSphereCenter - myCamEye).Modulus() - aSphereRadius > myDistCull)
{
return Standard_False;
}
}
// size culling - discard node if diagonal of it's bounding box is less than specified culling size
if (mySizeCull2 > 0.0)
{
if ((theMaxPt - theMinPt).SquareModulus() < mySizeCull2)
{
return Standard_False;
}
}
return Standard_True;
}

View File

@ -25,6 +25,16 @@
//! view volume. //! view volume.
class OpenGl_BVHTreeSelector class OpenGl_BVHTreeSelector
{ {
public:
//! Auxiliary structure holding non-persistent culling options.
struct CullingContext
{
Standard_Real DistCull; //!< culling distance
Standard_Real SizeCull2; //!< squared culling size
//! Empty constructor.
CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {}
};
public: public:
//! Creates an empty selector object with parallel projection type by default. //! Creates an empty selector object with parallel projection type by default.
@ -38,21 +48,30 @@ public:
Standard_Real theResolutionRatio); Standard_Real theResolutionRatio);
//! Setup distance culling. //! Setup distance culling.
Standard_EXPORT void SetCullingDistance (Standard_Real theDistance); Standard_EXPORT void SetCullingDistance (CullingContext& theCtx,
Standard_Real theDistance) const;
//! Setup size culling. //! Setup size culling.
Standard_EXPORT void SetCullingSize (Standard_Real theSize); Standard_EXPORT void SetCullingSize (CullingContext& theCtx,
Standard_Real theSize) const;
//! Caches view volume's vertices projections along its normals and AABBs dimensions. //! Caches view volume's vertices projections along its normals and AABBs dimensions.
//! Must be called at the beginning of each BVH tree traverse loop. //! Must be called at the beginning of each BVH tree traverse loop.
Standard_EXPORT void CacheClipPtsProjections(); Standard_EXPORT void CacheClipPtsProjections();
//! Detects if AABB overlaps view volume using separating axis theorem (SAT). //! Checks whether given AABB should be entirely culled or not.
//! @param theMinPt [in] maximum point of AABB. //! @param theCtx [in] culling properties
//! @param theMaxPt [in] minimum point of AABB. //! @param theMinPt [in] maximum point of AABB
//! @return Standard_True, if AABB is in viewing area, Standard_False otherwise. //! @param theMaxPt [in] minimum point of AABB
Standard_EXPORT Standard_Boolean Intersect (const OpenGl_Vec3d& theMinPt, //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise
const OpenGl_Vec3d& theMaxPt) const; bool IsCulled (const CullingContext& theCtx,
const OpenGl_Vec3d& theMinPt,
const OpenGl_Vec3d& theMaxPt) const
{
return isFullOut (theMinPt, theMaxPt)
|| isTooDistant(theCtx, theMinPt, theMaxPt)
|| isTooSmall (theCtx, theMinPt, theMaxPt);
}
//! Return the camera definition. //! Return the camera definition.
const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
@ -93,6 +112,93 @@ protected:
Standard_EXPORT Standard_Real SignedPlanePointDistance (const OpenGl_Vec4d& theNormal, Standard_EXPORT Standard_Real SignedPlanePointDistance (const OpenGl_Vec4d& theNormal,
const OpenGl_Vec4d& thePnt); const OpenGl_Vec4d& thePnt);
//! Detects if AABB overlaps view volume using separating axis theorem (SAT).
//! @param theMinPt [in] maximum point of AABB.
//! @param theMaxPt [in] minimum point of AABB.
//! @return FALSE, if AABB is in viewing area, TRUE otherwise.
bool isFullOut (const OpenGl_Vec3d& theMinPt,
const OpenGl_Vec3d& theMaxPt) const
{
// E1
// |_ E0
// /
// E2
// E0 test
if (theMinPt.x() > myMaxOrthoProjectionPts[0]
|| theMaxPt.x() < myMinOrthoProjectionPts[0])
{
return true;
}
// E1 test
if (theMinPt.y() > myMaxOrthoProjectionPts[1]
|| theMaxPt.y() < myMinOrthoProjectionPts[1])
{
return true;
}
// E2 test
if (theMinPt.z() > myMaxOrthoProjectionPts[2]
|| theMaxPt.z() < myMinOrthoProjectionPts[2])
{
return true;
}
Standard_Real aBoxProjMax = 0.0, aBoxProjMin = 0.0;
const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
for (Standard_Integer aPlaneIter = 0; aPlaneIter < 5; aPlaneIter += anIncFactor)
{
OpenGl_Vec4d aPlane = myClipPlanes[aPlaneIter];
aBoxProjMax = (aPlane.x() > 0.0 ? (aPlane.x() * theMaxPt.x()) : aPlane.x() * theMinPt.x())
+ (aPlane.y() > 0.0 ? (aPlane.y() * theMaxPt.y()) : aPlane.y() * theMinPt.y())
+ (aPlane.z() > 0.0 ? (aPlane.z() * theMaxPt.z()) : aPlane.z() * theMinPt.z());
if (aBoxProjMax > myMinClipProjectionPts[aPlaneIter]
&& aBoxProjMax < myMaxClipProjectionPts[aPlaneIter])
{
continue;
}
aBoxProjMin = (aPlane.x() < 0.0 ? aPlane.x() * theMaxPt.x() : aPlane.x() * theMinPt.x())
+ (aPlane.y() < 0.0 ? aPlane.y() * theMaxPt.y() : aPlane.y() * theMinPt.y())
+ (aPlane.z() < 0.0 ? aPlane.z() * theMaxPt.z() : aPlane.z() * theMinPt.z());
if (aBoxProjMin > myMaxClipProjectionPts[aPlaneIter]
|| aBoxProjMax < myMinClipProjectionPts[aPlaneIter])
{
return true;
}
}
return false;
}
//! Returns TRUE if given AABB should be discarded by distance culling criterion.
bool isTooDistant (const CullingContext& theCtx,
const OpenGl_Vec3d& theMinPt,
const OpenGl_Vec3d& theMaxPt) const
{
if (theCtx.DistCull <= 0.0)
{
return false;
}
// check distance to the bounding sphere as fast approximation
const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5;
const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5;
return (aSphereCenter - myCamEye).Modulus() - aSphereRadius > theCtx.DistCull;
}
//! Returns TRUE if given AABB should be discarded by size culling criterion.
bool isTooSmall (const CullingContext& theCtx,
const OpenGl_Vec3d& theMinPt,
const OpenGl_Vec3d& theMaxPt) const
{
if (theCtx.SizeCull2 <= 0.0)
{
return false;
}
return (theMaxPt - theMinPt).SquareModulus() < theCtx.SizeCull2;
}
protected: protected:
//! Enumerates planes of view volume. //! Enumerates planes of view volume.
@ -150,9 +256,7 @@ protected:
Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling
Standard_Real myCamScaleInv; //!< inverted camera scale for size culling Standard_Real myCamScaleInv; //!< inverted camera scale for size culling
Standard_Real myDistCull; //!< culling distance
Standard_Real myPixelSize; //!< pixel size for size culling Standard_Real myPixelSize; //!< pixel size for size culling
Standard_Real mySizeCull2; //!< squared culling size
}; };

View File

@ -34,7 +34,8 @@ OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities,
myNbStructures (0), myNbStructures (0),
myBVHPrimitivesTrsfPers (theBuilder), myBVHPrimitivesTrsfPers (theBuilder),
myBVHIsLeftChildQueuedFirst (Standard_True), myBVHIsLeftChildQueuedFirst (Standard_True),
myIsBVHPrimitivesNeedsReset (Standard_False) myIsBVHPrimitivesNeedsReset (Standard_False),
myIsCulled (Standard_False)
{ {
myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true; myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
} }
@ -147,7 +148,7 @@ bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
// function : InvalidateBVHData // function : InvalidateBVHData
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_Layer::InvalidateBVHData() const void OpenGl_Layer::InvalidateBVHData()
{ {
myIsBVHPrimitivesNeedsReset = Standard_True; myIsBVHPrimitivesNeedsReset = Standard_True;
} }
@ -429,12 +430,8 @@ void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) cons
for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
{ {
const OpenGl_Structure* aStruct = aStructIter.Value(); const OpenGl_Structure* aStruct = aStructIter.Value();
if (!aStruct->IsVisible()) if (aStruct->IsCulled()
{ || !aStruct->IsVisible (aViewId))
continue;
}
else if (!aStruct->ViewAffinity.IsNull()
&& !aStruct->ViewAffinity->IsVisible (aViewId))
{ {
continue; continue;
} }
@ -483,51 +480,43 @@ void OpenGl_Layer::updateBVH() const
} }
// ======================================================================= // =======================================================================
// function : renderTraverse // function : UpdateCulling
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const void OpenGl_Layer::UpdateCulling (const OpenGl_BVHTreeSelector& theSelector,
const Standard_Boolean theToTraverse)
{ {
updateBVH(); updateBVH();
if (myBVHPrimitives .Size() != 0
|| myBVHPrimitivesTrsfPers.Size() != 0)
{
OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
aSelector.SetCullingDistance (myLayerSettings.CullingDistance());
aSelector.SetCullingSize (myLayerSettings.CullingSize());
aSelector.CacheClipPtsProjections();
traverse (aSelector);
}
const Standard_Integer aViewId = theWorkspace->View()->Identification(); myIsCulled = false;
for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next()) for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
{ {
const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value(); const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next()) for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
{ {
const OpenGl_Structure* aStruct = aStructIter.Value(); const OpenGl_Structure* aStruct = aStructIter.Value();
if (aStruct->IsCulled() aStruct->SetCulled (theToTraverse);
|| !aStruct->IsVisible (aViewId))
{
continue;
}
aStruct->Render (theWorkspace);
aStruct->ResetCullingStatus();
} }
} }
}
// ======================================================================= if (!theToTraverse)
// function : traverse {
// purpose : return;
// ======================================================================= }
void OpenGl_Layer::traverse (const OpenGl_BVHTreeSelector& theSelector) const if (myBVHPrimitives .Size() == 0
{ && myBVHPrimitivesTrsfPers.Size() == 0)
opencascade::handle<BVH_Tree<Standard_Real, 3> > aBVHTree; {
return;
}
myIsCulled = myAlwaysRenderedMap.IsEmpty();
OpenGl_BVHTreeSelector::CullingContext aCullCtx;
theSelector.SetCullingDistance(aCullCtx, myLayerSettings.CullingDistance());
theSelector.SetCullingSize (aCullCtx, myLayerSettings.CullingSize());
for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx)
{ {
const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1;
opencascade::handle<BVH_Tree<Standard_Real, 3> > aBVHTree;
if (isTrsfPers) if (isTrsfPers)
{ {
if (myBVHPrimitivesTrsfPers.Size() == 0) if (myBVHPrimitivesTrsfPers.Size() == 0)
@ -549,26 +538,23 @@ void OpenGl_Layer::traverse (const OpenGl_BVHTreeSelector& theSelector) const
aBVHTree = myBVHPrimitives.BVH(); aBVHTree = myBVHPrimitives.BVH();
} }
Standard_Integer aNode = 0; // a root node if (theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
if (!theSelector.Intersect (aBVHTree->MinPoint (0),
aBVHTree->MaxPoint (0)))
{ {
continue; continue;
} }
myIsCulled = false;
Standard_Integer aStack[BVH_Constants_MaxTreeDepth]; Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
Standard_Integer aHead = -1; Standard_Integer aHead = -1;
Standard_Integer aNode = 0; // a root node
for (;;) for (;;)
{ {
if (!aBVHTree->IsOuter (aNode)) if (!aBVHTree->IsOuter (aNode))
{ {
const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode); const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode); const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx), const Standard_Boolean isLeftChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
aBVHTree->MaxPoint (aLeftChildIdx)); const Standard_Boolean isRightChildIn = !theSelector.IsCulled (aCullCtx, aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
aBVHTree->MaxPoint (aRightChildIdx));
if (isLeftChildIn if (isLeftChildIn
&& isRightChildIn) && isRightChildIn)
{ {
@ -743,7 +729,7 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
} }
// render priority list // render priority list
theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace); renderAll (theWorkspace);
if (hasLocalCS) if (hasLocalCS)
{ {

View File

@ -92,7 +92,7 @@ public:
//! Marks BVH tree for given priority list as dirty and //! Marks BVH tree for given priority list as dirty and
//! marks primitive set for rebuild. //! marks primitive set for rebuild.
void InvalidateBVHData() const; void InvalidateBVHData();
//! Marks cached bounding box as obsolete. //! Marks cached bounding box as obsolete.
void InvalidateBoundingBox() const void InvalidateBoundingBox() const
@ -119,6 +119,14 @@ public:
const Standard_Integer theWindowWidth, const Standard_Integer theWindowWidth,
const Standard_Integer theWindowHeight) const; const Standard_Integer theWindowHeight) const;
//! Update culling state - should be called before rendering.
//! Traverses through BVH tree to determine which structures are in view volume.
void UpdateCulling (const OpenGl_BVHTreeSelector& theSelector,
const Standard_Boolean theToTraverse);
//! Returns TRUE if layer is empty or has been discarded entirely by culling test.
bool IsCulled() const { return myNbStructures == 0 || myIsCulled; }
// Render all structures. // Render all structures.
void Render (const Handle(OpenGl_Workspace)& theWorkspace, void Render (const Handle(OpenGl_Workspace)& theWorkspace,
const OpenGl_GlobalLayerSettings& theDefaultSettings) const; const OpenGl_GlobalLayerSettings& theDefaultSettings) const;
@ -134,15 +142,9 @@ protected:
//! Updates BVH trees if their state has been invalidated. //! Updates BVH trees if their state has been invalidated.
void updateBVH() const; void updateBVH() const;
//! Traverses through BVH tree to determine which structures are in view volume.
void traverse (const OpenGl_BVHTreeSelector& theSelector) const;
//! Iterates through the hierarchical list of existing structures and renders them all. //! Iterates through the hierarchical list of existing structures and renders them all.
void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const; void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const;
//! Iterates through the hierarchical list of existing structures and renders only overlapping ones.
void renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const;
private: private:
//! Array of OpenGl_Structures by priority rendered in layer. //! Array of OpenGl_Structures by priority rendered in layer.
@ -164,7 +166,7 @@ private:
mutable NCollection_IndexedMap<const OpenGl_Structure*> myAlwaysRenderedMap; mutable NCollection_IndexedMap<const OpenGl_Structure*> myAlwaysRenderedMap;
//! Is needed for implementation of stochastic order of BVH traverse. //! Is needed for implementation of stochastic order of BVH traverse.
mutable Standard_Boolean myBVHIsLeftChildQueuedFirst; Standard_Boolean myBVHIsLeftChildQueuedFirst;
//! Defines if the primitive set for BVH is outdated. //! Defines if the primitive set for BVH is outdated.
mutable Standard_Boolean myIsBVHPrimitivesNeedsReset; mutable Standard_Boolean myIsBVHPrimitivesNeedsReset;
@ -172,13 +174,12 @@ private:
//! Defines if the cached bounding box is outdated. //! Defines if the cached bounding box is outdated.
mutable bool myIsBoundingBoxNeedsReset[2]; mutable bool myIsBoundingBoxNeedsReset[2];
//! Flag indicating that this layer is marked culled as whole
bool myIsCulled;
//! Cached layer bounding box. //! Cached layer bounding box.
mutable Bnd_Box myBoundingBox[2]; mutable Bnd_Box myBoundingBox[2];
public:
DEFINE_STANDARD_ALLOC
}; };
#endif //_OpenGl_Layer_Header #endif //_OpenGl_Layer_Header

View File

@ -509,6 +509,26 @@ void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId theLaye
aLayer.SetLayerSettings (theSettings); aLayer.SetLayerSettings (theSettings);
} }
//=======================================================================
//function : UpdateCulling
//purpose :
//=======================================================================
void OpenGl_LayerList::UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
const Standard_Boolean theToDrawImmediate)
{
const OpenGl_BVHTreeSelector& aSelector = theWorkspace->View()->BVHTreeSelector();
for (OpenGl_IndexedLayerIterator anIts (myLayers); anIts.More(); anIts.Next())
{
OpenGl_Layer& aLayer = *anIts.ChangeValue();
if (aLayer.IsImmediate() != theToDrawImmediate)
{
continue;
}
aLayer.UpdateCulling (aSelector, theWorkspace->IsCullingEnabled());
}
}
//======================================================================= //=======================================================================
//function : Render //function : Render
//purpose : //purpose :
@ -588,7 +608,7 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
{ {
aClearDepthLayer = aLayerIter.Index(); aClearDepthLayer = aLayerIter.Index();
} }
if (aLayer.NbStructures() < 1) if (aLayer.IsCulled())
{ {
continue; continue;
} }

View File

@ -88,6 +88,10 @@ public:
void SetLayerSettings (const Graphic3d_ZLayerId theLayerId, void SetLayerSettings (const Graphic3d_ZLayerId theLayerId,
const Graphic3d_ZLayerSettings& theSettings); const Graphic3d_ZLayerSettings& theSettings);
//! Update culling state - should be called before rendering.
void UpdateCulling (const Handle(OpenGl_Workspace)& theWorkspace,
const Standard_Boolean theToDrawImmediate);
//! Render this element //! Render this element
void Render (const Handle(OpenGl_Workspace)& theWorkspace, void Render (const Handle(OpenGl_Workspace)& theWorkspace,
const Standard_Boolean theToDrawImmediate, const Standard_Boolean theToDrawImmediate,

View File

@ -119,13 +119,10 @@ public:
//! Releases structure resources. //! Releases structure resources.
virtual void Release (const Handle(OpenGl_Context)& theGlCtx); virtual void Release (const Handle(OpenGl_Context)& theGlCtx);
//! Marks structure as not overlapping view volume (as it is by default). //! Marks structure as culled/not culled.
void ResetCullingStatus() const void SetCulled (Standard_Boolean theIsCulled) const
{ {
if (!IsAlwaysRendered()) myIsCulled = theIsCulled && !IsAlwaysRendered();
{
myIsCulled = Standard_True;
}
} }
//! Marks structure as overlapping the current view volume one. //! Marks structure as overlapping the current view volume one.

View File

@ -336,7 +336,7 @@ public:
//! Returns selector for BVH tree, providing a possibility to store information //! Returns selector for BVH tree, providing a possibility to store information
//! about current view volume and to detect which objects are overlapping it. //! about current view volume and to detect which objects are overlapping it.
OpenGl_BVHTreeSelector& BVHTreeSelector() { return myBVHSelector; } const OpenGl_BVHTreeSelector& BVHTreeSelector() const { return myBVHSelector; }
//! Returns true if there are immediate structures to display //! Returns true if there are immediate structures to display
bool HasImmediateStructures() const bool HasImmediateStructures() const

View File

@ -881,6 +881,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
// note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale // note that we pass here window dimensions ignoring Graphic3d_RenderingParams::RenderResolutionScale
myBVHSelector.SetViewVolume (myCamera); myBVHSelector.SetViewVolume (myCamera);
myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio()); myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio());
myBVHSelector.CacheClipPtsProjections();
const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager();
if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
@ -1058,6 +1059,8 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
myRaytraceInitStatus == OpenGl_RT_FAIL || myRaytraceInitStatus == OpenGl_RT_FAIL ||
aCtx->IsFeedback(); aCtx->IsFeedback();
myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
if (!toRenderGL) if (!toRenderGL)
{ {
toRenderGL = !initRaytraceResources (aCtx) || toRenderGL = !initRaytraceResources (aCtx) ||