1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/OpenGl/OpenGl_Layer.cxx
kgv a195430212 0024394: Visualization - implement more general way for rendering of immediate objects
Move OpenGl_Structure::myZLayer to base class Graphic3d_CStructure.
Graphic3d_ZLayerId - introduce new pre-defined ZLayers.
Do not clear Depth buffer twice for default ZLayer.

AIS_InteractiveContext::Display() - add new argument AIS_DisplayStatus to specify displaying status.

Drop unused Graphic3d_CPick and related methods.
Drop OpenGl_Structure::myNamedStatus - use flags from parent class Graphic3d_CStructure directly.
OpenGl_LayerList ::ChangeLayer(), ::ChangePriority - fix structure remove from unexpected layer.
Merge class OpenGl_PriorityList into OpenGl_Layer.

PrsMgr_PresentationManager::mySelectionColor - store selection color as field of Presentation Manager.
PrsMgr_Presentation class - do not declare private methods as virtual.
PrsMgr_Presentation::Highlight() - extend method syntax and drop methods ::Color() and ::BoundBox().

PrsMgr_PresentableObject - store ZLayer in presentable object
to display object presentations in required layer directly
(without displaying it in wrong layer first).

test/mesh/end - force re-displaying the shape to compute mesh anew

Test-case for issue
2015-01-22 17:31:53 +03:00

325 lines
10 KiB
C++

