VTK Learning Eighteen - Subvision
Description
vtkLinearSubdivisionFilter
vtkLinearSubdivisionFilter is a filter that generates output by
subdividing its input polydata. Each subdivision iteration create 4
new triangles for each triangle in the polydata.
每一次迭代一個三角形將創建四個新的三角形。一種線性直接細分的方法,即簡單的線性插值,不能達到平滑的效果。
vtkLoopSubdivisionFilter
vtkLoopSubdivisionFilter is an approximating subdivision scheme that
creates four new triangles for each triangle in the mesh.
每次細分一個三角形將創建四個新的三角形。一種近似逼近的細分方法,平滑效果好,結果不過原始點。
vtkButterflySubdivisionFilter
vtkButterflySubdivisionFilter is an interpolating subdivision scheme
that creates four new triangles for each triangle in the mesh.
每一次迭代一個三角形將創建四個新的三角形。一種較複雜的插值細分方法,平滑效果較好。
Code
#include <vtkSmartPointer.h>
#include <vtkCellData.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkPoints.h>
#include <vtkTriangle.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkSphereSource.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkTriangleFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <string>
#include <vtkButterflySubdivisionFilter.h>
#include <vtkLoopSubdivisionFilter.h>
#include <vtkLinearSubdivisionFilter.h>
int main(int argc, char *argv[])
{
vtkSmartPointer<vtkPolyData> originalMesh;
if(argc > 1) //If a file name is specified, open and use the file.
{
vtkSmartPointer<vtkXMLPolyDataReader> reader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(argv[1]);
// Subdivision filters only work on triangles
vtkSmartPointer<vtkTriangleFilter> triangles =
vtkSmartPointer<vtkTriangleFilter>::New();
triangles->SetInputConnection(reader->GetOutputPort());
triangles->Update();
originalMesh = triangles->GetOutput();
}
else //If a file name is not specified, create a sphere
{
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->Update();
originalMesh = sphereSource->GetOutput();
}
std::cout << "Before subdivision" << std::endl;
std::cout << " There are " << originalMesh->GetNumberOfPoints()
<< " points." << std::endl;
std::cout << " There are " << originalMesh->GetNumberOfPolys()
<< " triangles." << std::endl;
double numberOfViewports = 3.;
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(200* numberOfViewports,200); //(width, height)
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
int numberOfSubdivisions = 2;
for(unsigned i = 0; i < numberOfViewports; i++)
{
// Note: Here we create a superclass pointer (vtkPolyDataAlgorithm) so that we can easily instantiate different
// types of subdivision filters. Typically you would not want to do this, but rather create the pointer to be the type
// filter you will actually use, e.g.
// vtkSmartPointer<vtkLinearSubdivisionFilter> subdivisionFilter = vtkSmartPointer<vtkLinearSubdivisionFilter>::New();
vtkSmartPointer<vtkPolyDataAlgorithm> subdivisionFilter;
switch(i)
{
case 0:
subdivisionFilter = vtkSmartPointer<vtkLinearSubdivisionFilter>::New();
dynamic_cast<vtkLinearSubdivisionFilter *> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
break;
case 1:
subdivisionFilter = vtkSmartPointer<vtkLoopSubdivisionFilter>::New();
dynamic_cast<vtkLoopSubdivisionFilter *> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
break;
case 2:
subdivisionFilter = vtkSmartPointer<vtkButterflySubdivisionFilter>::New();
dynamic_cast<vtkButterflySubdivisionFilter *> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
break;
default:
break;
}
subdivisionFilter->SetInputData(originalMesh);
subdivisionFilter->Update();
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(renderer);
renderer->SetViewport(static_cast<double>(i)/numberOfViewports,0,static_cast<double>(i+1)/numberOfViewports,1);
//Create a mapper and actor
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(subdivisionFilter->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
renderer->AddActor(actor);
renderer->ResetCamera();
renderWindow->Render();
renderWindow->SetWindowName("Multiple ViewPorts");
}
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
Result
2次細分三角形數量:96*4^2=1536