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:
@@ -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);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user