From 7dced57d92bab21ef3868a06c9be6b9cbe35a116 Mon Sep 17 00:00:00 2001 From: asl Date: Thu, 17 May 2018 16:10:30 +0300 Subject: [PATCH] 0024437: Efficient HLR visualization based on OpenGL and GLSL New interior style Aspect_IS_OUTLINE is supported for Graphic3d_AspectFillArea3d. If this style is set, the triangles primitive array is drawn using the outline shader A new flag theMostAllowedEdgeClass is passed to the methods StdPrs_ShadedShape: Add, FillFaceBoundaries. It defines the most allowed continuity class of edges that will be included into the presentation. The edges with more continuity will be ignored. By default, the value is CN, i.e. all edges are included into the presentation. The new methods in AIS_Shape: SetMostContinuityClass, MostContinuityClass allows specifying the most allowed continuity class of edges at the level of shape's presentation --- src/AIS/AIS_Shape.cxx | 26 +++++++- src/AIS/AIS_Shape.hxx | 11 +++- src/Aspect/Aspect_InteriorStyle.hxx | 3 +- src/OpenGl/OpenGl_Context.cxx | 77 ++++++++++++++++++++++ src/OpenGl/OpenGl_Context.hxx | 8 +++ src/OpenGl/OpenGl_PrimitiveArray.cxx | 41 +++++++++++- src/OpenGl/OpenGl_SetOfShaderPrograms.hxx | 3 +- src/OpenGl/OpenGl_ShaderManager.cxx | 61 ++++++++++++++++- src/OpenGl/OpenGl_ShaderManager.hxx | 16 +++-- src/OpenGl/OpenGl_ShaderProgram.cxx | 8 ++- src/OpenGl/OpenGl_ShaderProgram.hxx | 7 ++ src/OpenGl/OpenGl_Text.cxx | 2 +- src/StdPrs/StdPrs_ShadedShape.cxx | 38 +++++++++-- src/StdPrs/StdPrs_ShadedShape.hxx | 24 +++++-- src/ViewerTest/ViewerTest.cxx | 80 ++++++++++++++++++++++- tests/bugs/vis/bug24437 | 36 ++++++++++ tests/bugs/vis/bug29787 | 25 +++++++ 17 files changed, 438 insertions(+), 28 deletions(-) create mode 100644 tests/bugs/vis/bug24437 create mode 100644 tests/bugs/vis/bug29787 diff --git a/src/AIS/AIS_Shape.cxx b/src/AIS/AIS_Shape.cxx index 82b805bc06..148f991541 100644 --- a/src/AIS/AIS_Shape.cxx +++ b/src/AIS/AIS_Shape.cxx @@ -90,7 +90,8 @@ AIS_Shape::AIS_Shape(const TopoDS_Shape& theShape) myUVRepeat(1.0, 1.0), myUVScale (1.0, 1.0), myInitAng (0.0), - myCompBB (Standard_True) + myCompBB (Standard_True), + myMostEdgeClass(GeomAbs_CN) { // } @@ -164,7 +165,8 @@ void AIS_Shape::Compute(const Handle(PrsMgr_PresentationManager3d)& /*aPresentat StdPrs_ShadedShape::Add (aPrs, myshape, myDrawer, myDrawer->ShadingAspect()->Aspect()->ToMapTexture() && !myDrawer->ShadingAspect()->Aspect()->TextureMap().IsNull(), - myUVOrigin, myUVRepeat, myUVScale); + myUVOrigin, myUVRepeat, myUVScale, StdPrs_Volume_Autodetection, + myMostEdgeClass); } catch (Standard_Failure const& anException) { @@ -1192,3 +1194,23 @@ Standard_Boolean AIS_Shape::OwnHLRDeviationAngle ( Standard_Real & anAngle, aPreviousAngle = myDrawer->PreviousHLRDeviationAngle (); return myDrawer->HasOwnHLRDeviationAngle(); } + +//======================================================================= +//function : SetMostContinuityClass +//purpose : +//======================================================================= + +void AIS_Shape::SetMostContinuityClass(const GeomAbs_Shape theMostAllowedEdgeClass) +{ + myMostEdgeClass = theMostAllowedEdgeClass; +} + +//======================================================================= +//function : MostContinuityClass +//purpose : +//======================================================================= + +GeomAbs_Shape AIS_Shape::MostContinuityClass() const +{ + return myMostEdgeClass; +} diff --git a/src/AIS/AIS_Shape.hxx b/src/AIS/AIS_Shape.hxx index c6f566f2f5..4a46b7d9fc 100644 --- a/src/AIS/AIS_Shape.hxx +++ b/src/AIS/AIS_Shape.hxx @@ -22,6 +22,7 @@ #include #include #include +#include //! A framework to manage presentation and selection of shapes. //! AIS_Shape is the interactive object which is used the @@ -214,6 +215,14 @@ public: //! the current facing model; Standard_EXPORT virtual Standard_Real Transparency() const Standard_OVERRIDE; + //! Set the most edge continuity class + //! @param theMostAllowedEdgeClass the most edge continuity class to be included to presentation + //! (edges with more continuity should be ignored) + Standard_EXPORT void SetMostContinuityClass(const GeomAbs_Shape theMostAllowedEdgeClass); + + //! Get the most edge continuity class + Standard_EXPORT GeomAbs_Shape MostContinuityClass() const; + //! Return shape type for specified selection mode. static TopAbs_ShapeEnum SelectionType (const Standard_Integer theSelMode) { @@ -330,7 +339,7 @@ protected: gp_Pnt2d myUVScale; //!< UV scale vector for generating texture coordinates Standard_Real myInitAng; Standard_Boolean myCompBB; //!< if TRUE, then bounding box should be recomputed - + GeomAbs_Shape myMostEdgeClass; //!< the most edge continuity class to be included to the presentation }; DEFINE_STANDARD_HANDLE(AIS_Shape, AIS_InteractiveObject) diff --git a/src/Aspect/Aspect_InteriorStyle.hxx b/src/Aspect/Aspect_InteriorStyle.hxx index e69a2589f2..b197970e39 100644 --- a/src/Aspect/Aspect_InteriorStyle.hxx +++ b/src/Aspect/Aspect_InteriorStyle.hxx @@ -32,7 +32,8 @@ Aspect_IS_HOLLOW, Aspect_IS_HATCH, Aspect_IS_SOLID, Aspect_IS_HIDDENLINE, -Aspect_IS_POINT +Aspect_IS_POINT, +Aspect_IS_OUTLINE }; #endif // _Aspect_InteriorStyle_HeaderFile diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 18cbea056d..00f395befc 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -3447,6 +3448,82 @@ void OpenGl_Context::SetPointSize (const Standard_ShortReal theSize) #endif } +// ======================================================================= +// function : PushOrthoScale +// purpose : +// ======================================================================= +void OpenGl_Context::PushOrthoScale (const Handle(OpenGl_Workspace)& theWorkspace) +{ + if (!myActiveProgram.IsNull() && !theWorkspace.IsNull()) + { + Handle(Graphic3d_Camera) aCamera = theWorkspace->View()->Camera(); + Standard_ShortReal aScale = 0.0; + if( aCamera->IsOrthographic() ) + aScale = (Standard_ShortReal)aCamera->Scale(); + myActiveProgram->SetUniform(this, myActiveProgram->GetStateLocation(OpenGl_OCCT_ORTHO_SCALE), aScale); + } +} + +// ======================================================================= +// function : SetIsSilhouettePass +// purpose : +// ======================================================================= +void OpenGl_Context::SetIsSilhouettePass (Standard_Boolean isSilhouettePass) +{ + if (!myActiveProgram.IsNull() ) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_IS_SILHOUETTE_PASS), + isSilhouettePass ? 1.0f : 0.0f); + } +} + +// ======================================================================= +// function : PushBackgroundColor +// purpose : +// ======================================================================= +void OpenGl_Context::PushBackgroundColor (const Handle(OpenGl_Workspace)& theWorkspace) +{ + if (!myActiveProgram.IsNull() && !theWorkspace.IsNull()) + { + const Quantity_Color& aBackground = theWorkspace->View()->BackgroundColor().GetRGB(); + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_BACKGROUND_COLOR), + OpenGl_Vec3((Standard_ShortReal)aBackground.Red(), + (Standard_ShortReal)aBackground.Green(), + (Standard_ShortReal)aBackground.Blue())); + } +} + +// ======================================================================= +// function : SetSilhouetteColor +// purpose : +// ======================================================================= +void OpenGl_Context::SetSilhouetteColor (const Quantity_Color& theColor) +{ + if (!myActiveProgram.IsNull()) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_SILHOUETTE_COLOR), + OpenGl_Vec3((Standard_ShortReal)theColor.Red(), + (Standard_ShortReal)theColor.Green(), + (Standard_ShortReal)theColor.Blue())); + } +} + +// ======================================================================= +// function : SetSilhouetteThickness +// purpose : +// ======================================================================= +void OpenGl_Context::SetSilhouetteThickness (Standard_ShortReal theThickness) +{ + if (!myActiveProgram.IsNull()) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_SILHOUETTE_THICKNESS), theThickness); + } +} + // ======================================================================= // function : SetPointSpriteOrigin // purpose : diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 96ac2636ee..b7a8a3f765 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -45,6 +45,8 @@ #include +class OpenGl_Workspace; + //! Forward declarations #if defined(__APPLE__) #import @@ -722,6 +724,12 @@ public: //! @name methods to alter or retrieve current state //! Setup texture matrix to active GLSL program or to FFP global state using glMatrixMode (GL_TEXTURE). Standard_EXPORT void SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams); + Standard_EXPORT void PushOrthoScale (const Handle(OpenGl_Workspace)& theWorkspace); + Standard_EXPORT void SetIsSilhouettePass (Standard_Boolean); + Standard_EXPORT void PushBackgroundColor (const Handle(OpenGl_Workspace)& theWorkspace); + Standard_EXPORT void SetSilhouetteColor (const Quantity_Color&); + Standard_EXPORT void SetSilhouetteThickness (Standard_ShortReal); + //! Bind default Vertex Array Object Standard_EXPORT void BindDefaultVao(); diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 71c96fe539..8804b51bcc 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -810,7 +811,39 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace anAspectFace->Aspect()->AlphaMode(), hasVertColor, toEnableEnvMap, - anAspectFace->ShaderProgramRes (aCtx)); + anAspectFace->ShaderProgramRes (aCtx), + anAspectFace->Aspect()->InteriorStyle()); + + if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_OUTLINE) + { + const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE + ? myBounds->Colors + : NULL; + + aCtx->PushOrthoScale(theWorkspace); + aCtx->PushBackgroundColor(theWorkspace); + aCtx->SetSilhouetteColor(anAspectFace->Aspect()->EdgeColor()); + + Standard_Integer aViewWidth, aViewHeight; + theWorkspace->View()->Window()->Size(aViewWidth, aViewHeight); + Standard_Integer aMin = aViewWidth < aViewHeight ? aViewWidth : aViewHeight; + + Standard_ShortReal anEdgeWidth = (Standard_ShortReal)anAspectFace->Aspect()->EdgeWidth() / (Standard_ShortReal)aMin; + aCtx->SetSilhouetteThickness(anEdgeWidth); + + aCtx->SetIsSilhouettePass(Standard_True); + GLboolean isCull = glIsEnabled(GL_CULL_FACE); + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + drawArray(theWorkspace, aFaceColors, hasColorAttrib); + + aCtx->SetIsSilhouettePass(Standard_False); + glCullFace(GL_BACK); + drawArray(theWorkspace, aFaceColors, hasColorAttrib); + + if (!isCull) + glDisable(GL_CULL_FACE); + } break; } } @@ -868,8 +901,9 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } else { - if (anAspectFace->Aspect()->ToDrawEdges() - || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) + if ((anAspectFace->Aspect()->ToDrawEdges() + || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) + && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_OUTLINE) { const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor(); drawEdges (anEdgeColor, theWorkspace); @@ -1026,3 +1060,4 @@ void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& th setDrawMode (theType); } + diff --git a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx index f04c5471ff..e4e3fd06d2 100644 --- a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx +++ b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx @@ -34,7 +34,8 @@ enum OpenGl_ProgramOptions OpenGl_PO_ClipPlanesN = 0x100, //!< handle N clipping planes OpenGl_PO_AlphaTest = 0x200, //!< discard fragment by alpha test (defined by cutoff value) OpenGl_PO_WriteOit = 0x400, //!< write coverage buffer for Blended Order-Independent Transparency - OpenGl_PO_NB = 0x800 //!< overall number of combinations + OpenGl_PO_OUTLINE = 0x800, //!< HLR presentation (outline shader) + OpenGl_PO_NB = 0x1000 //!< overall number of combinations }; //! Alias to programs array of predefined length diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index a83169c8b1..5bea2eff4a 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -1603,13 +1603,72 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha } } + if ((theBits & OpenGl_PO_OUTLINE) != 0) + { + aSrcVertExtraOut += + EOL"uniform float occOrthoScale;" + EOL"uniform float occIsSilhouettePass;" + EOL"uniform float occSilhouetteThickness;" + ; + + aSrcVertExtraMain += + EOL" vec3 delta = vec3(0.0, 0.0, 0.0);" + EOL" vec3 pdelta = vec3(0.0, 0.0, 0.0);" + EOL" vec4 proj_normal = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * vec4(occNormal, 0.0);" + EOL"" + EOL" float aShift = occSilhouetteThickness;" + EOL" if (occOrthoScale > 0.0)" + EOL" {" + EOL" if (abs(proj_normal[2]) < 0.25)" + EOL" {" + EOL" float k = 1.0;" + EOL" if (occIsSilhouettePass < 0.1)" + EOL" k = -1.0;" + EOL" " + EOL" vec3 pn = normalize(vec3(proj_normal.xy, 0.0));" + EOL" pdelta = k * pn * aShift / 2;" + EOL" }" + EOL" }" + EOL" else" + EOL" {" + EOL" if (occIsSilhouettePass > 0.1)" + EOL" {" + EOL" vec4 proj_vertex = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * vertex;" + EOL" delta = occNormal.xyz * aShift/2 * proj_vertex.w;" + EOL" }" + EOL" }" + EOL" " + EOL" vertex += vec4(delta, 0.0);" + EOL" vertex[3] = 1.0;" + ; + + aSrcVertEndMain += + EOL"gl_Position += vec4(pdelta.xy, 0.0, 0.0);" + ; + + aSrcFragExtraOut += + EOL"uniform float occIsSilhouettePass;" + EOL"uniform vec3 occBackgroundColor;" + EOL"uniform vec3 occSilhouetteColor;" + ; + + aSrcFragExtraMain += + EOL" vec3 aColor = occBackgroundColor;" + EOL" if (occIsSilhouettePass > 0.1)" + EOL" aColor = occSilhouetteColor;" + ; + + aSrcFragWriteOit = EOL" occSetFragColor(vec4(aColor, 1.0));"; + } + aSrcVert = aSrcVertExtraFunc + aSrcVertExtraOut + EOL"void main()" EOL"{" + EOL" vec4 vertex = occVertex;" + aSrcVertExtraMain - + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" + + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * vertex;" + aSrcVertEndMain + EOL"}"; diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 7c423e0066..83ff3f5da3 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -87,7 +87,8 @@ public: const Graphic3d_AlphaMode theAlphaMode, const Standard_Boolean theHasVertColor, const Standard_Boolean theEnableEnvMap, - const Handle(OpenGl_ShaderProgram)& theCustomProgram) + const Handle(OpenGl_ShaderProgram)& theCustomProgram, + const Aspect_InteriorStyle theStyle) { if (!theCustomProgram.IsNull() || myContext->caps->ffpEnable) @@ -99,7 +100,7 @@ public: && (theTextures.IsNull() || theTextures->IsModulate()) ? theShadingModel : Graphic3d_TOSM_UNLIT; - const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, theEnableEnvMap); + const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, theEnableEnvMap, theStyle); Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (aShadeModelOnFace, aBits); return bindProgramWithState (aProgram); } @@ -401,7 +402,8 @@ protected: Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures, Graphic3d_AlphaMode theAlphaMode, Standard_Boolean theHasVertColor, - Standard_Boolean theEnableEnvMap) + Standard_Boolean theEnableEnvMap, + Aspect_InteriorStyle theStyle=Aspect_IS_EMPTY) { Standard_Integer aBits = 0; @@ -444,6 +446,11 @@ protected: { aBits |= OpenGl_PO_WriteOit; } + + if (theStyle == Aspect_IS_OUTLINE) + { + aBits |= OpenGl_PO_OUTLINE; + } return aBits; } @@ -452,7 +459,8 @@ protected: Standard_Integer theBits) { if (theShadingModel == Graphic3d_TOSM_UNLIT - || (theBits & OpenGl_PO_TextureEnv) != 0) + || (theBits & OpenGl_PO_TextureEnv) != 0 + || (theBits & OpenGl_PO_OUTLINE) != 0) { // If environment map is enabled lighting calculations are // not needed (in accordance with default OCCT behavior) diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 784dc528ab..e9039714b6 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -74,7 +74,13 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] = "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D - "occPointSize" // OpenGl_OCCT_POINT_SIZE + "occPointSize", // OpenGl_OCCT_POINT_SIZE + + "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE + "occIsSilhouettePass", // OpenGl_OCCT_IS_SILHOUETTE_PASS + "occBackgroundColor", // OpenGl_OCCT_BACKGROUND_COLOR + "occSilhouetteColor", // OpenGl_OCCT_SILHOUETTE_COLOR + "occSilhouetteThickness" // OpenGl_OCCT_SILHOUETTE_THICKNESS }; namespace diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 87941ff0b3..639921f736 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -74,6 +74,13 @@ enum OpenGl_StateVariable OpenGl_OCCT_TEXTURE_TRSF2D, OpenGl_OCCT_POINT_SIZE, + // Parameters of outline (silhouette) shader + OpenGl_OCCT_ORTHO_SCALE, + OpenGl_OCCT_IS_SILHOUETTE_PASS, + OpenGl_OCCT_BACKGROUND_COLOR, + OpenGl_OCCT_SILHOUETTE_COLOR, + OpenGl_OCCT_SILHOUETTE_THICKNESS, + // DON'T MODIFY THIS ITEM (insert new items before it) OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES }; diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 9f162cc35b..bf92c354c7 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -761,7 +761,7 @@ void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx, // bind unlit program theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False, - Handle(OpenGl_ShaderProgram)()); + Handle(OpenGl_ShaderProgram)(), Aspect_IS_SOLID); #if !defined(GL_ES_VERSION_2_0) if (theCtx->core11 != NULL diff --git a/src/StdPrs/StdPrs_ShadedShape.cxx b/src/StdPrs/StdPrs_ShadedShape.cxx index e098fc47e6..b182a67267 100644 --- a/src/StdPrs/StdPrs_ShadedShape.cxx +++ b/src/StdPrs/StdPrs_ShadedShape.cxx @@ -301,7 +301,8 @@ namespace } //! Compute boundary presentation for faces of the shape. - static Handle(Graphic3d_ArrayOfSegments) fillFaceBoundaries (const TopoDS_Shape& theShape) + static Handle(Graphic3d_ArrayOfSegments) fillFaceBoundaries + (const TopoDS_Shape& theShape, const GeomAbs_Shape theMostAllowedEdgeClass) { // collection of all triangulation nodes on edges // for computing boundaries presentation @@ -341,6 +342,16 @@ namespace } const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key()); + if (anEdgeIter.Value().Extent() > 1) + { + TopTools_ListIteratorOfListOfShape anIter2(anEdgeIter.Value()); + anIter2.Next(); + const TopoDS_Face& aFace2 = TopoDS::Face(anIter2.Value()); + GeomAbs_Shape aShape = BRep_Tool::Continuity(anEdge, aFace, aFace2); + if (aShape > theMostAllowedEdgeClass) + continue; + } + Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf); if (!anEdgePoly.IsNull() && anEdgePoly->Nodes().Length() >= 2) @@ -384,6 +395,16 @@ namespace } const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key()); + if (anEdgeIter.Value().Extent() > 1) + { + TopTools_ListIteratorOfListOfShape anIter2(anEdgeIter.Value()); + anIter2.Next(); + const TopoDS_Face& aFace2 = TopoDS::Face(anIter2.Value()); + GeomAbs_Shape aShape = BRep_Tool::Continuity(anEdge, aFace, aFace2); + if (aShape > theMostAllowedEdgeClass) + continue; + } + Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf); if (anEdgePoly.IsNull() || anEdgePoly->Nodes().Length () < 2) @@ -501,11 +522,12 @@ void StdPrs_ShadedShape::ExploreSolids (const TopoDS_Shape& theShape, void StdPrs_ShadedShape::Add (const Handle(Prs3d_Presentation)& thePrs, const TopoDS_Shape& theShape, const Handle(Prs3d_Drawer)& theDrawer, - const StdPrs_Volume theVolume) + const StdPrs_Volume theVolume, + const GeomAbs_Shape theMostAllowedEdgeClass) { gp_Pnt2d aDummy; StdPrs_ShadedShape::Add (thePrs, theShape, theDrawer, - Standard_False, aDummy, aDummy, aDummy, theVolume); + Standard_False, aDummy, aDummy, aDummy, theVolume, theMostAllowedEdgeClass); } // ======================================================================= @@ -519,7 +541,8 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, const gp_Pnt2d& theUVOrigin, const gp_Pnt2d& theUVRepeat, const gp_Pnt2d& theUVScale, - const StdPrs_Volume theVolume) + const StdPrs_Volume theVolume, + const GeomAbs_Shape theMostAllowedEdgeClass) { if (theShape.IsNull()) { @@ -578,7 +601,7 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, if (theDrawer->FaceBoundaryDraw()) { - Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape); + Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape, theMostAllowedEdgeClass); if (!aBndSegments.IsNull()) { Handle(Graphic3d_AspectLine3d) aBoundaryAspect = theDrawer->FaceBoundaryAspect()->Aspect(); @@ -606,9 +629,10 @@ Handle(Graphic3d_ArrayOfTriangles) StdPrs_ShadedShape::FillTriangles (const Topo // function : FillFaceBoundaries // purpose : // ======================================================================= -Handle(Graphic3d_ArrayOfSegments) StdPrs_ShadedShape::FillFaceBoundaries (const TopoDS_Shape& theShape) +Handle(Graphic3d_ArrayOfSegments) StdPrs_ShadedShape::FillFaceBoundaries (const TopoDS_Shape& theShape, + const GeomAbs_Shape theMostAllowedEdgeClass) { - return fillFaceBoundaries (theShape); + return fillFaceBoundaries (theShape, theMostAllowedEdgeClass); } // ======================================================================= diff --git a/src/StdPrs/StdPrs_ShadedShape.hxx b/src/StdPrs/StdPrs_ShadedShape.hxx index cbb2a7df75..dc5bdcc12f 100644 --- a/src/StdPrs/StdPrs_ShadedShape.hxx +++ b/src/StdPrs/StdPrs_ShadedShape.hxx @@ -25,6 +25,7 @@ #include #include #include +#include class Graphic3d_ArrayOfSegments; class Graphic3d_ArrayOfTriangles; @@ -43,13 +44,27 @@ public: //! @param theVolumeType defines the way how to interpret input shapes - as Closed volumes (to activate back-face //! culling and capping plane algorithms), as Open volumes (shells or solids with holes) //! or to perform Autodetection (would split input shape into two groups) - Standard_EXPORT static void Add (const Handle(Prs3d_Presentation)& thePresentation, const TopoDS_Shape& theShape, const Handle(Prs3d_Drawer)& theDrawer, const StdPrs_Volume theVolume = StdPrs_Volume_Autodetection); + //! @param theMostAllowedEdgeClass the most edge continuity class to be included to result (edges with more continuity should be ignored) + Standard_EXPORT static void Add (const Handle(Prs3d_Presentation)& thePresentation, + const TopoDS_Shape& theShape, + const Handle(Prs3d_Drawer)& theDrawer, + const StdPrs_Volume theVolume = StdPrs_Volume_Autodetection, + const GeomAbs_Shape theMostAllowedEdgeClass = GeomAbs_CN); //! Shades with texture coordinates. //! @param theVolumeType defines the way how to interpret input shapes - as Closed volumes (to activate back-face //! culling and capping plane algorithms), as Open volumes (shells or solids with holes) //! or to perform Autodetection (would split input shape into two groups) - Standard_EXPORT static void Add (const Handle(Prs3d_Presentation)& thePresentation, const TopoDS_Shape& theShape, const Handle(Prs3d_Drawer)& theDrawer, const Standard_Boolean theHasTexels, const gp_Pnt2d& theUVOrigin, const gp_Pnt2d& theUVRepeat, const gp_Pnt2d& theUVScale, const StdPrs_Volume theVolume = StdPrs_Volume_Autodetection); + //! @param theMostAllowedEdgeClass the most edge continuity class to be included to result (edges with more continuity should be ignored) + Standard_EXPORT static void Add (const Handle(Prs3d_Presentation)& thePresentation, + const TopoDS_Shape& theShape, + const Handle(Prs3d_Drawer)& theDrawer, + const Standard_Boolean theHasTexels, + const gp_Pnt2d& theUVOrigin, + const gp_Pnt2d& theUVRepeat, + const gp_Pnt2d& theUVScale, + const StdPrs_Volume theVolume = StdPrs_Volume_Autodetection, + const GeomAbs_Shape theMostAllowedEdgeClass = GeomAbs_CN); //! Searches closed and unclosed subshapes in shape structure and puts them //! into two compounds for separate processing of closed and unclosed sub-shapes @@ -90,8 +105,9 @@ public: //! Define primitive array of boundary segments for specified shape. //! @param theShape segments array or NULL if specified face does not have computed triangulation - Standard_EXPORT static Handle(Graphic3d_ArrayOfSegments) FillFaceBoundaries (const TopoDS_Shape& theShape); - + //! @param theMostAllowedEdgeClass the most edge continuity class to be included to result (edges with more continuity should be ignored) + Standard_EXPORT static Handle(Graphic3d_ArrayOfSegments) FillFaceBoundaries + (const TopoDS_Shape& theShape, const GeomAbs_Shape theMostAllowedEdgeClass = GeomAbs_CN); }; #endif // _StdPrs_ShadedShape_HeaderFile diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 6f53cd3ada..05d0e77060 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -1575,14 +1575,18 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI, { anInterStyle = Aspect_IS_POINT; } + else if (aStyleArg == "outline") + { + anInterStyle = Aspect_IS_OUTLINE; + } else { const Standard_Integer anIntStyle = aStyleArg.IntegerValue(); if (anIntStyle < Aspect_IS_EMPTY - || anIntStyle > Aspect_IS_POINT) + || anIntStyle > Aspect_IS_OUTLINE) { std::cout << "Error: style must be within a range [0 (Aspect_IS_EMPTY), " - << Aspect_IS_POINT << " (Aspect_IS_POINT)]\n"; + << Aspect_IS_OUTLINE << " (Aspect_IS_OUTLINE)]\n"; return 1; } anInterStyle = (Aspect_InteriorStyle )anIntStyle; @@ -1615,6 +1619,72 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI, return 0; } +//============================================================================== +//function : VSetMostCont +//purpose : sets the most continuity class of edges in presentation +//============================================================================== +static int VSetMostCont(Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext(); + ViewerTest_AutoUpdater anUpdateTool(aCtx, ViewerTest::CurrentView()); + if (aCtx.IsNull()) + { + std::cerr << "Error: no active view!\n"; + return 1; + } + + if (theArgNb != 3) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp(theArgVec[0]); + return 1; + } + + TCollection_AsciiString aName = theArgVec[1]; + TCollection_AsciiString aClassArg = theArgVec[2]; + aClassArg.LowerCase(); + + GeomAbs_Shape aClass = GeomAbs_CN; + if (aClassArg == "c0") + aClass = GeomAbs_C0; + else if (aClassArg == "c1") + aClass = GeomAbs_C1; + else if (aClassArg == "c2") + aClass = GeomAbs_C2; + else if (aClassArg == "c3") + aClass = GeomAbs_C3; + else if (aClassArg == "cn") + aClass = GeomAbs_CN; + else + { + std::cout << "Error: incorrect class! See usage:\n"; + theDI.PrintHelp(theArgVec[0]); + return 1; + } + + if (!aName.IsEmpty() + && !GetMapOfAIS().IsBound2(aName)) + { + std::cout << "Error: object " << aName << " is not displayed!\n"; + return 1; + } + + for (ViewTest_PrsIter anIter(aName); anIter.More(); anIter.Next()) + { + const Handle(AIS_Shape)& aShape = Handle(AIS_Shape)::DownCast(anIter.Current()); + if (!aShape.IsNull()) + { + aShape->SetMostContinuityClass(aClass); + aCtx->RecomputePrsOnly(aShape, Standard_False, Standard_True); + } + } + return 0; +} + + + //! Auxiliary structure for VAspects struct ViewerTest_AspectsChangeSet { @@ -6070,6 +6140,12 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) "\n\t\t: Where style is: 0 = EMPTY, 1 = HOLLOW, 2 = HATCH, 3 = SOLID, 4 = HIDDENLINE.", __FILE__,VSetInteriorStyle,group); + theCommands.Add("vsetmostcont", + "vsetmostcont : ObjectName class" + "- sets the most continuity class of edges in presentation", + "\n\t\t: Where class is c0, c1, c2, c3, cn" + __FILE__, VSetMostCont, group); + theCommands.Add("vsensdis", "vsensdis : Display active entities (sensitive entities of one of the standard types corresponding to active selection modes)." "\n\t\t: Standard entity types are those defined in Select3D package:" diff --git a/tests/bugs/vis/bug24437 b/tests/bugs/vis/bug24437 new file mode 100644 index 0000000000..4b2ac3a834 --- /dev/null +++ b/tests/bugs/vis/bug24437 @@ -0,0 +1,36 @@ +puts "========" +puts "0024437: Efficient HLR visualization based on OpenGL and GLSL" +puts "========" +puts "" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vsetcolorbg 220 220 220 + +psphere sph 1.0 + +box b 1 2 3 +ttranslate b 2 -2 -2 + +pcylinder cyl 1.0 1.0 +ttranslate cyl 4.2 0 0 + +vdisplay -dispMode 1 b +vsetinteriorstyle b outline +vshowfaceboundary b 1 255 0 0 1 +vsetedgetype b -color 255 0 0 +vfit + +vdisplay -dispMode 1 sph +vsetinteriorstyle sph outline +vshowfaceboundary sph 1 255 0 0 1 +vsetedgetype sph -color 255 0 0 +vfit + +vdisplay -dispMode 1 cyl +vsetinteriorstyle cyl outline +vshowfaceboundary cyl 1 255 0 0 1 +vsetedgetype cyl -color 255 0 0 +vfit diff --git a/tests/bugs/vis/bug29787 b/tests/bugs/vis/bug29787 new file mode 100644 index 0000000000..bbfe712c3b --- /dev/null +++ b/tests/bugs/vis/bug29787 @@ -0,0 +1,25 @@ +puts "========" +puts "0029787: Avoid in presentation edges of certain continuity class" +puts "========" +puts "" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vsetcolorbg 255 255 255 + +psphere sph1 1.0 +psphere sph2 1.0 +psphere sph3 1.0 + +ttranslate sph2 4.0 0.0 0.0 +ttranslate sph3 8.0 0.0 0.0 + +vdisplay -dispMode 0 sph1 +vdisplay -dispMode 1 sph2 +vshowfaceboundary sph2 1 255 0 0 +vdisplay -dispMode 1 sph3 +vshowfaceboundary sph3 1 255 0 0 +vsetmostcont sph3 c2 +vfit -- 2.39.5