diff --git a/src/SelectMgr/FILES b/src/SelectMgr/FILES index bf2eb89118..6997ac27cd 100755 --- a/src/SelectMgr/FILES +++ b/src/SelectMgr/FILES @@ -28,8 +28,6 @@ SelectMgr_SelectableObject.cxx SelectMgr_SelectableObject.hxx SelectMgr_SelectableObjectSet.cxx SelectMgr_SelectableObjectSet.hxx -SelectMgr_SelectableObjectTrsfPersSet.cxx -SelectMgr_SelectableObjectTrsfPersSet.hxx SelectMgr_SelectingVolumeManager.cxx SelectMgr_SelectingVolumeManager.hxx SelectMgr_Selection.cxx diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.cxx b/src/SelectMgr/SelectMgr_BaseFrustum.cxx index 79dabddaf2..a70b9f4e24 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.cxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.cxx @@ -124,7 +124,7 @@ void SelectMgr_BaseFrustum::SetWindowSize (const Standard_Integer theWidth, cons // purpose : //======================================================================= void SelectMgr_BaseFrustum::WindowSize (Standard_Integer& theWidth, - Standard_Integer& theHeight) + Standard_Integer& theHeight) const { myBuilder->WindowSize (theWidth, theHeight); } diff --git a/src/SelectMgr/SelectMgr_BaseFrustum.hxx b/src/SelectMgr/SelectMgr_BaseFrustum.hxx index 487cece2af..88398faf87 100644 --- a/src/SelectMgr/SelectMgr_BaseFrustum.hxx +++ b/src/SelectMgr/SelectMgr_BaseFrustum.hxx @@ -75,7 +75,7 @@ public: const Standard_Integer theHeight); Standard_EXPORT void WindowSize (Standard_Integer& theWidth, - Standard_Integer& theHeight); + Standard_Integer& theHeight) const; //! Passes viewport parameters to builder Standard_EXPORT void SetViewport (const Standard_Real theX, @@ -109,8 +109,8 @@ public: //! There are no default parameters, but in case if: //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; //! - scale only is needed: @theTrsf must be set to gp_Identity. - Standard_EXPORT virtual NCollection_Handle ScaleAndTransform (const Standard_Integer /*theScaleFactor*/, - const gp_GTrsf& /*theTrsf*/) { return NULL; } + Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer /*theScaleFactor*/, + const gp_GTrsf& /*theTrsf*/) const { return NULL; } //! SAT intersection test between defined volume and given axis-aligned box Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theBoxMin, diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx index 75447a823d..c5c83486db 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.cxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.cxx @@ -119,7 +119,7 @@ void SelectMgr_FrustumBuilder::SetViewport (const Standard_Real theX, // purpose : //======================================================================= void SelectMgr_FrustumBuilder::WindowSize (Standard_Integer& theWidth, - Standard_Integer& theHeight) + Standard_Integer& theHeight) const { theWidth = myWidth; theHeight = myHeight; diff --git a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx index c490aad4f1..6956f797cd 100644 --- a/src/SelectMgr/SelectMgr_FrustumBuilder.hxx +++ b/src/SelectMgr/SelectMgr_FrustumBuilder.hxx @@ -63,7 +63,7 @@ public: Standard_EXPORT void InvalidateViewport(); Standard_EXPORT void WindowSize (Standard_Integer& theWidth, - Standard_Integer& theHeight); + Standard_Integer& theHeight) const; //! Calculates signed distance between plane with equation //! theEq and point thePnt diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx index fe2c835c65..1745cb74c5 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.cxx @@ -178,11 +178,11 @@ namespace // Top theNormals[0] = theEdges[0].Crossed (theEdges[4]); // Bottom - theNormals[1] = theEdges[2].Crossed (theEdges[3]); + theNormals[1] = theEdges[2].Crossed (theEdges[0]); // Left theNormals[2] = theEdges[4].Crossed (theEdges[1]); // Right - theNormals[3] = theEdges[5].Crossed (theEdges[3]); + theNormals[3] = theEdges[1].Crossed (theEdges[5]); // Near theNormals[4] = theEdges[0].Crossed (theEdges[1]); // Far @@ -195,7 +195,7 @@ namespace // purpose : Caches projection of frustum's vertices onto its plane directions // and {i, j, k} // ======================================================================= -void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum) +void SelectMgr_RectangularFrustum::cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum) const { if (theFrustum->myIsOrthographic) { @@ -322,13 +322,13 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt, // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. // ======================================================================= -NCollection_Handle SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf) +Handle(SelectMgr_BaseFrustum) SelectMgr_RectangularFrustum::ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_GTrsf& theTrsf) const { Standard_ASSERT_RAISE (theScaleFactor > 0, "Error! Pixel tolerance for selection should be greater than zero"); - SelectMgr_RectangularFrustum* aRes = new SelectMgr_RectangularFrustum(); + Handle(SelectMgr_RectangularFrustum) aRes = new SelectMgr_RectangularFrustum(); const Standard_Boolean isToScale = theScaleFactor != 1; const Standard_Boolean isToTrsf = theTrsf.Form() != gp_Identity; @@ -336,7 +336,7 @@ NCollection_Handle SelectMgr_RectangularFrustum::ScaleAnd return aRes; aRes->myIsOrthographic = myIsOrthographic; - SelectMgr_RectangularFrustum* aRef = this; + const SelectMgr_RectangularFrustum* aRef = this; if (isToScale) { @@ -352,7 +352,7 @@ NCollection_Handle SelectMgr_RectangularFrustum::ScaleAnd // recompute base frustum characteristics from scratch computeFrustum (aMinPnt, aMaxPnt, myBuilder, aRes->myVertices, aRes->myEdgeDirs); - aRef = aRes; + aRef = aRes.get(); } if (isToTrsf) @@ -396,11 +396,12 @@ NCollection_Handle SelectMgr_RectangularFrustum::ScaleAnd // compute frustum normals computeNormals (aRes->myEdgeDirs, aRes->myPlanes); - cacheVertexProjections (aRes); + cacheVertexProjections (aRes.get()); aRes->myViewClipRange = myViewClipRange; + aRes->myMousePos = myMousePos; - return NCollection_Handle (aRes); + return aRes; } // ======================================================================= diff --git a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx index 4f2a92ff74..53fa3db504 100644 --- a/src/SelectMgr/SelectMgr_RectangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_RectangularFrustum.hxx @@ -50,8 +50,8 @@ public: //! There are no default parameters, but in case if: //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; //! - scale only is needed: @theTrsf must be set to gp_Identity. - Standard_EXPORT virtual NCollection_Handle ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf) Standard_OVERRIDE; + Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScaleFactor, + const gp_GTrsf& theTrsf) const Standard_OVERRIDE; // SAT Tests for different objects @@ -143,7 +143,7 @@ protected: private: - void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum); + void cacheVertexProjections (SelectMgr_RectangularFrustum* theFrustum) const; private: enum { LeftTopNear, LeftTopFar, diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx index 5bc3f8f4ed..6aa38decef 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.cxx @@ -13,58 +13,236 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include -#include - #include +#include -//======================================================================= -// function : SelectMgr_SelectableObjectSet -// purpose : Creates new empty objects set and initializes BVH tree -// builder to Binned builder with 1 element per list -//======================================================================= -SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet() +#include +#include + +namespace { - myBuilder = new BVH_BinnedBuilder (1, 32, Standard_True); -} + //! Short-cut definition of indexed data map of selectable objects + typedef NCollection_IndexedMap ObjectsMap; -//======================================================================= -// function : Append -// purpose : Adds new object to the set and marks BVH tree for rebuild -//======================================================================= -Standard_Boolean SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) -{ - Standard_Integer aSize = Size(); + //------------------------------------------------------------------------------------- + // Adaptor over regular objects subset of SelectMgr_SelectableObjectSet for BVH builder + //------------------------------------------------------------------------------------- - if (aSize < myObjects.Add (theObject)) + //! This class provides direct access to fields of SelectMgr_SelectableObjectSet + //! so the BVH builder could explicitly arrange objects in the map as necessary + //! to provide synchronization of indexes with constructed BVH tree. + class BVHBuilderAdaptorRegular : public BVH_Set { - MarkDirty(); + public: - return Standard_True; - } + //! Construct adaptor. + BVHBuilderAdaptorRegular (ObjectsMap& theObjects) : myObjects (theObjects) {}; - return Standard_False; -} - -//======================================================================= -// function : Remove -// purpose : Removes object theObject from set and marks BVH tree for -// rebuild -//======================================================================= -Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) -{ - const Standard_Integer anIndex = myObjects.FindIndex (theObject); - - if (anIndex != 0) - { - if (anIndex != Size()) + //! Returns bounding box of object with index theIndex + virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE { - Swap (anIndex - 1, Size() - 1); + const Handle(SelectMgr_SelectableObject)& anObject = myObjects.FindKey (theIndex + 1); + Bnd_Box aBox; + anObject->BoundingBox (aBox); + if (aBox.IsVoid()) + return Select3D_BndBox3d(); + + return Select3D_BndBox3d (SelectMgr_Vec3 (aBox.CornerMin().X(), aBox.CornerMin().Y(), aBox.CornerMin().Z()), + SelectMgr_Vec3 (aBox.CornerMax().X(), aBox.CornerMax().Y(), aBox.CornerMax().Z())); } - myObjects.RemoveLast(); + //! Returns bounding box of the whole subset. + virtual Select3D_BndBox3d Box() const Standard_OVERRIDE + { + if (!myBox.IsValid()) + { + myBox = BVH_Set::Box(); + } + return myBox; + } - MarkDirty(); + //! Make inherited method Box() visible to avoid CLang warning + using BVH_Set::Box; + + //! Returns center of object with index theIndex in the set + //! along the given axis theAxis + virtual Standard_Real Center (const Standard_Integer theIndex, + const Standard_Integer theAxis) const Standard_OVERRIDE + { + const Select3D_BndBox3d aBndBox = Box (theIndex); + + return (aBndBox.CornerMin()[theAxis] + + aBndBox.CornerMax()[theAxis]) * 0.5; + } + + //! Returns size of objects set. + virtual Standard_Integer Size() const Standard_OVERRIDE + { + return myObjects.Size(); + } + + //! Swaps items with indexes theIndex1 and theIndex2 in the set + virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2) Standard_OVERRIDE + { + myObjects.Swap (theIndex1 + 1, theIndex2 + 1); + } + + private: + BVHBuilderAdaptorRegular& operator=(BVHBuilderAdaptorRegular) { return *this; } + + private: + ObjectsMap& myObjects; + mutable Select3D_BndBox3d myBox; + }; + + //---------------------------------------------------------------------------------------- + // Adaptor over persistent objects subset of SelectMgr_SelectableObjectSet for BVH builder + //---------------------------------------------------------------------------------------- + + //! This class provides direct access to fields of SelectMgr_SelectableObjectSet + //! so the BVH builder could explicitly arrange objects in the map as necessary + //! to provide synchronization of indexes with constructed BVH tree. + class BVHBuilderAdaptorPersistent : public BVH_Set + { + public: + + //! Construct adaptor. + //! @param theCamera, theProjectionMat, theWorldViewMat, + //! theWidth, theHeight [in] view properties used for computation of + //! bounding boxes within the world view camera space. + BVHBuilderAdaptorPersistent (ObjectsMap& theObjects, + const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Standard_Integer theWidth, + const Standard_Integer theHeight) + : myObjects (theObjects) + { + myBoundings.ReSize (myObjects.Size()); + for (Standard_Integer anI = 1; anI <= myObjects.Size(); ++anI) + { + const Handle(SelectMgr_SelectableObject)& anObject = myObjects (anI); + + Bnd_Box aBoundingBox; + anObject->BoundingBox (aBoundingBox); + if (aBoundingBox.IsVoid()) + { + myBoundings.Add (new Select3D_HBndBox3d()); + } + else + { + anObject->TransformPersistence().Apply ( + theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox); + + const gp_Pnt aMin = aBoundingBox.CornerMin(); + const gp_Pnt aMax = aBoundingBox.CornerMax(); + myBoundings.Add (new Select3D_HBndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()), + Select3D_Vec3 (aMax.X(), aMax.Y(), aMax.Z()))); + } + } + } + + //! Returns bounding box of object with index theIndex + virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE + { + return *myBoundings (theIndex + 1); + } + + //! Returns bounding box of the whole subset. + virtual Select3D_BndBox3d Box() const Standard_OVERRIDE + { + if (!myBox.IsValid()) + { + myBox = BVH_Set::Box(); + } + return myBox; + } + + //! Make inherited method Box() visible to avoid CLang warning + using BVH_Set::Box; + + //! Returns center of object with index theIndex in the set + //! along the given axis theAxis + virtual Standard_Real Center (const Standard_Integer theIndex, + const Standard_Integer theAxis) const Standard_OVERRIDE + { + const Select3D_BndBox3d& aBoundingBox = *myBoundings (theIndex + 1); + + return (aBoundingBox.CornerMin()[theAxis] + aBoundingBox.CornerMax()[theAxis]) * 0.5; + } + + //! Returns size of objects set. + virtual Standard_Integer Size() const Standard_OVERRIDE + { + return myObjects.Size(); + } + + //! Swaps items with indexes theIndex1 and theIndex2 in the set + virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2) Standard_OVERRIDE + { + const Standard_Integer aStructIdx1 = theIndex1 + 1; + const Standard_Integer aStructIdx2 = theIndex2 + 1; + + myObjects.Swap (aStructIdx1, aStructIdx2); + myBoundings.Swap (aStructIdx1, aStructIdx2); + } + + private: + BVHBuilderAdaptorPersistent& operator=(BVHBuilderAdaptorPersistent) { return *this; } + + private: + ObjectsMap& myObjects; + mutable Select3D_BndBox3d myBox; + typedef NCollection_Shared Select3D_HBndBox3d; + NCollection_IndexedMap myBoundings; + }; + + static const Graphic3d_Mat4d THE_IDENTITY_MAT; +} + +//============================================================================= +// Function: Constructor +// Purpose : +//============================================================================= +SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet() +: myLastWidth (0), + myLastHeight (0) +{ + myBVH[BVHSubset_2dPersistent] = new BVH_Tree(); + myBVH[BVHSubset_3dPersistent] = new BVH_Tree(); + myBVH[BVHSubset_3d] = new BVH_Tree(); + + myBuilder[BVHSubset_2dPersistent] = new BVH_LinearBuilder (1, 32); + myBuilder[BVHSubset_3dPersistent] = new BVH_LinearBuilder (1, 32); + myBuilder[BVHSubset_3d] = new BVH_BinnedBuilder (1, 32, Standard_True); + + myIsDirty[BVHSubset_2dPersistent] = Standard_False; + myIsDirty[BVHSubset_3dPersistent] = Standard_False; + myIsDirty[BVHSubset_3d] = Standard_False; +} + +//============================================================================= +// Function: Append +// Purpose : +//============================================================================= +Standard_Boolean SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) +{ + // get an appropriate BVH subset to insert the object into it + const Standard_Integer aSubsetIdx = appropriateSubset (theObject); + + // check that the object is excluded from other subsets + if (myObjects[(aSubsetIdx + 1) % BVHSubsetNb].Contains (theObject) + || myObjects[(aSubsetIdx + 2) % BVHSubsetNb].Contains (theObject)) + { + return Standard_False; + } + + // try adding it into the appropriate object subset + const Standard_Integer aSize = myObjects[aSubsetIdx].Size(); + + if (aSize < myObjects[aSubsetIdx].Add (theObject)) + { + myIsDirty[aSubsetIdx] = Standard_True; return Standard_True; } @@ -72,51 +250,142 @@ Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_S return Standard_False; } -//======================================================================= -// function : Box -// purpose : Returns bounding box of object with index theIndex -//======================================================================= -Select3D_BndBox3d SelectMgr_SelectableObjectSet::Box (const Standard_Integer theIndex) const +//============================================================================= +// Function: Remove +// Purpose : +//============================================================================= +Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) { - const Handle(SelectMgr_SelectableObject)& anObject = GetObjectById (theIndex); - Bnd_Box aBox; - anObject->BoundingBox (aBox); - if (aBox.IsVoid()) - return Select3D_BndBox3d(); + // remove object from the first found subset + for (Standard_Integer aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx) + { + const Standard_Integer anIndex = myObjects[aSubsetIdx].FindIndex (theObject); - return Select3D_BndBox3d (SelectMgr_Vec3 (aBox.CornerMin().X(), aBox.CornerMin().Y(), aBox.CornerMin().Z()), - SelectMgr_Vec3 (aBox.CornerMax().X(), aBox.CornerMax().Y(), aBox.CornerMax().Z())); + if (anIndex != 0) + { + const Standard_Integer aSize = myObjects[aSubsetIdx].Size(); + + if (anIndex != aSize) + { + myObjects[aSubsetIdx].Swap (anIndex, aSize); + } + + myObjects[aSubsetIdx].RemoveLast(); + myIsDirty[aSubsetIdx] = Standard_True; + + return Standard_True; + } + } + + return Standard_False; } -//======================================================================= -// function : Center -// purpose : Returns center of object with index theIndex in the set -// along the given axis theAxis -//======================================================================= -Standard_Real SelectMgr_SelectableObjectSet::Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const +//============================================================================= +// Function: ChangeSubset +// Purpose : +//============================================================================= +void SelectMgr_SelectableObjectSet::ChangeSubset (const Handle(SelectMgr_SelectableObject)& theObject) { - Select3D_BndBox3d aBndBox = Box (theIndex); + // do not do anything is object is not in the map + const Standard_Integer aCurrSubsetIdx = currentSubset (theObject); - return (aBndBox.CornerMin()[theAxis] + - aBndBox.CornerMax()[theAxis]) * 0.5; + if (aCurrSubsetIdx < 0) + { + return; + } + + // check whether the subset need to be changed at all + const Standard_Integer aSubsetIdx = appropriateSubset (theObject); + + if (aCurrSubsetIdx == aSubsetIdx) + { + return; + } + + // replace object in the maps + Remove (theObject); + Append (theObject); } -//======================================================================= -// function : Swap -// purpose : Swaps items with indexes theIndex1 and theIndex2 in the set -//======================================================================= -void SelectMgr_SelectableObjectSet::Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) +//============================================================================= +// Function: UpdateBVH +// Purpose : +//============================================================================= +void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Graphic3d_WorldViewProjState& theViewState, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) { - myObjects.Swap (theIndex1 + 1, theIndex2 + 1); + // ----------------------------------------- + // check and update 3D BVH tree if necessary + // ----------------------------------------- + if (!IsEmpty (BVHSubset_3d) && myIsDirty[BVHSubset_3d]) + { + // construct adaptor over private fields to provide direct access for the BVH builder + BVHBuilderAdaptorRegular anAdaptor (myObjects[BVHSubset_3d]); + + // update corresponding BVH tree data structure + myBuilder[BVHSubset_3d]->Build (&anAdaptor, myBVH[BVHSubset_3d].operator->(), anAdaptor.Box()); + + // release dirty state + myIsDirty[BVHSubset_3d] = Standard_False; + } + + if (!theCamera.IsNull()) + { + const Standard_Boolean isWindowSizeChanged = + (myLastHeight != theViewportHeight) || (myLastWidth != theViewportWidth); + + // ----------------------------------------------------- + // check and update 3D persistence BVH tree if necessary + // ----------------------------------------------------- + if (!IsEmpty (BVHSubset_3dPersistent) && + (myIsDirty[BVHSubset_3dPersistent] || myLastViewState.IsChanged (theViewState) || isWindowSizeChanged)) + { + // construct adaptor over private fields to provide direct access for the BVH builder + BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_3dPersistent], + theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight); + + // update corresponding BVH tree data structure + myBuilder[BVHSubset_3dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_3dPersistent].operator->(), anAdaptor.Box()); + } + + // ----------------------------------------------------- + // check and update 2D persistence BVH tree if necessary + // ----------------------------------------------------- + if (!IsEmpty (BVHSubset_2dPersistent) && + (myIsDirty[BVHSubset_2dPersistent] || myLastViewState.IsProjectionChanged (theViewState) || isWindowSizeChanged)) + { + // construct adaptor over private fields to provide direct access for the BVH builder + BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_2dPersistent], + theCamera, theProjectionMat, THE_IDENTITY_MAT, theViewportWidth, theViewportHeight); + + // update corresponding BVH tree data structure + myBuilder[BVHSubset_2dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_2dPersistent].operator->(), anAdaptor.Box()); + } + + // release dirty state for every subset + myIsDirty[BVHSubset_3dPersistent] = Standard_False; + myIsDirty[BVHSubset_2dPersistent] = Standard_False; + + // keep last view state + myLastViewState = theViewState; + } + + // keep last window state + myLastWidth = theViewportWidth; + myLastHeight = theViewportHeight; } -//======================================================================= -// function : Size -// purpose : Returns size of objects set -//======================================================================= -Standard_Integer SelectMgr_SelectableObjectSet::Size() const +//============================================================================= +// Function: MarkDirty +// Purpose : +//============================================================================= +void SelectMgr_SelectableObjectSet::MarkDirty() { - return myObjects.Size(); + myIsDirty[BVHSubset_3d] = Standard_True; + myIsDirty[BVHSubset_3dPersistent] = Standard_True; + myIsDirty[BVHSubset_2dPersistent] = Standard_True; } diff --git a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx index 22784edc41..770f182d44 100644 --- a/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx +++ b/src/SelectMgr/SelectMgr_SelectableObjectSet.hxx @@ -17,68 +17,210 @@ #define _SelectMgr_SelectableObjectSet_HeaderFile #include - -#include -#include -#include - +#include +#include +#include +#include #include +#include -//! The purpose of this class is to organize all selectable objects into -//! data structure, allowing to build BVH tree. For selectable objects -//! binned BVH builder is used with 32 bins and 1 element per leaf. -class SelectMgr_SelectableObjectSet : public BVH_PrimitiveSet +//! 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: - //! Creates new empty objects set and initializes BVH tree - //! builder to Binned builder with 1 element per list + //! 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. + enum BVHSubset + { + BVHSubset_3d, + BVHSubset_3dPersistent, + BVHSubset_2dPersistent, + 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 (NULL), 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. + Standard_Boolean More() + { + if (mySubsetIt.More()) + { + return Standard_True; + } + else if ((mySubsetIdx == BVHSubsetNb - 1) || mySet == NULL) + { + return Standard_False; + } + mySubsetIt = ObjectMapIterator (mySet->myObjects[++mySubsetIdx]); + return More(); + } + + //! Steps to next selectable object in the set. + void Next() { mySubsetIt.Next(); } + + //! Returns current object. + const Handle(SelectMgr_SelectableObject)& Value() const { return mySubsetIt.Value(); } + + private: + const SelectMgr_SelectableObjectSet* mySet; + Standard_Integer 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() { } - //! Adds new object to the set and marks BVH tree for rebuild. - //! @return true if structure added, otherwise returns false (structure already in the set). + //! 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 Standard_Boolean Append (const Handle(SelectMgr_SelectableObject)& theObject); - //! Removes object theObject from set and marks BVH tree for rebuild. - //! @return true if structure removed, otherwise returns false (structure is not in the set). + //! 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 Standard_Boolean Remove (const Handle(SelectMgr_SelectableObject)& theObject); - //! Returns bounding box of object with index theIndex - Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE; + //! 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 Handle(SelectMgr_SelectableObject)& theObject); - //! Make inherited method Box() visible to avoid CLang warning - using BVH_PrimitiveSet::Box; + //! Updates outdated BVH trees and remembers the last state of the + //! camera view-projection matrices and viewport (window) dimensions. + Standard_EXPORT void UpdateBVH (const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Graphic3d_WorldViewProjState& theViewState, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight); - //! Returns center of object with index theIndex in the set - //! along the given axis theAxis - Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const Standard_OVERRIDE; + //! Marks every BVH subset for update. + Standard_EXPORT void MarkDirty(); - //! Swaps items with indexes theIndex1 and theIndex2 in the set - Standard_EXPORT virtual void Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) Standard_OVERRIDE; - - //! Returns size of objects set - Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; - - //! Returns object from set by theIndex given - const Handle(SelectMgr_SelectableObject)& GetObjectById (const Standard_Integer theIndex) const - { - return myObjects.FindKey (theIndex + 1); - } - - //! Returns true if this objects set contains theObject given + //! Returns true if this objects set contains theObject given. Standard_Boolean Contains (const Handle(SelectMgr_SelectableObject)& theObject) const { - return myObjects.Contains (theObject); + return myObjects[BVHSubset_3d].Contains (theObject) + || myObjects[BVHSubset_3dPersistent].Contains (theObject) + || myObjects[BVHSubset_2dPersistent].Contains (theObject); + } + + //! Returns true if the object set does not contain any selectable objects. + Standard_Boolean IsEmpty() const + { + return myObjects[BVHSubset_3d].IsEmpty() + && myObjects[BVHSubset_3dPersistent].IsEmpty() + && myObjects[BVHSubset_2dPersistent].IsEmpty(); + } + + //! Returns true if the specified object subset is empty. + Standard_Boolean 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 Handle(SelectMgr_SelectableObject)& GetObjectById (const BVHSubset theSubset, + const Standard_Integer theIndex) const + { + return myObjects[theSubset].FindKey (theIndex + 1); + } + + //! Returns computed BVH for the theSubset given. + const NCollection_Handle >& BVH(const BVHSubset theSubset) const + { + return myBVH[theSubset]; } private: - NCollection_IndexedMap myObjects; + //! Returns an appropriate subset of theObject given depending on its persistence type. + Standard_Integer appropriateSubset (const Handle(SelectMgr_SelectableObject)& theObject) + { + if (!theObject->TransformPersistence().Flags) + { + return SelectMgr_SelectableObjectSet::BVHSubset_3d; + } + else if (theObject->TransformPersistence().Flags & Graphic3d_TMF_2d) + { + return SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent; + } + else + { + return SelectMgr_SelectableObjectSet::BVHSubset_3dPersistent; + } + } + + //! Returns current subset of theObject given. + Standard_Integer currentSubset (const Handle(SelectMgr_SelectableObject)& theObject) + { + for (Standard_Integer aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx) + { + if (myObjects[aSubsetIdx].Contains (theObject)) + { + return aSubsetIdx; + } + } + return -1; + } + +private: + + NCollection_IndexedMap myObjects[BVHSubsetNb]; //!< Map of objects for each subset + NCollection_Handle > myBVH[BVHSubsetNb]; //!< BVH tree computed for each subset + NCollection_Handle > myBuilder[BVHSubsetNb]; //!< Builder allocated for each subset + Standard_Boolean myIsDirty[BVHSubsetNb]; //!< Dirty flag for each subset + Graphic3d_WorldViewProjState myLastViewState; //!< Last view-projection state used for construction of BVH + Standard_Integer myLastWidth; //!< Last viewport's (window's) width used for construction of BVH + Standard_Integer myLastHeight; //!< Last viewport's (window's) height used for construction of BVH + friend class Iterator; }; #endif // _SelectMgr_SelectableObjectSet_HeaderFile diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx deleted file mode 100644 index 5cc3125a63..0000000000 --- a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.cxx +++ /dev/null @@ -1,170 +0,0 @@ -// Created on: 2015-06-30 -// Created by: Anton POLETAEV -// Copyright (c) 2015 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 - -#include -#include -#include - -//======================================================================= -// function : SelectMgr_SelectableObjectTrsfPersSet -// purpose : -//======================================================================= -SelectMgr_SelectableObjectTrsfPersSet::SelectMgr_SelectableObjectTrsfPersSet() -: myIsDirty (Standard_False), - myBVH (new BVH_Tree()) -{ - myBuilder = new BVH_LinearBuilder (1, 32); -} - -//======================================================================= -// function : Size -// purpose : -//======================================================================= -Standard_Integer SelectMgr_SelectableObjectTrsfPersSet::Size() const -{ - return myObjects.Size(); -} - -//======================================================================= -// function : Box -// purpose : -//======================================================================= -Select3D_BndBox3d SelectMgr_SelectableObjectTrsfPersSet::Box (const Standard_Integer theIndex) const -{ - return *myObjectBoxes (theIndex + 1); -} - -//======================================================================= -// function : Center -// purpose : -//======================================================================= -Standard_Real SelectMgr_SelectableObjectTrsfPersSet::Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const -{ - const Select3D_BndBox3d& aBndBox = *myObjectBoxes (theIndex + 1); - - return (aBndBox.CornerMin()[theAxis] + aBndBox.CornerMax()[theAxis]) * 0.5; -} - -//======================================================================= -// function : Swap -// purpose : -//======================================================================= -void SelectMgr_SelectableObjectTrsfPersSet::Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) -{ - const Standard_Integer aStructIdx1 = theIndex1 + 1; - const Standard_Integer aStructIdx2 = theIndex2 + 1; - - myObjects.Swap (aStructIdx1, aStructIdx2); - myObjectBoxes.Swap (aStructIdx1, aStructIdx2); -} - -//======================================================================= -// function : Append -// purpose : -//======================================================================= -Standard_Boolean SelectMgr_SelectableObjectTrsfPersSet::Append (const Handle(SelectMgr_SelectableObject)& theObject) -{ - Standard_Integer aSize = Size(); - - if (aSize < myObjects.Add (theObject)) - { - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -//======================================================================= -// function : Remove -// purpose : -//======================================================================= -Standard_Boolean SelectMgr_SelectableObjectTrsfPersSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject) -{ - const Standard_Integer anIndex = myObjects.FindIndex (theObject); - - if (anIndex != 0) - { - myObjects.Swap (Size(), anIndex); - myObjects.RemoveLast(); - MarkDirty(); - - return Standard_True; - } - - return Standard_False; -} - -//======================================================================= -// function : BVH -// purpose : -//======================================================================= -const NCollection_Handle >& - SelectMgr_SelectableObjectTrsfPersSet::BVH (const Handle(Graphic3d_Camera)& theCamera, - const Graphic3d_Mat4d& theProjectionMatrix, - const Graphic3d_Mat4d& theWorldViewMatrix, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight, - const Graphic3d_WorldViewProjState& theWVPState) -{ - if (!myIsDirty && (myObjectBoxesState.IsValid() && !myObjectBoxesState.IsChanged(theWVPState))) - { - return myBVH; - } - - myObjectBoxes.ReSize (myObjects.Size()); - - for (Standard_Integer anObjectIdx = 1; anObjectIdx <= myObjects.Size(); ++anObjectIdx) - { - const Handle(SelectMgr_SelectableObject)& anObject = myObjects (anObjectIdx); - - Bnd_Box aBoundingBox; - - if (anObject->TransformPersistence().Flags != 0) - { - anObject->BoundingBox (aBoundingBox); - if (!aBoundingBox.IsVoid()) - { - anObject->TransformPersistence().Apply (theCamera, theProjectionMatrix, theWorldViewMatrix, theViewportWidth, theViewportHeight, aBoundingBox); - } - } - - if (aBoundingBox.IsVoid()) - { - myObjectBoxes.Add (new Select3D_BndBox3d()); - } - else - { - gp_Pnt aMin = aBoundingBox.CornerMin(); - gp_Pnt aMax = aBoundingBox.CornerMax(); - - myObjectBoxes.Add (new Select3D_BndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()), - Select3D_Vec3 (aMax.X(), aMax.Y(), aMax.Z()))); - } - } - - myBuilder->Build (this, myBVH.operator->(), BVH_Set::Box()); - - myObjectBoxesState = theWVPState; - myObjectBoxes.Clear(); - myIsDirty = Standard_False; - - return myBVH; -} diff --git a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx b/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx deleted file mode 100644 index 86580c294f..0000000000 --- a/src/SelectMgr/SelectMgr_SelectableObjectTrsfPersSet.hxx +++ /dev/null @@ -1,118 +0,0 @@ -// Created on: 2015-06-30 -// Created by: Anton POLETAEV -// Copyright (c) 2015 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_SelectableObjectTrsfPersSet_HeaderFile -#define _SelectMgr_SelectableObjectTrsfPersSet_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//! Primitive set specialized for transformation persistent selectable objects. -//! Provides built-in mechanism to invalidate tree when world view projection state changes. -//! Due to frequent invalidation of BVH tree the choice of BVH tree builder is made -//! in favor of BVH linear builder (quick rebuild). -class SelectMgr_SelectableObjectTrsfPersSet : public BVH_Set -{ -private: - - typedef NCollection_Handle HBndBox3d; - - Handle(SelectMgr_SelectableObject) EMPTY_OBJ; - -public: - - //! Creates new empty objects set and initializes BVH tree - //! builder to Linear builder with 1 element per list. - Standard_EXPORT SelectMgr_SelectableObjectTrsfPersSet(); - - //! Returns size of objects set. - Standard_EXPORT virtual Standard_Integer Size() const Standard_OVERRIDE; - - //! Returns bounding box of object with index theIndex. - Standard_EXPORT virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE; - - //! Returns center of object with index theIndex in the set along the given axis theAxis. - Standard_EXPORT virtual Standard_Real Center (const Standard_Integer theIndex, - const Standard_Integer theAxis) const Standard_OVERRIDE; - - //! Swaps items with indexes theIndex1 and theIndex2 in the set. - Standard_EXPORT virtual void Swap (const Standard_Integer theIndex1, - const Standard_Integer theIndex2) Standard_OVERRIDE; - - //! Adds new selectable object to the set. - //! @return true if structure added, otherwise returns false (structure already in the set). - Standard_EXPORT Standard_Boolean Append (const Handle(SelectMgr_SelectableObject)& theObject); - - //! Removes selectable object from set. - //! @return true if structure removed, otherwise returns false (structure is not in the set). - Standard_EXPORT Standard_Boolean Remove (const Handle(SelectMgr_SelectableObject)& theObject); - - //! Returns object from set by theIndex given. - const Handle(SelectMgr_SelectableObject)& GetObjectById (const Standard_Integer theIndex) const - { - return myObjects.FindKey (theIndex + 1); - } - - //! Marks object state as outdated (needs BVH rebuilding). - void MarkDirty() - { - myIsDirty = Standard_True; - } - - //! Returns true if this objects set contains theObject given - Standard_Boolean Contains (const Handle(SelectMgr_SelectableObject)& theObject) const - { - return myObjects.Contains (theObject); - } - - //! Returns BVH tree for the given world view projection (builds it if necessary). - Standard_EXPORT const NCollection_Handle >& BVH (const Handle(Graphic3d_Camera)& theCamera, - const Graphic3d_Mat4d& theProjectionMatrix, - const Graphic3d_Mat4d& theWorldViewMatrix, - const Standard_Integer theViewportWidth, - const Standard_Integer theViewportHeight, - const Graphic3d_WorldViewProjState& theWVPState); - -private: - - //! Marks internal object state as outdated. - Standard_Boolean myIsDirty; - - //! Constructed bottom-level BVH. - NCollection_Handle > myBVH; - - //! Builder for bottom-level BVH. - NCollection_Handle > myBuilder; - - //! Set of transform persistence objects. - NCollection_IndexedMap myObjects; - - //! Cached set of bounding boxes precomputed for transformation persistent selectable objects. - //! Cache exists only during computation of BVH Tree. Bounding boxes are world view projection - //! dependent and should by synchronized. - NCollection_IndexedMap myObjectBoxes; - - //! State of world view projection used for generation of transformation persistence bounding boxes. - Graphic3d_WorldViewProjState myObjectBoxesState; -}; - -#endif diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx index 53406659e1..fd1b0588a7 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.cxx @@ -42,9 +42,13 @@ SelectMgr_SelectingVolumeManager::SelectMgr_SelectingVolumeManager (Standard_Boo // - transformation only is needed: @theScaleFactor must be initialized // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. +// Builder is an optional argument that represents corresponding settings for +// re-constructing transformed frustum from scratch. Can be null if reconstruction +// is not needed furthermore in the code. //======================================================================= SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf) + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder) const { SelectMgr_SelectingVolumeManager aMgr (Standard_False); @@ -52,10 +56,10 @@ SelectMgr_SelectingVolumeManager SelectMgr_SelectingVolumeManager::ScaleAndTrans return aMgr; aMgr.myActiveSelectionType = myActiveSelectionType; - aMgr.mySelectingVolumes[myActiveSelectionType / 2] = mySelectingVolumes[myActiveSelectionType / 2]->ScaleAndTransform (theScaleFactor, theTrsf); aMgr.myToAllowOverlap = myToAllowOverlap; + aMgr.mySelectingVolumes[myActiveSelectionType / 2]->SetBuilder (theBuilder); return aMgr; } @@ -141,7 +145,7 @@ const Graphic3d_WorldViewProjState& SelectMgr_SelectingVolumeManager::WorldViewP // function : WindowSize // purpose : //======================================================================= -void SelectMgr_SelectingVolumeManager::WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) +void SelectMgr_SelectingVolumeManager::WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) const { mySelectingVolumes[Frustum]->WindowSize (theWidth, theHeight); } diff --git a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx index 4d1b8feb8b..d06b5ef1e8 100644 --- a/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx +++ b/src/SelectMgr/SelectMgr_SelectingVolumeManager.hxx @@ -46,8 +46,11 @@ public: //! There are no default parameters, but in case if: //! - transformation only is needed: @theScaleFactor must be initialized as any negative value; //! - scale only is needed: @theTrsf must be set to gp_Identity. + //! Builder is an optional argument that represents corresponding settings for re-constructing transformed + //! frustum from scratch. Can be null if reconstruction is not expected furthermore. Standard_EXPORT virtual SelectMgr_SelectingVolumeManager ScaleAndTransform (const Standard_Integer theScaleFactor, - const gp_GTrsf& theTrsf); + const gp_GTrsf& theTrsf, + const Handle(SelectMgr_FrustumBuilder)& theBuilder = NULL) const; Standard_EXPORT virtual Standard_Integer GetActiveSelectionType() const Standard_OVERRIDE; @@ -71,7 +74,7 @@ public: //! @return current world view transformation common for all selecting volumes Standard_EXPORT const Graphic3d_Mat4d& WorldViewMatrix() const; - Standard_EXPORT void WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight); + Standard_EXPORT void WindowSize (Standard_Integer& theWidth, Standard_Integer& theHeight) const; //! @return current camera world view projection transformation state common for all selecting volumes Standard_EXPORT const Graphic3d_WorldViewProjState& WorldViewProjState() const; @@ -189,8 +192,8 @@ public: private: enum { Frustum, FrustumSet, VolumeTypesNb }; //!< Defines the amount of available selecting volumes - NCollection_Handle mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes - Standard_Boolean myToAllowOverlap; //!< Defines if partially overlapped entities will me detected or not + Handle(SelectMgr_BaseFrustum) mySelectingVolumes[VolumeTypesNb]; //!< Array of selecting volumes + Standard_Boolean myToAllowOverlap; //!< Defines if partially overlapped entities will me detected or not }; -#endif +#endif \ No newline at end of file diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx index d67f7c788c..9c318cc2e0 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.cxx @@ -44,7 +44,7 @@ namespace // purpose : Caches projection of frustum's vertices onto its plane directions // and {i, j, k} // ======================================================================= -void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) +void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const { for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) { @@ -128,10 +128,10 @@ void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1, // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. //======================================================================= -NCollection_Handle SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/, - const gp_GTrsf& theTrsf) +Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/, + const gp_GTrsf& theTrsf) const { - SelectMgr_TriangularFrustum* aRes = new SelectMgr_TriangularFrustum(); + Handle(SelectMgr_TriangularFrustum) aRes = new SelectMgr_TriangularFrustum(); for (Standard_Integer anIt = 0; anIt < 6; anIt++) { @@ -157,9 +157,9 @@ NCollection_Handle SelectMgr_TriangularFrustum::ScaleAndT computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes); - cacheVertexProjections (aRes); + cacheVertexProjections (aRes.get()); - return NCollection_Handle (aRes); + return aRes; } //======================================================================= diff --git a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx index 3e6c8da7b1..46a9443e21 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustum.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustum.hxx @@ -40,8 +40,8 @@ public: const gp_Pnt2d& theP3) Standard_OVERRIDE; //! Returns a copy of the frustum transformed according to the matrix given - Standard_EXPORT virtual NCollection_Handle ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) Standard_OVERRIDE; + Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf) const Standard_OVERRIDE; // SAT Tests for different objects @@ -86,7 +86,7 @@ public: private: - void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum); + void cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const; DEFINE_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient) }; diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index efce1f80dd..202b84e1b0 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -108,17 +108,17 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint // as any negative value; // - scale only is needed: @theTrsf must be set to gp_Identity. // ======================================================================= -NCollection_Handle SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) +Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustumSet::ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf) const { - SelectMgr_TriangularFrustumSet* aRes = new SelectMgr_TriangularFrustumSet(); + Handle(SelectMgr_TriangularFrustumSet) aRes = new SelectMgr_TriangularFrustumSet(); for (SelectMgr_TriangFrustumsIter anIter (myFrustums); anIter.More(); anIter.Next()) { aRes->myFrustums.Append (Handle(SelectMgr_TriangularFrustum)::DownCast (anIter.Value()->ScaleAndTransform (theScale, theTrsf))); } - return NCollection_Handle (aRes); + return aRes; } // ======================================================================= diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx index 474bb355fa..09f285b0a8 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.hxx @@ -47,8 +47,8 @@ public: Standard_EXPORT virtual void Build (const TColgp_Array1OfPnt2d& thePoints) Standard_OVERRIDE; //! Returns a copy of the frustum with all sub-volumes transformed according to the matrix given - Standard_EXPORT virtual NCollection_Handle ScaleAndTransform (const Standard_Integer theScale, - const gp_GTrsf& theTrsf) Standard_OVERRIDE; + Standard_EXPORT virtual Handle(SelectMgr_BaseFrustum) ScaleAndTransform (const Standard_Integer theScale, + const gp_GTrsf& theTrsf) const Standard_OVERRIDE; Standard_EXPORT virtual Standard_Boolean Overlaps (const SelectMgr_Vec3& theMinPnt, const SelectMgr_Vec3& theMaxPnt, diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.cxx b/src/SelectMgr/SelectMgr_ViewerSelector.cxx index 428bfe0cb7..ee209239ad 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.cxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.cxx @@ -76,6 +76,7 @@ namespace { } } + static const Graphic3d_Mat4d THE_IDENTITY_MAT; } //================================================== @@ -218,6 +219,7 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive // necessary calculations //======================================================================= void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt, + const SelectMgr_SelectingVolumeManager& theMgr, const gp_GTrsf& theInvTrsf, SelectMgr_FrustumCache& theCachedMgrs, SelectMgr_SelectingVolumeManager& theResMgr) @@ -228,19 +230,19 @@ void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_Sensiti const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity; if (toScale && toTransform) { - theResMgr = mySelectingVolumeMgr.ScaleAndTransform (aScale, aTrsfMtr); + theResMgr = theMgr.ScaleAndTransform (aScale, aTrsfMtr, NULL); } else if (toScale) { if (!theCachedMgrs.IsBound (aScale)) { - theCachedMgrs.Bind (aScale, mySelectingVolumeMgr.ScaleAndTransform (aScale, gp_Trsf())); + theCachedMgrs.Bind (aScale, theMgr.ScaleAndTransform (aScale, gp_Trsf(), NULL)); } theResMgr = theCachedMgrs.Find (aScale); } else if (toTransform) { - theResMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTrsfMtr); + theResMgr = theMgr.ScaleAndTransform (1, aTrsfMtr, NULL); } } @@ -250,7 +252,13 @@ void SelectMgr_ViewerSelector::computeFrustum (const Handle(SelectBasics_Sensiti // between some entity of selectable object theObject and // current selecting volume //======================================================================= -void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject) +void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject, + const SelectMgr_SelectingVolumeManager& theMgr, + const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight) { NCollection_Handle& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject); @@ -270,15 +278,10 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable } else { - const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); - const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); - - Standard_Integer aViewportWidth; - Standard_Integer aViewportHeight; - mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); - gp_GTrsf aTPers; - Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight); + Graphic3d_Mat4d aMat = theObject->TransformPersistence().Compute ( + theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight); + aTPers.SetValue (1, 1, aMat.GetValue (0, 0)); aTPers.SetValue (1, 2, aMat.GetValue (0, 1)); aTPers.SetValue (1, 3, aMat.GetValue (0, 2)); @@ -295,8 +298,8 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable } SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity - ? mySelectingVolumeMgr.ScaleAndTransform (1, aInversedTrsf) - : mySelectingVolumeMgr; + ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL) + : theMgr; SelectMgr_FrustumCache aScaledTrnsfFrustums; @@ -353,7 +356,7 @@ void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_Selectable { const Handle(SelectBasics_SensitiveEntity)& anEnt = aSensitive->BaseSensitive(); SelectMgr_SelectingVolumeManager aTmpMgr = aMgr; - computeFrustum (anEnt, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr); + computeFrustum (anEnt, theMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr); checkOverlap (anEnt, aInversedTrsf, aTmpMgr); } } @@ -377,36 +380,68 @@ void SelectMgr_ViewerSelector::TraverseSensitives() { mystored.Clear(); - NCollection_Handle > aBVHTree; - for (Standard_Integer aBVHTreeIdx = 0; aBVHTreeIdx < 2; ++aBVHTreeIdx) + Standard_Integer aWidth; + Standard_Integer aHeight; + mySelectingVolumeMgr.WindowSize (aWidth, aHeight); + mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), + mySelectingVolumeMgr.ProjectionMatrix(), + mySelectingVolumeMgr.WorldViewMatrix(), + mySelectingVolumeMgr.WorldViewProjState(), + aWidth, aHeight); + + for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt) { - const Standard_Boolean isTrsfPers = aBVHTreeIdx == 1; - if (isTrsfPers) + SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = + static_cast (aBVHSetIt); + + if (mySelectableObjects.IsEmpty (aBVHSubset)) { - if (mySelectableObjectsTrsfPers.Size() == 0) - { - continue; - } - const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); - const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); - const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); - Standard_Integer aViewportWidth; - Standard_Integer aViewportHeight; - mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); - aBVHTree = mySelectableObjectsTrsfPers.BVH (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + continue; + } + + gp_GTrsf aTFrustum; + + SelectMgr_SelectingVolumeManager aMgr (Standard_False); + + // for 2D space selection transform selecting volumes to perform overap testing + // directly in camera's eye space omitting the camera position, which is not + // needed there at all + if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent) + { + const Graphic3d_Mat4d& aMat = mySelectingVolumeMgr.WorldViewMatrix(); + aTFrustum.SetValue (1, 1, aMat.GetValue (0, 0)); + aTFrustum.SetValue (1, 2, aMat.GetValue (0, 1)); + aTFrustum.SetValue (1, 3, aMat.GetValue (0, 2)); + aTFrustum.SetValue (2, 1, aMat.GetValue (1, 0)); + aTFrustum.SetValue (2, 2, aMat.GetValue (1, 1)); + aTFrustum.SetValue (2, 3, aMat.GetValue (1, 2)); + aTFrustum.SetValue (3, 1, aMat.GetValue (2, 0)); + aTFrustum.SetValue (3, 2, aMat.GetValue (2, 1)); + aTFrustum.SetValue (3, 3, aMat.GetValue (2, 2)); + aTFrustum.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3))); + + // define corresponding frustum builder parameters + Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder(); + aBuilder->SetProjectionMatrix (mySelectingVolumeMgr.ProjectionMatrix()); + aBuilder->SetWorldViewMatrix (THE_IDENTITY_MAT); + aBuilder->SetWindowSize (aWidth, aHeight); + aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder); } else { - if (mySelectableObjects.Size() == 0) - { - continue; - } - aBVHTree = mySelectableObjects.BVH(); + aMgr = mySelectingVolumeMgr; } + const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera(); + const Graphic3d_Mat4d& aProjectionMat = mySelectingVolumeMgr.ProjectionMatrix(); + const Graphic3d_Mat4d& aWorldViewMat = aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent + ? mySelectingVolumeMgr.WorldViewMatrix() + : THE_IDENTITY_MAT; + + const NCollection_Handle >& aBVHTree = mySelectableObjects.BVH (aBVHSubset); + Standard_Integer aNode = 0; - if (!mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (0), - aBVHTree->MaxPoint (0))) + if (!aMgr.Overlaps (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0))) { continue; } @@ -420,11 +455,9 @@ void SelectMgr_ViewerSelector::TraverseSensitives() const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode); const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode); const Standard_Boolean isLeftChildIn = - mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), - aBVHTree->MaxPoint (aLeftChildIdx)); + aMgr.Overlaps (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx)); const Standard_Boolean isRightChildIn = - mySelectingVolumeMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), - aBVHTree->MaxPoint (aRightChildIdx)); + aMgr.Overlaps (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx)); if (isLeftChildIn && isRightChildIn) { @@ -454,11 +487,10 @@ void SelectMgr_ViewerSelector::TraverseSensitives() Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode); for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx) { - Handle(SelectMgr_SelectableObject) aSelectableObject = - isTrsfPers ? mySelectableObjectsTrsfPers.GetObjectById (anIdx) - : mySelectableObjects.GetObjectById (anIdx); + const Handle(SelectMgr_SelectableObject)& aSelectableObject = + mySelectableObjects.GetObjectById (aBVHSubset, anIdx); - traverseObject (aSelectableObject); + traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight); } if (aHead < 0) { @@ -528,8 +560,7 @@ const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standa //================================================== Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const { - return mySelectableObjects.Contains (theObject) - || mySelectableObjectsTrsfPers.Contains (theObject); + return mySelectableObjects.Contains (theObject); } //================================================== @@ -691,15 +722,7 @@ void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_Selec { if (!myMapOfObjectSensitives.IsBound (theObject)) { - if (!theObject->TransformPersistence().Flags) - { - mySelectableObjects.Append (theObject); - } - else - { - mySelectableObjectsTrsfPers.Append (theObject); - } - + mySelectableObjects.Append (theObject); NCollection_Handle anEntitySet = new SelectMgr_SensitiveEntitySet(); myMapOfObjectSensitives.Bind (theObject, anEntitySet); } @@ -732,19 +755,7 @@ void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_Sele //======================================================================= void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject) { - if (!mySelectableObjects.Remove (theObject)) - { - mySelectableObjectsTrsfPers.Remove (theObject); - } - - if (!theObject->TransformPersistence().Flags) - { - mySelectableObjects.Append (theObject); - } - else - { - mySelectableObjectsTrsfPers.Append (theObject); - } + mySelectableObjects.ChangeSubset (theObject); } //======================================================================= @@ -755,10 +766,7 @@ void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_Se { if (myMapOfObjectSensitives.IsBound (theObject)) { - if (!mySelectableObjects.Remove (theObject)) - { - mySelectableObjectsTrsfPers.Remove (theObject); - } + mySelectableObjects.Remove (theObject); myMapOfObjectSensitives.UnBind (theObject); } } @@ -786,19 +794,20 @@ void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_S void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce) { mySelectableObjects.MarkDirty(); - mySelectableObjectsTrsfPers.MarkDirty(); if (theIsForce) { - const Graphic3d_Mat4d& aProjection = mySelectingVolumeMgr.ProjectionMatrix(); - const Graphic3d_Mat4d& aWorldView = mySelectingVolumeMgr.WorldViewMatrix(); - const Graphic3d_WorldViewProjState& aWVPState = mySelectingVolumeMgr.WorldViewProjState(); - Standard_Integer aViewportWidth; - Standard_Integer aViewportHeight; + Standard_Integer aViewportWidth, aViewportHeight; mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight); - mySelectableObjects.BVH(); - mySelectableObjectsTrsfPers.BVH (mySelectingVolumeMgr.Camera(), aProjection, aWorldView, aViewportWidth, aViewportHeight, aWVPState); + Standard_Integer aWidth; + Standard_Integer aHeight; + mySelectingVolumeMgr.WindowSize (aWidth, aHeight); + mySelectableObjects.UpdateBVH (mySelectingVolumeMgr.Camera(), + mySelectingVolumeMgr.ProjectionMatrix(), + mySelectingVolumeMgr.WorldViewMatrix(), + mySelectingVolumeMgr.WorldViewProjState(), + aWidth, aHeight); } } diff --git a/src/SelectMgr/SelectMgr_ViewerSelector.hxx b/src/SelectMgr/SelectMgr_ViewerSelector.hxx index 30f033fd76..17c7ddc020 100644 --- a/src/SelectMgr/SelectMgr_ViewerSelector.hxx +++ b/src/SelectMgr/SelectMgr_ViewerSelector.hxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -248,10 +247,20 @@ protected: //! @return True if owner provides depth limits for sensitive clipping. Standard_EXPORT virtual Standard_Boolean HasDepthClipping (const Handle(SelectMgr_EntityOwner)& theOwner) const; - //! Internal function that checks if there is possible overlap - //! between some entity of selectable object theObject and - //! current selecting volume - Standard_EXPORT void traverseObject (const Handle(SelectMgr_SelectableObject)& theObject); + //! Internal function that checks if there is possible overlap between some entity of selectable object theObject and + //! current selecting volume. + //! @param theObject [in] the selectable object for traversal. + //! @param theMgr [in] the (un)transformed copy of the selecting volume manager representing active selection frustum. + //! @param theCamera, theProjectionMat, theWorldViewMat [in] the source camera and matrices for theMgr given. + //! @param theViewportWidth, theViewportHeight [in] viewport (window) dimensions for evaluating + //! object's transformation persistence. + Standard_EXPORT void traverseObject (const Handle(SelectMgr_SelectableObject)& theObject, + const SelectMgr_SelectingVolumeManager& theMgr, + const Handle(Graphic3d_Camera)& theCamera, + const Graphic3d_Mat4d& theProjectionMat, + const Graphic3d_Mat4d& theWorldViewMat, + const Standard_Integer theViewportWidth, + const Standard_Integer theViewportHeight); //! Internal function that checks if a particular sensitive //! entity theEntity overlaps current selecting volume precisely @@ -279,6 +288,7 @@ private: //! needs to be scaled and transformed for the entity and performs //! necessary calculations void computeFrustum (const Handle(SelectBasics_SensitiveEntity)& theEnt, + const SelectMgr_SelectingVolumeManager& theMgr, const gp_GTrsf& theInvTrsf, SelectMgr_FrustumCache& theCachedMgrs, SelectMgr_SelectingVolumeManager& theResMgr); @@ -307,7 +317,6 @@ protected: SelectMgr_IndexedDataMapOfOwnerCriterion mystored; SelectMgr_SelectingVolumeManager mySelectingVolumeMgr; mutable SelectMgr_SelectableObjectSet mySelectableObjects; - mutable SelectMgr_SelectableObjectTrsfPersSet mySelectableObjectsTrsfPers; SelectMgr_ToleranceMap myTolerances; NCollection_DataMap myZLayerOrderMap; diff --git a/src/StdSelect/StdSelect_ViewerSelector3d.cxx b/src/StdSelect/StdSelect_ViewerSelector3d.cxx index d79356c955..40ca4fa751 100644 --- a/src/StdSelect/StdSelect_ViewerSelector3d.cxx +++ b/src/StdSelect/StdSelect_ViewerSelector3d.cxx @@ -183,9 +183,11 @@ void StdSelect_ViewerSelector3d::Pick (const TColgp_Array1OfPnt2d& thePolyline, //======================================================================= void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theView) { - for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjects.Size(); ++anObjectIdx) + SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); + + for (; aSelectableIt.More(); aSelectableIt.Next()) { - const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjects.GetObjectById (anObjectIdx); + const Handle (SelectMgr_SelectableObject)& anObj = aSelectableIt.Value(); Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager()); @@ -200,28 +202,6 @@ void StdSelect_ViewerSelector3d::DisplaySensitive (const Handle(V3d_View)& theVi myStructs.Append (aStruct); } - for (Standard_Integer anObjectIdx = 0; anObjectIdx <= mySelectableObjectsTrsfPers.Size(); ++anObjectIdx) - { - const Handle (SelectMgr_SelectableObject)& anObj = mySelectableObjectsTrsfPers.GetObjectById (anObjectIdx); - - Handle(Graphic3d_Structure) aStruct = new Graphic3d_Structure (theView->Viewer()->StructureManager()); - - if (anObj->TransformPersistence().Flags == 0) - { - continue; - } - - for (anObj->Init(); anObj->More(); anObj->Next()) - { - if (anObj->CurrentSelection()->GetSelectionState() == SelectMgr_SOS_Activated) - { - computeSensitivePrs (aStruct, anObj->CurrentSelection(), anObj->Transformation(), anObj->TransformPersistence()); - } - } - - myStructs.Append (aStruct); - } - for (Standard_Integer aStructIdx = 1; aStructIdx <= myStructs.Length(); ++aStructIdx) { Handle(Graphic3d_Structure)& aStruct = myStructs.ChangeValue (aStructIdx); diff --git a/tests/bugs/vis/bug27739 b/tests/bugs/vis/bug27739 new file mode 100644 index 0000000000..91afe26362 --- /dev/null +++ b/tests/bugs/vis/bug27739 @@ -0,0 +1,81 @@ +puts "========" +puts "OCC27739" +puts "========" +puts "" +################################################################## +puts "Visualization, TKV3d - implement individual acceleration data structure for selection of 2D persistent objects" +################################################################## + +# Create view +set win_width 409 +set win_height 409 +vinit View1 w=$win_width h=$win_height +vclear + +# Display several different presentation types with orthographic camera +vcamera -ortho +vtrihedron tri1 +box box3d 100 100 100 +box box2d 100 100 1 +box box2d_pos 100 100 1 +box box2d_loc 100 100 1 +box box_zoom 100 100 100 + +vdisplay box3d -dispMode 1 -highMode 0 +vdisplay box2d -dispMode 1 -highMode 1 -2d +vdisplay box2d_pos -dispMode 1 -highMode 1 -2d -trsfPersPos -1 -1 +vdisplay box2d_loc -dispMode 1 -highMode 1 -2d +vdisplay box_zoom -dispMode 1 -highMode 0 -trsfPers zoom +vdisplay box2d +vsetlocation box2d_loc 100 0 0 +vsetlocation box_zoom -100 -100 100 + +vsetmaterial box3d box2d box2d_pos box2d_loc box_zoom PLASTIC +vsetcolor box3d GOLD +vsetcolor box2d GREEN +vsetcolor box2d_pos GREEN +vsetcolor box2d_loc GREEN +vsetcolor box_zoom RED +vfit + +# ========================================== +# Test selection for orthographic projection +# ========================================== + +set test_1 {220 120}; # box2d +set test_2 {350 150}; # box2d_pos +set test_3 { 50 350}; # box2d_loc + +vmoveto {*}$test_1 +if {[vreadpixel {*}$test_1 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_1.png + +vmoveto {*}$test_2 +if {[vreadpixel {*}$test_2 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_2.png + +vmoveto {*}$test_3 +if {[vreadpixel {*}$test_3 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_3.png + +# ========================================= +# Test selection for perspective projection +# ========================================= + +vcamera -persp +vcamera -distance 1000 +set test_1 {220 120}; # box2d +set test_2 {350 150}; # box2d_pos +set test_3 { 50 350}; # box2d_loc + +vmoveto {*}$test_1 +if {[vreadpixel {*}$test_1 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_4.png + +vmoveto {*}$test_2 +if {[vreadpixel {*}$test_2 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_5.png + +vmoveto {*}$test_3 +if {[vreadpixel {*}$test_3 name] != "CYAN1 1"} { puts "ERROR: zoom persistent box is not detected!" } +vdump $imagedir/${casename}_6.png