// Created on: 2014-08-15 // Created by: Varvara POSKONINA // Copyright (c) 2005-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. #ifndef _SelectMgr_SelectableObjectSet_HeaderFile #define _SelectMgr_SelectableObjectSet_HeaderFile #include "NCollection_Handle.hxx" #include "Select3D_BVHBuilder3d.hxx" #include "SelectMgr_SelectableObject.hxx" //! The purpose of this class is to organize all selectable objects into data structure, allowing to //! build set of BVH trees for each transformation persistence subclass of selectable objects. This //! allow to minify number of updates for BVH trees - for example 2D persistent object subclass //! depends only on camera's projection and the corresponding BVH tree needs to be updated when //! camera's projection parameters change, while another tree for non-persistent objects can be left //! unchanged in this case. class SelectMgr_SelectableObjectSet { public: //! This enumeration declares names for subsets of selectable objects. Each subset has independent //! BVH tree. The class maintains subsets of selectable objects by their persistence flag. This //! allows to restric rebuilding of the trees for particular subset when the camera change does //! not implicitly require it: //! - BVHSubset_3d refers to the subset of normal world-space 3D objects. Associated BVH tree does //! not depend on the camera's state at all. This subset uses binned BVH builder with 32 bins and //! 1 element per leaf. //! - BVHSubset_3dPersistent refers to the subset of 3D persistent selectable objects (rotate, //! pan, zoom persistence). Associated BVH tree needs to be updated when either the camera's //! projection and position change. This subset uses linear BVH builder with 32 levels of depth //! and 1 element per leaf. //! - BVHSubset_2dPersistent refers to the subset of 2D persistent selectable objects. Associated //! BVH tree needs to be updated only when camera's projection changes. Bounding volumes for this //! object subclass is represented directly in eye space coordinates. This subset uses linear BVH //! builder with 32 levels of depth and 1 element per leaf. //! - BVHSubset_ortho3dPersistent refers to the subset of 3D persistent selectable objects //! (rotate, pan, zoom persistence) that contains `Graphic3d_TMF_OrthoPers` persistence mode. //! Associated BVH tree needs to be updated when either the camera's projection and position //! change. This subset uses linear BVH builder with 32 levels of depth and 1 element per leaf. //! - BVHSubset_ortho2dPersistent refers to the subset of 2D persistent selectable objects //! that contains `Graphic3d_TMF_OrthoPers` persistence mode. Associated BVH tree //! needs to be updated only when camera's projection changes. Bounding volumes for this object //! subclass is represented directly in eye space coordinates. This subset uses linear BVH builder //! with 32 levels of depth and 1 element per leaf. enum BVHSubset { BVHSubset_3d, BVHSubset_3dPersistent, BVHSubset_2dPersistent, BVHSubset_ortho3dPersistent, BVHSubset_ortho2dPersistent, BVHSubsetNb }; public: //! Class to iterate sequentually over all objects from every subset. class Iterator { //! Short-cut definition of map iterator type typedef NCollection_IndexedMap>::Iterator ObjectMapIterator; public: //! Default constructor without initialization. Iterator() : mySet(nullptr), mySubsetIdx(BVHSubsetNb) { } //! Constructs and initializes the iterator. Iterator(const SelectMgr_SelectableObjectSet& theSet) { Init(theSet); } //! Initializes the iterator. void Init(const SelectMgr_SelectableObjectSet& theSet) { mySet = &theSet; mySubsetIdx = 0; mySubsetIt = ObjectMapIterator(theSet.myObjects[mySubsetIdx]); More(); } //! Returns false when there is no more objects to iterate over. bool More() { if (mySubsetIt.More()) { return true; } else if ((mySubsetIdx == BVHSubsetNb - 1) || mySet == nullptr) { return false; } mySubsetIt = ObjectMapIterator(mySet->myObjects[++mySubsetIdx]); return More(); } //! Steps to next selectable object in the set. void Next() { mySubsetIt.Next(); } //! Returns current object. const occ::handle& Value() const { return mySubsetIt.Value(); } private: const SelectMgr_SelectableObjectSet* mySet; int mySubsetIdx; ObjectMapIterator mySubsetIt; }; public: //! Creates new empty objects set and initializes BVH tree builders for each subset. Standard_EXPORT SelectMgr_SelectableObjectSet(); //! Releases resources of selectable object set. virtual ~SelectMgr_SelectableObjectSet() = default; //! Adds the new selectable object to the set. The selectable object is placed into one of the //! predefined subsets depending on its persistence type. After adding an object, this method //! marks the corresponding BVH tree for rebuild. //! @return true if selectable object is added, otherwise returns false (selectable object is //! already in the set). Standard_EXPORT bool Append(const occ::handle& theObject); //! Removes the selectable object from the set. The selectable object is removed from the subset //! it has been placed into. After removing an object, this method marks the corresponding //! BVH tree for rebuild. //! @return true if selectable object is removed, otherwise returns false (selectable object is //! not in the set). Standard_EXPORT bool Remove(const occ::handle& theObject); //! Performs necessary updates when object's persistence types changes. //! This method should be called right after changing transformation persistence flags of the //! objects and before updating BVH tree - to provide up-to-date state of the object set. Standard_EXPORT void ChangeSubset(const occ::handle& theObject); //! Updates outdated BVH trees and remembers the last state of the //! camera view-projection matrices and viewport (window) dimensions. Standard_EXPORT void UpdateBVH(const occ::handle& theCam, const NCollection_Vec2& theWinSize); //! Marks every BVH subset for update. Standard_EXPORT void MarkDirty(); //! Returns true if this objects set contains theObject given. bool Contains(const occ::handle& theObject) const { return myObjects[BVHSubset_3d].Contains(theObject) || myObjects[BVHSubset_3dPersistent].Contains(theObject) || myObjects[BVHSubset_2dPersistent].Contains(theObject) || myObjects[BVHSubset_ortho3dPersistent].Contains(theObject) || myObjects[BVHSubset_ortho2dPersistent].Contains(theObject); } //! Returns true if the object set does not contain any selectable objects. bool IsEmpty() const { return myObjects[BVHSubset_3d].IsEmpty() && myObjects[BVHSubset_3dPersistent].IsEmpty() && myObjects[BVHSubset_2dPersistent].IsEmpty() && myObjects[BVHSubset_ortho3dPersistent].IsEmpty() && myObjects[BVHSubset_ortho2dPersistent].IsEmpty(); } //! Returns true if the specified object subset is empty. bool IsEmpty(const BVHSubset theSubset) const { return myObjects[theSubset].IsEmpty(); } //! Returns object from subset theSubset by theIndex given. The method allows to get selectable //! object referred by the index of an element of the subset's BVH tree. const occ::handle& GetObjectById(const BVHSubset theSubset, const int theIndex) const { return myObjects[theSubset].FindKey(theIndex + 1); } //! Returns computed BVH for the theSubset given. const opencascade::handle>& BVH(const BVHSubset theSubset) const { return myBVH[theSubset]; } //! Dumps the content of me into the stream Standard_EXPORT void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const; private: //! Returns an appropriate subset of theObject given depending on its persistence type. int appropriateSubset(const occ::handle& theObject) { if (theObject->TransformPersistence().IsNull()) { const NCollection_Sequence>& aPresentations = theObject->Presentations(); for (NCollection_Sequence>::Iterator aPrsIter( aPresentations); aPrsIter.More(); aPrsIter.Next()) { const occ::handle& aPrs3d = aPrsIter.ChangeValue(); if (aPrs3d->CStructure()->HasGroupTransformPersistence() || aPrs3d->CStructure()->HasGroupFlipping()) { return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent; } } return SelectMgr_SelectableObjectSet::BVHSubset_3d; } else if ((theObject->TransformPersistence()->Mode() & Graphic3d_TMF_2d) != 0) { if (theObject->TransformPersistence()->IsOrthoPers()) { return SelectMgr_SelectableObjectSet::BVHSubset_ortho2dPersistent; } return SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent; } else if (theObject->TransformPersistence()->IsOrthoPers()) { return SelectMgr_SelectableObjectSet::BVHSubset_ortho3dPersistent; } else { return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent; } } //! Returns current subset of theObject given. int currentSubset(const occ::handle& theObject) { for (int aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx) { if (myObjects[aSubsetIdx].Contains(theObject)) { return aSubsetIdx; } } return -1; } private: // clang-format off NCollection_IndexedMap> myObjects[BVHSubsetNb]; //!< Map of objects for each subset opencascade::handle > myBVH[BVHSubsetNb]; //!< BVH tree computed for each subset occ::handle myBuilder[BVHSubsetNb]; //!< Builder allocated for each subset bool myIsDirty[BVHSubsetNb]; //!< Dirty flag for each subset Graphic3d_WorldViewProjState myLastViewState; //!< Last view-projection state used for construction of BVH NCollection_Vec2 myLastWinSize; //!< Last viewport's (window's) width used for construction of BVH // clang-format on friend class Iterator; }; #endif // _SelectMgr_SelectableObjectSet_HeaderFile