IVtk_IShapeData::InsertCoordinate() has been replaced by IVtk_IShapeData::InsertPoint()
defining vertex position with surface normal.
IVtkVTK_ShapeData now allocates normals array within vtkPolyData.
IVtkOCC_ShapeMesher now fills in vertex positions with surfcae normals.
IVtkTools_SubPolyDataFilter has been corrected to optionally copy normals.
ivtksetboundingdraw command has been merged into "ivtksetdispmode -faceBoundaryDraw".
#ifndef __IVTK_ISHAPEDATA_H__
#define __IVTK_ISHAPEDATA_H__
+#include <gp_Pnt.hxx>
#include <IVtk_Interface.hxx>
#include <IVtk_Types.hxx>
+#include <NCollection_Vec3.hxx>
-class IVtk_IShapeData;
DEFINE_STANDARD_HANDLE( IVtk_IShapeData, IVtk_Interface )
//! @class IVtk_IShapeData
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<float>& theNorm) = 0;
//! Insert a vertex.
//! @param [in] theShapeID id of the sub-shape to which the vertex belongs.
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<float>(0.0f, 0.0f, 1.0f));
+ }
+
};
#endif // __IVTK_ISHAPEDATA_H__
Handle(PipelinePtr) aPL = new PipelinePtr (theShape, theId, GetDefaultDrawer());
GetPipelines()->Bind (theId, aPL);
+ aPL->Actor()->GetProperty()->SetInterpolationToPhong();
return aPL->Actor();
}
//================================================================
// 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<vtkActor> > 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<vtkActor> 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())
- {
- IVtkTools_DisplayModeFilter* aFilter = GetPipeline ( anOccShape->GetId() )->GetDisplayModeFilter();
- aFilter->SetDisplayMode((IVtk_DisplayMode)aMode);
- aFilter->Modified();
- aFilter->Update();
- }
+ 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;
}
- anIter.Next();
}
- }
- // Set disp mode for named object
- else
- {
- TCollection_AsciiString aName = theArgs[1];
- vtkSmartPointer<vtkActor> anActor;
- if (!GetMapOfActors().Find2 (aName, anActor))
+ else if (aDispMode == -1
+ && (anArgCase == "0"
+ || anArgCase == "1"))
{
- Message::SendFail() << "Syntax error: object '" << aName << "' not found";
- return 1;
+ aDispMode = Draw::Atoi (theArgs[anArgIter]);
}
-
- Standard_Integer aMode = atoi(theArgs[2]);
- vtkSmartPointer<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
- if (aSrc)
+ else if (aDispMode == -1
+ && (anArgCase == "-shaded"
+ || anArgCase == "-shading"))
+ {
+ aDispMode = DM_Shading;
+ }
+ else if (aDispMode == -1
+ && anArgCase == "-wireframe")
{
- IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
- if (!anOccShape.IsNull())
+ aDispMode = DM_Wireframe;
+ }
+ else
+ {
+ TCollection_AsciiString aName = theArgs[anArgIter];
+ vtkSmartPointer<vtkActor> anActor;
+ if (!GetMapOfActors().Find2 (aName, anActor))
{
- IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter();
- aFilter->SetDisplayMode ((IVtk_DisplayMode)aMode);
- aFilter->Modified();
- aFilter->Update();
+ theDI << "Syntax error: object '" << aName << "' not found";
+ return 1;
}
+ anActors.Append (anActor);
}
}
-
- // 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())
+ if (aDispMode == -1)
{
- Message::SendFail() << "Error: call ivtkinit before";
- return 1;
- }
- else if (theArgNum != 2 && theArgNum != 3)
- {
- Message::SendFail() << "Syntax error: expects 1 or 2 arguments";
+ theDI << "Syntax error: wrong number of arguments";
return 1;
}
- if (theArgNum == 2)
+ if (anActors.IsEmpty())
{
- // Set disp mode for all objects
- Standard_Boolean toDraw = true;
- Draw::ParseOnOff (theArgs[1], toDraw);
- DoubleMapOfActorsAndNames::Iterator anIter(GetMapOfActors());
- while (anIter.More())
+ // update all objects
+ for (DoubleMapOfActorsAndNames::Iterator anIter (GetMapOfActors()); anIter.More(); anIter.Next())
{
- vtkSmartPointer<vtkActor> 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())
- {
- IVtkTools_DisplayModeFilter* aFilter = GetPipeline(anOccShape->GetId())->GetDisplayModeFilter();
- aFilter->SetDisplayMode(DM_Shading);
- aFilter->SetFaceBoundaryDraw(toDraw != 0);
- aFilter->Modified();
- aFilter->Update();
- }
- }
- anIter.Next();
+ anActors.Append (anIter.Key1());
}
}
- else
+
+ for (NCollection_Sequence< vtkSmartPointer<vtkActor> >::Iterator anActorIter (anActors); anActorIter.More(); anActorIter.Next())
{
- // Set disp mode for named object
- TCollection_AsciiString aName = theArgs[1];
- vtkSmartPointer<vtkActor> anActor;
- if (!GetMapOfActors().Find2 (aName, anActor))
+ vtkSmartPointer<vtkActor> anActor = anActorIter.Value();
+ IVtkTools_ShapeDataSource* aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
+ if (aSrc == NULL)
{
- Message::SendFail() << "Syntax error: object '" << aName << "' not found";
- return 1;
+ continue;
}
- 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<IVtkTools_ShapeDataSource> aSrc = IVtkTools_ShapeObject::GetShapeSource (anActor);
- if (aSrc)
+ IVtkOCC_Shape::Handle anOccShape = aSrc->GetShape();
+ if (!anOccShape.IsNull())
{
- 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)
{
- IVtkTools_DisplayModeFilter* aFilter = GetPipeline (anOccShape->GetId())->GetDisplayModeFilter();
- aFilter->SetDisplayMode (DM_Shading);
- aFilter->SetFaceBoundaryDraw (toDraw != 0);
- aFilter->Modified();
- aFilter->Update();
+ aFilter->SetSmoothShading (isSmoothShading == 1);
}
+ switch (aShadingModel)
+ {
+ case Graphic3d_TOSM_FACET:
+ {
+ anActor->GetProperty()->SetInterpolationToFlat();
+ break;
+ }
+ case Graphic3d_TOSM_VERTEX:
+ {
+ anActor->GetProperty()->SetInterpolationToGouraud();
+ break;
+ }
+ case Graphic3d_TOSM_FRAGMENT:
+ {
+ anActor->GetProperty()->SetInterpolationToPhong();
+ break;
+ }
+ default: break;
+ }
+
+ aFilter->Modified();
+ aFilter->Update();
}
}
__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'"
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.
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 :
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())
- {
+ 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);
+ gp_Dir aNorm = aTriangulation->HasNormals() ? aTriangulation->Normal (aPntId) : gp::DZ();
+ if (hasTransform)
+ {
+ aPoint.Transform (aTrsf);
+ aNorm .Transform (aTrsf);
+ }
+
+ 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;
}
- // Handle a non-identity transformation applied to the edge
- gp_Trsf anEdgeTransf;
- bool noTransform = true;
- if (!aLocation.IsIdentity())
+ // try polygon 3d
+ Handle(Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D (theEdge, aLoc);
+ if (aPoly3d.IsNull()
+ || aPoly3d->NbNodes() < 2)
{
- noTransform = false;
- anEdgeTransf = aLocation.Transformation();
+ return;
}
- if (!aPoly3d.IsNull())
+ const gp_Trsf anEdgeTransf = aLoc.Transformation();
+ const bool noTransform = aLoc.IsIdentity();
+ IVtk_PointIdList aPolyPointIds;
+ for (Standard_Integer aNodeIter = 1; aNodeIter <= aPoly3d->NbNodes(); ++aNodeIter)
{
- Standard_Integer aNbNodes = aPoly3d->NbNodes();
- const TColgp_Array1OfPnt& aPoints = aPoly3d->Nodes();
- TColStd_Array1OfInteger aPointIds (1, aNbNodes);
-
- for (Standard_Integer anI = 1; anI <= aNbNodes; anI++)
+ gp_Pnt aPnt = aPoly3d->Nodes().Value (aNodeIter);
+ if (!noTransform)
{
- aPointIds.SetValue (anI, anI);
+ aPnt.Transform (anEdgeTransf);
}
- 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); }
-
- IVtk_PointId anId = myShapeData->InsertCoordinate (aPoint.X(), aPoint.Y(), aPoint.Z());
- aPolyPointIds.Append (anId);
- }
- myShapeData->InsertLine (theShapeId, &aPolyPointIds, theMeshType);
+ const IVtk_PointId anId = myShapeData->InsertCoordinate (aPnt);
+ aPolyPointIds.Append (anId);
}
+ myShapeData->InsertLine (theShapeId, &aPolyPointIds, theMeshType);
}
//================================================================
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())
{
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);
}
return;
}
- // Build triangulation of the face.
TopLoc_Location aLoc;
const Handle(Poly_Triangulation)& anOcctTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
if (anOcctTriangulation.IsNull())
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();
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);
}
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);
}
}
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;
// 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();
vtkInformationVector *theOutputVector)
{
SetData (myModesDefinition[myDisplayMode]);
+ myToCopyNormals = myIsSmoothShading && (myDisplayMode == DM_Shading);
return Superclass::RequestData (theRequest, theInputVector, theOutputVector);
}
}
Modified();
}
+
+//============================================================================
+// Method: SetSmoothShading
+// Purpose:
+//============================================================================
+void IVtkTools_DisplayModeFilter::SetSmoothShading (bool theIsSmooth)
+{
+ if (myIsSmoothShading != theIsSmooth)
+ {
+ myIsSmoothShading = theIsSmooth;
+ Modified();
+ }
+}
//! 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;
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
#pragma warning(push)
#endif
#include <vtkCellData.h>
+#include <vtkFloatArray.h>
+#include <vtkGenericCell.h>
#include <vtkIdList.h>
#include <vtkIdTypeArray.h>
#include <vtkInformation.h>
#include <vtkInformationVector.h>
#include <vtkObjectFactory.h>
+#include <vtkPointData.h>
#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<vtkPoints>::New());
+ }
+
+ vtkSmartPointer<vtkIdList> aNewCellPts = vtkSmartPointer<vtkIdList>::New();
+ vtkSmartPointer<vtkGenericCell> aCell = vtkSmartPointer<vtkGenericCell>::New();
+ NCollection_Vec3<double> anXYZ;
+ vtkPointData* aNewPntData = theDst->GetPointData();
+ vtkCellData* aNewCellData = theDst->GetCellData();
+ vtkPoints* aNewPoints = theDst->GetPoints();
+ vtkSmartPointer<vtkFloatArray> aNewNormals;
+ if (anOldNormals != NULL)
+ {
+ aNewNormals = vtkSmartPointer<vtkFloatArray>::New();
+ aNewNormals->SetName ("Normals");
+ aNewNormals->SetNumberOfComponents (3);
+ theDst->GetPointData()->SetNormals (aNewNormals);
+ }
+
+ vtkSmartPointer<vtkIdList> aPntMap = vtkSmartPointer<vtkIdList>::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() { }
if (myDoFiltering)
{
- vtkSmartPointer<vtkCellData> aCellData = anInput->GetCellData();
- vtkIdType aSize = 0;
- vtkSmartPointer<vtkIdTypeArray> aDataArray =
- vtkIdTypeArray::SafeDownCast (aCellData->GetArray (myIdsArrayName));
+ vtkSmartPointer<vtkCellData> anInputCellData = anInput->GetCellData();
+ vtkSmartPointer<vtkCellData> anOutputCellData = anOutput->GetCellData();
+ vtkSmartPointer<vtkIdTypeArray> aDataArray = vtkIdTypeArray::SafeDownCast (anInputCellData->GetArray (myIdsArrayName));
// List of cell ids to be passed
vtkSmartPointer<vtkIdList> anIdList = vtkSmartPointer<vtkIdList>::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
}
}
// 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<vtkCellData> anInData = anInput->GetCellData();
- vtkSmartPointer<vtkCellData> anOutData = anOutput->GetCellData();
- vtkSmartPointer<vtkDataArray> 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<vtkDataArray>::Take(
- vtkDataArray::CreateDataArray(anInArr->GetDataType()));
- anOutArr->SetName(anInArr->GetName());
- anOutArr->Allocate(anIdList->GetNumberOfIds() * anInArr->GetNumberOfComponents());
+ vtkSmartPointer<vtkDataArray> anInArr = anInputCellData->GetArray (anI);
+ vtkSmartPointer<vtkDataArray> anOutArr = vtkSmartPointer<vtkDataArray>::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<vtkDataArray> anInArr = anInputCellData ->GetArray (anI);
+ vtkSmartPointer<vtkDataArray> 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);
}
}
//================================================================
// Function : SetDoFiltering
-// Purpose :
+// Purpose :
//================================================================
void IVtkTools_SubPolyDataFilter::SetDoFiltering (const bool theDoFiltering)
{
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";
}
//================================================================
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()))
{
//================================================================
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()))
{
}
}
-//! Set ids to be passed through this filter.
//================================================================
// Function : SetIdsArrayName
-// Purpose :
+// Purpose :
//================================================================
void IVtkTools_SubPolyDataFilter::SetIdsArrayName (const char* theArrayName)
{
IVtk_IdTypeMap myIdsSet;
const char* myIdsArrayName;
bool myDoFiltering;
+ bool myToCopyNormals;
};
#ifdef _MSC_VER
#include <Standard_WarningsDisable.hxx>
#include <vtkCellData.h>
#include <vtkDoubleArray.h>
+#include <vtkFloatArray.h>
#include <vtkIdList.h>
+#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <Standard_WarningsRestore.hxx>
//================================================================
// Function : Constructor
-// Purpose :
+// Purpose :
//================================================================
IVtkVTK_ShapeData::IVtkVTK_ShapeData()
{
myPolyData->Allocate();
myPolyData->SetPoints (vtkSmartPointer<vtkPoints>::New());
+ myNormals = vtkSmartPointer<vtkFloatArray>::New();
+ myNormals->SetName ("Normals");
+ myNormals->SetNumberOfComponents (3);
+ myPolyData->GetPointData()->SetNormals (myNormals);
+
mySubShapeIDs = vtkSmartPointer<vtkIdTypeArray>::New();
mySubShapeIDs->SetName (IVtkVTK_ShapeData::ARRNAME_SUBSHAPE_IDS());
mySubShapeIDs->SetNumberOfComponents (1);
//================================================================
// 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<float>& 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,
//================================================================
// Function : InsertLine
-// Purpose :
+// Purpose :
//================================================================
void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID,
const IVtk_PointId thePointId1,
//================================================================
// Function : InsertLine
-// Purpose :
+// Purpose :
//================================================================
void IVtkVTK_ShapeData::InsertLine (const IVtk_IdType theShapeID,
const IVtk_PointIdList* thePointIds,
//================================================================
// Function : InsertTriangle
-// Purpose :
+// Purpose :
//================================================================
void IVtkVTK_ShapeData::InsertTriangle (const IVtk_IdType theShapeID,
const IVtk_PointId thePointId1,
#ifndef __IVTKVTK_SHAPEDATA_H__
#define __IVTKVTK_SHAPEDATA_H__
+#include <gp_Dir.hxx>
+#include <gp_Pnt.hxx>
#include <IVtk_IShapeData.hxx>
// prevent disabling some MSVC warning messages by VTK headers
#include <Standard_WarningsRestore.hxx>
class vtkIdTypeArray;
+class vtkFloatArray;
class IVtkVTK_ShapeData;
DEFINE_STANDARD_HANDLE( IVtkVTK_ShapeData, IVtk_IShapeData )
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<float>& theNorm) Standard_OVERRIDE;
//! Insert a vertex.
//! @param [in] theShapeID id of the subshape to which the vertex belongs.
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
};
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
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