File indexing completed on 2025-01-18 10:03:48
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 <Graphic3d_Vec4.hxx>
0021 #include <Graphic3d_WorldViewProjState.hxx>
0022
0023
0024
0025 class Graphic3d_CullingTool
0026 {
0027 public:
0028
0029 struct CullingContext
0030 {
0031 Standard_Real DistCull;
0032 Standard_Real SizeCull2;
0033
0034
0035 CullingContext() : DistCull (-1.0), SizeCull2 (-1.0) {}
0036 };
0037
0038
0039 struct Plane
0040 {
0041
0042 Plane()
0043 : Origin (0.0, 0.0, 0.0),
0044 Normal (0.0, 0.0, 1.0) {}
0045
0046
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
0059 Standard_EXPORT Graphic3d_CullingTool();
0060
0061
0062
0063
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
0072 Standard_EXPORT void SetCullingDistance (CullingContext& theCtx,
0073 Standard_Real theDistance) const;
0074
0075
0076 Standard_EXPORT void SetCullingSize (CullingContext& theCtx,
0077 Standard_Real theSize) const;
0078
0079
0080
0081 Standard_EXPORT void CacheClipPtsProjections();
0082
0083
0084
0085
0086
0087
0088
0089
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
0101 const Handle(Graphic3d_Camera)& Camera() const { return myCamera; }
0102
0103
0104 const Graphic3d_Mat4d& ProjectionMatrix() const
0105 {
0106 return myProjectionMat;
0107 }
0108
0109
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
0126 const Graphic3d_WorldViewProjState& WorldViewProjState() const
0127 {
0128 return myWorldViewProjState;
0129 }
0130
0131
0132 const Graphic3d_Vec3d& CameraEye() const { return myCamEye; }
0133
0134
0135 const Graphic3d_Vec3d& CameraDirection() const { return myCamDir; }
0136
0137 public:
0138
0139
0140
0141
0142 Standard_EXPORT Standard_Real SignedPlanePointDistance (const Graphic3d_Vec4d& theNormal,
0143 const Graphic3d_Vec4d& thePnt);
0144
0145
0146
0147
0148
0149
0150
0151
0152 bool IsOutFrustum (const Graphic3d_Vec3d& theMinPnt,
0153 const Graphic3d_Vec3d& theMaxPnt,
0154 Standard_Boolean* theIsInside = NULL) const
0155 {
0156
0157
0158
0159
0160 if (theMinPnt[0] > myMaxOrthoProjectionPts[0]
0161 || theMaxPnt[0] < myMinOrthoProjectionPts[0]
0162 || theMinPnt[1] > myMaxOrthoProjectionPts[1]
0163 || theMaxPnt[1] < myMinOrthoProjectionPts[1]
0164 || theMinPnt[2] > myMaxOrthoProjectionPts[2]
0165 || theMaxPnt[2] < myMinOrthoProjectionPts[2])
0166 {
0167 return true;
0168 }
0169 if (theIsInside != NULL
0170 && *theIsInside)
0171 {
0172 *theIsInside = theMinPnt[0] >= myMinOrthoProjectionPts[0]
0173 && theMaxPnt[0] <= myMaxOrthoProjectionPts[0]
0174 && theMinPnt[1] >= myMinOrthoProjectionPts[1]
0175 && theMaxPnt[1] <= myMaxOrthoProjectionPts[1]
0176 && theMinPnt[1] >= myMinOrthoProjectionPts[2]
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
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
0220
0221
0222
0223
0224
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
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
0242 return true;
0243 }
0244 if (theIsInside != NULL
0245 && *theIsInside)
0246 {
0247
0248 *theIsInside = (aDistToCenter + aSphereRadius) <= theCtx.DistCull;
0249 }
0250 return false;
0251 }
0252
0253
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
0270
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
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];
0293 NCollection_Array1<Graphic3d_Vec3d> myClipVerts;
0294
0295 Handle(Graphic3d_Camera) myCamera;
0296
0297
0298
0299 Standard_Real myMaxClipProjectionPts[PlanesNB];
0300 Standard_Real myMinClipProjectionPts[PlanesNB];
0301
0302
0303
0304 Standard_Real myMaxOrthoProjectionPts[3];
0305 Standard_Real myMinOrthoProjectionPts[3];
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;
0316
0317 Graphic3d_Vec3d myCamEye;
0318 Graphic3d_Vec3d myCamDir;
0319 Standard_Real myCamScale;
0320 Standard_Real myPixelSize;
0321
0322 };
0323
0324 #endif