1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +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

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