1 // Created on: 2014-08-15
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <SelectMgr_SelectableObjectSet.hxx>
17 #include <SelectMgr_VectorTypes.hxx>
19 #include <BVH_BinnedBuilder.hxx>
20 #include <BVH_LinearBuilder.hxx>
24 //! Short-cut definition of indexed data map of selectable objects
25 typedef NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> ObjectsMap;
27 //-------------------------------------------------------------------------------------
28 // Adaptor over regular objects subset of SelectMgr_SelectableObjectSet for BVH builder
29 //-------------------------------------------------------------------------------------
31 //! This class provides direct access to fields of SelectMgr_SelectableObjectSet
32 //! so the BVH builder could explicitly arrange objects in the map as necessary
33 //! to provide synchronization of indexes with constructed BVH tree.
34 class BVHBuilderAdaptorRegular : public BVH_Set<Standard_Real, 3>
38 //! Construct adaptor.
39 BVHBuilderAdaptorRegular (ObjectsMap& theObjects) : myObjects (theObjects) {};
41 //! Returns bounding box of object with index theIndex
42 virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE
44 const Handle(SelectMgr_SelectableObject)& anObject = myObjects.FindKey (theIndex + 1);
46 anObject->BoundingBox (aBox);
48 return Select3D_BndBox3d();
50 return Select3D_BndBox3d (SelectMgr_Vec3 (aBox.CornerMin().X(), aBox.CornerMin().Y(), aBox.CornerMin().Z()),
51 SelectMgr_Vec3 (aBox.CornerMax().X(), aBox.CornerMax().Y(), aBox.CornerMax().Z()));
54 //! Returns bounding box of the whole subset.
55 virtual Select3D_BndBox3d Box() const Standard_OVERRIDE
59 myBox = BVH_Set<Standard_Real, 3>::Box();
64 //! Make inherited method Box() visible to avoid CLang warning
65 using BVH_Set<Standard_Real, 3>::Box;
67 //! Returns center of object with index theIndex in the set
68 //! along the given axis theAxis
69 virtual Standard_Real Center (const Standard_Integer theIndex,
70 const Standard_Integer theAxis) const Standard_OVERRIDE
72 const Select3D_BndBox3d aBndBox = Box (theIndex);
74 return (aBndBox.CornerMin()[theAxis] +
75 aBndBox.CornerMax()[theAxis]) * 0.5;
78 //! Returns size of objects set.
79 virtual Standard_Integer Size() const Standard_OVERRIDE
81 return myObjects.Size();
84 //! Swaps items with indexes theIndex1 and theIndex2 in the set
85 virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2) Standard_OVERRIDE
87 myObjects.Swap (theIndex1 + 1, theIndex2 + 1);
91 BVHBuilderAdaptorRegular& operator=(BVHBuilderAdaptorRegular) { return *this; }
94 ObjectsMap& myObjects;
95 mutable Select3D_BndBox3d myBox;
98 //----------------------------------------------------------------------------------------
99 // Adaptor over persistent objects subset of SelectMgr_SelectableObjectSet for BVH builder
100 //----------------------------------------------------------------------------------------
102 //! This class provides direct access to fields of SelectMgr_SelectableObjectSet
103 //! so the BVH builder could explicitly arrange objects in the map as necessary
104 //! to provide synchronization of indexes with constructed BVH tree.
105 class BVHBuilderAdaptorPersistent : public BVH_Set<Standard_Real, 3>
109 //! Construct adaptor.
110 //! @param theCamera, theProjectionMat, theWorldViewMat,
111 //! theWidth, theHeight [in] view properties used for computation of
112 //! bounding boxes within the world view camera space.
113 BVHBuilderAdaptorPersistent (ObjectsMap& theObjects,
114 const Handle(Graphic3d_Camera)& theCamera,
115 const Graphic3d_Mat4d& theProjectionMat,
116 const Graphic3d_Mat4d& theWorldViewMat,
117 const Standard_Integer theWidth,
118 const Standard_Integer theHeight)
119 : myObjects (theObjects)
121 myBoundings.ReSize (myObjects.Size());
122 for (Standard_Integer anI = 1; anI <= myObjects.Size(); ++anI)
124 const Handle(SelectMgr_SelectableObject)& anObject = myObjects (anI);
126 Bnd_Box aBoundingBox;
127 anObject->BoundingBox (aBoundingBox);
128 if (aBoundingBox.IsVoid()
129 || anObject->TransformPersistence().IsNull())
131 myBoundings.Add (new Select3D_HBndBox3d());
135 anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox);
137 const gp_Pnt aMin = aBoundingBox.CornerMin();
138 const gp_Pnt aMax = aBoundingBox.CornerMax();
139 myBoundings.Add (new Select3D_HBndBox3d (Select3D_Vec3 (aMin.X(), aMin.Y(), aMin.Z()),
140 Select3D_Vec3 (aMax.X(), aMax.Y(), aMax.Z())));
145 //! Returns bounding box of object with index theIndex
146 virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE
148 return *myBoundings (theIndex + 1);
151 //! Returns bounding box of the whole subset.
152 virtual Select3D_BndBox3d Box() const Standard_OVERRIDE
154 if (!myBox.IsValid())
156 myBox = BVH_Set<Standard_Real, 3>::Box();
161 //! Make inherited method Box() visible to avoid CLang warning
162 using BVH_Set<Standard_Real, 3>::Box;
164 //! Returns center of object with index theIndex in the set
165 //! along the given axis theAxis
166 virtual Standard_Real Center (const Standard_Integer theIndex,
167 const Standard_Integer theAxis) const Standard_OVERRIDE
169 const Select3D_BndBox3d& aBoundingBox = *myBoundings (theIndex + 1);
171 return (aBoundingBox.CornerMin()[theAxis] + aBoundingBox.CornerMax()[theAxis]) * 0.5;
174 //! Returns size of objects set.
175 virtual Standard_Integer Size() const Standard_OVERRIDE
177 return myObjects.Size();
180 //! Swaps items with indexes theIndex1 and theIndex2 in the set
181 virtual void Swap (const Standard_Integer theIndex1, const Standard_Integer theIndex2) Standard_OVERRIDE
183 const Standard_Integer aStructIdx1 = theIndex1 + 1;
184 const Standard_Integer aStructIdx2 = theIndex2 + 1;
186 myObjects.Swap (aStructIdx1, aStructIdx2);
187 myBoundings.Swap (aStructIdx1, aStructIdx2);
191 BVHBuilderAdaptorPersistent& operator=(BVHBuilderAdaptorPersistent) { return *this; }
194 ObjectsMap& myObjects;
195 mutable Select3D_BndBox3d myBox;
196 typedef NCollection_Shared<Select3D_BndBox3d> Select3D_HBndBox3d;
197 NCollection_IndexedMap<Handle(Select3D_HBndBox3d)> myBoundings;
200 static const Graphic3d_Mat4d SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT;
203 //=============================================================================
204 // Function: Constructor
206 //=============================================================================
207 SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet()
211 myBVH[BVHSubset_2dPersistent] = new BVH_Tree<Standard_Real, 3>();
212 myBVH[BVHSubset_3dPersistent] = new BVH_Tree<Standard_Real, 3>();
213 myBVH[BVHSubset_3d] = new BVH_Tree<Standard_Real, 3>();
215 myBuilder[BVHSubset_2dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth);
216 myBuilder[BVHSubset_3dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth);
217 myBuilder[BVHSubset_3d] = new BVH_BinnedBuilder<Standard_Real, 3, 4> (BVH_Constants_LeafNodeSizeSingle, BVH_Constants_MaxTreeDepth, Standard_True);
219 myIsDirty[BVHSubset_2dPersistent] = Standard_False;
220 myIsDirty[BVHSubset_3dPersistent] = Standard_False;
221 myIsDirty[BVHSubset_3d] = Standard_False;
224 //=============================================================================
227 //=============================================================================
228 Standard_Boolean SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject)
230 // get an appropriate BVH subset to insert the object into it
231 const Standard_Integer aSubsetIdx = appropriateSubset (theObject);
233 // check that the object is excluded from other subsets
234 if (myObjects[(aSubsetIdx + 1) % BVHSubsetNb].Contains (theObject)
235 || myObjects[(aSubsetIdx + 2) % BVHSubsetNb].Contains (theObject))
237 return Standard_False;
240 // try adding it into the appropriate object subset
241 const Standard_Integer aSize = myObjects[aSubsetIdx].Size();
243 if (aSize < myObjects[aSubsetIdx].Add (theObject))
245 myIsDirty[aSubsetIdx] = Standard_True;
247 return Standard_True;
250 return Standard_False;
253 //=============================================================================
256 //=============================================================================
257 Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject)
259 // remove object from the first found subset
260 for (Standard_Integer aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx)
262 const Standard_Integer anIndex = myObjects[aSubsetIdx].FindIndex (theObject);
266 const Standard_Integer aSize = myObjects[aSubsetIdx].Size();
268 if (anIndex != aSize)
270 myObjects[aSubsetIdx].Swap (anIndex, aSize);
273 myObjects[aSubsetIdx].RemoveLast();
274 myIsDirty[aSubsetIdx] = Standard_True;
276 return Standard_True;
280 return Standard_False;
283 //=============================================================================
284 // Function: ChangeSubset
286 //=============================================================================
287 void SelectMgr_SelectableObjectSet::ChangeSubset (const Handle(SelectMgr_SelectableObject)& theObject)
289 // do not do anything is object is not in the map
290 const Standard_Integer aCurrSubsetIdx = currentSubset (theObject);
292 if (aCurrSubsetIdx < 0)
297 // check whether the subset need to be changed at all
298 const Standard_Integer aSubsetIdx = appropriateSubset (theObject);
300 if (aCurrSubsetIdx == aSubsetIdx)
305 // replace object in the maps
310 //=============================================================================
311 // Function: UpdateBVH
313 //=============================================================================
314 void SelectMgr_SelectableObjectSet::UpdateBVH (const Handle(Graphic3d_Camera)& theCamera,
315 const Graphic3d_Mat4d& theProjectionMat,
316 const Graphic3d_Mat4d& theWorldViewMat,
317 const Graphic3d_WorldViewProjState& theViewState,
318 const Standard_Integer theViewportWidth,
319 const Standard_Integer theViewportHeight)
321 // -----------------------------------------
322 // check and update 3D BVH tree if necessary
323 // -----------------------------------------
324 if (!IsEmpty (BVHSubset_3d) && myIsDirty[BVHSubset_3d])
326 // construct adaptor over private fields to provide direct access for the BVH builder
327 BVHBuilderAdaptorRegular anAdaptor (myObjects[BVHSubset_3d]);
329 // update corresponding BVH tree data structure
330 myBuilder[BVHSubset_3d]->Build (&anAdaptor, myBVH[BVHSubset_3d].get(), anAdaptor.Box());
332 // release dirty state
333 myIsDirty[BVHSubset_3d] = Standard_False;
336 if (!theCamera.IsNull())
338 const Standard_Boolean isWindowSizeChanged =
339 (myLastHeight != theViewportHeight) || (myLastWidth != theViewportWidth);
341 // -----------------------------------------------------
342 // check and update 3D persistence BVH tree if necessary
343 // -----------------------------------------------------
344 if (!IsEmpty (BVHSubset_3dPersistent) &&
345 (myIsDirty[BVHSubset_3dPersistent] || myLastViewState.IsChanged (theViewState) || isWindowSizeChanged))
347 // construct adaptor over private fields to provide direct access for the BVH builder
348 BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_3dPersistent],
349 theCamera, theProjectionMat, theWorldViewMat, theViewportWidth, theViewportHeight);
351 // update corresponding BVH tree data structure
352 myBuilder[BVHSubset_3dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_3dPersistent].get(), anAdaptor.Box());
355 // -----------------------------------------------------
356 // check and update 2D persistence BVH tree if necessary
357 // -----------------------------------------------------
358 if (!IsEmpty (BVHSubset_2dPersistent) &&
359 (myIsDirty[BVHSubset_2dPersistent] || myLastViewState.IsProjectionChanged (theViewState) || isWindowSizeChanged))
361 // construct adaptor over private fields to provide direct access for the BVH builder
362 BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_2dPersistent],
363 theCamera, theProjectionMat, SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT, theViewportWidth, theViewportHeight);
365 // update corresponding BVH tree data structure
366 myBuilder[BVHSubset_2dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_2dPersistent].get(), anAdaptor.Box());
369 // release dirty state for every subset
370 myIsDirty[BVHSubset_3dPersistent] = Standard_False;
371 myIsDirty[BVHSubset_2dPersistent] = Standard_False;
373 // keep last view state
374 myLastViewState = theViewState;
377 // keep last window state
378 myLastWidth = theViewportWidth;
379 myLastHeight = theViewportHeight;
382 //=============================================================================
383 // Function: MarkDirty
385 //=============================================================================
386 void SelectMgr_SelectableObjectSet::MarkDirty()
388 myIsDirty[BVHSubset_3d] = Standard_True;
389 myIsDirty[BVHSubset_3dPersistent] = Standard_True;
390 myIsDirty[BVHSubset_2dPersistent] = Standard_True;