/*========================================================================= Program: Visualization Toolkit Module: vtkPolyDataMapperNode.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkPolyDataMapperNode.h" #include "vtkActor.h" #include "vtkCellArray.h" #include "vtkMath.h" #include "vtkMatrix4x4.h" #include "vtkObjectFactory.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkPolygon.h" #include "vtkProperty.h" //============================================================================ vtkStandardNewMacro(vtkPolyDataMapperNode); //------------------------------------------------------------------------------ vtkPolyDataMapperNode::vtkPolyDataMapperNode() = default; //------------------------------------------------------------------------------ vtkPolyDataMapperNode::~vtkPolyDataMapperNode() = default; //------------------------------------------------------------------------------ void vtkPolyDataMapperNode::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //------------------------------------------------------------------------------ void vtkPolyDataMapperNode::TransformPoints( vtkActor* act, vtkPolyData* poly, std::vector& _vertices) { vtkSmartPointer m = vtkSmartPointer::New(); act->GetMatrix(m); bool ident = (act->GetIsIdentity() == 1); double inPos[4]; inPos[3] = 1.0; double transPos[4]; for (int i = 0; i < poly->GetNumberOfPoints(); i++) { double* pos = poly->GetPoints()->GetPoint(i); bool wasNan = false; int fixIndex = i - 1; do { wasNan = false; for (int j = 0; j < 3; j++) { if (vtkMath::IsNan(pos[j])) { wasNan = true; } } if (wasNan && fixIndex >= 0) { pos = poly->GetPoints()->GetPoint(fixIndex--); } } while (wasNan && fixIndex >= 0); if (ident) { _vertices.push_back(pos[0]); _vertices.push_back(pos[1]); _vertices.push_back(pos[2]); } else { inPos[0] = pos[0]; inPos[1] = pos[1]; inPos[2] = pos[2]; m->MultiplyPoint(inPos, transPos); // alternatively use an OSPRay instance of something like that _vertices.push_back(transPos[0]); _vertices.push_back(transPos[1]); _vertices.push_back(transPos[2]); } } } namespace { // Helpers for MakeConnectivity() // The CreateXIndexBuffer's were adapted from vtkOpenGLIndexBufferObject. // Apply rule of three if made again somewhere in VTK. //------------------------------------------------------------------------------ // Description: // Homogenizes everything into a flat list of point indexes. // At same time creates a reverse cell index array for obtaining cell quantities for points void CreatePointIndexBuffer(vtkCellArray* cells, std::vector& indexArray, std::vector& reverseArray) { // TODO: restore the preallocate and append to offset features I omitted const vtkIdType* indices(nullptr); vtkIdType npts(0); if (!cells->GetNumberOfCells()) { return; } unsigned int cell_id = 0; for (cells->InitTraversal(); cells->GetNextCell(npts, indices);) { for (int i = 0; i < npts; ++i) { indexArray.push_back(static_cast(*(indices++))); reverseArray.push_back(cell_id); } cell_id++; } } //------------------------------------------------------------------------------ // Description: // Homogenizes lines into a flat list of line segments, each containing two point indexes // At same time creates a reverse cell index array for obtaining cell quantities for points void CreateLineIndexBuffer(vtkCellArray* cells, std::vector& indexArray, std::vector& reverseArray) { // TODO: restore the preallocate and append to offset features I omitted const vtkIdType* indices(nullptr); vtkIdType npts(0); if (!cells->GetNumberOfCells()) { return; } unsigned int cell_id = 0; for (cells->InitTraversal(); cells->GetNextCell(npts, indices);) { for (int i = 0; i < npts - 1; ++i) { indexArray.push_back(static_cast(indices[i])); indexArray.push_back(static_cast(indices[i + 1])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } cell_id++; } } //------------------------------------------------------------------------------ // Description: // Homogenizes polygons into a flat list of line segments, each containing two point indexes. // At same time creates a reverse cell index array for obtaining cell quantities for points // This differs from CreateLineIndexBuffer in that it closes loops, making a segment from last point // back to first. void CreateTriangleLineIndexBuffer(vtkCellArray* cells, std::vector& indexArray, std::vector& reverseArray) { // TODO: restore the preallocate and append to offset features I omitted const vtkIdType* indices(nullptr); vtkIdType npts(0); if (!cells->GetNumberOfCells()) { return; } unsigned int cell_id = 0; for (cells->InitTraversal(); cells->GetNextCell(npts, indices);) { for (int i = 0; i < npts; ++i) { indexArray.push_back(static_cast(indices[i])); indexArray.push_back(static_cast(indices[i < npts - 1 ? i + 1 : 0])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } cell_id++; } } //------------------------------------------------------------------------------ // Description: // Homogenizes polygons into a flat list of triangles, each containing three point indexes // At same time creates a reverse cell index array for obtaining cell quantities for points void CreateTriangleIndexBuffer(vtkCellArray* cells, vtkPoints* points, std::vector& indexArray, std::vector& reverseArray) { // TODO: restore the preallocate and append to offset features I omitted const vtkIdType* indices(nullptr); vtkIdType npts(0); if (!cells->GetNumberOfCells()) { return; } unsigned int cell_id = 0; // the following are only used if we have to triangulate a polygon // otherwise they just sit at nullptr vtkPolygon* polygon = nullptr; vtkIdList* tris = nullptr; vtkPoints* triPoints = nullptr; for (cells->InitTraversal(); cells->GetNextCell(npts, indices);) { // ignore degenerate triangles if (npts < 3) { cell_id++; continue; } // triangulate needed if (npts > 3) { // special case for quads, penta, hex which are common if (npts == 4) { indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[1])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[3])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } else if (npts == 5) { indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[1])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[3])); indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[3])); indexArray.push_back(static_cast(indices[4])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } else if (npts == 6) { indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[1])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[2])); indexArray.push_back(static_cast(indices[3])); indexArray.push_back(static_cast(indices[0])); indexArray.push_back(static_cast(indices[3])); indexArray.push_back(static_cast(indices[5])); indexArray.push_back(static_cast(indices[3])); indexArray.push_back(static_cast(indices[4])); indexArray.push_back(static_cast(indices[5])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } else // 7 sided polygon or higher, do a full smart triangulation { if (!polygon) { polygon = vtkPolygon::New(); tris = vtkIdList::New(); triPoints = vtkPoints::New(); } vtkIdType* triIndices = new vtkIdType[npts]; triPoints->SetNumberOfPoints(npts); for (int i = 0; i < npts; ++i) { int idx = indices[i]; triPoints->SetPoint(i, points->GetPoint(idx)); triIndices[i] = i; } polygon->Initialize(npts, triIndices, triPoints); polygon->Triangulate(tris); for (int j = 0; j < tris->GetNumberOfIds(); ++j) { indexArray.push_back(static_cast(indices[tris->GetId(j)])); reverseArray.push_back(cell_id); } delete[] triIndices; } } else { indexArray.push_back(static_cast(*(indices++))); indexArray.push_back(static_cast(*(indices++))); indexArray.push_back(static_cast(*(indices++))); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } cell_id++; } if (polygon) { polygon->Delete(); tris->Delete(); triPoints->Delete(); } } //------------------------------------------------------------------------------ // Description: // Homogenizes triangle strips. // Depending on wireframeTriStrips it will produce either line segments (two indices per edge) // or triangles (three indices per face). // At same time creates a reverse cell index array for obtaining cell quantities for points void CreateStripIndexBuffer(vtkCellArray* cells, std::vector& indexArray, std::vector& reverseArray, bool wireframeTriStrips) { if (!cells->GetNumberOfCells()) { return; } unsigned int cell_id = 0; const vtkIdType* pts = nullptr; vtkIdType npts = 0; size_t triCount = cells->GetNumberOfConnectivityIds() - 2 * cells->GetNumberOfCells(); size_t targetSize = wireframeTriStrips ? 2 * (triCount * 2 + 1) : triCount * 3; indexArray.reserve(targetSize); if (wireframeTriStrips) { for (cells->InitTraversal(); cells->GetNextCell(npts, pts);) { indexArray.push_back(static_cast(pts[0])); indexArray.push_back(static_cast(pts[1])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); for (int j = 0; j < npts - 2; ++j) { indexArray.push_back(static_cast(pts[j])); indexArray.push_back(static_cast(pts[j + 2])); indexArray.push_back(static_cast(pts[j + 1])); indexArray.push_back(static_cast(pts[j + 2])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } cell_id++; } } else { for (cells->InitTraversal(); cells->GetNextCell(npts, pts);) { for (int j = 0; j < npts - 2; ++j) { indexArray.push_back(static_cast(pts[j])); indexArray.push_back(static_cast(pts[j + 1 + j % 2])); indexArray.push_back(static_cast(pts[j + 1 + (j + 1) % 2])); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); reverseArray.push_back(cell_id); } cell_id++; } } } } //------------------------------------------------------------------------------ void vtkPolyDataMapperNode::MakeConnectivity( vtkPolyData* poly, int representation, vtkPDConnectivity& conn) { vtkCellArray* prims[4]; prims[0] = poly->GetVerts(); prims[1] = poly->GetLines(); prims[2] = poly->GetPolys(); prims[3] = poly->GetStrips(); CreatePointIndexBuffer(prims[0], conn.vertex_index, conn.vertex_reverse); switch (representation) { case VTK_POINTS: { CreatePointIndexBuffer(prims[1], conn.line_index, conn.line_reverse); CreatePointIndexBuffer(prims[2], conn.triangle_index, conn.triangle_reverse); CreatePointIndexBuffer(prims[3], conn.strip_index, conn.strip_reverse); break; } case VTK_WIREFRAME: { CreateLineIndexBuffer(prims[1], conn.line_index, conn.line_reverse); CreateTriangleLineIndexBuffer(prims[2], conn.triangle_index, conn.triangle_reverse); CreateStripIndexBuffer(prims[3], conn.strip_index, conn.strip_reverse, true); break; } default: { CreateLineIndexBuffer(prims[1], conn.line_index, conn.line_reverse); CreateTriangleIndexBuffer( prims[2], poly->GetPoints(), conn.triangle_index, conn.triangle_reverse); CreateStripIndexBuffer(prims[3], conn.strip_index, conn.strip_reverse, false); } } }