//! Remove group from this structure
virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) = 0;
+ //! Returns the number of LODs of the structure
virtual Standard_Integer NbDetailLevels() const = 0;
- virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo) = 0;
+ //! Sets range of LOD.
+ //! @param theLodIdx corresponds to the index of LOD in map of LOD manager. In case if no LOD was
+ //! removed, the LODs in map are located in order of addition and IDs are identical to the addition
+ //! iteration number
+ virtual void SetDetailLevelRange (const Standard_Integer theLodIdx, const Standard_Real theFrom, const Standard_Real theTo) = 0;
public:
#include <Standard_Macro.hxx>
#include <Standard_Transient.hxx>
+//! This structure is used for ranged LODs to store the lower and upper
+//! boundaries of the interval where the LOD is visible.
+//! It also performs the comparison that checks if the given value
+//! is in or out of the range.
struct Graphic3d_RangeOfLOD
{
public:
+
+ //! Constructs a range with the given boundaries
Graphic3d_RangeOfLOD (const Standard_Real theFrom, const Standard_Real theTo)
: myTo (theTo),
myFrom (theFrom)
"The upper boundary of the interval must be greater than lower one!");
}
+ //! Returns true, if the given value is between the lower and
+ //! upper boundaries
Standard_Boolean IsIn (const Standard_Real theVal) const
{
return (myFrom < theVal) && (theVal < myTo);
Standard_Real myTo;
};
+//! Base class for level of detail representation.
+//! It provides an interface to create and customize graphic groups for
+//! the LOD and contains information about the range for ranged LODs.
class Graphic3d_LOD : public Standard_Transient
{
public:
+
+ //! Destroys graphic groups of the LOD
Standard_EXPORT virtual ~Graphic3d_LOD();
Standard_EXPORT void SetRange (const Standard_Real theFrom, const Standard_Real theTo);
return myRange;
}
+ //! Create a new group within this LOD
Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& /*theParentStruct*/)
{
return NULL;
return myGroups;
}
+ //! If theWithDestruction is true, all the graphic groups of LOD will be destroyed
+ //! and new group must be created for further displaying.
+ //! If theWithDestruction is false, all the data of groups is reset to defauls
+ //! so it is threated like empty.
Standard_EXPORT virtual void Clear (const Standard_Boolean theWithDestruction);
DEFINE_STANDARD_RTTIEXT (Graphic3d_LOD, Standard_Transient)
protected:
+
+ //! Creates a new LOD that is visible from any distance
Standard_EXPORT Graphic3d_LOD() : myRange (-DBL_MAX, DBL_MAX) {};
protected:
class Graphic3d_CStructure;
class Graphic3d_Camera;
+//! This class implements computation of distance metrics for determinig
+//! LOD visibility. It computes distance from center of geometry of the object
+//! to camera's eye position.
class Graphic3d_LODDistanceSelector : public Graphic3d_LODSelector
{
public:
// purpose :
//=======================================================================
Graphic3d_LODManager::Graphic3d_LODManager (const Handle(Graphic3d_Structure)& theParentStructure)
- : myCurrentLODIdx (-1),
+ : myLodIndexes (NULL),
+ myIsToSortLods (Standard_False),
+ myCurrentLODIdx (-1),
mySelector (new Graphic3d_LODDistanceSelector())
{
myStructure = theParentStructure.operator->();
}
+//=======================================================================
+// function : Destructor
+// purpose :
+//=======================================================================
+Graphic3d_LODManager::~Graphic3d_LODManager()
+{
+ Clear (Standard_True);
+
+ myLODs.Clear();
+ myLodIndexes.Nullify();
+ mySelector.Nullify();
+}
+
//=======================================================================
// function : GetCurrentLODIdx
// purpose :
//=======================================================================
-Standard_Integer Graphic3d_LODManager::GetCurrentLODIdx (const Handle(Graphic3d_Camera)& theCamera)
+Standard_Boolean Graphic3d_LODManager::HasLodToDisplay (const Handle(Graphic3d_Camera)& theCamera)
{
if (theCamera->WorldViewProjState() == myPrevCameraState && myCurrentLODIdx != -1)
- return myCurrentLODIdx;
+ return Standard_True;
+
+ if (myIsToSortLods)
+ sortLODs();
myPrevCameraState = theCamera->WorldViewProjState();
const Standard_Real aMetric = mySelector->ComputeMetric (myStructure->CStructure(), theCamera);
- if (myLODs.Value (0)->GetRange().IsLess (aMetric))
+ if (myLODs.FindKey (1)->GetRange().IsLess (aMetric))
{
myCurrentLODIdx = -1;
+ return Standard_False;
}
- else if (myLODs.Value (myLODs.Size() - 1)->GetRange().IsGreater (aMetric))
+ else if (myLODs.FindKey (myLODs.Extent())->GetRange().IsGreater (aMetric))
{
- myCurrentLODIdx = myLODs.Size() - 1;
+ myCurrentLODIdx = myLODs.Extent();
}
else
{
- for (Standard_Integer aLodIdx = 0; aLodIdx < myLODs.Size(); ++aLodIdx)
+ for (Standard_Integer aLodIdx = 1; aLodIdx <= myLODs.Extent(); ++aLodIdx)
{
- if (myLODs.Value (aLodIdx)->GetRange().IsIn (aMetric))
+ if (myLODs.FindKey (aLodIdx)->GetRange().IsIn (aMetric))
{
myCurrentLODIdx = aLodIdx;
break;
}
}
- return myCurrentLODIdx;
+ return Standard_True;
}
//=======================================================================
// function : SetRange
// purpose :
//=======================================================================
-void Graphic3d_LODManager::SetRange (const Standard_Integer theLodIdx,
+void Graphic3d_LODManager::SetRange (Standard_Integer theLodIdx,
const Standard_Real theFrom,
const Standard_Real theTo)
{
- myLODs.ChangeValue (theLodIdx)->SetRange (theFrom, theTo);
- sortLODs();
+ if (theLodIdx < 1 || theLodIdx > myLODs.Extent())
+ return;
+
+ myLODs.FindKey (theLodIdx)->SetRange (theFrom, theTo);
+ myIsToSortLods = Standard_True;
}
//=======================================================================
//=======================================================================
const Graphic3d_SequenceOfGroup& Graphic3d_LODManager::GetCurrentGroups() const
{
- return myLODs.Value (myCurrentLODIdx)->GetDrawGroups();
+ return myLODs.FindKey (myCurrentLODIdx)->GetDrawGroups();
}
//=======================================================================
//=======================================================================
void Graphic3d_LODManager::GetCombinedBndBox (Graphic3d_BndBox4f& theBndBox) const
{
- for (Standard_Integer aLodIdx = 0; aLodIdx < myLODs.Size(); ++aLodIdx)
+ for (Standard_Integer aLodIdx = 1; aLodIdx <= myLODs.Extent(); ++aLodIdx)
{
- const Graphic3d_SequenceOfGroup& aGroups = myLODs.Value (aLodIdx)->GetDrawGroups();
+ const Graphic3d_SequenceOfGroup& aGroups = myLODs.FindKey (aLodIdx)->GetDrawGroups();
for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
{
theBndBox.Combine (aGroupIter.Value()->BoundingBox());
//=======================================================================
Standard_Boolean Graphic3d_LODManager::IsEmpty() const
{
- for (Standard_Integer aLodIdx = 0; aLodIdx < myLODs.Size(); ++aLodIdx)
+ for (Standard_Integer aLodIdx = 1; aLodIdx <= myLODs.Extent(); ++aLodIdx)
{
- const Graphic3d_SequenceOfGroup& aGroups = myLODs.Value (aLodIdx)->GetDrawGroups();
+ const Graphic3d_SequenceOfGroup& aGroups = myLODs.FindKey (aLodIdx)->GetDrawGroups();
if (!aGroups.IsEmpty())
return Standard_False;
}
//=======================================================================
void Graphic3d_LODManager::Clear (const Standard_Boolean theWithDestruction)
{
- for (Standard_Integer aLodIdx = 0; aLodIdx < myLODs.Size(); ++aLodIdx)
+ for (Standard_Integer aLodIdx = 1; aLodIdx <= myLODs.Extent(); ++aLodIdx)
{
- myLODs.Value (aLodIdx)->Clear (theWithDestruction);
+ myLODs.FindKey (aLodIdx)->Clear (theWithDestruction);
}
}
//=======================================================================
const Handle(Graphic3d_LOD)& Graphic3d_LODManager::GetLodById (const Standard_Integer theLodIdx)
{
- Standard_ASSERT_RAISE (theLodIdx >= 0 || theLodIdx < myLODs.Size(),
+ Standard_ASSERT_RAISE (theLodIdx > 0 || theLodIdx <= myLODs.Size(),
"Index of LOD is out of range");
- return myLODs.Value (theLodIdx);
+ return myLODs.FindKey (theLodIdx);
+}
+
+Standard_Boolean Graphic3d_LODManager::HasLod (const Handle(Graphic3d_LOD)& theLod) const
+{
+ return myLODs.Contains (theLod);
}
#include <Graphic3d_CStructure.hxx>
#include <Graphic3d_Camera.hxx>
-#include <Graphic3d_LOD.hxx>
#include <Graphic3d_LODSelector.hxx>
#include <Graphic3d_LODDistanceSelector.hxx>
#include <Graphic3d_SequenceOfGroup.hxx>
#include <Graphic3d_StructurePtr.hxx>
-#include <NCollection_Vector.hxx>
+#include <NCollection_IndexedMap.hxx>
#include <Standard.hxx>
#include <Standard_Handle.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
+class Graphic3d_LOD;
+
+typedef NCollection_IndexedMap<Handle(Graphic3d_LOD)> Graphic3d_MapOfLODs;
+
+//! This class is used to manage all the LODs of one Graphic3d_Structure.
+//! It provides an interface for the following actions:
+//! - addition of a new LOD;
+//! - management of current method for LOD metrics calculation;
+//! - access to LODs and its characteristics, such as quantity, range,
+//! combined bounding box.
+//! The class also runs a procedure that picks the LOD that should be
+//! rendered according to the current state of camera and stores choosen
+//! LOD index.
class Graphic3d_LODManager : public Standard_Transient
{
public:
- Standard_EXPORT virtual ~Graphic3d_LODManager() {};
+ //! Nullifies the pointer to current selector and clears used data maps,
+ //! destroys the LODs used, so they can not be referenced to after the destruction
+ //! of corresponding LOD manager
+ Standard_EXPORT virtual ~Graphic3d_LODManager();
+ //! Sets up a method for LOD metrics computation
Standard_EXPORT void SetSelector (const Handle(Graphic3d_LODSelector)& theSelector)
{
mySelector = theSelector;
}
+ //! Returns a number of addded detail levels
Standard_EXPORT inline Standard_Integer NbOfDetailLevels() const
{
return myLODs.Size();
}
+ //! For ranged LODs, sets the distance interval where the LOD will be visible.
+ //! @param theLodIdx the index of LOD in sorted list
Standard_EXPORT void SetRange (const Standard_Integer theLodIdx,
const Standard_Real theFrom,
const Standard_Real theTo);
- Standard_EXPORT Standard_Integer GetCurrentLODIdx (const Handle(Graphic3d_Camera)& theCamera);
+ //! Returns own index of the LOD that is displayed
+ Standard_EXPORT Standard_Boolean HasLodToDisplay (const Handle(Graphic3d_Camera)& theCamera);
+ //! Returns graphic groups of the LOD that must be displayed according to the current
+ //! camera state
Standard_EXPORT const Graphic3d_SequenceOfGroup& GetCurrentGroups() const;
Standard_EXPORT virtual Handle(Graphic3d_LOD) AddNewLOD() = 0;
+ //! Returns combined bounding box for all LOD groups that were added to this
+ //! manager
Standard_EXPORT void GetCombinedBndBox (Graphic3d_BndBox4f& theBndBox) const;
//! Returns false if at least one of LODs has non-empty sequence of Graphic3d_Groups
Standard_EXPORT Standard_Boolean IsEmpty() const;
+ //! Iterates through added LODs and clears up its resources.
+ //! If theWithDestruction is true, all the graphic groups of each LOD will be destroyed
+ //! and new group must be created for further displaying.
+ //! If theWithDestruction is false, all the data of groups is reset to defauls
+ //! so it is threated like empty.
Standard_EXPORT void Clear (const Standard_Boolean theWithDestruction);
+ //! The indexes are from 1 to NbOfDetailLevels(). The ID of the element corresponds
+ //! to the index of the LOD in the map of LOD manager. Therefore, in case if no LOD was
+ //! removed, the LODs in map are located in order of addition and IDs are identical to
+ //! the addition iteration number
Standard_EXPORT const Handle(Graphic3d_LOD)& GetLodById (const Standard_Integer theLodIdx);
+ //! Checks if the given LOD is added to this manager
+ Standard_EXPORT Standard_Boolean HasLod (const Handle(Graphic3d_LOD)& theLod) const;
+
DEFINE_STANDARD_RTTIEXT (Graphic3d_LODManager, Standard_Transient)
protected:
+
+ //! Creates an empty manager with invalid LOD metrics calculation method
Standard_EXPORT Graphic3d_LODManager (const Handle(Graphic3d_Structure)& theParentStructure);
+ //! Sorts LODs in the map according to its ranges to improve search for LOD to display.
+ //! After the sort is done, flag myIsToSortLods will be set to false.
Standard_EXPORT virtual void sortLODs() {};
protected:
- NCollection_Vector<Handle(Graphic3d_LOD)> myLODs;
+ Graphic3d_MapOfLODs myLODs; //!< Map of LODs
+ Handle(TColStd_HArray1OfInteger) myLodIndexes; //!< Array of LOD indexes, for sorting purposes
+ Standard_Boolean myIsToSortLods; //!< Is true when LODs must be sorted before picking procedure. For example, when new LOD was added
private:
- Standard_Integer myCurrentLODIdx;
- Handle(Graphic3d_LODSelector) mySelector;
- Graphic3d_StructurePtr myStructure;
- Graphic3d_WorldViewProjState myPrevCameraState;
+ Standard_Integer myCurrentLODIdx; //!< Index of current LOD that should be rendered; is -1 by default.
+ Handle(Graphic3d_LODSelector) mySelector; //!< A wrapper that performs measurement of LOD metrics
+ Graphic3d_StructurePtr myStructure; //!< A pointer to graphic structure that is common for all LODs
+ Graphic3d_WorldViewProjState myPrevCameraState; //!< Previous state of the camera for current LOD detection procedure
};
DEFINE_STANDARD_HANDLE (Graphic3d_LODManager, Standard_Transient)
class Graphic3d_CStructure;
class Graphic3d_Camera;
+//! Base interface for classes implementing computation of
+//! LOD visibility metrics
class Graphic3d_LODSelector : public Standard_Transient
{
public:
+ //! Computes the value of LOD visibility metrics according to current camera state
+ //! and choosen approach for metrics calculation
virtual Standard_Real ComputeMetric (const Handle(Graphic3d_CStructure)& theParentStructure,
const Handle(Graphic3d_Camera)& theCamera) = 0;
//! Returns the low-level structure
const Handle(Graphic3d_CStructure)& CStructure() const;
+ //! Returns number of LODs created for this structure
Standard_EXPORT Standard_Integer NbDetailLevels() const;
+ //! Sets range of LOD.
+ //! @param theLodIdx corresponds to the index of LOD in map of LOD manager. In case if no LOD was
+ //! removed, the LODs in map are located in order of addition and IDs are identical to the addition
+ //! iteration number
Standard_EXPORT void SetDetailLevelRange (const Standard_Integer theIdOfLOD, const Standard_Real theFrom, const Standard_Real theTo);
friend class Graphic3d_Group;
#include <OpenGl_AspectLine.hxx>
#include <OpenGl_Structure.hxx>
+//! This class provides an implementation of TKOpenGl-dependent LOD
+//! functionality, such as creation of new graphic groups and cleaning
+//! up graphic resources
class OpenGl_LOD : public Graphic3d_LOD
{
public:
Standard_EXPORT OpenGl_LOD() : Graphic3d_LOD () {};
Standard_EXPORT ~OpenGl_LOD() {};
+ //! Creates new graphic group for LOD rendering and adds it to the map
Standard_EXPORT virtual Handle(Graphic3d_Group) NewGroup (const Handle(Graphic3d_Structure)& theParentStruct) Standard_OVERRIDE;
+ //! Releases graphic resources of each created graphic group
void ReleaseGraphicResources (const Handle(OpenGl_Context)& theGlCtx);
DEFINE_STANDARD_RTTIEXT (OpenGl_LOD, Graphic3d_LOD)
{
public:
- CompareLODS (const NCollection_Vector<Handle(Graphic3d_LOD)>& theLODs)
+ CompareLODS (const Graphic3d_MapOfLODs& theLODs)
: myLODs (theLODs) {}
- Standard_Boolean operator() (const Handle(Graphic3d_LOD)& theLeft, const Handle(Graphic3d_LOD)& theRight) const
+ Standard_Boolean operator() (const Standard_Integer theLeftIdx, const Standard_Integer theRightIdx) const
{
- return theLeft->GetRange() < theRight->GetRange();
+ return myLODs.FindKey (theLeftIdx)->GetRange() < myLODs.FindKey (theRightIdx)->GetRange();
}
private:
void operator = (const CompareLODS&);
private:
- const NCollection_Vector<Handle(Graphic3d_LOD)>& myLODs;
+ const Graphic3d_MapOfLODs& myLODs;
};
}
Handle(Graphic3d_LOD) OpenGl_LODManager::AddNewLOD()
{
Handle(Graphic3d_LOD) aNewLOD = new OpenGl_LOD();
- myLODs.Append (aNewLOD);
- sortLODs();
+ myLODs.Add (aNewLOD);
+ myIsToSortLods = Standard_True;
return aNewLOD;
}
//=======================================================================
void OpenGl_LODManager::sortLODs()
{
- std::sort (myLODs.begin(), myLODs.end(), CompareLODS (myLODs));
+ Standard_Integer aIndArrSize = myLODs.Extent();
+ myLodIndexes.Nullify();
+ myLodIndexes = new TColStd_HArray1OfInteger (0, aIndArrSize - 1);
+ for (Standard_Integer aIdx = 0; aIdx < aIndArrSize; ++aIdx)
+ {
+ myLodIndexes->SetValue (aIdx, aIdx + 1);
+ }
+ TColStd_Array1OfInteger& anIdxArr = myLodIndexes->ChangeArray1();
+ std::sort (anIdxArr.begin(), anIdxArr.end(), CompareLODS (myLODs));
+ myIsToSortLods = Standard_False;
}
#include <Graphic3d_LODManager.hxx>
+//! This class provides an API for LOD manager to TKOpenGl
+//! structures, such as OpenGl_Structure. It also implements
+//! the TKOpenGl-dependent functionality of LOD manager, for
+//! example, creation of a new LOD.
class OpenGl_LODManager : public Graphic3d_LODManager
{
public:
+
+ //! Creates new empty manager and checks the parent structure pointer for validity
Standard_EXPORT OpenGl_LODManager (const Handle(Graphic3d_Structure)& theParentStructure);
Standard_EXPORT virtual ~OpenGl_LODManager() {};
+ //! Creates new LOD without any graphic groups and marks map of LODs for sorting
Standard_EXPORT virtual Handle(Graphic3d_LOD) AddNewLOD() Standard_OVERRIDE;
DEFINE_STANDARD_RTTIEXT (OpenGl_LODManager, Graphic3d_LODManager)
protected:
+
+ //! Sorts added LODs according to its ranges in order to speed up
+ //! the process of picking the LOD to display
Standard_EXPORT virtual void sortLODs() Standard_OVERRIDE;
};
return;
}
- if (!myLODManager.IsNull() && myLODManager->GetCurrentLODIdx (theWorkspace->View()->Camera()) == -1)
+ if (!myLODManager.IsNull() && !myLODManager->HasLodToDisplay (theWorkspace->View()->Camera()))
return;
const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
}
if (!myLODManager.IsNull())
{
- for (Standard_Integer aLodIdx = 0; aLodIdx < myLODManager->NbOfDetailLevels(); ++aLodIdx)
+ for (Standard_Integer aLodIdx = 1; aLodIdx <= myLODManager->NbOfDetailLevels(); ++aLodIdx)
{
Handle(OpenGl_LOD) aLod = Handle(OpenGl_LOD)::DownCast (myLODManager->GetLodById (aLodIdx));
aLod->ReleaseGraphicResources (theGlCtx);
//function : SetDetailLevelRange
//purpose :
//=======================================================================
-void OpenGl_Structure::SetDetailLevelRange (const Standard_Integer theIdOfLOD,
+void OpenGl_Structure::SetDetailLevelRange (const Standard_Integer theLodIdx,
const Standard_Real theFrom,
const Standard_Real theTo)
{
Standard_ASSERT_RAISE (theFrom < theTo,
"The upper boundary of the interval must be greater than lower one!");
- if (myLODManager.IsNull() || theIdOfLOD < 0 || theIdOfLOD > myLODManager->NbOfDetailLevels())
+ if (myLODManager.IsNull() || theLodIdx < 1 || theLodIdx > myLODManager->NbOfDetailLevels())
return;
- myLODManager->SetRange (theIdOfLOD, theFrom, theTo);
+ myLODManager->SetRange (theLodIdx, theFrom, theTo);
}
//=======================================================================
//! Remove group from this structure
Standard_EXPORT virtual void RemoveGroup (const Handle(Graphic3d_Group)& theGroup) Standard_OVERRIDE;
- Standard_EXPORT virtual void SetDetailLevelRange (const Standard_Integer theIdOfLOD,
+ Standard_EXPORT virtual void SetDetailLevelRange (const Standard_Integer theLodIdx,
const Standard_Real theFrom,
const Standard_Real theTo) Standard_OVERRIDE;
VDisplayAISObject (aShapeName, anOriginMesh);
aCtx->Deactivate (anOriginMesh);
- Standard_Integer aLodIdx = 0;
+ Standard_Integer aLodIdx = 1;
for (NCollection_List<DetailLevelData>::Iterator aLodDataIter (myLODDataList); aLodDataIter.More(); aLodDataIter.Next())
{
anOriginMesh->Presentation()->SetDetailLevelRange (aLodIdx, aLodDataIter.Value().myFrom, aLodDataIter.Value().myTo);
+ aLodIdx++;
}
Draw::Set (aShapeName, new XSDRAWSTLVRML_DrawableMesh (anOriginMesh));