// Created on: 2014-03-31
// Created by: Danila ULYANOV
// Copyright (c) 2014 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.
#include <OpenGl_Layer.hxx>
#include <OpenGl_BVHTreeSelector.hxx>
#include <OpenGl_Structure.hxx>
#include <OpenGl_View.hxx>
#include <OpenGl_Workspace.hxx>
// =======================================================================
// function : OpenGl_PriorityList
// purpose :
// =======================================================================
OpenGl_Layer::OpenGl_Layer (const Standard_Integer theNbPriorities)
: myArray (0, theNbPriorities - 1),
myNbStructures (0),
myBVHIsLeftChildQueuedFirst (Standard_True),
myIsBVHPrimitivesNeedsReset (Standard_False)
{
//
}
// =======================================================================
// function : ~OpenGl_Layer
// purpose :
// =======================================================================
OpenGl_Layer::~OpenGl_Layer()
{
//
}
// =======================================================================
// function : Add
// purpose :
// =======================================================================
void OpenGl_Layer::Add (const OpenGl_Structure* theStruct,
const Standard_Integer thePriority,
Standard_Boolean isForChangePriority)
{
const Standard_Integer anIndex = Min (Max (thePriority, 0), myArray.Length() - 1);
if (theStruct == NULL)
{
return;
}
myArray (anIndex).Append (theStruct);
if (theStruct->IsAlwaysRendered())
{
theStruct->MarkAsNotCulled();
}
else if (!isForChangePriority)
{
myBVHPrimitives.Add (theStruct);
}
++myNbStructures;
}
// =======================================================================
// function : Remove
// purpose :
// =======================================================================
bool OpenGl_Layer::Remove (const OpenGl_Structure* theStruct,
Standard_Integer& thePriority,
Standard_Boolean isForChangePriority)
{
if (theStruct == NULL)
{
thePriority = -1;
return false;
}
const Standard_Integer aNbPriorities = myArray.Length();
for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
{
OpenGl_SequenceOfStructure& aSeq = myArray (aPriorityIter);
for (OpenGl_SequenceOfStructure::Iterator aStructIter (aSeq); aStructIter.More(); aStructIter.Next())
{
if (aStructIter.Value() == theStruct)
{
aSeq.Remove (aStructIter);
if (!theStruct->IsAlwaysRendered()
&& !isForChangePriority)
{
myBVHPrimitives.Remove (theStruct);
}
--myNbStructures;
thePriority = aPriorityIter;
return true;
}
}
}
thePriority = -1;
return false;
}
// =======================================================================
// function : InvalidateBVHData
// purpose :
// =======================================================================
void OpenGl_Layer::InvalidateBVHData()
{
myIsBVHPrimitivesNeedsReset = Standard_True;
}
// =======================================================================
// function : renderAll
// purpose :
// =======================================================================
void OpenGl_Layer::renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const
{
const Standard_Integer aNbPriorities = myArray.Length();
for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
{
for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
{
const OpenGl_Structure* aStruct = aStructIter.Value();
if (!aStruct->IsVisible())
{
continue;
}
aStruct->Render (theWorkspace);
}
}
}
// =======================================================================
// function : renderTraverse
// purpose :
// =======================================================================
void OpenGl_Layer::renderTraverse (const Handle(OpenGl_Workspace)& theWorkspace) const
{
if (myIsBVHPrimitivesNeedsReset)
{
myBVHPrimitives.Assign (myArray);
myIsBVHPrimitivesNeedsReset = Standard_False;
}
OpenGl_BVHTreeSelector& aSelector = theWorkspace->ActiveView()->BVHTreeSelector();
traverse (aSelector);
const Standard_Integer aNbPriorities = myArray.Length();
for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
{
for (OpenGl_SequenceOfStructure::Iterator aStructIter (myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
{
const OpenGl_Structure* aStruct = aStructIter.Value();
if (!aStruct->IsVisible()
|| aStruct->IsCulled())
{
continue;
}
aStruct->Render (theWorkspace);
aStruct->ResetCullingStatus();
}
}
}
// =======================================================================
// function : traverse
// purpose :
// =======================================================================
void OpenGl_Layer::traverse (OpenGl_BVHTreeSelector& theSelector) const
{
// handle a case when all objects are infinite
if (myBVHPrimitives.Size() == 0)
return;
const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVHTree = myBVHPrimitives.BVH();
Standard_Integer aNode = 0; // a root node
theSelector.CacheClipPtsProjections();
if (!theSelector.Intersect (aBVHTree->MinPoint (0),
aBVHTree->MaxPoint (0)))
{
return;
}
Standard_Integer aStack[32];
Standard_Integer aHead = -1;
for (;;)
{
if (!aBVHTree->IsOuter (aNode))
{
const Standard_Integer aLeftChildIdx = aBVHTree->LeftChild (aNode);
const Standard_Integer aRightChildIdx = aBVHTree->RightChild (aNode);
const Standard_Boolean isLeftChildIn = theSelector.Intersect (aBVHTree->MinPoint (aLeftChildIdx),
aBVHTree->MaxPoint (aLeftChildIdx));
const Standard_Boolean isRightChildIn = theSelector.Intersect (aBVHTree->MinPoint (aRightChildIdx),
aBVHTree->MaxPoint (aRightChildIdx));
if (isLeftChildIn
&& isRightChildIn)
{
aNode = myBVHIsLeftChildQueuedFirst ? aLeftChildIdx : aRightChildIdx;
++aHead;
aStack[aHead] = myBVHIsLeftChildQueuedFirst ? aRightChildIdx : aLeftChildIdx;
myBVHIsLeftChildQueuedFirst = !myBVHIsLeftChildQueuedFirst;
}
else if (isLeftChildIn
|| isRightChildIn)
{
aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
}
else
{
if (aHead < 0)
{
return;
}
aNode = aStack[aHead];
--aHead;
}
}
else
{
if (theSelector.Intersect (aBVHTree->MinPoint (aNode),
aBVHTree->MaxPoint (aNode)))
{
Standard_Integer aIdx = aBVHTree->BegPrimitive (aNode);
myBVHPrimitives.GetStructureById (aIdx)->MarkAsNotCulled();
if (aHead < 0)
{
return;
}
aNode = aStack[aHead];
--aHead;
}
}
}
}
// =======================================================================
// function : Append
// purpose :
// =======================================================================
Standard_Boolean OpenGl_Layer::Append (const OpenGl_Layer& theOther)
{
// the source priority list shouldn't have more priorities
const Standard_Integer aNbPriorities = theOther.NbPriorities();
if (aNbPriorities > NbPriorities())
{
return Standard_False;
}
// add all structures to destination priority list
for (Standard_Integer aPriorityIter = 0; aPriorityIter < aNbPriorities; ++aPriorityIter)
{
for (OpenGl_SequenceOfStructure::Iterator aStructIter (theOther.myArray (aPriorityIter)); aStructIter.More(); aStructIter.Next())
{
Add (aStructIter.Value(), aPriorityIter);
}
}
return Standard_True;
}
//=======================================================================
//function : Render
//purpose :
//=======================================================================
void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)& theWorkspace,
const OpenGl_GlobalLayerSettings& theDefaultSettings) const
{
TEL_POFFSET_PARAM anAppliedOffsetParams = theWorkspace->AppliedPolygonOffset();
// separate depth buffers
if (IsSettingEnabled (Graphic3d_ZLayerDepthClear))
{
glClear (GL_DEPTH_BUFFER_BIT);
}
// handle depth test
if (IsSettingEnabled (Graphic3d_ZLayerDepthTest))
{
// assuming depth test is enabled by default
glDepthFunc (theDefaultSettings.DepthFunc);
}
else
{
glDepthFunc (GL_ALWAYS);
}
// handle depth offset
if (IsSettingEnabled (Graphic3d_ZLayerDepthOffset))
{
theWorkspace->SetPolygonOffset (Aspect_POM_Fill,
myLayerSettings.DepthOffsetFactor,
myLayerSettings.DepthOffsetUnits);
}
else
{
theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
anAppliedOffsetParams.factor,
anAppliedOffsetParams.units);
}
// handle depth write
glDepthMask (IsSettingEnabled (Graphic3d_ZLayerDepthWrite) ? GL_TRUE : GL_FALSE);
// render priority list
theWorkspace->IsCullingEnabled() ? renderTraverse (theWorkspace) : renderAll (theWorkspace);
// always restore polygon offset between layers rendering
theWorkspace->SetPolygonOffset (anAppliedOffsetParams.mode,
anAppliedOffsetParams.factor,
anAppliedOffsetParams.units);
}