Added calculation of normals to boundary edges.
Extended draw harness commands.
Added new test case.
{
if (Handle(Graphic3d_ArrayOfSegments) aBndSegments = StdPrs_ShadedShape::FillFaceBoundaries (aShapeDraw, aDrawer->FaceBoundaryUpperContinuity()))
{
- if (anEdgesGroup.IsNull())
+ Handle(Graphic3d_AspectLine3d) aLineAspect = aDrawer->FaceBoundaryAspect()->Aspect();
+ if (aDrawer->FaceBoundaryShadingOverride())
{
+ Quantity_Color aColor = aDrawer->Color();
+ if (aDrawer->HasOwnShadingAspect())
+ {
+ aColor = aDrawer->ShadingAspect()->Color();
+ }
+ aLineAspect->SetColor (aColor);
anEdgesGroup = thePrs->NewGroup();
}
-
- anEdgesGroup->SetPrimitivesAspect (aDrawer->FaceBoundaryAspect()->Aspect());
+ else if (anEdgesGroup.IsNull())
+ {
+ anEdgesGroup = thePrs->NewGroup();
+ }
+ anEdgesGroup->SetGroupPrimitivesAspect (aLineAspect);
anEdgesGroup->AddPrimitiveArray (aBndSegments);
}
}
//! @param theMaxVertexs defines the maximum allowed vertex number in the array
//! @param theMaxEdges defines the maximum allowed edge number in the array
//! @param theHasVColors when TRUE, AddVertex(Point,Color) should be used for specifying vertex color
+ //! @param theHasVNormals when TRUE, AddVertex(Point,Normal) or AddVertex(Point,Normal,Color) should be used to specify vertex normal;
+ //! vertex normals should be specified coherent to the edge's neighbour triangle face's orientation
+ //! (defined by order of vertexes within triangle) for proper rendering
Graphic3d_ArrayOfSegments (Standard_Integer theMaxVertexs,
- Standard_Integer theMaxEdges = 0,
- Standard_Boolean theHasVColors = Standard_False)
- : Graphic3d_ArrayOfPrimitives (Graphic3d_TOPA_SEGMENTS, theMaxVertexs, 0, theMaxEdges, theHasVColors ? Graphic3d_ArrayFlags_VertexColor : Graphic3d_ArrayFlags_None) {}
-
+ Standard_Integer theMaxEdges = 0,
+ Standard_Boolean theHasVColors = Standard_False,
+ Standard_Boolean theHasVNormals = Standard_False)
+ : Graphic3d_ArrayOfPrimitives (Graphic3d_TOPA_SEGMENTS, theMaxVertexs, 0, theMaxEdges,
+ (theHasVNormals ? Graphic3d_ArrayFlags_VertexNormal : Graphic3d_ArrayFlags_None)
+ | (theHasVColors ? Graphic3d_ArrayFlags_VertexColor : Graphic3d_ArrayFlags_None)) {}
};
myFaceBoundaryDraw = false;
}
+ //! Return flag value for boundary shading edge color override
+ Standard_Boolean FaceBoundaryShadingOverride() const
+ {
+ return myHasOwnFaceBoundaryDraw || myLink.IsNull()
+ ? myFaceBoundaryShadingOverride
+ : myLink->FaceBoundaryShadingOverride();
+ }
+
+ //! Return flag value for boundary shading edge color override
+ void SetFaceBoundaryShadingOverride (Standard_Boolean theFlag) { myFaceBoundaryShadingOverride = theFlag; }
+
//! Returns true if the drawer has its own attribute for face boundaries upper edge continuity class that overrides the one in the link.
Standard_Boolean HasOwnFaceBoundaryUpperContinuity() const { return myFaceBoundaryUpperContinuity != -1; }
Standard_Integer myFaceBoundaryUpperContinuity; //!< the most edge continuity class (GeomAbs_Shape) to be included to face boundaries presentation, or -1 if undefined
Standard_Boolean myFaceBoundaryDraw;
Standard_Boolean myHasOwnFaceBoundaryDraw;
+ Standard_Boolean myFaceBoundaryShadingOverride;
Handle(Prs3d_DimensionAspect) myDimensionAspect;
Prs3d_DimensionUnits myDimensionModelUnits;
// for computing boundaries presentation
Standard_Integer aNodeNumber = 0;
Standard_Integer aNbPolylines = 0;
-
- TopLoc_Location aTrsf;
-
+ TopLoc_Location aLoc;
Handle(NCollection_Shared<TColgp_SequenceOfPnt>) aSeqPntsExtra;
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
{
// take one of the shared edges and get edge triangulation
const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First());
- Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf);
+ Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLoc);
if (aTriangulation.IsNull())
{
continue;
continue;
}
- Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf);
+ Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aLoc);
if (!anEdgePoly.IsNull()
&& anEdgePoly->Nodes().Length() >= 2)
{
// create indexed segments array to pack polylines from different edges into single array
const Standard_Integer aSegmentEdgeNb = (aNodeNumber - aNbPolylines) * 2;
- Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNodeNumber + aNbExtra, aSegmentEdgeNb + aNbExtra);
+ const Standard_Boolean aToAddNormals = Standard_True;
+ Handle(Graphic3d_ArrayOfSegments) aSegments = new Graphic3d_ArrayOfSegments (aNodeNumber + aNbExtra, aSegmentEdgeNb + aNbExtra,
+ Standard_False, aToAddNormals);
for (TopTools_IndexedDataMapOfShapeListOfShape::Iterator anEdgeIter (anEdgesMap); anEdgeIter.More(); anEdgeIter.Next())
{
if (anEdgeIter.Value().Extent() == 0)
continue;
}
- const TopoDS_Face& aFace = TopoDS::Face (anEdgeIter.Value().First());
- Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aTrsf);
- if (aTriangulation.IsNull())
- {
- continue;
- }
-
- const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key());
- if (theUpperContinuity < GeomAbs_CN
- && anEdgeIter.Value().Extent() >= 2
- && BRep_Tool::MaxContinuity (anEdge) > theUpperContinuity)
- {
- continue;
- }
-
- Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aTrsf);
- if (anEdgePoly.IsNull()
- || anEdgePoly->Nodes().Length () < 2)
+ Standard_Integer aFaceIndex = 0;
+ const Standard_Integer aFirstNodeInFace = aSegments->VertexNumber() + 1;
+ for (TopTools_ListOfShape::Iterator aFaceIter (anEdgeIter.Value()); aFaceIter.More(); aFaceIter.Next())
{
- continue;
- }
+ const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value());
+ Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (aFace, aLoc);
+ if (aTriangulation.IsNull())
+ {
+ continue;
+ }
- // get edge nodes indexes from face triangulation
- const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes();
+ const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Key());
+ if (theUpperContinuity < GeomAbs_CN
+ && anEdgeIter.Value().Extent() >= 2
+ && BRep_Tool::MaxContinuity (anEdge) > theUpperContinuity)
+ {
+ continue;
+ }
- // collect the edge nodes
- Standard_Integer aSegmentEdge = aSegments->VertexNumber() + 1;
- for (Standard_Integer aNodeIdx = anEdgeNodes.Lower(); aNodeIdx <= anEdgeNodes.Upper(); ++aNodeIdx)
- {
- // node index in face triangulation
- // get node and apply location transformation to the node
- const Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx);
- gp_Pnt aTriNode = aTriangulation->Node (aTriIndex);
- if (!aTrsf.IsIdentity())
+ Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTriangulation, aLoc);
+ if (anEdgePoly.IsNull()
+ || anEdgePoly->Nodes().Length () < 2)
{
- aTriNode.Transform (aTrsf);
+ continue;
}
- aSegments->AddVertex (aTriNode);
- if (aNodeIdx != anEdgeNodes.Lower())
+ // get edge nodes indexes from face triangulation
+ ++aFaceIndex;
+ const TColStd_Array1OfInteger& anEdgeNodes = anEdgePoly->Nodes();
+ const gp_Trsf& aTrsf = aLoc.Transformation();
+
+ // collect the edge nodes
+ Standard_Integer aSegmentEdge = aFirstNodeInFace;
+ for (Standard_Integer aNodeIdx = anEdgeNodes.Lower(); aNodeIdx <= anEdgeNodes.Upper(); ++aNodeIdx)
{
- aSegments->AddEdge ( aSegmentEdge);
- aSegments->AddEdge (++aSegmentEdge);
+ // node index in face triangulation
+ // get node and apply location transformation to the node
+ const Standard_Integer aTriIndex = anEdgeNodes.Value (aNodeIdx);
+
+ gp_Pnt aTriNode = aTriangulation->Node (aTriIndex);
+ gp_Dir aNorm = aTriangulation->Normal (aTriIndex);
+ if (aFace.Orientation() == TopAbs_REVERSED)
+ {
+ aNorm.Reverse();
+ }
+ if (!aLoc.IsIdentity())
+ {
+ aTriNode.Transform (aTrsf);
+ aNorm.Transform (aTrsf);
+ }
+
+ if (aFaceIndex == 1)
+ {
+ aSegments->AddVertex (aTriNode, aNorm);
+ if (aNodeIdx != anEdgeNodes.Lower())
+ {
+ aSegments->AddEdge (aSegmentEdge);
+ aSegments->AddEdge (++aSegmentEdge);
+ }
+ }
+ else
+ {
+ gp_XYZ aNormSum;
+ aSegments->VertexNormal (aSegmentEdge, aNormSum.ChangeCoord (1), aNormSum.ChangeCoord (2), aNormSum.ChangeCoord (3));
+ aNormSum += aNorm.XYZ();
+ aNormSum.Normalize();
+ aSegments->SetVertexNormal (aSegmentEdge, aNormSum.ChangeCoord (1), aNormSum.ChangeCoord (2), aNormSum.ChangeCoord (3));
+ ++aSegmentEdge;
+ }
}
}
}
if (Handle(Graphic3d_ArrayOfSegments) aBndSegments = fillFaceBoundaries (theShape, theDrawer->FaceBoundaryUpperContinuity()))
{
Handle(Graphic3d_Group) aPrsGrp = !theGroup.IsNull() ? theGroup : thePrs->NewGroup();
- aPrsGrp->SetGroupPrimitivesAspect (theDrawer->FaceBoundaryAspect()->Aspect());
+ Handle(Graphic3d_AspectLine3d) aLineAspect = theDrawer->FaceBoundaryAspect()->Aspect();
+ if (theDrawer->FaceBoundaryShadingOverride())
+ {
+ Quantity_Color aColor = theDrawer->ShadingAspect()->Color();
+ aLineAspect->SetColor (aColor);
+ }
+ aPrsGrp->SetGroupPrimitivesAspect (aLineAspect);
aPrsGrp->AddPrimitiveArray (aBndSegments);
}
}
Standard_Integer ToSetTypeOfFaceBoundaryLine;
Aspect_TypeOfLine TypeOfFaceBoundaryLine;
+ Standard_Integer ToSetFaceBoundaryShading;
+ Standard_Integer ToFaceBoundaryEdgeColorOverride;
+ Graphic3d_TypeOfShadingModel FaceBoundaryShading;
+ TCollection_AsciiString FaceBoundaryShadingModelName;
+
Standard_Integer ToSetMaxParamValue;
Standard_Real MaxParamValue;
FaceBoundaryWidth (1.0f),
ToSetTypeOfFaceBoundaryLine(0),
TypeOfFaceBoundaryLine (Aspect_TOL_SOLID),
+ ToSetFaceBoundaryShading (0),
+ ToFaceBoundaryEdgeColorOverride (0),
+ FaceBoundaryShading (Graphic3d_TypeOfShadingModel_DEFAULT),
//
ToSetMaxParamValue (0),
MaxParamValue (500000),
&& ToSetFaceBoundaryUpperContinuity == 0
&& ToSetFaceBoundaryColor == 0
&& ToSetFaceBoundaryWidth == 0
+ && ToSetFaceBoundaryShading == 0
&& ToSetTypeOfFaceBoundaryLine == 0
&& ToSetMaxParamValue == 0
&& ToSetSensitivity == 0
Message::SendFail() << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")";
isOk = Standard_False;
}
+ if (ToSetFaceBoundaryShading == 1
+ && (FaceBoundaryShading < Graphic3d_TypeOfShadingModel_DEFAULT || FaceBoundaryShading > Graphic3d_TypeOfShadingModel_PbrFacet))
+ {
+ Message::SendFail() << "Error: unknown face boundary shading model " << FaceBoundaryShadingModelName << ".";
+ isOk = Standard_False;
+ }
if (MaxParamValue < 0.0)
{
Message::SendFail() << "Error: the max parameter value should be greater than zero (specified " << MaxParamValue << ")";
theDrawer->FaceBoundaryAspect()->SetWidth (FaceBoundaryWidth);
}
}
+ if (ToSetFaceBoundaryShading != 0)
+ {
+ if (ToSetFaceBoundaryShading != -1
+ || theDrawer->HasOwnFaceBoundaryAspect())
+ {
+ toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
+ theDrawer->FaceBoundaryAspect()->Aspect()->SetShadingModel (FaceBoundaryShading);
+ theDrawer->SetFaceBoundaryShadingOverride (ToFaceBoundaryEdgeColorOverride);
+ }
+ }
if (ToSetTypeOfFaceBoundaryLine != 0)
{
if (ToSetTypeOfFaceBoundaryLine != -1
if (aNames.Size() >= 2
&& aNames.Value (2).IsIntegerValue())
{
+ if (aNames.Size() == 9 && aNames.Value (9).IsIntegerValue())
+ {
+ if (ViewerTest::ParseShadingModel (aNames.Value (8).ToCString(), aChangeSet->FaceBoundaryShading)
+ && (aNames.Value (9).IsIntegerValue() == 0 || aNames.Value (9).IsIntegerValue() == 1))
+ {
+ aChangeSet->ToSetFaceBoundaryShading = 1;
+ aChangeSet->ToFaceBoundaryEdgeColorOverride = aNames.Value (9).IsIntegerValue();
+ aNames.Remove (9);
+ aNames.Remove (8);
+ }
+ }
if (aNames.Size() == 7)
{
if (ViewerTest::ParseLineType (aNames.Value (7).ToCString(), aChangeSet->TypeOfFaceBoundaryLine))
aChangeSet->ToSetShadingModel = -1;
aChangeSet->ShadingModel = Graphic3d_TypeOfShadingModel_DEFAULT;
}
+ else if (anArg == "-setboundaryshading")
+ {
+ aChangeSet->ToSetFaceBoundaryShading = 1;
+ aChangeSet->FaceBoundaryShadingModelName = theArgVec[++anArgIter];
+ if (!ViewerTest::ParseShadingModel (theArgVec[anArgIter], aChangeSet->FaceBoundaryShading))
+ {
+ Message::SendFail() << "Error: wrong syntax at " << anArg;
+ return 1;
+ }
+ Standard_Integer anOverrideFlag = Draw::Atoi (theArgVec[++anArgIter]);
+ if (!(anOverrideFlag == 0 || anOverrideFlag == 1))
+ {
+ Message::SendFail() << "Error: wrong syntax at " << anArg;
+ return 1;
+ }
+ aChangeSet->ToFaceBoundaryEdgeColorOverride = anOverrideFlag;
+ }
+ else if (anArg == "-unsetboundaryshading")
+ {
+ aChangeSet->ToSetFaceBoundaryShading = -1;
+ aChangeSet->ToFaceBoundaryEdgeColorOverride = 0;
+ aChangeSet->FaceBoundaryShading = Graphic3d_TypeOfShadingModel_Unlit;
+ }
else if (anArg == "-setinterior"
|| anArg == "-setinteriorstyle"
|| anArg == "-interior"
aChangeSet->FaceBoundaryWidth = 1.0f;
aChangeSet->ToSetTypeOfFaceBoundaryLine = -1;
aChangeSet->TypeOfFaceBoundaryLine = Aspect_TOL_SOLID;
+ aChangeSet->ToSetFaceBoundaryShading = -1;
+ aChangeSet->FaceBoundaryShading = Graphic3d_TypeOfShadingModel_DEFAULT;
//
aChangeSet->ToSetHatch = -1;
aChangeSet->StdHatchStyle = -1;
[-sensitivity {selection_mode} {value}]
[-shadingModel {unlit|flat|gouraud|phong|pbr|pbr_facet}]
[-unsetShadingModel]
+ [-setboundaryshading {unlit|flat|gouraud|phong|pbr|pbr_facet}]
+ [-unsetboundaryshading]
[-interior {solid|hatch|hidenline|point}] [-setHatch HatchStyle]
[-unsetInterior]
[-faceBoundaryDraw {0|1}] [-mostContinuity {c0|g1|c1|g2|c2|c3|cn}]
Standard_Integer argc,
const char ** argv)
{
- if (( argc != 4 && argc < 7 ) || argc > 9)
+ if (( argc != 4 && argc < 7 ) || argc > 11)
{
di << "Usage :\n " << argv[0]
<< " Doc Label IsOn [R G B [LineWidth [LineStyle]]]\n"
<< " 1 - dashed \n"
<< " 2 - dot \n"
<< " 3 - dashdot\n"
- << " (default is solid)";
+ << " (default is solid)\n"
+ << " Shading - flag indicating if the boundaries\n"
+ << " should be shaded:"
+ << " 0 - no override edge color"
+ << " 1 - override edge color";
return 1;
}
aDrawer->SetFaceBoundaryAspect (aBoundaryAspect);
+ // set shading properties for face boundaries
+ if (argc == 11)
+ {
+ Graphic3d_TypeOfShadingModel aShadingModel;
+ if (ViewerTest::ParseShadingModel (argv[9], aShadingModel))
+ {
+ aDrawer->FaceBoundaryAspect()->Aspect()->SetShadingModel (aShadingModel);
+ aDrawer->SetFaceBoundaryShadingOverride (Draw::Atoi (argv[10]) == 1 ? Standard_True : Standard_False);
+ }
+ }
+
aContext->Redisplay (anInteractive, Standard_True);
return 0;
--- /dev/null
+puts "========"
+puts "0026072: Visualization - more realistic display of face edges"
+puts "========"
+
+pload MODELING VISUALIZATION XDE
+testreadstep [locate_data_file as1-oc-214-mat.stp] s
+vclear
+vinit
+vdisplay s -dispmode 1
+vfit
+vshowfaceboundary s -setboundaryshading phong 1 -boundarycolor 50 250 50
+vviewparams -scale 4.0 -proj 1.0 1.0 1.0 -up -1.0 -1.0 0.0 -at 20.0 0.0 -20.0
+vdump $::imagedir/${::casename}_shading_1.png
+vviewparams -scale 4.0 -proj 2.0 -1.5 3.0 -up 0.0 1.0 1.0 -at 20.0 130.0 -50.0
+vdump $::imagedir/${::casename}_shading_2.png
+
+vshowfaceboundary s -setboundaryshading phong 0 -boundarycolor 50 250 50
+vviewparams -scale 4.0 -proj 1.0 1.0 1.0 -up -1.0 -1.0 0.0 -at 20.0 0.0 -20.0
+vdump $::imagedir/${::casename}_noshading_1.png
+vviewparams -scale 4.0 -proj 2.0 -1.5 3.0 -up 0.0 1.0 1.0 -at 20.0 130.0 -50.0
+vdump $::imagedir/${::casename}_noshading_2.png
+
+vclear
+vclose
+ReadStep D [locate_data_file as1-oc-214-mat.stp]
+XShow D
+vfit
+vsetdispmode 1
+
+XShowFaceBoundary D 0:1:1:1 1 156 156 156 1 0 phong 1
+vviewparams -scale 4.0 -proj 1.0 1.0 1.0 -up -1.0 -1.0 0.0 -at 20.0 0.0 -20.0
+vdump $::imagedir/${::casename}_xview_shading_1.png
+vviewparams -scale 4.0 -proj 2.0 -1.5 3.0 -up 0.0 1.0 1.0 -at 20.0 130.0 -50.0
+vdump $::imagedir/${::casename}_xview_shading_2.png
+
+XShowFaceBoundary D 0:1:1:1 1 156 156 156 1 0 phong 0
+vviewparams -scale 4.0 -proj 1.0 1.0 1.0 -up -1.0 -1.0 0.0 -at 20.0 0.0 -20.0
+vdump $::imagedir/${::casename}_xview_noshading_1.png
+vviewparams -scale 4.0 -proj 2.0 -1.5 3.0 -up 0.0 1.0 1.0 -at 20.0 130.0 -50.0
+vdump $::imagedir/${::casename}_xview_noshading_2.png