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