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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user