1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-04 18:06:22 +03:00

0027739: Visualization, TKV3d - implement individual acceleration data structure for selection of 2D persistent objects

Low-level selection algorithms has been improved to explicitly support 2D
transformation persistent objects. This patch generally touches:

1) SelectMgr_SelectableObjectSet - the lists of objects has been split onto three
subsets (regular, 3d-persistent, 2d-persistent). Each subset has individual BVH
tree. The algorithms are now have more flexibility to update only those trees
that is really required for actual camera state.

2) SelectMgr_ViewerSelector - explicitly supports Eye space selection operations
on BVH tree for 2d-persistent subset. Change of camera position does not
anymore affect acceleration data structure (BVH tree) of 2d-persistent selectable objects.

3) Other classes from SelectMgr have been fine-tuned to provide appropriate API.

Porting notes:

This patch touches very low-level selection classes. If the low-level features were used
the following modifications may need to be considered for porting:

1) Iteration over objects of SelectMgr_SelectableObjectSet should now
be implemented with corresponding Iterator class.

2) SelectMgr_BaseFrustum::ScaleAndTransform and derived classes return
Handle(SelectMgr_BaseFrustum) instead of NCollection_Handle<> type.

Small correction of test case for issue CR27739
This commit is contained in:
apl 2016-09-09 15:53:58 +03:00 committed by bugmaster
parent c10703215e
commit 099f351396
21 changed files with 765 additions and 557 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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<SelectMgr_BaseFrustum> 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,

View File

@ -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;

View File

@ -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

View File

@ -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_BaseFrustum> 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_BaseFrustum> 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_BaseFrustum> 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_BaseFrustum> 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<SelectMgr_BaseFrustum> (aRes);
return aRes;
}
// =======================================================================

View File

@ -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<SelectMgr_BaseFrustum> 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,

View File

