0031511: Point Cloud Rendering, Volume Rendering - reuse Graphic3d_CullingTool
[occt.git] / src / Graphic3d / Graphic3d_CullingTool.hxx
CommitLineData
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.
25class Graphic3d_CullingTool
b7cd4ba7 26{
27public:
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 56public:
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.
9ad4ff93 62 //! @param theCamera [in] camera definition
63 //! @param theModelWorld [in] optional object transformation for computing frustum in object local coordinate system
64 Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera,
65 const Graphic3d_Mat4d& theModelWorld = Graphic3d_Mat4d());
b7cd4ba7 66
4ecf34cc 67 Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth,
68 Standard_Integer theViewportHeight,
69 Standard_Real theResolutionRatio);
70
71 //! Setup distance culling.
2b8832bb 72 Standard_EXPORT void SetCullingDistance (CullingContext& theCtx,
73 Standard_Real theDistance) const;
4ecf34cc 74
75 //! Setup size culling.
2b8832bb 76 Standard_EXPORT void SetCullingSize (CullingContext& theCtx,
77 Standard_Real theSize) const;
4ecf34cc 78
79 //! Caches view volume's vertices projections along its normals and AABBs dimensions.
80 //! Must be called at the beginning of each BVH tree traverse loop.
81 Standard_EXPORT void CacheClipPtsProjections();
91d96372 82
2b8832bb 83 //! Checks whether given AABB should be entirely culled or not.
9ad4ff93 84 //! @param theCtx [in] culling properties
85 //! @param theMinPnt [in] maximum point of AABB
86 //! @param theMaxPnt [in] minimum point of AABB
87 //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
88 //! @return TRUE if AABB is completely outside of view frustum or culled by size/distance;
89 //! FALSE in case of partial or complete overlap (use theIsInside to distinguish)
2b8832bb 90 bool IsCulled (const CullingContext& theCtx,
9ad4ff93 91 const Graphic3d_Vec3d& theMinPnt,
92 const Graphic3d_Vec3d& theMaxPnt,
93 Standard_Boolean* theIsInside = NULL) const
2b8832bb 94 {
9ad4ff93 95 return IsOutFrustum(theMinPnt, theMaxPnt, theIsInside)
96 || IsTooDistant(theCtx, theMinPnt, theMaxPnt, theIsInside)
97 || IsTooSmall (theCtx, theMinPnt, theMaxPnt);
2b8832bb 98 }
b7cd4ba7 99
3fe9ce0e 100 //! Return the camera definition.
101 const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
102
825aa485 103 //! Returns current projection matrix.
d325cb7f 104 const Graphic3d_Mat4d& ProjectionMatrix() const
825aa485 105 {
106 return myProjectionMat;
107 }
b7cd4ba7 108
825aa485 109 //! Returns current world view transformation matrix.
d325cb7f 110 const Graphic3d_Mat4d& WorldViewMatrix() const
825aa485 111 {
112 return myWorldViewMat;
113 }
b7cd4ba7 114
91d96372 115 Standard_Integer ViewportWidth() const
116 {
117 return myViewportWidth;
118 }
119
120 Standard_Integer ViewportHeight() const
121 {
122 return myViewportHeight;
123 }
124
825aa485 125 //! Returns state of current world view projection transformation matrices.
126 const Graphic3d_WorldViewProjState& WorldViewProjState() const
127 {
128 return myWorldViewProjState;
129 }
b7cd4ba7 130
9ad4ff93 131 //! Returns camera eye position.
132 const Graphic3d_Vec3d& CameraEye() const { return myCamEye; }
133
134 //! Returns camera direction.
135 const Graphic3d_Vec3d& CameraDirection() const { return myCamDir; }
136
137public:
b7cd4ba7 138
139 //! Calculates signed distance from plane to point.
140 //! @param theNormal [in] the plane's normal.
141 //! @param thePnt [in]
d325cb7f 142 Standard_EXPORT Standard_Real SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal,
143 const Graphic3d_Vec4d& thePnt);
b7cd4ba7 144
2b8832bb 145 //! Detects if AABB overlaps view volume using separating axis theorem (SAT).
9ad4ff93 146 //! @param theMinPnt [in] maximum point of AABB
147 //! @param theMaxPnt [in] minimum point of AABB
148 //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
149 //! @return TRUE if AABB is completely outside of view frustum;
150 //! FALSE in case of partial or complete overlap (use theIsInside to distinguish)
151 //! @sa SelectMgr_Frustum::hasOverlap()
152 bool IsOutFrustum (const Graphic3d_Vec3d& theMinPnt,
153 const Graphic3d_Vec3d& theMaxPnt,
154 Standard_Boolean* theIsInside = NULL) const
2b8832bb 155 {
156 // E1
157 // |_ E0
158 // /
159 // E2
9ad4ff93 160 if (theMinPnt[0] > myMaxOrthoProjectionPts[0] // E0 test (x axis)
161 || theMaxPnt[0] < myMinOrthoProjectionPts[0]
162 || theMinPnt[1] > myMaxOrthoProjectionPts[1] // E1 test (y axis)
163 || theMaxPnt[1] < myMinOrthoProjectionPts[1]
164 || theMinPnt[2] > myMaxOrthoProjectionPts[2] // E2 test (z axis)
165 || theMaxPnt[2] < myMinOrthoProjectionPts[2])
2b8832bb 166 {
167 return true;
168 }
9ad4ff93 169 if (theIsInside != NULL
170 && *theIsInside)
2b8832bb 171 {
9ad4ff93 172 *theIsInside = theMinPnt[0] >= myMinOrthoProjectionPts[0] // E0 test (x axis)
173 && theMaxPnt[0] <= myMaxOrthoProjectionPts[0]
174 && theMinPnt[1] >= myMinOrthoProjectionPts[1] // E1 test (y axis)
175 && theMaxPnt[1] <= myMaxOrthoProjectionPts[1]
176 && theMinPnt[1] >= myMinOrthoProjectionPts[2] // E2 test (z axis)
177 && theMaxPnt[1] <= myMaxOrthoProjectionPts[2];
2b8832bb 178 }
179
2b8832bb 180 const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
30a1b24e 181 for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
2b8832bb 182 {
30a1b24e 183 // frustum normals
9ad4ff93 184 const Graphic3d_Vec3d& anAxis = myClipPlanes[aPlaneIter].Normal;
185 const Graphic3d_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPnt.x() : theMinPnt.x(),
186 anAxis.y() > 0.0 ? theMaxPnt.y() : theMinPnt.y(),
187 anAxis.z() > 0.0 ? theMaxPnt.z() : theMinPnt.z());
188 const Standard_Real aPnt0 = aPVertex.Dot (anAxis);
189 if (theIsInside == NULL
190 && aPnt0 >= myMinClipProjectionPts[aPlaneIter]
30a1b24e 191 && aPnt0 <= myMaxClipProjectionPts[aPlaneIter])
2b8832bb 192 {
193 continue;
194 }
30a1b24e 195
9ad4ff93 196 const Graphic3d_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPnt.x() : theMaxPnt.x(),
197 anAxis.y() > 0.0 ? theMinPnt.y() : theMaxPnt.y(),
198 anAxis.z() > 0.0 ? theMinPnt.z() : theMaxPnt.z());
199 const Standard_Real aPnt1 = aNVertex.Dot (anAxis);
200
201 const Standard_Real aBoxProjMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1;
202 const Standard_Real aBoxProjMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1;
203 if (aBoxProjMin > myMaxClipProjectionPts[aPlaneIter]
204 || aBoxProjMax < myMinClipProjectionPts[aPlaneIter])
2b8832bb 205 {
206 return true;
207 }
9ad4ff93 208
209 if (theIsInside != NULL
210 && *theIsInside)
211 {
212 *theIsInside = aBoxProjMin >= myMinClipProjectionPts[aPlaneIter]
213 && aBoxProjMax <= myMaxClipProjectionPts[aPlaneIter];
214 }
2b8832bb 215 }
216 return false;
217 }
218
219 //! Returns TRUE if given AABB should be discarded by distance culling criterion.
9ad4ff93 220 //! @param theMinPnt [in] maximum point of AABB
221 //! @param theMaxPnt [in] minimum point of AABB
222 //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
223 //! @return TRUE if AABB is completely behind culling distance;
224 //! FALSE in case of partial or complete overlap (use theIsInside to distinguish)
225 bool IsTooDistant (const CullingContext& theCtx,
226 const Graphic3d_Vec3d& theMinPnt,
227 const Graphic3d_Vec3d& theMaxPnt,
228 Standard_Boolean* theIsInside = NULL) const
2b8832bb 229 {
230 if (theCtx.DistCull <= 0.0)
231 {
232 return false;
233 }
234
235 // check distance to the bounding sphere as fast approximation
9ad4ff93 236 const Graphic3d_Vec3d aSphereCenter = (theMinPnt + theMaxPnt) * 0.5;
237 const Standard_Real aSphereRadius = (theMaxPnt - theMinPnt).maxComp() * 0.5;
238 const Standard_Real aDistToCenter = (aSphereCenter - myCamEye).Modulus();
239 if ((aDistToCenter - aSphereRadius) > theCtx.DistCull)
240 {
241 // clip if closest point is behind culling distance
242 return true;
243 }
244 if (theIsInside != NULL
245 && *theIsInside)
246 {
247 // check if farthest point is before culling distance
248 *theIsInside = (aDistToCenter + aSphereRadius) <= theCtx.DistCull;
249 }
250 return false;
2b8832bb 251 }
252
253 //! Returns TRUE if given AABB should be discarded by size culling criterion.
9ad4ff93 254 bool IsTooSmall (const CullingContext& theCtx,
255 const Graphic3d_Vec3d& theMinPnt,
256 const Graphic3d_Vec3d& theMaxPnt) const
2b8832bb 257 {
258 if (theCtx.SizeCull2 <= 0.0)
259 {
260 return false;
261 }
f29de682 262
9ad4ff93 263 const Standard_Real aBoxDiag2 = (theMaxPnt - theMinPnt).SquareModulus();
f29de682 264 if (myIsProjectionParallel)
265 {
266 return aBoxDiag2 < theCtx.SizeCull2;
267 }
268
269 // note that distances behind the Eye (aBndDist < 0) are not scaled correctly here,
270 // but majority of such objects should be culled by frustum
9ad4ff93 271 const Graphic3d_Vec3d aBndCenter = (theMinPnt + theMaxPnt) * 0.5;
d325cb7f 272 const Standard_Real aBndDist = (aBndCenter - myCamEye).Dot (myCamDir);
f29de682 273 return aBoxDiag2 < theCtx.SizeCull2 * aBndDist * aBndDist;
2b8832bb 274 }
275
b7cd4ba7 276protected:
277
278 //! Enumerates planes of view volume.
279 enum
280 {
b7cd4ba7 281 Plane_Left,
282 Plane_Right,
30a1b24e 283 Plane_Bottom,
284 Plane_Top,
b7cd4ba7 285 Plane_Near,
286 Plane_Far,
287 PlanesNB
288 };
289
b7cd4ba7 290protected:
291
d325cb7f 292 Plane myClipPlanes[PlanesNB]; //!< Planes
293 NCollection_Array1<Graphic3d_Vec3d> myClipVerts; //!< Vertices
b7cd4ba7 294
3fe9ce0e 295 Handle(Graphic3d_Camera) myCamera; //!< camera definition
296
b7cd4ba7 297 // for caching clip points projections onto viewing area normals once per traverse
30a1b24e 298 // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
7c3ef2f7 299 Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals
300 Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals
b7cd4ba7 301
302 // for caching clip points projections onto AABB normals once per traverse
303 // ORDER: E0, E1, E2
7c3ef2f7 304 Standard_Real myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB
305 Standard_Real myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB
b7cd4ba7 306
825aa485 307 Standard_Boolean myIsProjectionParallel;
b7cd4ba7 308
d325cb7f 309 Graphic3d_Mat4d myProjectionMat;
310 Graphic3d_Mat4d myWorldViewMat;
b7cd4ba7 311
91d96372 312 Standard_Integer myViewportWidth;
313 Standard_Integer myViewportHeight;
314
825aa485 315 Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices.
4ecf34cc 316
317 Graphic3d_Vec3d myCamEye; //!< camera eye position for distance culling
f29de682 318 Graphic3d_Vec3d myCamDir; //!< camera direction for size culling
319 Standard_Real myCamScale; //!< camera scale for size culling
4ecf34cc 320 Standard_Real myPixelSize; //!< pixel size for size culling
4ecf34cc 321
b7cd4ba7 322};
323
d325cb7f 324#endif // _Graphic3d_CullingTool_HeaderFile