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 |
22 | namespace |
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 | |
200 | static const Graphic3d_Mat4d THE_IDENTITY_MAT; |
201 | } |
202 | |
203 | //============================================================================= |
204 | // Function: Constructor |
205 | // Purpose : |
206 | //============================================================================= |
f751596e |
207 | SelectMgr_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 | |
215 | myBuilder[BVHSubset_2dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (1, 32); |
216 | myBuilder[BVHSubset_3dPersistent] = new BVH_LinearBuilder<Standard_Real, 3> (1, 32); |
217 | myBuilder[BVHSubset_3d] = new BVH_BinnedBuilder<Standard_Real, 3, 4> (1, 32, Standard_True); |
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 |
228 | Standard_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 |
257 | Standard_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 | //============================================================================= |
287 | void 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 | //============================================================================= |
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) |
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 |
330 | myBuilder[BVHSubset_3d]->Build (&anAdaptor, myBVH[BVHSubset_3d].operator->(), anAdaptor.Box()); |
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 |
352 | myBuilder[BVHSubset_3dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_3dPersistent].operator->(), anAdaptor.Box()); |
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], |
363 | theCamera, theProjectionMat, THE_IDENTITY_MAT, theViewportWidth, theViewportHeight); |
364 | |
365 | // update corresponding BVH tree data structure |
366 | myBuilder[BVHSubset_2dPersistent]->Build (&anAdaptor, myBVH[BVHSubset_2dPersistent].operator->(), anAdaptor.Box()); |
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 | //============================================================================= |
386 | void 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 | } |