1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-06 18:26:22 +03:00

0024521: Visualization - automatic back face culling is not turned on for Solids packed into compound

StdPrs_ToolShadedShape::IsClosed():
- return true if shape is closed Solid (NOT just free closed Shell)
- accept compound of closed Solids as well
- ignore Solids with incomplete triangulation

TKOpenGl, automatically disable back face culling when:
- clipping/capping planes are in effect
- for translucent objects

Update bug23227 test case (now back faces are clipped).

OpenGl_Workspace::AspectFace() - disable culling in case of hatched style
This commit is contained in:
kgv 2014-01-16 21:09:20 +04:00 committed by bugmaster
parent fd03ee4b3b
commit 3b1817a9e2
10 changed files with 316 additions and 143 deletions

View File

@ -46,7 +46,8 @@ typedef TEL_COLOUR* tel_colour;
typedef enum typedef enum
{ {
TelCullNone, TelCullUndefined = -1,
TelCullNone = 0,
TelCullFront, TelCullFront,
TelCullBack TelCullBack
} TelCullMode; } TelCullMode;

View File

@ -27,9 +27,9 @@ namespace
// purpose : // purpose :
// ======================================================================= // =======================================================================
OpenGl_Clipping::OpenGl_Clipping () OpenGl_Clipping::OpenGl_Clipping ()
: myPlanes(), : myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE5)),
myPlaneStates(), myNbClipping (0),
myEmptyPlaneIds (new Aspect_GenId (GL_CLIP_PLANE0, GL_CLIP_PLANE5)) myNbCapping (0)
{} {}
// ======================================================================= // =======================================================================
@ -40,6 +40,8 @@ void OpenGl_Clipping::Init (const Standard_Integer theMaxPlanes)
{ {
myPlanes.Clear(); myPlanes.Clear();
myPlaneStates.Clear(); myPlaneStates.Clear();
myNbClipping = 0;
myNbCapping = 0;
Standard_Integer aLowerId = GL_CLIP_PLANE0; Standard_Integer aLowerId = GL_CLIP_PLANE0;
Standard_Integer aUpperId = GL_CLIP_PLANE0 + theMaxPlanes - 1; Standard_Integer aUpperId = GL_CLIP_PLANE0 + theMaxPlanes - 1;
myEmptyPlaneIds = new Aspect_GenId (aLowerId, aUpperId); myEmptyPlaneIds = new Aspect_GenId (aLowerId, aUpperId);
@ -104,6 +106,15 @@ void OpenGl_Clipping::Add (Graphic3d_SequenceOfHClipPlane& thePlanes, const Equa
glEnable ((GLenum)anID); glEnable ((GLenum)anID);
glClipPlane ((GLenum)anID, aPlane->GetEquation()); glClipPlane ((GLenum)anID, aPlane->GetEquation());
if (aPlane->IsCapping())
{
++myNbCapping;
}
else
{
++myNbClipping;
}
aPlaneIt.Next(); aPlaneIt.Next();
} }
@ -129,10 +140,22 @@ void OpenGl_Clipping::Remove (const Graphic3d_SequenceOfHClipPlane& thePlanes)
} }
Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID; Standard_Integer anID = myPlaneStates.Find (aPlane).ContextID;
PlaneProps& aProps = myPlaneStates.ChangeFind (aPlane);
if (aProps.IsEnabled)
{
glDisable ((GLenum)anID);
if (aPlane->IsCapping())
{
--myNbCapping;
}
else
{
--myNbClipping;
}
}
myEmptyPlaneIds->Free (anID); myEmptyPlaneIds->Free (anID);
myPlaneStates.UnBind (aPlane); myPlaneStates.UnBind (aPlane);
glDisable ((GLenum)anID);
} }
// renew collection of planes // renew collection of planes
@ -173,10 +196,26 @@ void OpenGl_Clipping::SetEnabled (const Handle(Graphic3d_ClipPlane)& thePlane,
if (theIsEnabled) if (theIsEnabled)
{ {
glEnable (anID); glEnable (anID);
if (thePlane->IsCapping())
{
++myNbCapping;
}
else
{
++myNbClipping;
}
} }
else else
{ {
glDisable (anID); glDisable (anID);
if (thePlane->IsCapping())
{
--myNbCapping;
}
else
{
--myNbClipping;
}
} }
aProps.IsEnabled = theIsEnabled; aProps.IsEnabled = theIsEnabled;

View File

@ -81,6 +81,24 @@ public: //! @name non-modifying getters
return myPlaneStates.Find (thePlane).IsEnabled; return myPlaneStates.Find (thePlane).IsEnabled;
} }
//! @return true if there are enabled clipping planes (NOT capping)
inline Standard_Boolean IsClippingOn() const
{
return myNbClipping > 0;
}
//! @return true if there are enabled capping planes
inline Standard_Boolean IsCappingOn() const
{
return myNbCapping > 0;
}
//! @return true if there are enabled clipping or capping planes
inline Standard_Boolean IsClippingOrCappingOn() const
{
return (myNbClipping + myNbCapping) > 0;
}
public: //! @name clipping state modification commands public: //! @name clipping state modification commands
//! Add planes to the context clipping at the specified system of coordinates. //! Add planes to the context clipping at the specified system of coordinates.
@ -198,9 +216,11 @@ private:
typedef NCollection_DataMap<Handle(Graphic3d_ClipPlane), PlaneProps> OpenGl_MapOfPlaneStates; typedef NCollection_DataMap<Handle(Graphic3d_ClipPlane), PlaneProps> OpenGl_MapOfPlaneStates;
typedef NCollection_Handle<Aspect_GenId> OpenGl_EmptyPlaneIds; typedef NCollection_Handle<Aspect_GenId> OpenGl_EmptyPlaneIds;
Graphic3d_SequenceOfHClipPlane myPlanes; //!< defined clipping planes. Graphic3d_SequenceOfHClipPlane myPlanes; //!< defined clipping planes
OpenGl_MapOfPlaneStates myPlaneStates; //!< map of clip planes bound for the props. OpenGl_MapOfPlaneStates myPlaneStates; //!< map of clip planes bound for the props
OpenGl_EmptyPlaneIds myEmptyPlaneIds; //!< generator of empty ids. OpenGl_EmptyPlaneIds myEmptyPlaneIds; //!< generator of empty ids
Standard_Boolean myNbClipping; //!< number of enabled clipping-only planes (NOT capping)
Standard_Boolean myNbCapping; //!< number of enabled capping planes
private: private:

