0030640: Visualization, Graphic3d_Camera - add option creating Projection matrix...
[occt.git] / src / SelectMgr / SelectMgr_SelectableObjectSet.cxx
CommitLineData
f751596e 1// Created on: 2014-08-15
2// Created by: Varvara POSKONINA
3// Copyright (c) 2005-2014 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
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.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
099f3513 16#include <SelectMgr_SelectableObjectSet.hxx>
17#include <SelectMgr_VectorTypes.hxx>
18
f751596e 19#include <BVH_BinnedBuilder.hxx>
099f3513 20#include <BVH_LinearBuilder.hxx>
f751596e 21
099f3513 22namespace
23{
24 //! Short-cut definition of indexed data map of selectable objects
25 typedef NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)> ObjectsMap;
26
27 //-------------------------------------------------------------------------------------
28 // Adaptor over regular objects subset of SelectMgr_SelectableObjectSet for BVH builder
29 //-------------------------------------------------------------------------------------
30
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>
35 {
36 public:
37
38 //! Construct adaptor.
39 BVHBuilderAdaptorRegular (ObjectsMap& theObjects) : myObjects (theObjects) {};
40
41 //! Returns bounding box of object with index theIndex
42 virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE
43 {
44 const Handle(SelectMgr_SelectableObject)& anObject = myObjects.FindKey (theIndex + 1);
45 Bnd_Box aBox;
46 anObject->BoundingBox (aBox);
47 if (aBox.IsVoid())
48 return Select3D_BndBox3d();
49
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()));
52 }
53
54 //! Returns bounding box of the whole subset.
55 virtual Select3D_BndBox3d Box() const Standard_OVERRIDE
56 {
57 if (!myBox.IsValid())
58 {
59 myBox = BVH_Set<Standard_Real, 3>::Box();
60 }
61 return myBox;
62 }
63
64 //! Make inherited method Box() visible to avoid CLang warning
65 using BVH_Set<Standard_Real, 3>::Box;
66
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
71 {
72 const Select3D_BndBox3d aBndBox = Box (theIndex);
73
74 return (aBndBox.CornerMin()[theAxis] +
75 aBndBox.CornerMax()[theAxis]) * 0.5;
76 }
77
78 //! Returns size of objects set.
79 virtual Standard_Integer Size() const Standard_OVERRIDE
80 {
81 return myObjects.Size();
82 }
83
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
86 {
87 myObjects.Swap (theIndex1 + 1, theIndex2 + 1);
88 }
89
90 private:
91 BVHBuilderAdaptorRegular& operator=(BVHBuilderAdaptorRegular) { return *this; }
92
93 private:
94 ObjectsMap& myObjects;
95 mutable Select3D_BndBox3d myBox;
96 };
97
98 //----------------------------------------------------------------------------------------
99 // Adaptor over persistent objects subset of SelectMgr_SelectableObjectSet for BVH builder
100 //----------------------------------------------------------------------------------------
101
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>
106 {
107 public:
108
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)
120 {
121 myBoundings.ReSize (myObjects.Size());
122 for (Standard_Integer anI = 1; anI <= myObjects.Size(); ++anI)
123 {
124 const Handle(SelectMgr_SelectableObject)& anObject = myObjects (anI);
125
126 Bnd_Box aBoundingBox;
127 anObject->BoundingBox (aBoundingBox);
778cd667 128 if (aBoundingBox.IsVoid()
129 || anObject->TransformPersistence().IsNull())
099f3513 130 {
131 myBoundings.Add (new Select3D_HBndBox3d());
132 }
133 else
134 {
778cd667 135 anObject->TransformPersistence()->Apply (theCamera, theProjectionMat, theWorldViewMat, theWidth, theHeight, aBoundingBox);
099f3513 136
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())));
141 }
142 }
143 }
f751596e 144
099f3513 145 //! Returns bounding box of object with index theIndex
146 virtual Select3D_BndBox3d Box (const Standard_Integer theIndex) const Standard_OVERRIDE
147 {
148 return *myBoundings (theIndex + 1);
149 }
150
151 //! Returns bounding box of the whole subset.
152 virtual Select3D_BndBox3d Box() const Standard_OVERRIDE
153 {
154 if (!myBox.IsValid())
155 {
156 myBox = BVH_Set<Standard_Real, 3>::Box();
157 }
158 return myBox;
159 }
160
161 //! Make inherited method Box() visible to avoid CLang warning
162 using BVH_Set<Standard_Real, 3>::Box;
163
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
168 {
169 const Select3D_BndBox3d& aBoundingBox = *myBoundings (theIndex + 1);
170
171 return (aBoundingBox.CornerMin()[theAxis] + aBoundingBox.CornerMax()[theAxis]) * 0.5;
172 }
173
174 //! Returns size of objects set.
175 virtual Standard_Integer Size() const Standard_OVERRIDE
176 {
177 return myObjects.Size();
178 }
179
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
182 {
183 const Standard_Integer aStructIdx1 = theIndex1 + 1;
184 const Standard_Integer aStructIdx2 = theIndex2 + 1;
185
186 myObjects.Swap (aStructIdx1, aStructIdx2);
187 myBoundings.Swap (aStructIdx1, aStructIdx2);
188 }
189
190 private:
191 BVHBuilderAdaptorPersistent& operator=(BVHBuilderAdaptorPersistent) { return *this; }
192
193 private:
194 ObjectsMap& myObjects;
195 mutable Select3D_BndBox3d myBox;
196 typedef NCollection_Shared<Select3D_BndBox3d> Select3D_HBndBox3d;
197 NCollection_IndexedMap<Handle(Select3D_HBndBox3d)> myBoundings;
198 };
199
896faa72 200 static const Graphic3d_Mat4d SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT;
099f3513 201}
202
203//=============================================================================
204// Function: Constructor
205// Purpose :
206//=============================================================================
f751596e 207SelectMgr_SelectableObjectSet::SelectMgr_SelectableObjectSet()
099f3513 208: myLastWidth (0),
209 myLastHeight (0)
f751596e 210{
099f3513 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>();
214
f5b72419 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);
099f3513 218
219 myIsDirty[BVHSubset_2dPersistent] = Standard_False;
220 myIsDirty[BVHSubset_3dPersistent] = Standard_False;
221 myIsDirty[BVHSubset_3d] = Standard_False;
f751596e 222}
223
099f3513 224//=============================================================================
225// Function: Append
226// Purpose :
227//=============================================================================
825aa485 228Standard_Boolean SelectMgr_SelectableObjectSet::Append (const Handle(SelectMgr_SelectableObject)& theObject)
f751596e 229{
099f3513 230 // get an appropriate BVH subset to insert the object into it
231 const Standard_Integer aSubsetIdx = appropriateSubset (theObject);
825aa485 232
099f3513 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))
d4aaad5b 236 {
099f3513 237 return Standard_False;
238 }
239
240 // try adding it into the appropriate object subset
241 const Standard_Integer aSize = myObjects[aSubsetIdx].Size();
242
243 if (aSize < myObjects[aSubsetIdx].Add (theObject))
244 {
245 myIsDirty[aSubsetIdx] = Standard_True;
825aa485 246
247 return Standard_True;
d4aaad5b 248 }
825aa485 249
250 return Standard_False;
f751596e 251}
252
099f3513 253//=============================================================================
254// Function: Remove
255// Purpose :
256//=============================================================================
825aa485 257Standard_Boolean SelectMgr_SelectableObjectSet::Remove (const Handle(SelectMgr_SelectableObject)& theObject)
f751596e 258{
099f3513 259 // remove object from the first found subset
260 for (Standard_Integer aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx)
f751596e 261 {
099f3513 262 const Standard_Integer anIndex = myObjects[aSubsetIdx].FindIndex (theObject);
263
264 if (anIndex != 0)
ec81011f 265 {
099f3513 266 const Standard_Integer aSize = myObjects[aSubsetIdx].Size();
d4aaad5b 267
099f3513 268 if (anIndex != aSize)
269 {
270 myObjects[aSubsetIdx].Swap (anIndex, aSize);
271 }
d4aaad5b 272
099f3513 273 myObjects[aSubsetIdx].RemoveLast();
274 myIsDirty[aSubsetIdx] = Standard_True;
825aa485 275
099f3513 276 return Standard_True;
277 }
f751596e 278 }
825aa485 279
280 return Standard_False;
f751596e 281}
282
099f3513 283//=============================================================================
284// Function: ChangeSubset
285// Purpose :
286//=============================================================================
287void SelectMgr_SelectableObjectSet::ChangeSubset (const Handle(SelectMgr_SelectableObject)& theObject)
f751596e 288{
099f3513 289 // do not do anything is object is not in the map
290 const Standard_Integer aCurrSubsetIdx = currentSubset (theObject);
f751596e 291
099f3513 292 if (aCurrSubsetIdx < 0)
293 {
294 return;
295 }
296
297 // check whether the subset need to be changed at all
298 const Standard_Integer aSubsetIdx = appropriateSubset (theObject);
299
300 if (aCurrSubsetIdx == aSubsetIdx)
301 {
302 return;
303 }
f751596e 304
099f3513 305 // replace object in the maps
306 Remove (theObject);
307 Append (theObject);
f751596e 308}
309
099f3513 310//=============================================================================
311// Function: UpdateBVH
312// Purpose :
313//=============================================================================
314void 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)
f751596e 320{
099f3513 321 // -----------------------------------------
322 // check and update 3D BVH tree if necessary
323 // -----------------------------------------
324 if (!IsEmpty (BVHSubset_3d) && myIsDirty[BVHSubset_3d])
325 {
326 // construct adaptor over private fields to provide direct access for the BVH builder
327 BVHBuilderAdaptorRegular anAdaptor (myObjects[BVHSubset_3d]);
328
329 // update corresponding BVH tree data structure
f5b72419 330 myBuilder[BVHSubset_3d]->Build (&anAdaptor, myBVH[BVHSubset_3d].get(), anAdaptor.Box());
099f3513 331
332 // release dirty state
333 myIsDirty[BVHSubset_3d] = Standard_False;
334 }
335
336 if (!theCamera.IsNull())
337 {
338 const Standard_Boolean isWindowSizeChanged =
339 (myLastHeight != theViewportHeight) || (myLastWidth != theViewportWidth);
340
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))
346 {
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);
350
351 // update corresponding BVH tree data structure
f5b72419 352 myBuilder[BVHSubset_3dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_3dPersistent].get(), anAdaptor.Box());
099f3513 353 }
354
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))
360 {
361 // construct adaptor over private fields to provide direct access for the BVH builder
362 BVHBuilderAdaptorPersistent anAdaptor (myObjects[BVHSubset_2dPersistent],
896faa72 363 theCamera, theProjectionMat, SelectMgr_SelectableObjectSet_THE_IDENTITY_MAT, theViewportWidth, theViewportHeight);
099f3513 364
365 // update corresponding BVH tree data structure
f5b72419 366 myBuilder[BVHSubset_2dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_2dPersistent].get(), anAdaptor.Box());
099f3513 367 }
368
369 // release dirty state for every subset
370 myIsDirty[BVHSubset_3dPersistent] = Standard_False;
371 myIsDirty[BVHSubset_2dPersistent] = Standard_False;
372
373 // keep last view state
374 myLastViewState = theViewState;
375 }
376
377 // keep last window state
378 myLastWidth = theViewportWidth;
379 myLastHeight = theViewportHeight;
f751596e 380}
381
099f3513 382//=============================================================================
383// Function: MarkDirty
384// Purpose :
385//=============================================================================
386void SelectMgr_SelectableObjectSet::MarkDirty()
f751596e 387{
099f3513 388 myIsDirty[BVHSubset_3d] = Standard_True;
389 myIsDirty[BVHSubset_3dPersistent] = Standard_True;
390 myIsDirty[BVHSubset_2dPersistent] = Standard_True;
f751596e 391}
bc73b006 392//=======================================================================
393//function : DumpJson
394//purpose :
395//=======================================================================
396void SelectMgr_SelectableObjectSet::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
397{
398 for (Standard_Integer aSubsetIdx = 0; aSubsetIdx < BVHSubsetNb; ++aSubsetIdx)
399 {
400 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aSubsetIdx)
401
402 Standard_Boolean IsDirty = myIsDirty[aSubsetIdx];
403 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, IsDirty)
404
405 for (NCollection_IndexedMap<Handle(SelectMgr_SelectableObject)>::Iterator anObjectIt (myObjects[aSubsetIdx]);
406 anObjectIt.More(); anObjectIt.Next())
407 {
408 const Handle(SelectMgr_SelectableObject)& SelectableObject = anObjectIt.Value();
409 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, SelectableObject.get())
410 }
411
412 TCollection_AsciiString separator;
413 OCCT_DUMP_FIELD_VALUE_STRING (theOStream, separator)
414 }
415 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastWidth)
416 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLastHeight)
417}