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