Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:48

0001 // Created on: 2013-12-25
0002 // Created by: Varvara POSKONINA
0003 // Copyright (c) 1999-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _Graphic3d_CullingTool_HeaderFile
0017 #define _Graphic3d_CullingTool_HeaderFile
0018 
0019 #include <Graphic3d_Camera.hxx>
0020 #include <Graphic3d_Vec4.hxx>
0021 #include <Graphic3d_WorldViewProjState.hxx>
0022 
0023 //! Graphic3d_CullingTool class provides a possibility to store parameters of view volume,
0024 //! such as its vertices and equations, and contains methods detecting if given AABB overlaps view volume.
0025 class Graphic3d_CullingTool
0026 {
0027 public:
0028   //! Auxiliary structure holding non-persistent culling options.
0029   struct CullingContext
0030   {
0031     Standard_Real DistCull;  //!< culling distance
0032     Standard_Real SizeCull2; //!< squared culling size
0033 
0034     //! Empty constructor.
0035     CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {}
0036   };
0037 
0038   //! Auxiliary structure representing 3D plane.
0039   struct Plane
0040   {
0041     //! Creates default plane.
0042     Plane()
0043     : Origin (0.0, 0.0, 0.0),
0044       Normal (0.0, 0.0, 1.0) {}
0045 
0046     //! Creates plane with specific parameters.
0047     Plane (const Graphic3d_Vec3d& theOrigin,
0048            const Graphic3d_Vec3d& theNormal)
0049     : Origin (theOrigin),
0050       Normal (theNormal) {}
0051 
0052     Graphic3d_Vec3d Origin;
0053     Graphic3d_Vec3d Normal;
0054   };
0055 
0056 public:
0057 
0058   //! Creates an empty selector object with parallel projection type by default.
0059   Standard_EXPORT Graphic3d_CullingTool();
0060 
0061   //! Retrieves view volume's planes equations and its vertices from projection and world-view matrices.
0062   //! @param theCamera [in] camera definition
0063   //! @param theModelWorld [in] optional object transformation for computing frustum in object local coordinate system
0064   Standard_EXPORT void SetViewVolume (const Handle(Graphic3d_Camera)& theCamera,
0065                                       const Graphic3d_Mat4d& theModelWorld = Graphic3d_Mat4d());
0066 
0067   Standard_EXPORT void SetViewportSize (Standard_Integer theViewportWidth,
0068                                         Standard_Integer theViewportHeight,
0069                                         Standard_Real theResolutionRatio);
0070 
0071   //! Setup distance culling.
0072   Standard_EXPORT void SetCullingDistance (CullingContext& theCtx,
0073                                            Standard_Real theDistance) const;
0074 
0075   //! Setup size culling.
0076   Standard_EXPORT void SetCullingSize (CullingContext& theCtx,
0077                                        Standard_Real theSize) const;
0078 
0079   //! Caches view volume's vertices projections along its normals and AABBs dimensions.
0080   //! Must be called at the beginning of each BVH tree traverse loop.
0081   Standard_EXPORT void CacheClipPtsProjections();
0082 
0083   //! Checks whether given AABB should be entirely culled or not.
0084   //! @param theCtx    [in] culling properties
0085   //! @param theMinPnt [in] maximum point of AABB
0086   //! @param theMaxPnt [in] minimum point of AABB
0087   //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
0088   //! @return TRUE if AABB is completely outside of view frustum or culled by size/distance;
0089   //!         FALSE in case of partial or complete overlap (use theIsInside to distinguish)
0090   bool IsCulled (const CullingContext& theCtx,
0091                  const Graphic3d_Vec3d& theMinPnt,
0092                  const Graphic3d_Vec3d& theMaxPnt,
0093                  Standard_Boolean*      theIsInside = NULL) const
0094   {
0095     return IsOutFrustum(theMinPnt, theMaxPnt, theIsInside)
0096         || IsTooDistant(theCtx, theMinPnt, theMaxPnt, theIsInside)
0097         || IsTooSmall  (theCtx, theMinPnt, theMaxPnt);
0098   }
0099 
0100   //! Return the camera definition.
0101   const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
0102 
0103   //! Returns current projection matrix.
0104   const Graphic3d_Mat4d& ProjectionMatrix() const
0105   {
0106     return myProjectionMat;
0107   }
0108 
0109   //! Returns current world view transformation matrix.
0110   const Graphic3d_Mat4d& WorldViewMatrix() const
0111   {
0112     return myWorldViewMat;
0113   }
0114 
0115   Standard_Integer ViewportWidth() const
0116   {
0117     return myViewportWidth;
0118   }
0119 
0120   Standard_Integer ViewportHeight() const
0121   {
0122     return myViewportHeight;
0123   }
0124 
0125   //! Returns state of current world view projection transformation matrices.
0126   const Graphic3d_WorldViewProjState& WorldViewProjState() const
0127   {
0128     return myWorldViewProjState;
0129   }
0130 
0131   //! Returns camera eye position.
0132   const Graphic3d_Vec3d& CameraEye() const { return myCamEye; }
0133 
0134   //! Returns camera direction.
0135   const Graphic3d_Vec3d& CameraDirection() const { return myCamDir; }
0136 
0137 public:
0138 
0139   //! Calculates signed distance from plane to point.
0140   //! @param theNormal [in] the plane's normal.
0141   //! @param thePnt    [in]
0142   Standard_EXPORT Standard_Real SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal,
0143                                                           const Graphic3d_Vec4d& thePnt);
0144 
0145   //! Detects if AABB overlaps view volume using separating axis theorem (SAT).
0146   //! @param theMinPnt   [in] maximum point of AABB
0147   //! @param theMaxPnt   [in] minimum point of AABB
0148   //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
0149   //! @return TRUE if AABB is completely outside of view frustum;
0150   //!         FALSE in case of partial or complete overlap (use theIsInside to distinguish)
0151   //! @sa SelectMgr_Frustum::hasOverlap()
0152   bool IsOutFrustum (const Graphic3d_Vec3d& theMinPnt,
0153                      const Graphic3d_Vec3d& theMaxPnt,
0154                      Standard_Boolean*      theIsInside = NULL) const
0155   {
0156     //     E1
0157     //    |_ E0
0158     //   /
0159     //    E2
0160     if (theMinPnt[0] > myMaxOrthoProjectionPts[0] // E0 test (x axis)
0161      || theMaxPnt[0] < myMinOrthoProjectionPts[0]
0162      || theMinPnt[1] > myMaxOrthoProjectionPts[1] // E1 test (y axis)
0163      || theMaxPnt[1] < myMinOrthoProjectionPts[1]
0164      || theMinPnt[2] > myMaxOrthoProjectionPts[2] // E2 test (z axis)
0165      || theMaxPnt[2] < myMinOrthoProjectionPts[2])
0166     {
0167       return true;
0168     }
0169     if (theIsInside != NULL
0170     && *theIsInside)
0171     {
0172       *theIsInside = theMinPnt[0] >= myMinOrthoProjectionPts[0] // E0 test (x axis)
0173                   && theMaxPnt[0] <= myMaxOrthoProjectionPts[0]
0174                   && theMinPnt[1] >= myMinOrthoProjectionPts[1] // E1 test (y axis)
0175                   && theMaxPnt[1] <= myMaxOrthoProjectionPts[1]
0176                   && theMinPnt[1] >= myMinOrthoProjectionPts[2] // E2 test (z axis)
0177                   && theMaxPnt[1] <= myMaxOrthoProjectionPts[2];
0178     }
0179 
0180     const Standard_Integer anIncFactor = myIsProjectionParallel ? 2 : 1;
0181     for (Standard_Integer aPlaneIter = 0; aPlaneIter < PlanesNB - 1; aPlaneIter += anIncFactor)
0182     {
0183       // frustum normals
0184       const Graphic3d_Vec3d& anAxis = myClipPlanes[aPlaneIter].Normal;
0185       const Graphic3d_Vec3d aPVertex (anAxis.x() > 0.0 ? theMaxPnt.x() : theMinPnt.x(),
0186                                       anAxis.y() > 0.0 ? theMaxPnt.y() : theMinPnt.y(),
0187                                       anAxis.z() > 0.0 ? theMaxPnt.z() : theMinPnt.z());
0188       const Standard_Real aPnt0 = aPVertex.Dot (anAxis);
0189       if (theIsInside == NULL
0190        && aPnt0 >= myMinClipProjectionPts[aPlaneIter]
0191        && aPnt0 <= myMaxClipProjectionPts[aPlaneIter])
0192       {
0193         continue;
0194       }
0195       
0196       const Graphic3d_Vec3d aNVertex (anAxis.x() > 0.0 ? theMinPnt.x() : theMaxPnt.x(),
0197                                       anAxis.y() > 0.0 ? theMinPnt.y() : theMaxPnt.y(),
0198                                       anAxis.z() > 0.0 ? theMinPnt.z() : theMaxPnt.z());
0199       const Standard_Real aPnt1 = aNVertex.Dot (anAxis);
0200 
0201       const Standard_Real aBoxProjMin = aPnt0 < aPnt1 ? aPnt0 : aPnt1;
0202       const Standard_Real aBoxProjMax = aPnt0 > aPnt1 ? aPnt0 : aPnt1;
0203       if (aBoxProjMin > myMaxClipProjectionPts[aPlaneIter]
0204        || aBoxProjMax < myMinClipProjectionPts[aPlaneIter])
0205       {
0206         return true;
0207       }
0208 
0209       if (theIsInside != NULL
0210       && *theIsInside)
0211       {
0212         *theIsInside = aBoxProjMin >= myMinClipProjectionPts[aPlaneIter]
0213                     && aBoxProjMax <= myMaxClipProjectionPts[aPlaneIter];
0214       }
0215     }
0216     return false;
0217   }
0218 
0219   //! Returns TRUE if given AABB should be discarded by distance culling criterion.
0220   //! @param theMinPnt   [in] maximum point of AABB
0221   //! @param theMaxPnt   [in] minimum point of AABB
0222   //! @param theIsInside [out] flag indicating if AABB is fully inside; initial value should be set to TRUE
0223   //! @return TRUE if AABB is completely behind culling distance;
0224   //!         FALSE in case of partial or complete overlap (use theIsInside to distinguish)
0225   bool IsTooDistant (const CullingContext&  theCtx,
0226                      const Graphic3d_Vec3d& theMinPnt,
0227                      const Graphic3d_Vec3d& theMaxPnt,
0228                      Standard_Boolean*      theIsInside = NULL) const
0229   {
0230     if (theCtx.DistCull <= 0.0)
0231     {
0232       return false;
0233     }
0234 
0235     // check distance to the bounding sphere as fast approximation
0236     const Graphic3d_Vec3d aSphereCenter = (theMinPnt + theMaxPnt) * 0.5;
0237     const Standard_Real   aSphereRadius = (theMaxPnt - theMinPnt).maxComp() * 0.5;
0238     const Standard_Real   aDistToCenter = (aSphereCenter - myCamEye).Modulus();
0239     if ((aDistToCenter - aSphereRadius) > theCtx.DistCull)
0240     {
0241       // clip if closest point is behind culling distance
0242       return true;
0243     }
0244     if (theIsInside != NULL
0245     && *theIsInside)
0246     {
0247       // check if farthest point is before culling distance
0248       *theIsInside = (aDistToCenter + aSphereRadius) <= theCtx.DistCull;
0249     }
0250     return false;
0251   }
0252 
0253   //! Returns TRUE if given AABB should be discarded by size culling criterion.
0254   bool IsTooSmall (const CullingContext&  theCtx,
0255                    const Graphic3d_Vec3d& theMinPnt,
0256                    const Graphic3d_Vec3d& theMaxPnt) const
0257   {
0258     if (theCtx.SizeCull2 <= 0.0)
0259     {
0260       return false;
0261     }
0262 
0263     const Standard_Real aBoxDiag2 = (theMaxPnt - theMinPnt).SquareModulus();
0264     if (myIsProjectionParallel)
0265     {
0266       return aBoxDiag2 < theCtx.SizeCull2;
0267     }
0268 
0269     // note that distances behind the Eye (aBndDist < 0) are not scaled correctly here,
0270     // but majority of such objects should be culled by frustum
0271     const Graphic3d_Vec3d aBndCenter = (theMinPnt + theMaxPnt) * 0.5;
0272     const Standard_Real   aBndDist   = (aBndCenter - myCamEye).Dot (myCamDir);
0273     return aBoxDiag2 < theCtx.SizeCull2 * aBndDist * aBndDist;
0274   }
0275 
0276 protected:
0277 
0278   //! Enumerates planes of view volume.
0279   enum
0280   {
0281     Plane_Left,
0282     Plane_Right,
0283     Plane_Bottom,
0284     Plane_Top,
0285     Plane_Near,
0286     Plane_Far,
0287     PlanesNB
0288   };
0289 
0290 protected:
0291 
0292   Plane                               myClipPlanes[PlanesNB]; //!< Planes
0293   NCollection_Array1<Graphic3d_Vec3d> myClipVerts;            //!< Vertices
0294 
0295   Handle(Graphic3d_Camera) myCamera; //!< camera definition
0296 
0297   // for caching clip points projections onto viewing area normals once per traverse
0298   // ORDER: LEFT, RIGHT, BOTTOM, TOP, NEAR, FAR
0299   Standard_Real myMaxClipProjectionPts[PlanesNB]; //!< Max view volume's vertices projections onto its normals
0300   Standard_Real myMinClipProjectionPts[PlanesNB]; //!< Min view volume's vertices projections onto its normals
0301 
0302   // for caching clip points projections onto AABB normals once per traverse
0303   // ORDER: E0, E1, E2
0304   Standard_Real myMaxOrthoProjectionPts[3]; //!< Max view volume's vertices projections onto normalized dimensions of AABB
0305   Standard_Real myMinOrthoProjectionPts[3]; //!< Min view volume's vertices projections onto normalized dimensions of AABB
0306 
0307   Standard_Boolean myIsProjectionParallel;
0308 
0309   Graphic3d_Mat4d myProjectionMat;
0310   Graphic3d_Mat4d myWorldViewMat;
0311 
0312   Standard_Integer myViewportWidth;
0313   Standard_Integer myViewportHeight;
0314 
0315   Graphic3d_WorldViewProjState myWorldViewProjState; //!< State of world view projection matrices.
0316 
0317   Graphic3d_Vec3d myCamEye;      //!< camera eye position for distance culling
0318   Graphic3d_Vec3d myCamDir;      //!< camera direction for size culling
0319   Standard_Real   myCamScale;    //!< camera scale for size culling
0320   Standard_Real   myPixelSize;   //!< pixel size for size culling
0321 
0322 };
0323 
0324 #endif // _Graphic3d_CullingTool_HeaderFile