1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0029729: Visualization, Graphic3d_ClipPlane - add support of clipping plane chains

Graphic3d_ClipPlane now can define a Chain of Planes (logical AND).
OpenGl_ShaderManager - added new GLSL sub-programs for clipping plane chains.
Bnd_Range::TrimFrom(), ::TrimTo() - added auxiliary methods for trimming the range.
SelectMgr_ViewClipRange now handles non-continuous clipping range.
Graphic3d_SequenceOfHClipPlane now aggregates NCollection_Sequence instead of inheritance.
OpenGl_CappingPlaneResource - triangulation has been adjusted to make front face following CCW order.
This commit is contained in:
kgv
2018-05-25 10:13:38 +03:00
committed by bugmaster
parent 012264339e
commit 25c35042b6
34 changed files with 1063 additions and 407 deletions

View File

@@ -276,7 +276,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d &thePoint)
// {i, j, k} vectors and store them to corresponding class fields
cacheVertexProjections (this);
myViewClipRange.Clear();
myViewClipRange.SetVoid();
myScale = 1.0;
}
@@ -306,7 +306,7 @@ void SelectMgr_RectangularFrustum::Build (const gp_Pnt2d& theMinPnt,
// {i, j, k} vectors and store them to corresponding class fields
cacheVertexProjections (this);
myViewClipRange.Clear();
myViewClipRange.SetVoid();
myScale = 1.0;
}
@@ -645,53 +645,74 @@ gp_Pnt SelectMgr_RectangularFrustum::DetectedPoint (const Standard_Real theDepth
// purpose :
// =======================================================================
void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
Standard_Real& theDepthMin,
Standard_Real& theDepthMax)
SelectMgr_ViewClipRange& theRange)
{
theDepthMax = DBL_MAX;
theDepthMin = -DBL_MAX;
Standard_Real aPlaneA, aPlaneB, aPlaneC, aPlaneD;
for (Graphic3d_SequenceOfHClipPlane::Iterator aPlaneIt (thePlanes); aPlaneIt.More(); aPlaneIt.Next())
{
const Handle(Graphic3d_ClipPlane)& aClipPlane = aPlaneIt.Value();
if (!aClipPlane->IsOn())
continue;
gp_Pln aGeomPlane = aClipPlane->ToPlane();
aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
Standard_Real aDotProduct = myViewRayDir.XYZ ().Dot (aPlaneDirXYZ);
Standard_Real aDistance = - myNearPickedPnt.XYZ ().Dot (aPlaneDirXYZ)
- aPlaneD;
// check whether the pick line is parallel to clip plane
if (Abs (aDotProduct) < Precision::Angular())
{
// line lies below the plane and is not clipped, skip
continue;
}
// compute distance to point of pick line intersection with the plane
const Standard_Real aParam = aDistance / aDotProduct;
const gp_Pnt anIntersectionPt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
Standard_Real aDistToPln = anIntersectionPt.Distance (myNearPickedPnt);
if (aParam < 0.0)
Bnd_Range aSubRange (RealFirst(), RealLast());
for (const Graphic3d_ClipPlane* aSubPlaneIter = aClipPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
{
// the plane is "behind" the ray
aDistToPln = -aDistToPln;
const gp_Pln aGeomPlane = aSubPlaneIter->ToPlane();
aGeomPlane.Coefficients (aPlaneA, aPlaneB, aPlaneC, aPlaneD);
const gp_XYZ& aPlaneDirXYZ = aGeomPlane.Axis().Direction().XYZ();
Standard_Real aDotProduct = myViewRayDir.XYZ().Dot (aPlaneDirXYZ);
Standard_Real aDistance = -myNearPickedPnt.XYZ().Dot (aPlaneDirXYZ) - aPlaneD;
// check whether the pick line is parallel to clip plane
if (Abs (aDotProduct) < Precision::Angular())
{
// line lies below the plane and is not clipped, skip
continue;
}
// compute distance to point of pick line intersection with the plane
const Standard_Real aParam = aDistance / aDotProduct;
const gp_Pnt anIntersectionPnt = myNearPickedPnt.XYZ() + myViewRayDir.XYZ() * aParam;
Standard_Real aDistToPln = anIntersectionPnt.Distance (myNearPickedPnt);
if (aParam < 0.0)
{
// the plane is "behind" the ray
aDistToPln = -aDistToPln;
}
// change depth limits for case of opposite and directed planes
if (!aClipPlane->IsChain())
{
if (aDotProduct < 0.0)
{
theRange.ChangeMain().Add (Bnd_Range (aDistToPln, RealLast()));
}
else
{
theRange.ChangeMain().Add (Bnd_Range (RealFirst(), aDistToPln));
}
}
else
{
if (aDotProduct < 0.0)
{
aSubRange.TrimFrom (aDistToPln);
}
else
{
aSubRange.TrimTo (aDistToPln);
}
}
}
// change depth limits for case of opposite and directed planes
if (aDotProduct < 0.0)
if (!aSubRange.IsVoid()
&& aClipPlane->IsChain())
{
theDepthMax = Min (aDistToPln, theDepthMax);
}
else if (aDistToPln > theDepthMin)
{
theDepthMin = Max (aDistToPln, theDepthMin);
theRange.AddSubRange (aSubRange);
}
}
}
@@ -704,10 +725,9 @@ void SelectMgr_RectangularFrustum::computeClippingRange (const Graphic3d_Sequenc
Standard_Boolean SelectMgr_RectangularFrustum::IsClipped (const Graphic3d_SequenceOfHClipPlane& thePlanes,
const Standard_Real theDepth)
{
Standard_Real aMaxDepth, aMinDepth;
computeClippingRange (thePlanes, aMinDepth, aMaxDepth);
return (theDepth <= aMinDepth || theDepth >= aMaxDepth);
SelectMgr_ViewClipRange aRange;
computeClippingRange (thePlanes, aRange);
return aRange.IsClipped (theDepth);
}
// =======================================================================
@@ -719,13 +739,11 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
if (thePlanes.IsNull()
|| thePlanes->IsEmpty())
{
myViewClipRange.Clear();
myViewClipRange.SetVoid();
return;
}
Standard_Real aMaxDepth, aMinDepth;
computeClippingRange (*thePlanes, aMinDepth, aMaxDepth);
myViewClipRange.Set (aMinDepth, aMaxDepth);
computeClippingRange (*thePlanes, myViewClipRange);
}
// =======================================================================
@@ -734,14 +752,8 @@ void SelectMgr_RectangularFrustum::SetViewClipping (const Handle(Graphic3d_Seque
// =======================================================================
Standard_Boolean SelectMgr_RectangularFrustum::isViewClippingOk (const Standard_Real theDepth) const
{
if (!myViewClipRange.IsValid()
|| !myIsViewClipEnabled)
{
return Standard_True;
}
return myViewClipRange.MaxDepth() > theDepth
&& myViewClipRange.MinDepth() < theDepth;
return !myIsViewClipEnabled
|| !myViewClipRange.IsClipped (theDepth);
}
// =======================================================================

View File

@@ -149,8 +149,7 @@ protected:
//! Computes valid depth range for the given clipping planes
Standard_EXPORT void computeClippingRange (const Graphic3d_SequenceOfHClipPlane& thePlanes,
Standard_Real& theDepthMin,
Standard_Real& theDepthMax);
SelectMgr_ViewClipRange& theRange);
//! Returns false if theDepth must be clipped by current view clip range
Standard_EXPORT Standard_Boolean isViewClippingOk (const Standard_Real theDepth) const;

View File

@@ -16,58 +16,52 @@
#ifndef _SelectMgr_ViewClipRange_HeaderFile
#define _SelectMgr_ViewClipRange_HeaderFile
#include <Bnd_Range.hxx>
#include <Standard_TypeDef.hxx>
//! Class for handling depth clipping range.
//! It is used to perform checks in case if global (for the whole view)
//! clipping planes are defined inside of SelectMgr_RectangularFrustum
//! class methods.
//! clipping planes are defined inside of SelectMgr_RectangularFrustum class methods.
class SelectMgr_ViewClipRange
{
public:
//! Creates new empty view clip range
//! Creates an empty clip range.
SelectMgr_ViewClipRange()
{
Clear();
SetVoid();
}
//! Sets boundaries and validates view clipping range
void Set (const Standard_Real theDepthMin, const Standard_Real theDepthMax)
//! Check if the given depth is not within clipping range(s),
//! e.g. TRUE means depth is clipped.
Standard_Boolean IsClipped (const Standard_Real theDepth) const
{
myMin = theDepthMin;
myMax = theDepthMax;
myIsValid = Standard_True;
for (size_t aRangeIter = 0; aRangeIter < myRanges.size(); ++aRangeIter)
{
if (!myRanges[aRangeIter].IsOut (theDepth))
{
return Standard_True;
}
}
return Standard_False;
}
//! Returns true if clip range is set and depth of each matched
//! primitive must be tested for satisfying the defined interval
Standard_Boolean IsValid() const
//! Clears clipping range.
void SetVoid()
{
return myIsValid;
myRanges.resize (1);
myRanges[0].SetVoid();
}
//! Returns the upper bound of valid depth range
Standard_Real MaxDepth() const
{
return myMax;
}
//! Returns the main range.
Bnd_Range& ChangeMain() { return myRanges[0]; }
//! Returns the lower bound of valid depth range
Standard_Real MinDepth() const
{
return myMin;
}
//! Invalidates view clipping range
void Clear()
{
myIsValid = Standard_False;
}
//! Adds a sub-range.
void AddSubRange (const Bnd_Range& theRange) { myRanges.push_back (theRange); }
private:
Standard_Real myMin; //!< Lower bound of valid depth range
Standard_Real myMax; //!< Upper bound of valid depth range
Standard_Boolean myIsValid; //!< The flag is set to true when range boundaries are set and depth check must be performed
std::vector<Bnd_Range> myRanges;
};
#endif // _SelectMgr_ViewClipRange_HeaderFile

View File

@@ -225,9 +225,8 @@ void SelectMgr_ViewerSelector::checkOverlap (const Handle(SelectBasics_Sensitive
continue;
}
const Graphic3d_Vec4d& aPlaneEquation = aPlane->GetEquation();
const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
if (aPlaneEquation.Dot (aCheckPnt) < 0.0) // vertex is outside the half-space
const Graphic3d_Vec4d aCheckPnt (anAnchor.X(), anAnchor.Y(), anAnchor.Z(), 1.0);
if (aPlane->ProbePoint (aCheckPnt) == Graphic3d_ClipState_Out)
{
return;
}