目录
VTK的编译与环境搭建
这部分目前已经有了大佬做了成熟的傻瓜式配置,大家可以参考这篇文章:VTK+VS2019(或其他版本均可) 傻瓜式一站式 配置_Nancy_fairy的博客-优快云博客_vs2019 vtk
VTK一般渲染流程
VTK数据类型-vtkPolyData
多边形数据集主要由顶点、多顶点、线、折线和三角形地带等单元组成。
顶点、线和多边形构成了用来表达0、1和2维几何图形的基本要素的最小集合。特别是三角形带,表达N个三角形仅需N+2个点,且大多数图形渲染三角形带速度极快。
使用vtk自带的多边形数据
vtk自带很多的成熟的多边形数据,包括圆柱,球体,锥体等。我们仅需设置几个属性就可以使用现成的数据创建模型并显示。以下为创建显示锥体的代码
void SimpleVtk()
{
vtkConeSource* source = vtkConeSource::New();
source->SetHeight(13);
source->SetRadius(5);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputConnection(source->GetOutputPort());
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkRenderer* render = vtkRenderer::New();
vtkRenderWindow* renwin = vtkRenderWindow::New();
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
render->AddActor(coneActor);
render->SetBackground(0.8, 0.4, 0.4);
renwin->AddRenderer(render);
iren->SetRenderWindow(renwin);
iren->Initialize();
iren->Start();
source->Delete();
coneMapper->Delete();
coneActor->Delete();
render->Delete();
renwin->Delete();
iren->Delete();
}
首先创建锥体资源,并设置其属性,紧接着将其传递给映射器,映射器将结果传递给渲染组件进行渲染显示。以下为运行的结果:
使用自己创建的数据
当然有时候默认的模型会不够用,我们想要自己创建模型。以下为创建一个四面体的代码:
void makePolyData()
{
vtkPoints* points = vtkPoints::New();
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 0.0, 1.0);
vtkTriangle* tran1 = vtkTriangle::New();
tran1->GetPointIds()->SetId(0, 0);
tran1->GetPointIds()->SetId(1, 1);
tran1->GetPointIds()->SetId(2, 2);
vtkTriangle* tran2 = vtkTriangle::New();
tran2->GetPointIds()->SetId(0, 0);
tran2->GetPointIds()->SetId(1, 1);
tran2->GetPointIds()->SetId(2, 3);
vtkTriangle* tran3 = vtkTriangle::New();
tran3->GetPointIds()->SetId(0, 0);
tran3->GetPointIds()->SetId(1, 2);
tran3->GetPointIds()->SetId(2, 3);
vtkTriangle* tran4 = vtkTriangle::New();
tran4->GetPointIds()->SetId(0, 1);
tran4->GetPointIds()->SetId(1, 2);
tran4->GetPointIds()->SetId(2, 3);
vtkCellArray* cells = vtkCellArray::New();
cells->InsertNextCell(tran1);
cells->InsertNextCell(tran2);
cells->InsertNextCell(tran3);
cells->InsertNextCell(tran4);
vtkPolyData* source = vtkPolyData::New();
source->SetPoints(points);
source->SetPolys(cells);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputData(source);
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkRenderer* render = vtkRenderer::New();
vtkRenderWindow* renwin = vtkRenderWindow::New();
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
render->AddActor(coneActor);
render->SetBackground(0.8, 0.4, 0.4);
renwin->AddRenderer(render);
iren->SetRenderWindow(renwin);
iren->Initialize();
iren->Start();
points->Delete();
tran1->Delete();
tran2->Delete();
tran3->Delete();
tran4->Delete();
cells->Delete();
source->Delete();
coneMapper->Delete();
coneActor->Delete();
render->Delete();
renwin->Delete();
iren->Delete();
}
首先创建点资源,并通过InsertNextPoint方法添加坐标点,其次创建四面体的四个三角形,通过GetPointIds()->SetId()方法设置点的索引,然后再将四个三角形通过InsertNextCell方法添加进多边形单元中。再然后将点资源和多边形单元添加到vtkPolyData中,将Data置入渲染流程即可显示这个四面体。以下为输出的结果:
很显然这种生成方式略显繁琐,vtk可以添加三角形带进入多边形单元中。一般情况下的3D模型都是由三角形带组成的,且三角形带非常节约资源且渲染速度快。以下为三角形带的代码:
void makePolyData2()
{
vtkPoints* points = vtkPoints::New();
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 0.0, 1.0);
vtkCellArray* array = vtkCellArray::New();
array->InsertNextCell(6);
array->InsertCellPoint(1);
array->InsertCellPoint(3);
array->InsertCellPoint(0);
array->InsertCellPoint(2);
array->InsertCellPoint(1);
array->InsertCellPoint(3);
vtkPolyData* source = vtkPolyData::New();
source->SetPoints(points);
source->SetStrips(array);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputData(source);
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkRenderer* render = vtkRenderer::New();
vtkRenderWindow* renwin = vtkRenderWindow::New();
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
render->AddActor(coneActor);
render->SetBackground(0.8, 0.4, 0.4);
renwin->AddRenderer(render);
iren->SetRenderWindow(renwin);
iren->Initialize();
iren->Start();
points->Delete();
array->Delete();
source->Delete();
coneMapper->Delete();
coneActor->Delete();
render->Delete();
renwin->Delete();
iren->Delete();
}
通过InsertCellPoint方法将点的索引添加进三角带中,在资源中使用SetStrips添加三角带。以下为渲染结果:
添加顶点颜色
既然我们已经成功的生成了四面体,但他是灰色的,显然不是很好看。以下为添加颜色显示的代码,首先是添加顶点颜色:
void makePolyDataAndSetColor()
{
unsigned char red[3] = { 255, 0, 0 };
unsigned char green[3] = { 0, 255, 0 };
unsigned char blue[3] = { 0, 0, 255 };
vtkPoints* points = vtkPoints::New();
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 0.0, 1.0);
vtkCellArray* array = vtkCellArray::New();
array->InsertNextCell(6);
array->InsertCellPoint(1);
array->InsertCellPoint(3);
array->InsertCellPoint(0);
array->InsertCellPoint(2);
array->InsertCellPoint(1);
array->InsertCellPoint(3);
vtkUnsignedCharArray* pointsColors = vtkUnsignedCharArray::New();
pointsColors->SetNumberOfComponents(3);
pointsColors->InsertNextTypedTuple(red);
pointsColors->InsertNextTypedTuple(green);
pointsColors->InsertNextTypedTuple(blue);
pointsColors->InsertNextTypedTuple(red);
vtkPolyData* source = vtkPolyData::New();
source->SetPoints(points);
source->SetStrips(array);
source->GetPointData()->SetScalars(pointsColors);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputData(source);
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkRenderer* render = vtkRenderer::New();
vtkRenderWindow* renwin = vtkRenderWindow::New();
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
render->AddActor(coneActor);
render->SetBackground(0.8, 0.4, 0.4);
renwin->AddRenderer(render);
iren->SetRenderWindow(renwin);
iren->Initialize();
iren->Start();
points->Delete();
array->Delete();
pointsColors->Delete();
source->Delete();
coneMapper->Delete();
coneActor->Delete();
render->Delete();
renwin->Delete();
iren->Delete();
}
新建一个unsignedchar数组作为颜色资源,将颜色通过InsertNextTypedTuple()方法加入到颜色资源中。然后将顶点颜色资源通过GetPointData()->SetScalars()方法加入到polyData中。以下为渲染结果:
添加面颜色
当然我们也可以给每个面添加纯色:
void makePolyDataAndSetColor2()
{
unsigned char red[3] = { 255, 0, 0 };
unsigned char green[3] = { 0, 255, 0 };
unsigned char blue[3] = { 0, 0, 255 };
vtkPoints* points = vtkPoints::New();
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(0.0, 0.0, 1.0);
vtkTriangle* tran1 = vtkTriangle::New();
tran1->GetPointIds()->SetId(0, 0);
tran1->GetPointIds()->SetId(1, 1);
tran1->GetPointIds()->SetId(2, 2);
vtkTriangle* tran2 = vtkTriangle::New();
tran2->GetPointIds()->SetId(0, 0);
tran2->GetPointIds()->SetId(1, 1);
tran2->GetPointIds()->SetId(2, 3);
vtkTriangle* tran3 = vtkTriangle::New();
tran3->GetPointIds()->SetId(0, 0);
tran3->GetPointIds()->SetId(1, 2);
tran3->GetPointIds()->SetId(2, 3);
vtkTriangle* tran4 = vtkTriangle::New();
tran4->GetPointIds()->SetId(0, 1);
tran4->GetPointIds()->SetId(1, 2);
tran4->GetPointIds()->SetId(2, 3);
vtkCellArray* cells = vtkCellArray::New();
cells->InsertNextCell(tran1);
cells->InsertNextCell(tran2);
cells->InsertNextCell(tran3);
cells->InsertNextCell(tran4);
vtkUnsignedCharArray* cellColors = vtkUnsignedCharArray::New();
cellColors->SetNumberOfComponents(3);
cellColors->InsertNextTypedTuple(red);
cellColors->InsertNextTypedTuple(green);
cellColors->InsertNextTypedTuple(blue);
cellColors->InsertNextTypedTuple(red);
vtkPolyData* source = vtkPolyData::New();
source->SetPoints(points);
source->SetPolys(cells);
source->GetCellData()->SetScalars(cellColors);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputData(source);
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkRenderer* render = vtkRenderer::New();
vtkRenderWindow* renwin = vtkRenderWindow::New();
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
render->AddActor(coneActor);
render->SetBackground(0.8, 0.4, 0.4);
renwin->AddRenderer(render);
iren->SetRenderWindow(renwin);
iren->Initialize();
iren->Start();
points->Delete();
cellColors->Delete();
tran1->Delete();
tran2->Delete();
tran3->Delete();
tran4->Delete();
cells->Delete();
source->Delete();
coneMapper->Delete();
coneActor->Delete();
render->Delete();
renwin->Delete();
iren->Delete();
}
这次用的是GetCellData()->SetScalars()方法将面颜色传递给各个面。渲染结果如下:
大家也可以试试同时添加顶点颜色和面颜色是什么效果。