b7cd4ba7 |
1 | // Created on: 2013-12-25 |
2 | // Created by: Varvara POSKONINA |
3 | // Copyright (c) 1999-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 | |
16 | #ifndef _OpenGl_BVHTreeSelector_HeaderFile |
17 | #define _OpenGl_BVHTreeSelector_HeaderFile |
18 | |
19 | #include <Graphic3d_Camera.hxx> |
825aa485 |
20 | #include <Graphic3d_WorldViewProjState.hxx> |
b7cd4ba7 |
21 | #include <OpenGl_Vec.hxx> |
22 | |
23 | //! BVHTreeSelector class provides a possibility to store parameters of view volume, |
24 | //! such as its vertices and equations, and contains methods detecting if given AABB overlaps |
25 | //! view volume. |
26 | class OpenGl_BVHTreeSelector |
27 | { |
2b8832bb |
28 | public: |
29 | //! Auxiliary structure holding non-persistent culling options. |
30 | struct CullingContext |
31 | { |
32 | Standard_Real DistCull; //!< culling distance |
33 | Standard_Real SizeCull2; //!< squared culling size |
34 | |
35 | //! Empty constructor. |
36 | CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {} |
37 | }; |
30a1b24e |
38 | |
39 | //! Auxiliary structure representing 3D plane. |
40 | struct Plane |
41 | { |
42 | //! Creates default plane. |
43 | Plane() |
44 | : Origin (0.0, 0.0, 0.0), |
45 | Normal (0.0, 0.0, 1.0) {} |
46 | |
47 | //! Creates plane with specific parameters. |
48 | Plane (const OpenGl_Vec3d& theOrigin, |
49 | const OpenGl_Vec3d& theNormal) |
50 | : Origin (theOrigin), |
51 | Normal (theNormal) {} |
52 | |
53 | OpenGl_Vec3d Origin; |
54 | OpenGl_Vec3d Normal; |
55 | }; |
56 | |
b7cd4ba7 |
57 | public: |
58 | |
59 | //! Creates an empty selector object with parallel projection type by default. |
60 | Standard_EXPORT OpenGl_BVHTreeSelector(); |
61 | |
825aa485 |
62 | //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices. |
b7cd4ba7 |
63 | Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera); |
64 | |
4ecf34cc |
65 | Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth, |
66 | Standard_Integer theViewportHeight, |
67 | Standard_Real theResolutionRatio); |
68 | |
69 | //! Setup distance culling. |
2b8832bb |
70 | Standard_EXPORT void SetCullingDistance (CullingContext& theCtx, |
71 | Standard_Real theDistance) const; |
4ecf34cc |
72 | |
73 | //! Setup size culling. |
2b8832bb |
74 | Standard_EXPORT void SetCullingSize (CullingContext& theCtx, |
75 | Standard_Real theSize) const; |
4ecf34cc |
76 | |
77 | //! Caches view volume's vertices projections along its normals and AABBs dimensions. |
78 | //! Must be called at the beginning of each BVH tree traverse loop. |
79 | Standard_EXPORT void CacheClipPtsProjections(); |
91d96372 |
80 | |
2b8832bb |
81 | //! Checks whether given AABB should be entirely culled or not. |
82 | //! @param theCtx [in] culling properties |
83 | //! @param theMinPt [in] maximum point of AABB |
84 | //! @param theMaxPt [in] minimum point of AABB |
85 | //! @return Standard_True, if AABB is in viewing area, Standard_False otherwise |
86 | bool IsCulled (const CullingContext& theCtx, |
87 | const OpenGl_Vec3d& theMinPt, |
88 | const OpenGl_Vec3d& theMaxPt) const |
89 | { |
90 | return isFullOut (theMinPt, theMaxPt) |
91 | || isTooDistant(theCtx, theMinPt, theMaxPt) |
92 | || isTooSmall (theCtx, theMinPt, theMaxPt); |
93 | } |
b7cd4ba7 |
94 | |
3fe9ce0e |
95 | //! Return the camera definition. |
96 | const Handle(Graphic3d_Camera)& Camera() const { return myCamera; } |
97 | |
825aa485 |
98 | //! Returns current projection matrix. |
7c3ef2f7 |
99 | const OpenGl_Mat4d& ProjectionMatrix() const |
825aa485 |
100 | { |
101 | return myProjectionMat; |
102 | } |
b7cd4ba7 |
103 | |
825aa485 |
104 | //! Returns current world view transformation matrix. |
7c3ef2f7 |
105 | const OpenGl_Mat4d& WorldViewMatrix() const |
825aa485 |
106 | { |
107 | return myWorldViewMat; |
108 | } |
b7cd4ba7 |
109 | |
91d96372 |
110 | Standard_Integer ViewportWidth() const |
111 | { |
112 | return myViewportWidth; |
113 | } |
114 | |
115 | Standard_Integer ViewportHeight() const |
116 | { |
117 | return myViewportHeight; |
118 | } |
119 | |
825aa485 |
120 | //! Returns state of current world view projection transformation matrices. |
121 | const Graphic3d_WorldViewProjState& WorldViewProjState() const |
122 | { |
123 | return myWorldViewProjState; |
124 | } |
b7cd4ba7 |
125 | |
126 | protected: |
127 | |
128 | //! Calculates signed distance from plane to point. |
129 | //! @param theNormal [in] the plane's normal. |
130 | //! @param thePnt [in] |
7c3ef2f7 |
131 | Standard_EXPORT Standard_Real SignedPlanePointDistance (const OpenGl_Vec4d& theNormal, |
132 | const OpenGl_Vec4d& thePnt); |
b7cd4ba7 |
133 | |
2b8832bb |
134 | //! Detects if AABB overlaps view volume using separating axis theorem (SAT). |
135 | //! @param theMinPt [in] maximum point of AABB. |
136 | //! @param theMaxPt [in] minimum point of AABB. |
137 | //! @return FALSE, if AABB is in viewing area, TRUE otherwise. |
138 | bool isFullOut (const OpenGl_Vec3d& theMinPt, |
139 | const OpenGl_Vec3d& theMaxPt) const |
140 | { |
141 | // E1 |
142 | // |_ E0 |
143 | // / |
144 | // E2 |
145 | |
30a1b24e |
146 | // E0 test (x axis) |
2b8832bb |
147 | if (theMinPt.x() > myMaxOrthoProjectionPts[0] |
148 | || theMaxPt.x() < myMinOrthoProjectionPts[0]) |
149 | { |
150 | return true; |
151 | } |
152 | |
30a1b24e |
153 | // E1 test (y axis) |
2b8832bb |
154 | if (theMinPt.y() > myMaxOrthoProjectionPts[1] |
155 | || theMaxPt.y() < myMinOrthoProjectionPts[1]) |
156 | { |
157 | return true; |
158 | } |
159 | |
30a1b24e |
160 | // E2 test (z axis) |
2b8832bb |
161 | if (theMinPt.z() > myMaxOrthoProjectionPts[2] |
162 | || theMaxPt.z() < myMinOrthoProjectionPts[2]) |
163 | { |
164 | return true; |
165 | } |
166 | |
2b8832bb |
167 | const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1; |
30a1b24e |
168 | for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor) |
2b8832bb |
169 | { |
30a1b24e |
170 | // frustum normals |
171 | const OpenGl_Vec3d anAxis = myClipPlanes[aPlaneIter].Normal; |
172 | |
173 | const OpenGl_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPt.x() : theMinPt.x(), |
174 | anAxis.y() > 0.0 ? theMaxPt.y() : theMinPt.y(), |
175 | anAxis.z() > 0.0 ? theMaxPt.z() : theMinPt.z()); |
176 | Standard_Real aPnt0 = aPVertex.Dot (anAxis); |
177 | |
178 | if (aPnt0 >= myMinClipProjectionPts[aPlaneIter] |
179 | && aPnt0 <= myMaxClipProjectionPts[aPlaneIter]) |
2b8832bb |
180 | { |
181 | continue; |
182 | } |
30a1b24e |
183 | |
184 | const OpenGl_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPt.x() : theMaxPt.x(), |
185 | anAxis.y() > 0.0 ? theMinPt.y() : theMaxPt.y(), |
186 | anAxis.z() > 0.0 ? theMinPt.z() : theMaxPt.z()); |
187 | Standard_Real aPnt1 = aNVertex.Dot (anAxis); |
188 | |
189 | const Standard_Real aMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1; |
190 | const Standard_Real aMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1; |
191 | |
192 | if (aMin > myMaxClipProjectionPts[aPlaneIter] |
193 | || aMax < myMinClipProjectionPts[aPlaneIter]) |
2b8832bb |
194 | { |
195 | return true; |
196 | } |
197 | } |
198 | return false; |
199 | } |
200 | |
201 | //! Returns TRUE if given AABB should be discarded by distance culling criterion. |
202 | bool isTooDistant (const CullingContext& theCtx, |
203 | const OpenGl_Vec3d& theMinPt, |
204 | const OpenGl_Vec3d& theMaxPt) const |
205 | { |
206 | if (theCtx.DistCull <= 0.0) |
207 | { |
208 | return false; |
209 | } |
210 | |
211 | // check distance to the bounding sphere as fast approximation |
212 | const Graphic3d_Vec3d aSphereCenter = (theMinPt + theMaxPt) * 0.5; |
213 | const Standard_Real aSphereRadius = (theMaxPt - theMinPt).maxComp() * 0.5; |
214 | return (aSphereCenter - myCamEye).Modulus() - aSphereRadius > theCtx.DistCull; |
215 | } |
216 | |
217 | //! Returns TRUE if given AABB should be discarded by size culling criterion. |
218 | bool isTooSmall (const CullingContext& theCtx, |
219 | const OpenGl_Vec3d& theMinPt, |
220 | const OpenGl_Vec3d& theMaxPt) const |
221 | { |
222 | if (theCtx.SizeCull2 <= 0.0) |
223 | { |
224 | return false; |
225 | } |
f29de682 |
226 | |
227 | const Standard_Real aBoxDiag2 = (theMaxPt - theMinPt).SquareModulus(); |
228 | if (myIsProjectionParallel) |
229 | { |
230 | return aBoxDiag2 < theCtx.SizeCull2; |
231 | } |
232 | |
233 | // note that distances behind the Eye (aBndDist < 0) are not scaled correctly here, |
234 | // but majority of such objects should be culled by frustum |
235 | const OpenGl_Vec3d aBndCenter = (theMinPt + theMaxPt) * 0.5; |
236 | const Standard_Real aBndDist = (aBndCenter - myCamEye).Dot (myCamDir); |
237 | return aBoxDiag2 < theCtx.SizeCull2 * aBndDist * aBndDist; |
2b8832bb |
238 | } |
239 | |
b7cd4ba7 |
240 | protected: |
241 | |
242 | //! Enumerates planes of view volume. |
243 | enum |
244 | { |
b7cd4ba7 |
245 | Plane_Left, |
246 | Plane_Right, |
30a1b24e |
247 | Plane_Bottom, |
248 | Plane_Top, |
b7cd4ba7 |
249 | Plane_Near, |
250 | Plane_Far, |
251 | PlanesNB |
252 | }; |
253 | |
b7cd4ba7 |
254 | protected: |
255 | |
30a1b24e |
256 | Plane myClipPlanes[PlanesNB]; //!< Planes |
257 | NCollection_Array1<OpenGl_Vec3d> myClipVerts; //!< Vertices |
b7cd4ba7 |
258 | |
3fe9ce0e |
259 | Handle(Graphic3d_Camera) myCamera; //!< camera definition |
260 | |
b7cd4ba7 |
261 | // for caching clip points projections onto viewing area normals once per traverse |
30a1b24e |
262 | // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR |
7c3ef2f7 |
263 | Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals |
264 | Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals |
b7cd4ba7 |
265 | |
266 | // for caching clip points projections onto AABB normals once per traverse |
267 | // ORDER: E0, E1, E2 |
7c3ef2f7 |
268 | Standard_Real myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB |
269 | Standard_Real myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB |
b7cd4ba7 |
270 | |
825aa485 |
271 | Standard_Boolean myIsProjectionParallel; |
b7cd4ba7 |
272 | |
7c3ef2f7 |
273 | OpenGl_Mat4d myProjectionMat; |
274 | OpenGl_Mat4d myWorldViewMat; |
b7cd4ba7 |
275 | |
91d96372 |
276 | Standard_Integer myViewportWidth; |
277 | Standard_Integer myViewportHeight; |
278 | |
825aa485 |
279 | Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices. |
4ecf34cc |
280 | |
281 | Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling |
f29de682 |
282 | Graphic3d_Vec3d myCamDir; //!< camera direction for size culling |
283 | Standard_Real myCamScale; //!< camera scale for size culling |
4ecf34cc |
284 | Standard_Real myPixelSize; //!< pixel size for size culling |
4ecf34cc |
285 | |
b7cd4ba7 |
286 | }; |
287 | |
288 | #endif // _OpenGl_BVHTreeSelector_HeaderFile |