View File

@ -166,6 +166,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_Display)& theDisplay,
TextParam_applied (NULL), TextParam_applied (NULL),
ViewMatrix_applied (&myDefaultMatrix), ViewMatrix_applied (&myDefaultMatrix),
StructureMatrix_applied (&myDefaultMatrix), StructureMatrix_applied (&myDefaultMatrix),
myCullingMode (TelCullUndefined),
myModelViewMatrix (myDefaultMatrix), myModelViewMatrix (myDefaultMatrix),
PolygonOffset_applied (NULL) PolygonOffset_applied (NULL)
{ {
@ -269,6 +270,7 @@ void OpenGl_Workspace::ResetAppliedAspect()
TextParam_set = &myDefaultTextParam; TextParam_set = &myDefaultTextParam;
TextParam_applied = NULL; TextParam_applied = NULL;
PolygonOffset_applied = NULL; PolygonOffset_applied = NULL;
myCullingMode = TelCullUndefined;
AspectLine(Standard_True); AspectLine(Standard_True);
AspectFace(Standard_True); AspectFace(Standard_True);

View File

@ -442,6 +442,7 @@ protected: //! @name fields related to status
OpenGl_Material myMatFront; //!< current front material state (cached to reduce GL context updates) OpenGl_Material myMatFront; //!< current front material state (cached to reduce GL context updates)
OpenGl_Material myMatBack; //!< current back material state OpenGl_Material myMatBack; //!< current back material state
OpenGl_Material myMatTmp; //!< temporary variable OpenGl_Material myMatTmp; //!< temporary variable
TelCullMode myCullingMode; //!< back face culling mode, applied from face aspect
//! Model matrix with applied structure transformations //! Model matrix with applied structure transformations
OpenGl_Matrix myModelViewMatrix; OpenGl_Matrix myModelViewMatrix;

View File

@ -319,7 +319,55 @@ const OpenGl_AspectLine * OpenGl_Workspace::AspectLine(const Standard_Boolean Wi
const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply) const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean theToApply)
{ {
if (!theToApply || (AspectFace_set == AspectFace_applied)) if (!theToApply)
{
return AspectFace_set;
}
if (!ActiveView()->Backfacing())
{
// manage back face culling mode, disable culling when clipping is enabled
TelCullMode aCullingMode = (myGlContext->Clipping().IsClippingOrCappingOn()
|| AspectFace_set->InteriorStyle() == Aspect_IS_HATCH)
? TelCullNone
: (TelCullMode )AspectFace_set->CullingMode();
if (aCullingMode != TelCullNone
&& myUseTransparency && !(NamedStatus & OPENGL_NS_2NDPASSDO))
{
// disable culling in case of translucent shading aspect
if (AspectFace_set->IntFront().trans != 1.0f)
{
aCullingMode = TelCullNone;
}
}
if (myCullingMode != aCullingMode)
{
myCullingMode = aCullingMode;
switch (myCullingMode)
{
case TelCullNone:
case TelCullUndefined:
{
glDisable (GL_CULL_FACE);
break;
}
case TelCullFront:
{
glCullFace (GL_FRONT);
glEnable (GL_CULL_FACE);
break;
}
case TelCullBack:
{
glCullFace (GL_BACK);
glEnable (GL_CULL_FACE);
break;
}
}
}
}
if (AspectFace_set == AspectFace_applied)
{ {
return AspectFace_set; return AspectFace_set;
} }
@ -365,34 +413,6 @@ const OpenGl_AspectFace* OpenGl_Workspace::AspectFace (const Standard_Boolean th
} }
} }
if (!ActiveView()->Backfacing())
{
const Tint aCullingMode = AspectFace_set->CullingMode();
if (AspectFace_applied == NULL || AspectFace_applied->CullingMode() != aCullingMode)
{
switch ((TelCullMode )aCullingMode)
{
case TelCullNone:
{
glDisable (GL_CULL_FACE);
break;
}
case TelCullFront:
{
glCullFace (GL_FRONT);
glEnable (GL_CULL_FACE);
break;
}
case TelCullBack:
{
glCullFace (GL_BACK);
glEnable (GL_CULL_FACE);
break;
}
}
}
}
// Aspect_POM_None means: do not change current settings // Aspect_POM_None means: do not change current settings
if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None) if ((AspectFace_set->PolygonOffset().mode & Aspect_POM_None) != Aspect_POM_None)
{ {

View File

@ -100,7 +100,7 @@ namespace
Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0); Standard_Real aUmin (0.0), aUmax (0.0), aVmin (0.0), aVmax (0.0), dUmax (0.0), dVmax (0.0);
// precision for compare square distances // precision for compare square distances
const double aPreci = Precision::SquareConfusion(); const Standard_Real aPreci = Precision::SquareConfusion();
if (!theDrawer->ShadingAspectGlobal()) if (!theDrawer->ShadingAspectGlobal())
{ {
@ -126,9 +126,12 @@ namespace
nbVertices += T->NbNodes(); nbVertices += T->NbNodes();
} }
} }
if (nbVertices < 3
if (nbVertices > 2 && nbTriangles > 0) || nbTriangles <= 0)
{ {
return Standard_False;
}
Handle(Graphic3d_ArrayOfTriangles) aPArray Handle(Graphic3d_ArrayOfTriangles) aPArray
= new Graphic3d_ArrayOfTriangles (nbVertices, 3 * nbTriangles, = new Graphic3d_ArrayOfTriangles (nbVertices, 3 * nbTriangles,
Standard_True, Standard_False, theHasTexels, Standard_True); Standard_True, Standard_False, theHasTexels, Standard_True);
@ -177,7 +180,7 @@ namespace
} }
} }
// Fill parray with vertex and edge visibillity info // Fill array with vertex and edge visibility info
const Poly_Array1OfTriangle& aTriangles = T->Triangles(); const Poly_Array1OfTriangle& aTriangles = T->Triangles();
for (Standard_Integer aTriIter = 1; aTriIter <= T->NbTriangles(); ++aTriIter) for (Standard_Integer aTriIter = 1; aTriIter <= T->NbTriangles(); ++aTriIter)
{ {
@ -218,7 +221,7 @@ namespace
} }
} }
Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPArray); Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPArray);
}
return Standard_True; return Standard_True;
} }

