1 // Created on: 1995-02-15
2 // Created by: Roberc Coublanc
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <SelectMgr_ViewerSelector.hxx>
19 #include <BVH_Tree.hxx>
20 #include <gp_GTrsf.hxx>
22 #include <OSD_Environment.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_SensitiveEntity.hxx>
25 #include <SelectBasics_PickResult.hxx>
26 #include <SelectMgr_EntityOwner.hxx>
27 #include <SelectMgr_FrustumBuilder.hxx>
28 #include <SelectMgr_SortCriterion.hxx>
29 #include <SelectMgr_SensitiveEntitySet.hxx>
30 #include <TColStd_Array1OfInteger.hxx>
31 #include <TCollection_AsciiString.hxx>
32 #include <TColStd_HArray1OfInteger.hxx>
33 #include <TColStd_ListOfInteger.hxx>
37 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_ViewerSelector, Standard_Transient)
41 //! Comparison operator for sorting selection results
46 CompareResults (const SelectMgr_IndexedDataMapOfOwnerCriterion& theMapOfCriterion,
47 bool theToPreferClosest)
48 : myMapOfCriterion (&theMapOfCriterion),
49 myToPreferClosest (theToPreferClosest) {}
51 Standard_Boolean operator() (Standard_Integer theLeft, Standard_Integer theRight) const
53 const SelectMgr_SortCriterion& anElemLeft = myMapOfCriterion->FindFromIndex (theLeft);
54 const SelectMgr_SortCriterion& anElemRight = myMapOfCriterion->FindFromIndex (theRight);
55 if (myToPreferClosest)
57 return anElemLeft.IsCloserDepth (anElemRight);
61 return anElemLeft.IsHigherPriority (anElemRight);
66 const SelectMgr_IndexedDataMapOfOwnerCriterion* myMapOfCriterion;
67 bool myToPreferClosest;
70 static const Graphic3d_Mat4d SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
73 //=======================================================================
74 // function : updatePoint3d
76 //=======================================================================
77 void SelectMgr_ViewerSelector::updatePoint3d (SelectMgr_SortCriterion& theCriterion,
78 const SelectBasics_PickResult& thePickResult,
79 const Handle(Select3D_SensitiveEntity)& theEntity,
80 const gp_GTrsf& theInversedTrsf,
81 const SelectMgr_SelectingVolumeManager& theMgr) const
83 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Point)
88 bool hasNormal = false;
89 if (thePickResult.HasPickedPoint())
91 theCriterion.Point = thePickResult.PickedPoint();
92 theCriterion.Normal = thePickResult.SurfaceNormal();
93 const float aNormLen2 = theCriterion.Normal.SquareModulus();
94 if (aNormLen2 > ShortRealEpsilon())
97 theCriterion.Normal *= 1.0f / sqrtf (aNormLen2);
100 else if (!thePickResult.IsValid())
102 theCriterion.Point = thePickResult.PickedPoint();
107 theCriterion.Point = theMgr.DetectedPoint (theCriterion.Depth);
110 gp_GTrsf anInvTrsf = theInversedTrsf;
111 if (theCriterion.Entity->HasInitLocation())
113 anInvTrsf = theCriterion.Entity->InvInitLocation() * anInvTrsf;
115 if (anInvTrsf.Form() != gp_Identity)
117 const gp_GTrsf anInvInvTrsd = anInvTrsf.Inverted();
118 anInvInvTrsd.Transforms (theCriterion.Point.ChangeCoord());
121 Graphic3d_Mat4d aMat4;
122 anInvInvTrsd.GetMat4 (aMat4);
123 const Graphic3d_Vec4d aNormRes = aMat4 * Graphic3d_Vec4d (Graphic3d_Vec3d (theCriterion.Normal), 0.0);
124 theCriterion.Normal = Graphic3d_Vec3 (aNormRes.xyz());
128 const Standard_Real aSensFactor = myDepthTolType == SelectMgr_TypeOfDepthTolerance_SensitivityFactor ? theEntity->SensitivityFactor() : myDepthTolerance;
129 switch (myDepthTolType)
131 case SelectMgr_TypeOfDepthTolerance_Uniform:
133 theCriterion.Tolerance = myDepthTolerance;
136 case SelectMgr_TypeOfDepthTolerance_UniformPixels:
137 case SelectMgr_TypeOfDepthTolerance_SensitivityFactor:
139 if (mySelectingVolumeMgr.Camera().IsNull())
141 // fallback for an arbitrary projection matrix
142 theCriterion.Tolerance = aSensFactor / 33.0;
144 else if (mySelectingVolumeMgr.Camera()->IsOrthographic())
146 theCriterion.Tolerance = myCameraScale * aSensFactor;
150 const Standard_Real aDistFromEye = Abs ((theCriterion.Point.XYZ() - myCameraEye.XYZ()).Dot (myCameraDir.XYZ()));
151 theCriterion.Tolerance = aDistFromEye * myCameraScale * aSensFactor;
158 //==================================================
159 // Function: Initialize
161 //==================================================
162 SelectMgr_ViewerSelector::SelectMgr_ViewerSelector()
163 : myDepthTolerance (0.0),
164 myDepthTolType (SelectMgr_TypeOfDepthTolerance_SensitivityFactor),
165 myToPreferClosest (Standard_True),
167 myToPrebuildBVH (Standard_False),
168 myIsLeftChildQueuedFirst (Standard_False)
170 myEntitySetBuilder = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
173 //=======================================================================
174 // Function: SetPixelTolerance
176 //=======================================================================
177 void SelectMgr_ViewerSelector::SetPixelTolerance (const Standard_Integer theTolerance)
179 if (myTolerances.Tolerance() == theTolerance)
183 if (theTolerance < 0)
185 myTolerances.ResetDefaults();
189 myTolerances.SetCustomTolerance (theTolerance);
193 //==================================================
194 // Function: Activate
196 //==================================================
197 void SelectMgr_ViewerSelector::Activate (const Handle(SelectMgr_Selection)& theSelection)
199 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
201 aSelEntIter.Value()->SetActiveForSelection();
204 if (theSelection->GetSelectionState() != SelectMgr_SOS_Activated)
206 theSelection->SetSelectionState (SelectMgr_SOS_Activated);
208 myTolerances.Add (theSelection->Sensitivity());
212 //==================================================
213 // Function: Deactivate
215 //==================================================
216 void SelectMgr_ViewerSelector::Deactivate (const Handle(SelectMgr_Selection)& theSelection)
218 for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (theSelection->Entities()); aSelEntIter.More(); aSelEntIter.Next())
220 aSelEntIter.Value()->ResetSelectionActiveStatus();
223 if (theSelection->GetSelectionState() == SelectMgr_SOS_Activated)
225 theSelection->SetSelectionState (SelectMgr_SOS_Deactivated);
227 myTolerances.Decrement (theSelection->Sensitivity());
231 //==================================================
234 //==================================================
235 void SelectMgr_ViewerSelector::Clear()
240 //=======================================================================
241 // function: isToScaleFrustum
242 // purpose : Checks if the entity given requires to scale current selecting frustum
243 //=======================================================================
244 Standard_Boolean SelectMgr_ViewerSelector::isToScaleFrustum (const Handle(Select3D_SensitiveEntity)& theEntity)
246 return mySelectingVolumeMgr.IsScalableActiveVolume()
247 && sensitivity (theEntity) < myTolerances.Tolerance();
250 //=======================================================================
251 // function: sensitivity
252 // purpose : In case if custom tolerance is set, this method will return sum of entity
253 // sensitivity and custom tolerance.
254 //=======================================================================
255 Standard_Integer SelectMgr_ViewerSelector::sensitivity (const Handle(Select3D_SensitiveEntity)& theEntity) const
257 return myTolerances.IsCustomTolSet() ?
258 theEntity->SensitivityFactor() + myTolerances.CustomTolerance() : theEntity->SensitivityFactor();
261 //=======================================================================
262 // function: checkOverlap
263 // purpose : Internal function that checks if a particular sensitive
264 // entity theEntity overlaps current selecting volume precisely
265 //=======================================================================
266 void SelectMgr_ViewerSelector::checkOverlap (const Handle(Select3D_SensitiveEntity)& theEntity,
267 const gp_GTrsf& theInversedTrsf,
268 SelectMgr_SelectingVolumeManager& theMgr)
270 const Handle(SelectMgr_EntityOwner)& anOwner = theEntity->OwnerId();
271 Handle(SelectMgr_SelectableObject) aSelectable = !anOwner.IsNull() ? anOwner->Selectable() : Handle(SelectMgr_SelectableObject)();
272 SelectBasics_PickResult aPickResult;
273 const Standard_Boolean isMatched = theEntity->Matches(theMgr, aPickResult);
280 SelectMgr_SortCriterion aCriterion;
281 myZLayerOrderMap.Find (!aSelectable.IsNull() ? aSelectable->ZLayer() : Graphic3d_ZLayerId_Default, aCriterion.ZLayerPosition);
282 aCriterion.Entity = theEntity;
283 aCriterion.Priority = anOwner->Priority();
284 aCriterion.Depth = aPickResult.Depth();
285 aCriterion.MinDist = aPickResult.DistToGeomCenter();
287 if (SelectMgr_SortCriterion* aPrevCriterion = mystored.ChangeSeek (anOwner))
289 ++aPrevCriterion->NbOwnerMatches;
290 aCriterion.NbOwnerMatches = aPrevCriterion->NbOwnerMatches;
291 if (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box)
293 if (aCriterion.IsCloserDepth (*aPrevCriterion))
295 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
296 *aPrevCriterion = aCriterion;
302 aCriterion.NbOwnerMatches = 1;
303 updatePoint3d (aCriterion, aPickResult, theEntity, theInversedTrsf, theMgr);
304 mystored.Add (anOwner, aCriterion);
308 //=======================================================================
309 // function: computeFrustum
311 //=======================================================================
312 void SelectMgr_ViewerSelector::computeFrustum (const Handle(Select3D_SensitiveEntity)& theEnt,
313 const SelectMgr_SelectingVolumeManager& theMgrGlobal,
314 const SelectMgr_SelectingVolumeManager& theMgrObject,
315 const gp_GTrsf& theInvTrsf,
316 SelectMgr_FrustumCache& theCachedMgrs,
317 SelectMgr_SelectingVolumeManager& theResMgr)
319 Standard_Integer aScale = isToScaleFrustum (theEnt) ? sensitivity (theEnt) : 1;
320 const gp_GTrsf aTrsfMtr = theEnt->HasInitLocation() ? theEnt->InvInitLocation() * theInvTrsf : theInvTrsf;
321 const Standard_Boolean toScale = aScale != 1;
322 const Standard_Boolean toTransform = aTrsfMtr.Form() != gp_Identity;
323 if (toScale && toTransform)
325 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, aTrsfMtr, NULL);
326 theResMgr.SetViewClipping (theMgrObject);
330 if (!theCachedMgrs.Find (aScale, theResMgr))
332 theResMgr = theMgrGlobal.ScaleAndTransform (aScale, gp_Trsf(), NULL);
333 theCachedMgrs.Bind (aScale, theResMgr);
335 theResMgr.SetViewClipping (theMgrObject);
337 else if (toTransform)
339 theResMgr = theMgrGlobal.ScaleAndTransform (1, aTrsfMtr, NULL);
340 theResMgr.SetViewClipping (theMgrObject);
344 theResMgr = theMgrObject;
348 //=======================================================================
349 // function: traverseObject
350 // purpose : Internal function that checks if there is possible overlap
351 // between some entity of selectable object theObject and
352 // current selecting volume
353 //=======================================================================
354 void SelectMgr_ViewerSelector::traverseObject (const Handle(SelectMgr_SelectableObject)& theObject,
355 const SelectMgr_SelectingVolumeManager& theMgr,
356 const Handle(Graphic3d_Camera)& theCamera,
357 const Graphic3d_Mat4d& theProjectionMat,
358 const Graphic3d_Mat4d& theWorldViewMat,
359 const Standard_Integer theViewportWidth,
360 const Standard_Integer theViewportHeight)
362 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
363 if (anEntitySet->Size() == 0)
368 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aSensitivesTree = anEntitySet->BVH();
369 gp_GTrsf aInversedTrsf;
370 if (theObject->HasTransformation() || !theObject->TransformPersistence().IsNull())
372 if (theObject->TransformPersistence().IsNull())
374 aInversedTrsf = theObject->InversedTransformation();
378 if (theCamera.IsNull())
383 Graphic3d_Mat4d aMat = theObject->TransformPersistence()->Compute (theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
385 aTPers.SetValue (1, 1, aMat.GetValue (0, 0));
386 aTPers.SetValue (1, 2, aMat.GetValue (0, 1));
387 aTPers.SetValue (1, 3, aMat.GetValue (0, 2));
388 aTPers.SetValue (2, 1, aMat.GetValue (1, 0));
389 aTPers.SetValue (2, 2, aMat.GetValue (1, 1));
390 aTPers.SetValue (2, 3, aMat.GetValue (1, 2));
391 aTPers.SetValue (3, 1, aMat.GetValue (2, 0));
392 aTPers.SetValue (3, 2, aMat.GetValue (2, 1));
393 aTPers.SetValue (3, 3, aMat.GetValue (2, 2));
394 aTPers.SetTranslationPart (gp_XYZ (aMat.GetValue (0, 3), aMat.GetValue (1, 3), aMat.GetValue (2, 3)));
396 aInversedTrsf = (aTPers * gp_GTrsf (theObject->Transformation())).Inverted();
400 SelectMgr_SelectingVolumeManager aMgr = aInversedTrsf.Form() != gp_Identity
401 ? theMgr.ScaleAndTransform (1, aInversedTrsf, NULL)
403 if (!aMgr.OverlapsBox (aSensitivesTree->MinPoint (0),
404 aSensitivesTree->MaxPoint (0)))
409 if (!theObject->ClipPlanes().IsNull()
410 && theObject->ClipPlanes()->ToOverrideGlobal())
412 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
414 else if (!theObject->TransformPersistence().IsNull())
416 if (theObject->TransformPersistence()->IsZoomOrRotate()
417 && !theMgr.ViewClipping().IsNull())
419 // Zoom/rotate persistence object lives in two worlds at the same time.
420 // Global clipping planes can not be trivially applied without being converted
421 // into local space of transformation persistence object.
422 // As more simple alternative - just clip entire object by its anchor point defined in the world space.
423 const gp_Pnt anAnchor = theObject->TransformPersistence()->AnchorPoint();
424 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*theMgr.ViewClipping()); aPlaneIt.More(); aPlaneIt.Next())
426 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
432 const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
433 if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
440 aMgr.SetViewClipping (Handle(Graphic3d_SequenceOfHClipPlane)(), theObject->ClipPlanes(), &theMgr);
442 else if (!theObject->ClipPlanes().IsNull()
443 && !theObject->ClipPlanes()->IsEmpty())
445 aMgr.SetViewClipping (theMgr.ViewClipping(), theObject->ClipPlanes(), &theMgr);
448 if (!theMgr.ViewClipping().IsNull() &&
449 theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
451 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (0), aSensitivesTree->MaxPoint (0));
452 // If box selection is active, and the whole sensitive tree is out of the clip planes
453 // selection is empty for this object
454 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
456 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
458 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
464 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
465 if (aState == Graphic3d_ClipState_Out) // do not process only whole trees, next check on the tree node
472 const Standard_Integer aFirstStored = mystored.Extent() + 1;
474 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
475 Standard_Integer aHead = -1;
476 Standard_Integer aNode = 0; // a root node
477 SelectMgr_FrustumCache aScaledTrnsfFrustums;
478 SelectMgr_SelectingVolumeManager aTmpMgr;
481 if (!aSensitivesTree->IsOuter (aNode))
483 const Standard_Integer aLeftChildIdx = aSensitivesTree->Child<0> (aNode);
484 const Standard_Integer aRightChildIdx = aSensitivesTree->Child<1> (aNode);
485 const Standard_Boolean isLeftChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aLeftChildIdx),
486 aSensitivesTree->MaxPoint (aLeftChildIdx));
487 const Standard_Boolean isRightChildIn = aMgr.OverlapsBox (aSensitivesTree->MinPoint (aRightChildIdx),
488 aSensitivesTree->MaxPoint (aRightChildIdx));
492 aNode = aLeftChildIdx;
494 aStack[aHead] = aRightChildIdx;
496 else if (isLeftChildIn
499 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
508 aNode = aStack[aHead];
514 bool aClipped = false;
515 if (!theMgr.ViewClipping().IsNull() &&
516 theMgr.GetActiveSelectionType() == SelectMgr_SelectionType_Box)
518 Graphic3d_BndBox3d aBBox (aSensitivesTree->MinPoint (aNode), aSensitivesTree->MaxPoint (aNode));
519 // If box selection is active, and the whole sensitive tree is out of the clip planes
520 // selection is empty for this object
521 const Handle(Graphic3d_SequenceOfHClipPlane)& aViewPlanes = theMgr.ViewClipping();
523 for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (*aViewPlanes); aPlaneIt.More(); aPlaneIt.Next())
525 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIt.Value();
530 Graphic3d_ClipState aState = aPlane->ProbeBox (aBBox);
531 if (aState == Graphic3d_ClipState_Out)
536 if (aState == Graphic3d_ClipState_On && !mySelectingVolumeMgr.IsOverlapAllowed()) // partially clipped
538 if (aPlane->ProbeBoxTouch (aBBox))
547 Standard_Integer aStartIdx = aSensitivesTree->BegPrimitive (aNode);
548 Standard_Integer anEndIdx = aSensitivesTree->EndPrimitive (aNode);
549 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
551 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
552 if (aSensitive->IsActiveForSelection())
554 const Handle(Select3D_SensitiveEntity)& anEnt = aSensitive->BaseSensitive();
555 computeFrustum (anEnt, theMgr, aMgr, aInversedTrsf, aScaledTrnsfFrustums, aTmpMgr);
556 checkOverlap (anEnt, aInversedTrsf, aTmpMgr);
565 aNode = aStack[aHead];
570 // in case of Box/Polyline selection - keep only Owners having all Entities detected
571 if (mySelectingVolumeMgr.IsOverlapAllowed()
572 || (theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Box
573 && theMgr.GetActiveSelectionType() != SelectMgr_SelectionType_Polyline))
578 for (Standard_Integer aStoredIter = mystored.Extent(); aStoredIter >= aFirstStored; --aStoredIter)
580 const SelectMgr_SortCriterion& aCriterion = mystored.FindFromIndex (aStoredIter);
581 const Handle(SelectMgr_EntityOwner)& anOwner = aCriterion.Entity->OwnerId();
582 Standard_Integer aNbOwnerEntities = 0;
583 anEntitySet->Owners().Find (anOwner, aNbOwnerEntities);
584 if (aNbOwnerEntities > aCriterion.NbOwnerMatches)
586 mystored.RemoveFromIndex (aStoredIter);
591 //=======================================================================
592 // function: TraverseSensitives
593 // purpose : Traverses BVH containing all added selectable objects and
594 // finds candidates for further search of overlap
595 //=======================================================================
596 void SelectMgr_ViewerSelector::TraverseSensitives()
598 SelectMgr_BVHThreadPool::Sentry aSentry (myBVHThreadPool);
602 Standard_Integer aWidth = 0;
603 Standard_Integer aHeight = 0;
604 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
606 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
607 Graphic3d_Mat4d aProjectionMat, aWorldViewMat;
608 Graphic3d_WorldViewProjState aViewState;
609 if (!aCamera.IsNull())
611 aProjectionMat = aCamera->ProjectionMatrix();
612 aWorldViewMat = aCamera->OrientationMatrix();
613 aViewState = aCamera->WorldViewProjState();
615 myCameraEye = aCamera->Eye().XYZ();
616 myCameraDir = aCamera->Direction().XYZ();
617 myCameraScale = aCamera->IsOrthographic()
619 : 2.0 * Tan (aCamera->FOVy() * M_PI / 360.0);
620 const double aPixelSize = Max (1.0 / aWidth, 1.0 / aHeight);
621 myCameraScale *= aPixelSize;
623 mySelectableObjects.UpdateBVH (aCamera, aProjectionMat, aWorldViewMat, aViewState, aWidth, aHeight);
625 for (Standard_Integer aBVHSetIt = 0; aBVHSetIt < SelectMgr_SelectableObjectSet::BVHSubsetNb; ++aBVHSetIt)
627 const SelectMgr_SelectableObjectSet::BVHSubset aBVHSubset = (SelectMgr_SelectableObjectSet::BVHSubset )aBVHSetIt;
628 if (mySelectableObjects.IsEmpty (aBVHSubset))
633 && aBVHSubset != SelectMgr_SelectableObjectSet::BVHSubset_3d)
638 SelectMgr_SelectingVolumeManager aMgr;
640 // for 2D space selection transform selecting volumes to perform overlap testing
641 // directly in camera's eye space omitting the camera position, which is not
642 // needed there at all
643 if (aBVHSubset == SelectMgr_SelectableObjectSet::BVHSubset_2dPersistent)
646 aTFrustum.SetValue (1, 1, aWorldViewMat.GetValue (0, 0));
647 aTFrustum.SetValue (1, 2, aWorldViewMat.GetValue (0, 1));
648 aTFrustum.SetValue (1, 3, aWorldViewMat.GetValue (0, 2));
649 aTFrustum.SetValue (2, 1, aWorldViewMat.GetValue (1, 0));
650 aTFrustum.SetValue (2, 2, aWorldViewMat.GetValue (1, 1));
651 aTFrustum.SetValue (2, 3, aWorldViewMat.GetValue (1, 2));
652 aTFrustum.SetValue (3, 1, aWorldViewMat.GetValue (2, 0));
653 aTFrustum.SetValue (3, 2, aWorldViewMat.GetValue (2, 1));
654 aTFrustum.SetValue (3, 3, aWorldViewMat.GetValue (2, 2));
655 aTFrustum.SetTranslationPart (gp_XYZ (aWorldViewMat.GetValue (0, 3),
656 aWorldViewMat.GetValue (1, 3),
657 aWorldViewMat.GetValue (2, 3)));
659 // define corresponding frustum builder parameters
660 Handle(SelectMgr_FrustumBuilder) aBuilder = new SelectMgr_FrustumBuilder();
661 Handle(Graphic3d_Camera) aNewCamera = new Graphic3d_Camera();
662 aNewCamera->CopyMappingData (aCamera);
663 aNewCamera->SetIdentityOrientation();
664 aWorldViewMat = aNewCamera->OrientationMatrix(); // should be identity matrix
665 aProjectionMat = aNewCamera->ProjectionMatrix(); // should be the same to aProjectionMat
666 aBuilder->SetCamera (aNewCamera);
667 aBuilder->SetWindowSize (aWidth, aHeight);
668 aMgr = mySelectingVolumeMgr.ScaleAndTransform (1, aTFrustum, aBuilder);
672 aMgr = mySelectingVolumeMgr;
675 const opencascade::handle<BVH_Tree<Standard_Real, 3> >& aBVHTree = mySelectableObjects.BVH (aBVHSubset);
677 Standard_Integer aNode = 0;
678 if (!aMgr.OverlapsBox (aBVHTree->MinPoint (0), aBVHTree->MaxPoint (0)))
683 Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
684 Standard_Integer aHead = -1;
687 if (!aBVHTree->IsOuter (aNode))
689 const Standard_Integer aLeftChildIdx = aBVHTree->Child<0> (aNode);
690 const Standard_Integer aRightChildIdx = aBVHTree->Child<1> (aNode);
691 const Standard_Boolean isLeftChildIn =
692 aMgr.OverlapsBox (aBVHTree->MinPoint (aLeftChildIdx), aBVHTree->MaxPoint (aLeftChildIdx));
693 const Standard_Boolean isRightChildIn =
694 aMgr.OverlapsBox (aBVHTree->MinPoint (aRightChildIdx), aBVHTree->MaxPoint (aRightChildIdx));
698 aNode = aLeftChildIdx;
700 aStack[aHead] = aRightChildIdx;
702 else if (isLeftChildIn
705 aNode = isLeftChildIn ? aLeftChildIdx : aRightChildIdx;
714 aNode = aStack[aHead];
720 Standard_Integer aStartIdx = aBVHTree->BegPrimitive (aNode);
721 Standard_Integer anEndIdx = aBVHTree->EndPrimitive (aNode);
722 for (Standard_Integer anIdx = aStartIdx; anIdx <= anEndIdx; ++anIdx)
724 const Handle(SelectMgr_SelectableObject)& aSelectableObject =
725 mySelectableObjects.GetObjectById (aBVHSubset, anIdx);
727 traverseObject (aSelectableObject, aMgr, aCamera, aProjectionMat, aWorldViewMat, aWidth, aHeight);
734 aNode = aStack[aHead];
743 //==================================================
744 // Function: ClearPicked
746 //==================================================
747 void SelectMgr_ViewerSelector::ClearPicked()
752 //=======================================================================
755 //=======================================================================
756 Handle(SelectMgr_EntityOwner) SelectMgr_ViewerSelector::Picked (const Standard_Integer theRank) const
758 if (theRank < 1 || theRank > NbPicked())
760 return Handle(SelectMgr_EntityOwner)();
763 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
764 const Handle(SelectMgr_EntityOwner)& aStoredOwner = mystored.FindKey (anOwnerIdx);
768 //=======================================================================
769 //function : PickedData
771 //=======================================================================
772 const SelectMgr_SortCriterion& SelectMgr_ViewerSelector::PickedData(const Standard_Integer theRank) const
774 Standard_OutOfRange_Raise_if (theRank < 1 || theRank > NbPicked(), "SelectMgr_ViewerSelector::PickedData() out of range index");
775 const Standard_Integer anOwnerIdx = myIndexes->Value (theRank);
776 return mystored.FindFromIndex (anOwnerIdx);
779 //===================================================
781 // INTERNAL METHODS ....
783 //==================================================
785 //==================================================
786 // Function: SetEntitySetBuilder
788 //==================================================
789 void SelectMgr_ViewerSelector::SetEntitySetBuilder (const Handle(Select3D_BVHBuilder3d)& theBuilder)
791 myEntitySetBuilder = theBuilder;
792 for (SelectMgr_MapOfObjectSensitives::Iterator aSetIter (myMapOfObjectSensitives); aSetIter.More(); aSetIter.Next())
794 aSetIter.ChangeValue()->SetBuilder (myEntitySetBuilder);
798 //==================================================
799 // Function: Contains
801 //==================================================
802 Standard_Boolean SelectMgr_ViewerSelector::Contains (const Handle(SelectMgr_SelectableObject)& theObject) const
804 return mySelectableObjects.Contains (theObject);
807 //==================================================
808 // Function: ActiveModes
809 // Purpose : return all the modes with a given state for an object
810 //==================================================
811 Standard_Boolean SelectMgr_ViewerSelector::Modes (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
812 TColStd_ListOfInteger& theModeList,
813 const SelectMgr_StateOfSelection theWantedState) const
815 Standard_Boolean hasActivatedStates = Contains (theSelectableObject);
816 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
818 if (theWantedState == SelectMgr_SOS_Any)
820 theModeList.Append (aSelIter.Value()->Mode());
822 else if (theWantedState == aSelIter.Value()->GetSelectionState())
824 theModeList.Append (aSelIter.Value()->Mode());
828 return hasActivatedStates;
831 //==================================================
832 // Function: IsActive
834 //==================================================
835 Standard_Boolean SelectMgr_ViewerSelector::IsActive (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
836 const Standard_Integer theMode) const
838 if (!Contains (theSelectableObject))
839 return Standard_False;
841 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
842 return !aSel.IsNull()
843 && aSel->GetSelectionState() == SelectMgr_SOS_Activated;
846 //==================================================
847 // Function: IsInside
849 //==================================================
850 Standard_Boolean SelectMgr_ViewerSelector::IsInside (const Handle(SelectMgr_SelectableObject)& theSelectableObject,
851 const Standard_Integer theMode) const
853 if (!Contains (theSelectableObject))
854 return Standard_False;
856 const Handle(SelectMgr_Selection)& aSel = theSelectableObject->Selection (theMode);
857 return !aSel.IsNull()
858 && aSel->GetSelectionState() != SelectMgr_SOS_Unknown;
862 //=======================================================================
865 //=======================================================================
867 SelectMgr_StateOfSelection SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_Selection)& theSelection) const
869 return theSelection->GetSelectionState();
872 //==================================================
874 // Purpose : gives Information about selectors
875 //==================================================
877 TCollection_AsciiString SelectMgr_ViewerSelector::Status (const Handle(SelectMgr_SelectableObject)& theSelectableObject) const
879 TCollection_AsciiString aStatus ("Status Object :\n\t");
880 for (SelectMgr_SequenceOfSelection::Iterator aSelIter (theSelectableObject->Selections()); aSelIter.More(); aSelIter.Next())
882 if (aSelIter.Value()->GetSelectionState() != SelectMgr_SOS_Unknown)
884 aStatus = aStatus + "Mode " + TCollection_AsciiString (aSelIter.Value()->Mode()) + " present - "
885 + (aSelIter.Value()->GetSelectionState() == SelectMgr_SOS_Activated ? " Active \n\t" : " Inactive \n\t");
889 if (!Contains (theSelectableObject))
891 aStatus = aStatus + "Not Present in the selector\n\n";
897 //=======================================================================
898 //function : SortResult
900 //=======================================================================
901 void SelectMgr_ViewerSelector::SortResult()
903 if (mystored.IsEmpty())
908 const Standard_Integer anExtent = mystored.Extent();
909 if (myIndexes.IsNull() || anExtent != myIndexes->Length())
911 myIndexes = new TColStd_HArray1OfInteger (1, anExtent);
914 TColStd_Array1OfInteger& anIndexArray = myIndexes->ChangeArray1();
915 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExtent; ++anIndexIter)
917 anIndexArray.SetValue (anIndexIter, anIndexIter);
919 std::sort (anIndexArray.begin(), anIndexArray.end(), CompareResults (mystored, myToPreferClosest));
922 //=======================================================================
923 // function : AddSelectableObject
924 // purpose : Adds new object to the map of selectable objects
925 //=======================================================================
926 void SelectMgr_ViewerSelector::AddSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
928 if (!myMapOfObjectSensitives.IsBound (theObject))
930 mySelectableObjects.Append (theObject);
931 Handle(SelectMgr_SensitiveEntitySet) anEntitySet = new SelectMgr_SensitiveEntitySet (myEntitySetBuilder);
932 myMapOfObjectSensitives.Bind (theObject, anEntitySet);
936 //=======================================================================
937 // function : AddSelectionToObject
938 // purpose : Adds new selection to the object and builds its BVH tree
939 //=======================================================================
940 void SelectMgr_ViewerSelector::AddSelectionToObject (const Handle(SelectMgr_SelectableObject)& theObject,
941 const Handle(SelectMgr_Selection)& theSelection)
943 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
945 (*anEntitySet)->Append (theSelection);
946 (*anEntitySet)->BVH();
950 AddSelectableObject (theObject);
951 AddSelectionToObject (theObject, theSelection);
955 //=======================================================================
956 // function : MoveSelectableObject
958 //=======================================================================
959 void SelectMgr_ViewerSelector::MoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
961 mySelectableObjects.ChangeSubset (theObject);
964 //=======================================================================
965 // function : RemoveSelectableObject
966 // purpose : Removes selectable object from map of selectable ones
967 //=======================================================================
968 void SelectMgr_ViewerSelector::RemoveSelectableObject (const Handle(SelectMgr_SelectableObject)& theObject)
970 Handle(SelectMgr_SelectableObject) anObj = theObject;
971 if (myMapOfObjectSensitives.UnBind (theObject))
973 mySelectableObjects.Remove (theObject);
977 //=======================================================================
978 // function : RemoveSelectionOfObject
979 // purpose : Removes selection of the object and marks its BVH tree
981 //=======================================================================
982 void SelectMgr_ViewerSelector::RemoveSelectionOfObject (const Handle(SelectMgr_SelectableObject)& theObject,
983 const Handle(SelectMgr_Selection)& theSelection)
985 if (Handle(SelectMgr_SensitiveEntitySet)* anEntitySet = myMapOfObjectSensitives.ChangeSeek (theObject))
987 (*anEntitySet)->Remove (theSelection);
991 //=======================================================================
992 // function : RebuildObjectsTree
993 // purpose : Marks BVH of selectable objects for rebuild
994 //=======================================================================
995 void SelectMgr_ViewerSelector::RebuildObjectsTree (const Standard_Boolean theIsForce)
997 mySelectableObjects.MarkDirty();
1001 Standard_Integer aViewportWidth, aViewportHeight;
1002 mySelectingVolumeMgr.WindowSize (aViewportWidth, aViewportHeight);
1004 Standard_Integer aWidth;
1005 Standard_Integer aHeight;
1006 mySelectingVolumeMgr.WindowSize (aWidth, aHeight);
1007 const Handle(Graphic3d_Camera)& aCamera = mySelectingVolumeMgr.Camera();
1008 const Graphic3d_Mat4d& aProjMat = !aCamera.IsNull() ? aCamera->ProjectionMatrix()
1009 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
1010 const Graphic3d_Mat4d& anOrientMat = !aCamera.IsNull() ? aCamera->OrientationMatrix()
1011 : SelectMgr_ViewerSelector_THE_IDENTITY_MAT;
1012 Graphic3d_WorldViewProjState aViewState = !aCamera.IsNull() ? aCamera->WorldViewProjState()
1013 : Graphic3d_WorldViewProjState();
1014 mySelectableObjects.UpdateBVH (aCamera, aProjMat, anOrientMat, aViewState, aWidth, aHeight);
1018 //=======================================================================
1019 // function : RebuildSensitivesTree
1020 // purpose : Marks BVH of sensitive entities of particular selectable
1021 // object for rebuild
1022 //=======================================================================
1023 void SelectMgr_ViewerSelector::RebuildSensitivesTree (const Handle(SelectMgr_SelectableObject)& theObject,
1024 const Standard_Boolean theIsForce)
1026 if (!Contains (theObject))
1029 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = myMapOfObjectSensitives.ChangeFind (theObject);
1030 anEntitySet->MarkDirty();
1038 //=======================================================================
1039 // function : resetSelectionActivationStatus
1040 // purpose : Marks all added sensitive entities of all objects as
1042 //=======================================================================
1043 void SelectMgr_ViewerSelector::ResetSelectionActivationStatus()
1045 for (SelectMgr_MapOfObjectSensitivesIterator aSensitivesIter (myMapOfObjectSensitives); aSensitivesIter.More(); aSensitivesIter.Next())
1047 Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = aSensitivesIter.ChangeValue();
1048 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1049 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1051 anEntitySet->GetSensitiveById (anIdx)->ResetSelectionActiveStatus();
1056 //=======================================================================
1057 // function : ActiveOwners
1058 // purpose : Returns the list of active entity owners
1059 //=======================================================================
1060 void SelectMgr_ViewerSelector::ActiveOwners (NCollection_List<Handle(SelectMgr_EntityOwner)>& theOwners) const
1062 for (SelectMgr_MapOfObjectSensitivesIterator anIter (myMapOfObjectSensitives); anIter.More(); anIter.Next())
1064 const Handle(SelectMgr_SensitiveEntitySet)& anEntitySet = anIter.Value();
1065 const Standard_Integer anEntitiesNb = anEntitySet->Size();
1066 for (Standard_Integer anIdx = 0; anIdx < anEntitiesNb; ++anIdx)
1068 const Handle(SelectMgr_SensitiveEntity)& aSensitive = anEntitySet->GetSensitiveById (anIdx);
1069 if (aSensitive->IsActiveForSelection())
1071 theOwners.Append (aSensitive->BaseSensitive()->OwnerId());
1077 //=======================================================================
1078 //function : AllowOverlapDetection
1079 //purpose : Sets the detection type: if theIsToAllow is false,
1080 // only fully included sensitives will be detected, otherwise
1081 // the algorithm will mark both included and overlapped entities
1083 //=======================================================================
1084 void SelectMgr_ViewerSelector::AllowOverlapDetection (const Standard_Boolean theIsToAllow)
1086 mySelectingVolumeMgr.AllowOverlapDetection (theIsToAllow);
1089 //=======================================================================
1090 //function : DumpJson
1092 //=======================================================================
1093 void SelectMgr_ViewerSelector::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1095 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1097 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToPreferClosest)
1098 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mystored.Extent())
1100 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &mySelectingVolumeMgr)
1101 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, &mySelectableObjects)
1103 Standard_Integer aNbOfSelectableObjects = 0;
1104 for (SelectMgr_SelectableObjectSet::Iterator aSelectableIt (mySelectableObjects); aSelectableIt.More(); aSelectableIt.Next())
1106 aNbOfSelectableObjects++;
1108 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aNbOfSelectableObjects)
1110 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.Tolerance())
1111 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTolerances.CustomTolerance())
1112 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerOrderMap.Extent())
1114 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myEntitySetBuilder.get())
1115 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraEye)
1116 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCameraDir)
1117 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCameraScale)
1119 if (!myIndexes.IsNull())
1120 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIndexes->Size())
1122 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsLeftChildQueuedFirst)
1123 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMapOfObjectSensitives.Extent())
1126 //=======================================================================
1127 //function : SetToPrebuildBVH
1129 //=======================================================================
1130 void SelectMgr_ViewerSelector::SetToPrebuildBVH (Standard_Boolean theToPrebuild, Standard_Integer theThreadsNum)
1132 if (!theToPrebuild && !myBVHThreadPool.IsNull())
1134 myBVHThreadPool.Nullify();
1136 else if (theToPrebuild)
1138 myBVHThreadPool = new SelectMgr_BVHThreadPool (theThreadsNum);
1140 myToPrebuildBVH = theToPrebuild;
1143 //=======================================================================
1144 //function : QueueBVHBuild
1146 //=======================================================================
1147 void SelectMgr_ViewerSelector::QueueBVHBuild (const Handle(Select3D_SensitiveEntity)& theEntity)
1149 if (myToPrebuildBVH)
1151 myBVHThreadPool->AddEntity (theEntity);
1155 //=======================================================================
1156 //function : WaitForBVHBuild
1158 //=======================================================================
1159 void SelectMgr_ViewerSelector::WaitForBVHBuild()
1161 if (myToPrebuildBVH)
1163 myBVHThreadPool->WaitThreads();