Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/opencascade/Graphic3d_CullingTool.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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