View File

@ -25,7 +25,9 @@ uses
Location from TopLoc Location from TopLoc
is is
IsClosed(myclass; aShape: Shape from TopoDS) returns Boolean from Standard; IsClosed (myclass; theShape : Shape from TopoDS) returns Boolean from Standard;
---Purpose: Checks back faces visibility for specified shape (to activate back-face culling).
-- @return true if shape is closed Solid or compound of closed Solids.
Triangulation(myclass; aFace: Face from TopoDS; Triangulation(myclass; aFace: Face from TopoDS;
loc : out Location from TopLoc) loc : out Location from TopLoc)

View File

@ -32,13 +32,99 @@
#include <TShort_HArray1OfShortReal.hxx> #include <TShort_HArray1OfShortReal.hxx>
#include <TShort_Array1OfShortReal.hxx> #include <TShort_Array1OfShortReal.hxx>
namespace
{
//=======================================================================
//function : isTriangulated
//purpose : Returns true if all faces within shape are triangulated.
// Same as BRepTools::Triangulation() but without extra checks.
//=======================================================================
static Standard_Boolean isTriangulated (const TopoDS_Shape& theShape)
{
TopLoc_Location aLocDummy;
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
{
const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aLocDummy);
if (aTri.IsNull())
{
return Standard_False;
}
}
return Standard_True;
}
}
//======================================================================= //=======================================================================
//function : IsClosed //function : IsClosed
//purpose : //purpose :
//======================================================================= //=======================================================================
Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape) Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape)
{ {
return theShape.Closed(); if (theShape.IsNull())
{
return Standard_True;
}
switch (theShape.ShapeType())
{
case TopAbs_COMPOUND:
case TopAbs_COMPSOLID:
default:
{
// check that compound consists of closed solids
for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
{
const TopoDS_Shape& aShape = anIter.Value();
if (!IsClosed (aShape))
{
return Standard_False;
}
}
return Standard_True;
}
case TopAbs_SOLID:
{
for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
{
const TopoDS_Shape& aShape = anIter.Value();
if (aShape.IsNull())
{
continue;
}
if (aShape.ShapeType() == TopAbs_SHELL
&& !aShape.Closed())
{
return Standard_False;
}
else if (aShape.ShapeType() == TopAbs_FACE)
{
// invalid solid
return Standard_False;
}
else if (!isTriangulated (aShape))
{
// mesh contains holes
return Standard_False;
}
}
return Standard_True;
}
case TopAbs_SHELL:
case TopAbs_FACE:
{
// free faces / shell are not allowed
return Standard_False;
}
case TopAbs_WIRE:
case TopAbs_EDGE:
case TopAbs_VERTEX:
{
// ignore
return Standard_True;
}
}
} }
//======================================================================= //=======================================================================