@ -13,58 +13,236 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Bnd_Box.hxx>
#include <BVH_BinnedBuilder.hxx>
#include <SelectMgr_SelectableObjectSet.hxx>
#include <SelectMgr_VectorTypes.hxx>
//=======================================================================
// 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 <BVH_BinnedBuilder.hxx>
#include <BVH_LinearBuilder.hxx>
namespace
{
myBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (1, 32, Standard_True);
}
//! Short-cut definition of indexed data map of selectable objects
typedef NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> 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<Standard_Real, 3>
{
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<Standard_Real, 3>::Box();
}
return myBox;
}
MarkDirty();
//! Make inherited method Box() visible to avoid CLang warning
using BVH_Set<Standard_Real, 3>::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<Standard_Real, 3>
{
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<Standard_Real, 3>::Box();
}
return myBox;
}
//! Make inherited method Box() visible to avoid CLang warning
using BVH_Set<Standard_Real, 3>::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_BndBox3d> Select3D_HBndBox3d;
NCollection_IndexedMap<Handle(Select3D_HBndBox3d)> 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<Standard_Real, 3>();
myBVH[BVHSubset_3dPersistent] = new BVH_Tree<Standard_Real, 3>();
myBVH[BVHSubset_3d] = new BVH_Tree<Standard_Real, 3>();
myBuilder[BVHSubset_2dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (1, 32);
myBuilder[BVHSubset_3dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (1, 32);
myBuilder[BVHSubset_3d] = new BVH_BinnedBuilder<Standard_Real, 3, 4> (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;
}

View File

@ -17,68 +17,210 @@
#define _SelectMgr_SelectableObjectSet_HeaderFile
#include <BVH_PrimitiveSet.hxx>
#include <Select3D_BndBox3d.hxx>
#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_VectorTypes.hxx>
#include <BVH_Tree.hxx>
#include <Graphic3d_Mat4d.hxx>
#include <Graphic3d_WorldViewProjState.hxx>
#include <NCollection_Handle.hxx>
#include <NCollection_IndexedMap.hxx>
#include <SelectMgr_SelectableObject.hxx>
//! 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<Standard_Real, 3>
//! 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<Handle(SelectMgr_SelectableObject)>::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<Standard_Real, 3>::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_Tree<Standard_Real, 3> >& BVH(const BVHSubset theSubset) const
{
return myBVH[theSubset];
}
private:
NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> 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<Handle(SelectMgr_SelectableObject)> myObjects[BVHSubsetNb]; //!< Map of objects for each subset
NCollection_Handle<BVH_Tree<Standard_Real, 3> > myBVH[BVHSubsetNb]; //!< BVH tree computed for each subset
NCollection_Handle<BVH_Builder<Standard_Real, 3> > 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

View File

@ -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 <SelectMgr_SelectableObjectTrsfPersSet.hxx>
#include <Bnd_Box.hxx>
#include <BVH_LinearBuilder.hxx>
#include <SelectMgr_VectorTypes.hxx>
//=======================================================================
// function : SelectMgr_SelectableObjectTrsfPersSet
// purpose :
//=======================================================================
SelectMgr_SelectableObjectTrsfPersSet::SelectMgr_SelectableObjectTrsfPersSet()
: myIsDirty (Standard_False),
myBVH (new BVH_Tree<Standard_Real, 3>())
{
myBuilder = new BVH_LinearBuilder<Standard_Real, 3> (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<BVH_Tree<Standard_Real, 3> >&
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<Standard_Real, 3>::Box());
myObjectBoxesState = theWVPState;
myObjectBoxes.Clear();
myIsDirty = Standard_False;
return myBVH;
}

View File

@ -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 <BVH_Builder.hxx>
#include <BVH_Set.hxx>
#include <BVH_Tree.hxx>
#include <Graphic3d_Camera.hxx>
#include <Graphic3d_WorldViewProjState.hxx>
#include <NCollection_Handle.hxx>
#include <NCollection_IndexedMap.hxx>
#include <Select3D_BndBox3d.hxx>
#include <SelectMgr_SelectableObject.hxx>
//! 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<Standard_Real, 3>
{
private:
typedef NCollection_Handle<Select3D_BndBox3d> 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_Tree<Standard_Real, 3> >& 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<BVH_Tree<Standard_Real, 3> > myBVH;
//! Builder for bottom-level BVH.
NCollection_Handle<BVH_Builder<Standard_Real, 3> > myBuilder;
//! Set of transform persistence objects.
NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> 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<HBndBox3d> myObjectBoxes;
//! State of world view projection used for generation of transformation persistence bounding boxes.
Graphic3d_WorldViewProjState myObjectBoxesState;
};
#endif

View File

@ -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);
}

View File

@ -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<SelectMgr_BaseFrustum> 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

View File

@ -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_BaseFrustum> 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_BaseFrustum> SelectMgr_TriangularFrustum::ScaleAndT
computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes);
cacheVertexProjections (aRes);
cacheVertexProjections (aRes.get());
return NCollection_Handle<SelectMgr_BaseFrustum> (aRes);
return aRes;
}
//=======================================================================

View File

@ -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<SelectMgr_BaseFrustum> 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)
};

View File

@ -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_BaseFrustum> 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<SelectMgr_BaseFrustum> (aRes);
return aRes;
}
// =======================================================================

View File

@ -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<SelectMgr_BaseFrustum> 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,

View File

@ -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<SelectMgr_SensitiveEntitySet>& 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<BVH_Tree<Standard_Real, 3> > 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<SelectMgr_SelectableObjectSet::BVHSubset> (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<BVH_Tree<Standard_Real, 3> >& 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<SelectMgr_SensitiveEntitySet> 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);
}
}

View File

@ -28,7 +28,6 @@
#include <SelectMgr_Selection.hxx>
#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_SelectableObjectSet.hxx>
#include <SelectMgr_SelectableObjectTrsfPersSet.hxx>
#include <SelectMgr_StateOfSelection.hxx>
#include <SelectMgr_ToleranceMap.hxx>
#include <Standard_OStream.hxx>
@ -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<Graphic3d_ZLayerId, Standard_Integer> myZLayerOrderMap;

View File

@ -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);

81
tests/bugs/vis/bug27739 Normal file
View File

@ -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