diff --git a/src/IVtk/IVtk_IShapeData.hxx b/src/IVtk/IVtk_IShapeData.hxx index f6e7c6be19..aed7ddebc2 100644 --- a/src/IVtk/IVtk_IShapeData.hxx +++ b/src/IVtk/IVtk_IShapeData.hxx @@ -16,10 +16,11 @@ #ifndef __IVTK_ISHAPEDATA_H__ #define __IVTK_ISHAPEDATA_H__ +#include #include #include +#include -class IVtk_IShapeData; DEFINE_STANDARD_HANDLE( IVtk_IShapeData, IVtk_Interface ) //! @class IVtk_IShapeData @@ -34,11 +35,11 @@ public: DEFINE_STANDARD_RTTIEXT(IVtk_IShapeData,IVtk_Interface) //! Insert a coordinate - //! @param [in] theX X coordinate - //! @param [in] theY Y coordinate - //! @param [in] theZ Z coordinate + //! @param [in] thePnt point position + //! @param [in] theNorm point normal //! @return id of added point - virtual IVtk_PointId InsertCoordinate (double theX, double theY, double theZ) = 0; + virtual IVtk_PointId InsertPoint (const gp_Pnt& thePnt, + const NCollection_Vec3& theNorm) = 0; //! Insert a vertex. //! @param [in] theShapeID id of the sub-shape to which the vertex belongs. @@ -77,6 +78,27 @@ public: const IVtk_PointId thePointId2, const IVtk_PointId thePointId3, const IVtk_MeshType theMeshType = MT_Undefined) = 0; + +public: + + //! Insert a coordinate + //! @param [in] theX X coordinate + //! @param [in] theY Y coordinate + //! @param [in] theZ Z coordinate + //! @return id of added point + virtual IVtk_PointId InsertCoordinate (double theX, double theY, double theZ) + { + return InsertCoordinate (gp_Pnt (theX, theY, theZ)); + } + + //! Insert a coordinate + //! @param [in] thePnt point position + //! @return id of added point + IVtk_PointId InsertCoordinate (const gp_Pnt& thePnt) + { + return InsertPoint (thePnt, NCollection_Vec3(0.0f, 0.0f, 1.0f)); + } + }; #endif // __IVTK_ISHAPEDATA_H__ diff --git a/src/IVtkDraw/IVtkDraw.cxx b/src/IVtkDraw/IVtkDraw.cxx index b459f0c4ab..e71826b5ef 100644 --- a/src/IVtkDraw/IVtkDraw.cxx +++ b/src/IVtkDraw/IVtkDraw.cxx @@ -514,6 +514,7 @@ vtkActor* CreateActor (const Standard_Integer theId, Handle(PipelinePtr) aPL = new PipelinePtr (theShape, theId, GetDefaultDrawer()); GetPipelines()->Bind (theId, aPL); + aPL->Actor()->GetProperty()->SetInterpolationToPhong(); return aPL->Actor(); } @@ -828,158 +829,159 @@ static Standard_Integer VtkRemove (Draw_Interpretor& , //================================================================ // Function : VtkSetDisplayMode -// Purpose : -// Draw args : ivtksetdispmode [name] mode(0,1) +// Purpose : //================================================================ -static Standard_Integer VtkSetDisplayMode (Draw_Interpretor& , +static Standard_Integer VtkSetDisplayMode (Draw_Interpretor& theDI, Standard_Integer theArgNum, const char** theArgs) { if (!GetInteractor() || !GetInteractor()->IsEnabled()) { - Message::SendFail() << "Error: call ivtkinit before"; - return 1; - } - else if (theArgNum != 2 && theArgNum != 3) - { - Message::SendFail() << "Syntax error: expects 1 or 2 arguments"; + theDI << "Error: call ivtkinit before"; return 1; } - if (theArgNum == 2) + Standard_Integer aDispMode = -1; + Standard_Integer isFaceBoundaryDraw = -1, isSmoothShading = -1; + Graphic3d_TypeOfShadingModel aShadingModel = Graphic3d_TOSM_DEFAULT; + NCollection_Sequence< vtkSmartPointer > anActors; + for (Standard_Integer anArgIter = 1; anArgIter < theArgNum; ++anArgIter) { - // Set disp mode for all objects - Standard_Integer aMode = Draw::Atoi (theArgs[1]); // Get mode - DoubleMapOfActorsAndNames::Iterator anIter (GetMapOfActors()); - while (anIter.More()) + TCollection_AsciiString anArgCase (theArgs[anArgIter]); + anArgCase.LowerCase(); + if (anArgCase == "-faceboundarydraw" + || anArgCase == "-drawfaceboundary" + || anArgCase == "-faceboundary") { - vtkSmartPointer anActor = anIter.Key1(); - IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor); - if (aSrc) + bool toDraw = Draw::ParseOnOffNoIterator (theArgNum, theArgs, anArgIter); + isFaceBoundaryDraw = toDraw ? 1 : 0; + } + else if (anArgCase == "-smoothshading" + || anArgCase == "-smooth") + { + bool toEnable = Draw::ParseOnOffNoIterator (theArgNum, theArgs, anArgIter); + isSmoothShading = toEnable ? 1 : 0; + } + else if (anArgIter + 1 < theArgNum + && (anArgCase == "-shadingmodel")) + { + TCollection_AsciiString aModelName (theArgs[++anArgIter]); + aModelName.LowerCase(); + if (aModelName == "fragment" + || aModelName == "frag" + || aModelName == "phong") { - IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape(); - if (!anOccShape.IsNull()) + aShadingModel = Graphic3d_TOSM_FRAGMENT; + } + else if (aModelName == "vertex" + || aModelName == "vert" + || aModelName == "gouraud") + { + aShadingModel = Graphic3d_TOSM_VERTEX; + } + else if (aModelName == "facet" + || aModelName == "flat") + { + aShadingModel = Graphic3d_TOSM_FACET; + } + else + { + theDI << "Syntax error: unknown shading model '" << theArgs[anArgIter] << "'"; + return 1; + } + } + else if (aDispMode == -1 + && (anArgCase == "0" + || anArgCase == "1")) + { + aDispMode = Draw::Atoi (theArgs[anArgIter]); + } + else if (aDispMode == -1 + && (anArgCase == "-shaded" + || anArgCase == "-shading")) + { + aDispMode = DM_Shading; + } + else if (aDispMode == -1 + && anArgCase == "-wireframe") + { + aDispMode = DM_Wireframe; + } + else + { + TCollection_AsciiString aName = theArgs[anArgIter]; + vtkSmartPointer anActor; + if (!GetMapOfActors().Find2 (aName, anActor)) + { + theDI << "Syntax error: object '" << aName << "' not found"; + return 1; + } + anActors.Append (anActor); + } + } + if (aDispMode == -1) + { + theDI << "Syntax error: wrong number of arguments"; + return 1; + } + + if (anActors.IsEmpty()) + { + // update all objects + for (DoubleMapOfActorsAndNames::Iterator anIter (GetMapOfActors()); anIter.More(); anIter.Next()) + { + anActors.Append (anIter.Key1()); + } + } + + for (NCollection_Sequence< vtkSmartPointer >::Iterator anActorIter (anActors); anActorIter.More(); anActorIter.Next()) + { + vtkSmartPointer anActor = anActorIter.Value(); + IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor); + if (aSrc == NULL) + { + continue; + } + + IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape(); + if (!anOccShape.IsNull()) + { + IVtkTools_DisplayModeFilter* aFilter = GetPipeline ( anOccShape->GetId() )->GetDisplayModeFilter(); + aFilter->SetDisplayMode ((IVtk_DisplayMode)aDispMode); + if (isFaceBoundaryDraw != -1) + { + // Set Red color for boundary edges + vtkLookupTable* aTable = (vtkLookupTable*)anActor->GetMapper()->GetLookupTable(); + IVtkTools::SetLookupTableColor (aTable, MT_SharedEdge, 1., 0., 0., 1.); + aFilter->SetFaceBoundaryDraw (isFaceBoundaryDraw == 1); + } + if (isSmoothShading != -1) + { + aFilter->SetSmoothShading (isSmoothShading == 1); + } + switch (aShadingModel) + { + case Graphic3d_TOSM_FACET: { - IVtkTools_DisplayModeFilter* aFilter = GetPipeline ( anOccShape->GetId() )->GetDisplayModeFilter(); - aFilter->SetDisplayMode((IVtk_DisplayMode)aMode); - aFilter->Modified(); - aFilter->Update(); + anActor->GetProperty()->SetInterpolationToFlat(); + break; } - } - anIter.Next(); - } - } - // Set disp mode for named object - else - { - TCollection_AsciiString aName = theArgs[1]; - vtkSmartPointer anActor; - if (!GetMapOfActors().Find2 (aName, anActor)) - { - Message::SendFail() << "Syntax error: object '" << aName << "' not found"; - return 1; - } - - Standard_Integer aMode = atoi(theArgs[2]); - vtkSmartPointer aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor); - if (aSrc) - { - IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape(); - if (!anOccShape.IsNull()) - { - IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter(); - aFilter->SetDisplayMode ((IVtk_DisplayMode)aMode); - aFilter->Modified(); - aFilter->Update(); - } - } - } - - // Redraw window - GetInteractor()->Render(); - return 0; -} - -//================================================================ -// Function : VtkSetBoundaryDraw -// Purpose : -//================================================================ -static Standard_Integer VtkSetBoundaryDraw (Draw_Interpretor& , - Standard_Integer theArgNum, - const char** theArgs) -{ - if (!GetInteractor() - || !GetInteractor()->IsEnabled()) - { - Message::SendFail() << "Error: call ivtkinit before"; - return 1; - } - else if (theArgNum != 2 && theArgNum != 3) - { - Message::SendFail() << "Syntax error: expects 1 or 2 arguments"; - return 1; - } - - if (theArgNum == 2) - { - // Set disp mode for all objects - Standard_Boolean toDraw = true; - Draw::ParseOnOff (theArgs[1], toDraw); - DoubleMapOfActorsAndNames::Iterator anIter(GetMapOfActors()); - while (anIter.More()) - { - vtkSmartPointer anActor = anIter.Key1(); - // Set Red color for boundary edges - vtkLookupTable* aTable = (vtkLookupTable*)anActor->GetMapper()->GetLookupTable(); - IVtkTools::SetLookupTableColor(aTable, MT_SharedEdge, 1., 0., 0., 1.); - - IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource(anActor); - if (aSrc) - { - IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape(); - if (!anOccShape.IsNull()) + case Graphic3d_TOSM_VERTEX: { - IVtkTools_DisplayModeFilter* aFilter = GetPipeline(anOccShape->GetId())->GetDisplayModeFilter(); - aFilter->SetDisplayMode(DM_Shading); - aFilter->SetFaceBoundaryDraw(toDraw != 0); - aFilter->Modified(); - aFilter->Update(); + anActor->GetProperty()->SetInterpolationToGouraud(); + break; } + case Graphic3d_TOSM_FRAGMENT: + { + anActor->GetProperty()->SetInterpolationToPhong(); + break; + } + default: break; } - anIter.Next(); - } - } - else - { - // Set disp mode for named object - TCollection_AsciiString aName = theArgs[1]; - vtkSmartPointer anActor; - if (!GetMapOfActors().Find2 (aName, anActor)) - { - Message::SendFail() << "Syntax error: object '" << aName << "' not found"; - return 1; - } - Standard_Boolean toDraw = true; - Draw::ParseOnOff (theArgs[2], toDraw); - - // Set Red color for boundary edges - vtkLookupTable* aTable = (vtkLookupTable*)anActor->GetMapper()->GetLookupTable(); - IVtkTools::SetLookupTableColor (aTable, MT_SharedEdge, 1., 0., 0., 1.); - - vtkSmartPointer aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor); - if (aSrc) - { - IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape(); - if (!anOccShape.IsNull()) - { - IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter(); - aFilter->SetDisplayMode (DM_Shading); - aFilter->SetFaceBoundaryDraw (toDraw != 0); - aFilter->Modified(); - aFilter->Update(); - } + aFilter->Modified(); + aFilter->Update(); } } @@ -1655,16 +1657,14 @@ void IVtkDraw::Commands (Draw_Interpretor& theCommands) __FILE__, VtkRemove, group); theCommands.Add("ivtksetdispmode", - "ivtksetdispmode [name] mode={0|1}" - "\n\t\t: Sets or unsets display mode 'mode' to the object with name 'name' or to all objects.", + "ivtksetdispmode [name] mode={0|1} [-faceBoundaryDraw {0|1}] [-smoothShading {0|1}]" + "\n\t\t: [-shadingModel {phong|gouraud|flat}]" + "\n\t\t: Sets or unsets display mode to the object with the given name or to all objects." + "\n\t\t: -faceBoundaryDraw show/hide boundaries within shading display mode" + "\n\t\t: -smoothShading enable/disable vertex normals for smooth shading" + "\n\t\t: -shadingModel sets specified shading model", __FILE__, VtkSetDisplayMode, group); - theCommands.Add("ivtksetboundingdraw", - "ivtksetboundingdraw [name] {on|off}" - "\n\t\t: Sets or unsets boundaries drawing for shading display mode" - "\n\t\t: to the object with name 'name' or to all objects.", - __FILE__, VtkSetBoundaryDraw, group); - theCommands.Add("ivtksetselmode", "ivtksetselmode [name] mode {on|off}" "\n\t\t: Sets or unsets selection mode 'mode' to the object with name 'name'" diff --git a/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx b/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx index f0caffdcf6..9e341e8d3c 100644 --- a/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx +++ b/src/IVtkOCC/IVtkOCC_ShapeMesher.cxx @@ -71,6 +71,15 @@ void IVtkOCC_ShapeMesher::internalBuild() StdPrs_ToolTriangulatedShape::ClearOnOwnDeflectionChange (anOcctShape, anOcctDrawer, true); StdPrs_ToolTriangulatedShape::Tessellate (anOcctShape, anOcctDrawer); } + for (TopExp_Explorer aFaceIter (anOcctShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) + { + const TopoDS_Face& anOcctFace = TopoDS::Face (aFaceIter.Current()); + TopLoc_Location aLoc; + if (const Handle(Poly_Triangulation)& anOcctTriangulation = BRep_Tool::Triangulation (anOcctFace, aLoc)) + { + StdPrs_ToolTriangulatedShape::ComputeNormals (anOcctFace, anOcctTriangulation); + } + } // Free vertices and free edges should always be shown. // Shared edges are needed in WF representation only. @@ -232,49 +241,11 @@ void IVtkOCC_ShapeMesher::addVertex (const TopoDS_Vertex& theVertex, gp_Pnt aPnt3d = BRep_Tool::Pnt (theVertex); - IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt3d.X(), aPnt3d.Y(), aPnt3d.Z()); + IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt3d); myShapeData->InsertVertex (theShapeId, anId, theMeshType); } -//================================================================ -// Function : processPolyline -// Purpose : -//================================================================ -void IVtkOCC_ShapeMesher::processPolyline (Standard_Integer theNbNodes, - const TColgp_Array1OfPnt& thePoints, - const TColStd_Array1OfInteger& thePointIds, - const IVtk_IdType theOcctId, - bool theNoTransform, - gp_Trsf theTransformation, - const IVtk_MeshType theMeshType) -{ - if (theNbNodes < 2) - { - return; - } - - IVtk_PointIdList aPolyPointIds; - - IVtk_PointId anId; - for (Standard_Integer aJ = 0; aJ < theNbNodes; aJ++) - { - Standard_Integer aPntId = thePointIds (aJ + 1); - gp_Pnt point = thePoints (aPntId); - - if (!theNoTransform) - { - // Apply the transformation to points - point.Transform (theTransformation); - } - - anId = myShapeData->InsertCoordinate (point.X(), point.Y(), point.Z()); - aPolyPointIds.Append (anId); - } - - myShapeData->InsertLine (theOcctId, &aPolyPointIds, theMeshType); -} - //================================================================ // Function : addEdge // Purpose : @@ -288,73 +259,60 @@ void IVtkOCC_ShapeMesher::addEdge (const TopoDS_Edge& theEdge, return; } - // Two discrete representations of an OCCT edge are possible: - // 1. Polygon on triangulation - holds Ids of points - // contained in Poly_Triangulation object Handle(Poly_PolygonOnTriangulation) aPolyOnTriangulation; Handle(Poly_Triangulation) aTriangulation; - TopLoc_Location aLocation; - BRep_Tool::PolygonOnTriangulation (theEdge, - aPolyOnTriangulation, - aTriangulation, - aLocation, - 1); - - // 2. 3D polygon - holds 3D points - Handle(Poly_Polygon3D) aPoly3d; - if (aPolyOnTriangulation.IsNull()) + TopLoc_Location aLoc; + BRep_Tool::PolygonOnTriangulation (theEdge, aPolyOnTriangulation, aTriangulation, aLoc, 1); + if (!aPolyOnTriangulation.IsNull() + && aPolyOnTriangulation->NbNodes() >= 2) { - aPoly3d = BRep_Tool::Polygon3D (theEdge, aLocation); - } + // prefer polygon on triangulation when defined + const gp_Trsf aTrsf = aLoc.Transformation(); + const bool hasTransform = !aLoc.IsIdentity(); - if (aPoly3d.IsNull() && aPolyOnTriangulation.IsNull()) - { - return; - } - - // Handle a non-identity transformation applied to the edge - gp_Trsf anEdgeTransf; - bool noTransform = true; - if (!aLocation.IsIdentity()) - { - noTransform = false; - anEdgeTransf = aLocation.Transformation(); - } - - if (!aPoly3d.IsNull()) - { - Standard_Integer aNbNodes = aPoly3d->NbNodes(); - const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes(); - TColStd_Array1OfInteger aPointIds (1, aNbNodes); - - for (Standard_Integer anI = 1; anI <= aNbNodes; anI++) - { - aPointIds.SetValue (anI, anI); - } - - processPolyline (aNbNodes, - aPoints, - aPointIds, - theShapeId, - noTransform, - anEdgeTransf, - theMeshType); - } - else if (aPolyOnTriangulation->NbNodes() >= 2) - { IVtk_PointIdList aPolyPointIds; const Standard_Integer aNbNodes = aPolyOnTriangulation->NbNodes(); for (Standard_Integer aJ = 0; aJ < aNbNodes; aJ++) { const Standard_Integer aPntId = aPolyOnTriangulation->Node (aJ + 1); gp_Pnt aPoint = aTriangulation->Node (aPntId); - if (!noTransform) { aPoint.Transform (anEdgeTransf); } + gp_Dir aNorm = aTriangulation->HasNormals() ? aTriangulation->Normal (aPntId) : gp::DZ(); + if (hasTransform) + { + aPoint.Transform (aTrsf); + aNorm .Transform (aTrsf); + } - IVtk_PointId anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z()); + IVtk_PointId anId = myShapeData->InsertPoint (aPoint, Graphic3d_Vec3 ((float )aNorm.X(), (float )aNorm.Y(), (float )aNorm.Z())); aPolyPointIds.Append (anId); } myShapeData->InsertLine (theShapeId, &aPolyPointIds, theMeshType); + return; } + + // try polygon 3d + Handle(Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D (theEdge, aLoc); + if (aPoly3d.IsNull() + || aPoly3d->NbNodes() < 2) + { + return; + } + + const gp_Trsf anEdgeTransf = aLoc.Transformation(); + const bool noTransform = aLoc.IsIdentity(); + IVtk_PointIdList aPolyPointIds; + for (Standard_Integer aNodeIter = 1; aNodeIter <= aPoly3d->NbNodes(); ++aNodeIter) + { + gp_Pnt aPnt = aPoly3d->Nodes().Value (aNodeIter); + if (!noTransform) + { + aPnt.Transform (anEdgeTransf); + } + + const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt); + aPolyPointIds.Append (anId); + } + myShapeData->InsertLine (theShapeId, &aPolyPointIds, theMeshType); } //================================================================ @@ -373,12 +331,6 @@ void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace, TopoDS_Face aFaceToMesh = theFace; aFaceToMesh.Orientation (TopAbs_FORWARD); - // The code that builds wireframe representation for a TopoDS_Face - // has been adapted from some OCCT 6.5.1 methods: - // - Prs3d_WFShape::Add() - // - StdPrs_WFDeflectionRestrictedFace::Add() - // - StdPrs_DeflectionCurve::Add() - // Add face's edges here but with the face ID for (TopExp_Explorer anEdgeIter (aFaceToMesh, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) { @@ -408,7 +360,7 @@ void IVtkOCC_ShapeMesher::addWFFace (const TopoDS_Face& theFace, for (TColgp_HSequenceOfPnt::Iterator aNodeIter (*aPoints); aNodeIter.More(); aNodeIter.Next()) { const gp_Pnt& aPnt = aNodeIter.Value(); - const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt.X(), aPnt.Y(), aPnt.Z()); + const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt); aPolyPointIds.Append (anId); } @@ -428,7 +380,6 @@ void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace, return; } - // Build triangulation of the face. TopLoc_Location aLoc; const Handle(Poly_Triangulation)& anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc); if (anOcctTriangulation.IsNull()) @@ -436,13 +387,10 @@ void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace, return; } - gp_Trsf aPntTransform; - Standard_Boolean noTransform = Standard_True; - if (!aLoc.IsIdentity()) - { - noTransform = Standard_False; - aPntTransform = aLoc.Transformation(); - } + // Determinant of transform matrix less then 0 means that mirror transform applied + const gp_Trsf aTrsf = aLoc.Transformation(); + const bool hasTransform = !aLoc.IsIdentity(); + const bool isMirrored = aTrsf.VectorialPart().Determinant() < 0; // Get triangulation points. Standard_Integer aNbPoints = anOcctTriangulation->NbNodes(); @@ -453,14 +401,19 @@ void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace, for (Standard_Integer anI = 1; anI <= aNbPoints; anI++) { gp_Pnt aPoint = anOcctTriangulation->Node (anI); - - if (!noTransform) + gp_Dir aNorm = anOcctTriangulation->HasNormals() ? anOcctTriangulation->Normal (anI) : gp::DZ(); + if ((theFace.Orientation() == TopAbs_REVERSED) ^ isMirrored) { - aPoint.Transform (aPntTransform); + aNorm.Reverse(); + } + if (hasTransform) + { + aPoint.Transform (aTrsf); + aNorm .Transform (aTrsf); } // Add a point into output shape data and keep its id in the array. - anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z()); + anId = myShapeData->InsertPoint (aPoint, Graphic3d_Vec3 ((float )aNorm.X(), (float )aNorm.Y(), (float )aNorm.Z())); aPointIds.SetValue (anI, anId); } @@ -469,9 +422,16 @@ void IVtkOCC_ShapeMesher::addShadedFace (const TopoDS_Face& theFace, Standard_Integer aN1, aN2, aN3; for (Standard_Integer anI = 1; anI <= aNbTriangles; anI++) { - anOcctTriangulation->Triangle (anI).Get (aN1, aN2, aN3); // get indexes of triangle's points + if (theFace.Orientation() == TopAbs_REVERSED) + { + anOcctTriangulation->Triangle (anI).Get (aN1, aN3, aN2); + } + else + { + anOcctTriangulation->Triangle (anI).Get (aN1, aN2, aN3); + } + // Insert new triangle on these points into output shape data. - myShapeData->InsertTriangle ( - theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace); + myShapeData->InsertTriangle (theShapeId, aPointIds(aN1), aPointIds(aN2), aPointIds(aN3), MT_ShadedFace); } } diff --git a/src/IVtkOCC/IVtkOCC_ShapeMesher.hxx b/src/IVtkOCC/IVtkOCC_ShapeMesher.hxx index d369c2d5ae..591fe72cb9 100644 --- a/src/IVtkOCC/IVtkOCC_ShapeMesher.hxx +++ b/src/IVtkOCC/IVtkOCC_ShapeMesher.hxx @@ -122,19 +122,6 @@ private: void addShadedFace (const TopoDS_Face& theFace, const IVtk_IdType theShapeId); - //! Internal helper method that unpacks the input arrays of points and - //! connectivity and creates the polyline using IPolyData interface. - //! Optionally, the transformation specified through the last argument - //! can be applied to each point's coordinates (noTransform == true). - //! The polyline is associated with the given sub-shape ID. - void processPolyline (Standard_Integer theNbNodes, - const TColgp_Array1OfPnt& thePoints, - const TColStd_Array1OfInteger& thePointIds, - const IVtk_IdType theOcctId, - bool theNoTransform, - gp_Trsf theTransformation, - const IVtk_MeshType theMeshType); - //! Get the IShape as OCC implementation const IVtkOCC_Shape::Handle GetShapeObj() const; diff --git a/src/IVtkTools/IVtkTools_DisplayModeFilter.cxx b/src/IVtkTools/IVtkTools_DisplayModeFilter.cxx index e80a2104f0..d478fc1460 100644 --- a/src/IVtkTools/IVtkTools_DisplayModeFilter.cxx +++ b/src/IVtkTools/IVtkTools_DisplayModeFilter.cxx @@ -34,9 +34,10 @@ vtkStandardNewMacro(IVtkTools_DisplayModeFilter) // Purpose: //============================================================================ IVtkTools_DisplayModeFilter::IVtkTools_DisplayModeFilter() - : myDisplayMode (DM_Wireframe), - myDoDisplaySharedVertices (false), - myDrawFaceBoundaries( false ) +: myDisplayMode (DM_Wireframe), + myDoDisplaySharedVertices (false), + myDrawFaceBoundaries (false), + myIsSmoothShading (true) { // Filter according to values in subshapes types array. myIdsArrayName = IVtkVTK_ShapeData::ARRNAME_MESH_TYPES(); @@ -78,6 +79,7 @@ int IVtkTools_DisplayModeFilter::RequestData (vtkInformation *theRequest, vtkInformationVector *theOutputVector) { SetData (myModesDefinition[myDisplayMode]); + myToCopyNormals = myIsSmoothShading && (myDisplayMode == DM_Shading); return Superclass::RequestData (theRequest, theInputVector, theOutputVector); } @@ -184,3 +186,16 @@ void IVtkTools_DisplayModeFilter::SetFaceBoundaryDraw(bool theToDraw) } Modified(); } + +//============================================================================ +// Method: SetSmoothShading +// Purpose: +//============================================================================ +void IVtkTools_DisplayModeFilter::SetSmoothShading (bool theIsSmooth) +{ + if (myIsSmoothShading != theIsSmooth) + { + myIsSmoothShading = theIsSmooth; + Modified(); + } +} diff --git a/src/IVtkTools/IVtkTools_DisplayModeFilter.hxx b/src/IVtkTools/IVtkTools_DisplayModeFilter.hxx index a81e331e45..72ee21188a 100644 --- a/src/IVtkTools/IVtkTools_DisplayModeFilter.hxx +++ b/src/IVtkTools/IVtkTools_DisplayModeFilter.hxx @@ -58,6 +58,12 @@ public: //! Returns True if drawing Boundary of faces for shading mode is defined. bool FaceBoundaryDraw() const { return myDrawFaceBoundaries; } + //! Returns TRUE if vertex normals should be included for smooth shading within DM_Shading mode or not. + bool IsSmoothShading() const { return myIsSmoothShading; } + + //! Set if vertex normals should be included for smooth shading or not. + void SetSmoothShading (bool theIsSmooth); + protected: //! Filter cells according to the given set of ids. virtual int RequestData (vtkInformation *, vtkInformationVector **, vtkInformationVector *) Standard_OVERRIDE; @@ -66,13 +72,12 @@ protected: virtual ~IVtkTools_DisplayModeFilter(); protected: - //! Display mode defining mesh types to pass through this filter. - IVtk_DisplayMode myDisplayMode; + IVtk_DisplayMode myDisplayMode; //!< Display mode defining mesh types to pass through this filter IVtk_IdTypeMap myModesDefinition[2]; bool myDoDisplaySharedVertices; - //! Draw Face boundaries flag is applicable only for shading display mode. - bool myDrawFaceBoundaries; + bool myDrawFaceBoundaries; //!< Draw Face boundaries within shading display mode + bool myIsSmoothShading; //!< include vertex normals for smooth shading or not }; #ifdef _MSC_VER diff --git a/src/IVtkTools/IVtkTools_SubPolyDataFilter.cxx b/src/IVtkTools/IVtkTools_SubPolyDataFilter.cxx index 26ded68af5..31163f6028 100644 --- a/src/IVtkTools/IVtkTools_SubPolyDataFilter.cxx +++ b/src/IVtkTools/IVtkTools_SubPolyDataFilter.cxx @@ -21,30 +21,109 @@ #pragma warning(push) #endif #include +#include +#include #include #include #include #include #include +#include #ifdef _MSC_VER #pragma warning(pop) #endif +namespace +{ + //! Modified version of vtkPolyData::CopyCells() that includes copying of normals. + //! How to ask vtkPolyData::CopyCells() to do that automatically? + static void copyCells (vtkPolyData* theDst, + vtkPolyData* theSrc, + vtkIdList* theIdList) + { + //theDst->CopyCells (theSrc, theIdList); + + const vtkIdType aNbPts = theSrc->GetNumberOfPoints(); + vtkDataArray* anOldNormals = theSrc->GetPointData()->GetNormals(); + + if (theDst->GetPoints() == NULL) + { + theDst->SetPoints (vtkSmartPointer::New()); + } + + vtkSmartPointer aNewCellPts = vtkSmartPointer::New(); + vtkSmartPointer aCell = vtkSmartPointer::New(); + NCollection_Vec3 anXYZ; + vtkPointData* aNewPntData = theDst->GetPointData(); + vtkCellData* aNewCellData = theDst->GetCellData(); + vtkPoints* aNewPoints = theDst->GetPoints(); + vtkSmartPointer aNewNormals; + if (anOldNormals != NULL) + { + aNewNormals = vtkSmartPointer::New(); + aNewNormals->SetName ("Normals"); + aNewNormals->SetNumberOfComponents (3); + theDst->GetPointData()->SetNormals (aNewNormals); + } + + vtkSmartPointer aPntMap = vtkSmartPointer::New(); // maps old pt ids into new + aPntMap->SetNumberOfIds (aNbPts); + for (vtkIdType i = 0; i < aNbPts; ++i) + { + aPntMap->SetId (i, -1); + } + + // Filter the cells + for (vtkIdType aCellIter = 0; aCellIter < theIdList->GetNumberOfIds(); ++aCellIter) + { + theSrc->GetCell (theIdList->GetId (aCellIter), aCell); + vtkIdList* aCellPts = aCell->GetPointIds(); + const vtkIdType aNbCellPts = aCell->GetNumberOfPoints(); + for (vtkIdType i = 0; i < aNbCellPts; ++i) + { + const vtkIdType aPtId = aCellPts->GetId (i); + vtkIdType aNewId = aPntMap->GetId (aPtId); + if (aNewId < 0) + { + theSrc->GetPoint (aPtId, anXYZ.ChangeData()); + + aNewId = aNewPoints->InsertNextPoint (anXYZ.GetData()); + aPntMap->SetId (aPtId, aNewId); + aNewPntData->CopyData (theSrc->GetPointData(), aPtId, aNewId); + + if (anOldNormals != NULL) + { + anOldNormals->GetTuple (aPtId, anXYZ.ChangeData()); + aNewNormals->InsertNextTuple (anXYZ.GetData()); + } + } + aNewCellPts->InsertId (i, aNewId); + } + + const vtkIdType aNewCellId = theDst->InsertNextCell (aCell->GetCellType(), aNewCellPts); + aNewCellData->CopyData (theSrc->GetCellData(), theIdList->GetId (aCellIter), aNewCellId); + aNewCellPts->Reset(); + } + } +} + vtkStandardNewMacro(IVtkTools_SubPolyDataFilter) //================================================================ // Function : Constructor -// Purpose : +// Purpose : //================================================================ IVtkTools_SubPolyDataFilter::IVtkTools_SubPolyDataFilter() +: myIdsArrayName (IVtkVTK_ShapeData::ARRNAME_SUBSHAPE_IDS()), + myDoFiltering (true), + myToCopyNormals (true) { - myIdsArrayName = IVtkVTK_ShapeData::ARRNAME_SUBSHAPE_IDS(); - myDoFiltering = true; + // } //================================================================ // Function : Destructor -// Purpose : +// Purpose : //================================================================ IVtkTools_SubPolyDataFilter::~IVtkTools_SubPolyDataFilter() { } @@ -70,18 +149,17 @@ int IVtkTools_SubPolyDataFilter::RequestData (vtkInformation *vtkNotUsed(theRequ if (myDoFiltering) { - vtkSmartPointer aCellData = anInput->GetCellData(); - vtkIdType aSize = 0; - vtkSmartPointer aDataArray = - vtkIdTypeArray::SafeDownCast (aCellData->GetArray (myIdsArrayName)); + vtkSmartPointer anInputCellData = anInput->GetCellData(); + vtkSmartPointer anOutputCellData = anOutput->GetCellData(); + vtkSmartPointer aDataArray = vtkIdTypeArray::SafeDownCast (anInputCellData->GetArray (myIdsArrayName)); // List of cell ids to be passed vtkSmartPointer anIdList = vtkSmartPointer::New(); - anIdList->Allocate(myIdsSet.Extent()); // Allocate the list of ids + anIdList->Allocate (myIdsSet.Extent()); // Allocate the list of ids - if (aDataArray.GetPointer() != NULL) + const vtkIdType aSize = aDataArray.GetPointer() != NULL ? aDataArray->GetNumberOfTuples() : 0; + if (aSize != 0) { - aSize = aDataArray->GetNumberOfTuples(); anIdList->Allocate (aSize); // Allocate the list of ids } @@ -100,39 +178,41 @@ int IVtkTools_SubPolyDataFilter::RequestData (vtkInformation *vtkNotUsed(theRequ } // Copy cells with their points according to the prepared list of cell ids. - anOutput->GetCellData()->AllocateArrays(anInput->GetCellData()->GetNumberOfArrays()); - anOutput->Allocate(anInput, anIdList->GetNumberOfIds()); // Allocate output cells + anOutputCellData->AllocateArrays (anInputCellData->GetNumberOfArrays()); + anOutput->Allocate (anInput, anIdList->GetNumberOfIds()); // Allocate output cells + // Pass data arrays. // Create new arrays for output data - vtkSmartPointer anInData = anInput->GetCellData(); - vtkSmartPointer anOutData = anOutput->GetCellData(); - vtkSmartPointer anInArr, anOutArr; - - for (Standard_Integer anI = 0; anI < anInData->GetNumberOfArrays(); anI++) + for (Standard_Integer anI = 0; anI < anInputCellData->GetNumberOfArrays(); anI++) { - anInArr = anInData->GetArray (anI); - anOutArr = vtkSmartPointer::Take( - vtkDataArray::CreateDataArray(anInArr->GetDataType())); - anOutArr->SetName(anInArr->GetName()); - anOutArr->Allocate(anIdList->GetNumberOfIds() * anInArr->GetNumberOfComponents()); + vtkSmartPointer anInArr = anInputCellData->GetArray (anI); + vtkSmartPointer anOutArr = vtkSmartPointer::Take (vtkDataArray::CreateDataArray(anInArr->GetDataType())); + + anOutArr->SetName (anInArr->GetName()); + anOutArr->Allocate (anIdList->GetNumberOfIds() * anInArr->GetNumberOfComponents()); anOutArr->SetNumberOfTuples (anIdList->GetNumberOfIds()); anOutArr->SetNumberOfComponents (anInArr->GetNumberOfComponents()); - anOutData->AddArray(anOutArr); + anOutputCellData->AddArray (anOutArr); } // Copy cells with ids from our list. - anOutput->CopyCells (anInput, anIdList); + if (myToCopyNormals) + { + copyCells (anOutput, anInput, anIdList); + } + else + { + anOutput->CopyCells (anInput, anIdList); + } // Copy filtered arrays data - vtkIdType anOutId, anInId; - - for (Standard_Integer anI = 0; anI < anInData->GetNumberOfArrays(); anI++) + for (Standard_Integer anI = 0; anI < anInputCellData->GetNumberOfArrays(); anI++) { - anInArr = anInData->GetArray (anI); - anOutArr = anOutData->GetArray(anI); - for (anOutId = 0; anOutId < anIdList->GetNumberOfIds(); anOutId++) + vtkSmartPointer anInArr = anInputCellData ->GetArray (anI); + vtkSmartPointer anOutArr = anOutputCellData->GetArray (anI); + for (vtkIdType anOutId = 0; anOutId < anIdList->GetNumberOfIds(); anOutId++) { - anInId = anIdList->GetId (anOutId); + const vtkIdType anInId = anIdList->GetId (anOutId); anOutArr->SetTuple (anOutId, anInId, anInArr); } } @@ -148,7 +228,7 @@ int IVtkTools_SubPolyDataFilter::RequestData (vtkInformation *vtkNotUsed(theRequ //================================================================ // Function : SetDoFiltering -// Purpose : +// Purpose : //================================================================ void IVtkTools_SubPolyDataFilter::SetDoFiltering (const bool theDoFiltering) { @@ -169,12 +249,12 @@ void IVtkTools_SubPolyDataFilter::PrintSelf (std::ostream& theOs, vtkIndent theI IVtk_IdTypeMap::Iterator anIter(myIdsSet); while (anIter.More()) { - theOs << " " << anIter.Value(); - anIter.Next(); - if (anIter.More()) - { - theOs << "; "; - } + theOs << " " << anIter.Value(); + anIter.Next(); + if (anIter.More()) + { + theOs << "; "; + } } theOs << "}" << "\n"; } @@ -203,8 +283,7 @@ void IVtkTools_SubPolyDataFilter::SetData (const IVtk_IdTypeMap theSet) //================================================================ void IVtkTools_SubPolyDataFilter::AddData (const IVtk_IdTypeMap theSet) { - IVtk_IdTypeMap::Iterator anIt (theSet); - for (; anIt.More(); anIt.Next()) + for (IVtk_IdTypeMap::Iterator anIt (theSet); anIt.More(); anIt.Next()) { if (!myIdsSet.Contains (anIt.Value())) { @@ -229,8 +308,7 @@ void IVtkTools_SubPolyDataFilter::SetData (const IVtk_ShapeIdList theIdList) //================================================================ void IVtkTools_SubPolyDataFilter::AddData (const IVtk_ShapeIdList theIdList) { - IVtk_ShapeIdList::Iterator anIt (theIdList); - for (; anIt.More(); anIt.Next()) + for (IVtk_ShapeIdList::Iterator anIt (theIdList); anIt.More(); anIt.Next()) { if (!myIdsSet.Contains (anIt.Value())) { @@ -239,10 +317,9 @@ void IVtkTools_SubPolyDataFilter::AddData (const IVtk_ShapeIdList theIdList) } } -//! Set ids to be passed through this filter. //================================================================ // Function : SetIdsArrayName -// Purpose : +// Purpose : //================================================================ void IVtkTools_SubPolyDataFilter::SetIdsArrayName (const char* theArrayName) { diff --git a/src/IVtkTools/IVtkTools_SubPolyDataFilter.hxx b/src/IVtkTools/IVtkTools_SubPolyDataFilter.hxx index 1ea839c5ad..709f08823d 100644 --- a/src/IVtkTools/IVtkTools_SubPolyDataFilter.hxx +++ b/src/IVtkTools/IVtkTools_SubPolyDataFilter.hxx @@ -70,6 +70,7 @@ protected: IVtk_IdTypeMap myIdsSet; const char* myIdsArrayName; bool myDoFiltering; + bool myToCopyNormals; }; #ifdef _MSC_VER diff --git a/src/IVtkVTK/IVtkVTK_ShapeData.cxx b/src/IVtkVTK/IVtkVTK_ShapeData.cxx index e647fd8df8..90387972f2 100644 --- a/src/IVtkVTK/IVtkVTK_ShapeData.cxx +++ b/src/IVtkVTK/IVtkVTK_ShapeData.cxx @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -28,7 +30,7 @@ IMPLEMENT_STANDARD_RTTIEXT(IVtkVTK_ShapeData,IVtk_IShapeData) //================================================================ // Function : Constructor -// Purpose : +// Purpose : //================================================================ IVtkVTK_ShapeData::IVtkVTK_ShapeData() { @@ -36,6 +38,11 @@ IVtkVTK_ShapeData::IVtkVTK_ShapeData() myPolyData->Allocate(); myPolyData->SetPoints (vtkSmartPointer::New()); + myNormals = vtkSmartPointer::New(); + myNormals->SetName ("Normals"); + myNormals->SetNumberOfComponents (3); + myPolyData->GetPointData()->SetNormals (myNormals); + mySubShapeIDs = vtkSmartPointer::New(); mySubShapeIDs->SetName (IVtkVTK_ShapeData::ARRNAME_SUBSHAPE_IDS()); mySubShapeIDs->SetNumberOfComponents (1); @@ -49,25 +56,29 @@ IVtkVTK_ShapeData::IVtkVTK_ShapeData() //================================================================ // Function : Destructor -// Purpose : +// Purpose : //================================================================ IVtkVTK_ShapeData::~IVtkVTK_ShapeData() { } //================================================================ -// Function : InsertCoordinate -// Purpose : +// Function : InsertPoint +// Purpose : //================================================================ -IVtk_PointId IVtkVTK_ShapeData::InsertCoordinate (double theX, - double theY, - double theZ) +IVtk_PointId IVtkVTK_ShapeData::InsertPoint (const gp_Pnt& thePnt, + const NCollection_Vec3& theNorm) { - return myPolyData->GetPoints()->InsertNextPoint (theX, theY, theZ); + IVtk_PointId aPointId = myPolyData->GetPoints()->InsertNextPoint (thePnt.X(), thePnt.Y(), thePnt.Z()); + if (myNormals.GetPointer() != NULL) + { + myNormals->InsertNextTuple (theNorm.GetData()); + } + return aPointId; } //================================================================ // Function : InsertVertex -// Purpose : +// Purpose : //================================================================ void IVtkVTK_ShapeData::InsertVertex (const IVtk_IdType theShapeID, const IVtk_PointId thePointId, @@ -80,7 +91,7 @@ void IVtkVTK_ShapeData::InsertVertex (const IVtk_IdType theShapeID, //================================================================ // Function : InsertLine -// Purpose : +// Purpose : //================================================================ void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID, const IVtk_PointId thePointId1, @@ -94,7 +105,7 @@ void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID, //================================================================ // Function : InsertLine -// Purpose : +// Purpose : //================================================================ void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID, const IVtk_PointIdList* thePointIds, @@ -119,7 +130,7 @@ void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID, //================================================================ // Function : InsertTriangle -// Purpose : +// Purpose : //================================================================ void IVtkVTK_ShapeData::InsertTriangle (const IVtk_IdType theShapeID, const IVtk_PointId thePointId1, diff --git a/src/IVtkVTK/IVtkVTK_ShapeData.hxx b/src/IVtkVTK/IVtkVTK_ShapeData.hxx index 0fda1748ab..a12d245885 100644 --- a/src/IVtkVTK/IVtkVTK_ShapeData.hxx +++ b/src/IVtkVTK/IVtkVTK_ShapeData.hxx @@ -16,6 +16,8 @@ #ifndef __IVTKVTK_SHAPEDATA_H__ #define __IVTKVTK_SHAPEDATA_H__ +#include +#include #include // prevent disabling some MSVC warning messages by VTK headers @@ -26,6 +28,7 @@ #include class vtkIdTypeArray; +class vtkFloatArray; class IVtkVTK_ShapeData; DEFINE_STANDARD_HANDLE( IVtkVTK_ShapeData, IVtk_IShapeData ) @@ -51,11 +54,11 @@ public: DEFINE_STANDARD_RTTIEXT(IVtkVTK_ShapeData,IVtk_IShapeData) //! Insert a coordinate - //! @param [in] theX X coordinate - //! @param [in] theY Y coordinate - //! @param [in] theZ Z coordinate + //! @param [in] thePnt point position + //! @param [in] theNorm point normal //! @return id of added point - Standard_EXPORT virtual IVtk_PointId InsertCoordinate (double theX, double theY, double theZ) Standard_OVERRIDE; + Standard_EXPORT virtual IVtk_PointId InsertPoint (const gp_Pnt& thePnt, + const NCollection_Vec3& theNorm) Standard_OVERRIDE; //! Insert a vertex. //! @param [in] theShapeID id of the subshape to which the vertex belongs. @@ -121,6 +124,7 @@ private: private: vtkSmartPointer< vtkPolyData > myPolyData; //!< Shape geometry as vtkPolyData + vtkSmartPointer< vtkFloatArray > myNormals; //!< vertex normals vtkSmartPointer< vtkIdTypeArray > mySubShapeIDs; //!< Array of sub-shapes ids vtkSmartPointer< vtkIdTypeArray > myMeshTypes; //!< Array of type codes of mesh parts }; diff --git a/tests/vtk/ivtk/boundary_draw b/tests/vtk/ivtk/boundary_draw index 986bae04f1..a4cf453dd2 100644 --- a/tests/vtk/ivtk/boundary_draw +++ b/tests/vtk/ivtk/boundary_draw @@ -7,9 +7,8 @@ pload MODELING VIS box b 1 1 1 ivtkinit ivtkdisplay b -ivtksetdispmode 1 -ivtksetboundingdraw 1 -ivtkdump $imagedir/${casename}_1.png - -ivtksetboundingdraw 0 +ivtksetdispmode 1 -faceBoundaryDraw 0 -smoothShading 1 ivtkdump $imagedir/${casename}_2.png + +ivtksetdispmode 1 -faceBoundaryDraw 1 -smoothShading 0 +ivtkdump $imagedir/${casename}_1.png diff --git a/tests/vtk/ivtk/seam_edges b/tests/vtk/ivtk/seam_edges index dd6c9034aa..607a57a147 100644 --- a/tests/vtk/ivtk/seam_edges +++ b/tests/vtk/ivtk/seam_edges @@ -7,7 +7,8 @@ pload MODELING VIS psphere s 10 15 80 ivtkinit ivtkdisplay s -ivtksetdispmode 1 -ivtksetboundingdraw 1 - +ivtksetdispmode 1 -faceBoundaryDraw 1 -smoothShading 0 ivtkdump $imagedir/${casename}.png + +ivtksetdispmode 1 -faceBoundaryDraw 1 -smoothShading 1 +ivtkdump $imagedir/${casename}_smooth.png