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
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0025
0026
0027 class Graphic3d_CullingTool
0028 {
0029 public:
0030
0031 struct CullingContext
0032 {
0033 double DistCull;
0034 double SizeCull2;
0035
0036
0037 CullingContext()
0038 : DistCull(-1.0),
0039 SizeCull2(-1.0)
0040 {
0041 }
0042 };
0043
0044
0045 struct Plane
0046 {
0047
0048 Plane()
0049 : Origin(0.0, 0.0, 0.0),
0050 Normal(0.0, 0.0, 1.0)
0051 {
0052 }
0053
0054
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
0067 Standard_EXPORT Graphic3d_CullingTool();
0068
0069
0070
0071
0072
0073
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
0083 Standard_EXPORT void SetCullingDistance(CullingContext& theCtx, double theDistance) const;
0084
0085
0086 Standard_EXPORT void SetCullingSize(CullingContext& theCtx, double theSize) const;
0087
0088
0089
0090 Standard_EXPORT void CacheClipPtsProjections();
0091
0092
0093
0094
0095
0096
0097
0098
0099
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
0111 const occ::handle<Graphic3d_Camera>& Camera() const { return myCamera; }
0112
0113
0114 const NCollection_Mat4<double>& ProjectionMatrix() const { return myProjectionMat; }
0115
0116
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
0124 const Graphic3d_WorldViewProjState& WorldViewProjState() const { return myWorldViewProjState; }
0125
0126
0127 const NCollection_Vec3<double>& CameraEye() const { return myCamEye; }
0128
0129
0130 const NCollection_Vec3<double>& CameraDirection() const { return myCamDir; }
0131
0132 public:
0133
0134
0135
0136 Standard_EXPORT double SignedPlanePointDistance(const NCollection_Vec4<double>& theNormal,
0137 const NCollection_Vec4<double>& thePnt);
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 bool IsOutFrustum(const NCollection_Vec3<double>& theMinPnt,
0148 const NCollection_Vec3<double>& theMaxPnt,
0149 bool* theIsInside = nullptr) const
0150 {
0151
0152
0153
0154
0155 if (theMinPnt[0] > myMaxOrthoProjectionPts[0]
0156 || theMaxPnt[0] < myMinOrthoProjectionPts[0]
0157 || theMinPnt[1] > myMaxOrthoProjectionPts[1]
0158 || theMaxPnt[1] < myMinOrthoProjectionPts[1]
0159 || theMinPnt[2] > myMaxOrthoProjectionPts[2]
0160 || theMaxPnt[2] < myMinOrthoProjectionPts[2])
0161 {
0162 return true;
0163 }
0164 if (theIsInside != nullptr && *theIsInside)
0165 {
0166 *theIsInside = theMinPnt[0] >= myMinOrthoProjectionPts[0]
0167 && theMaxPnt[0] <= myMaxOrthoProjectionPts[0]
0168 && theMinPnt[1] >= myMinOrthoProjectionPts[1]
0169 && theMaxPnt[1] <= myMaxOrthoProjectionPts[1]
0170 && theMinPnt[1] >= myMinOrthoProjectionPts[2]
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
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
0212
0213
0214
0215
0216
0217
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
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
0235 return true;
0236 }
0237 if (theIsInside != nullptr && *theIsInside)
0238 {
0239
0240 *theIsInside = (aDistToCenter + aSphereRadius) <= theCtx.DistCull;
0241 }
0242 return false;
0243 }
0244
0245
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
0262
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
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];
0283 NCollection_Array1<NCollection_Vec3<double>> myClipVerts;
0284
0285 occ::handle<Graphic3d_Camera> myCamera;
0286
0287
0288
0289
0290 double myMaxClipProjectionPts[PlanesNB];
0291 double myMinClipProjectionPts[PlanesNB];
0292
0293
0294
0295 double myMaxOrthoProjectionPts[3];
0296 double myMinOrthoProjectionPts[3];
0297
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;
0308
0309 NCollection_Vec3<double> myCamEye;
0310 NCollection_Vec3<double> myCamDir;
0311 double myCamScale;
0312 double myPixelSize;
0313 };
0314
0315 #endif