View File

@ -1,19 +1,19 @@
puts "============" puts "============"
puts "OCC23227" puts "OCC23227"
puts "New Draw Harness command to estimate current geometry complexity of OpenGL scene"
puts "============" puts "============"
puts "" puts ""
#######################################################################
# New Draw Harness command to estimate current geometry complexity of OpenGL scene
#######################################################################
set BugNumber OCC23227 set BugNumber OCC23227
box b 1 2 3 box b 1 2 3
vinit vinit View1
vclear
vdisplay b vdisplay b
vsetdispmode 1 vsetdispmode 1
vfit vfit
set vfeedback1 [vfeedback] set vfeedback1 [vfeedback]
vdump $imagedir/${casename}_box.png
vclear vclear
set vfeedback2 [vfeedback] set vfeedback2 [vfeedback]
@ -29,7 +29,7 @@ if { ${llength_vfeedback1} < 36 || ${llength_vfeedback2} < 36 || ${IndexTriangle
} else { } else {
set Triangles1 [lindex ${vfeedback1} ${IndexTriangles1}+1] set Triangles1 [lindex ${vfeedback1} ${IndexTriangles1}+1]
set Triangles2 [lindex ${vfeedback2} ${IndexTriangles1}+1] set Triangles2 [lindex ${vfeedback2} ${IndexTriangles1}+1]
if { ${Triangles1} == 12 && ${Triangles2} == 0 } { if { ${Triangles1} == 6 && ${Triangles2} == 0 } {
puts "OK ${BugNumber}" puts "OK ${BugNumber}"
} else { } else {
puts "Faulty ${BugNumber}" puts "Faulty ${BugNumber}"
@ -37,4 +37,3 @@ if { ${llength_vfeedback1} < 36 || ${llength_vfeedback2} < 36 || ${IndexTriangle
} }
set only_screen 1 set only_screen 1