使用 VTK 渲染网格 api
Rendering a mesh with VTK api
我正在制作一个更简单的查看器来读取和可视化网格。
VTK 对我来说是新手,我首先尝试找出 best/most 为查看器设置网格数据的有效方法。我看到有很多使用 C++ 的 VTK 示例,但是其中很多都是转换为 vtk 格式或渲染原语。
我对转换为 vtk 格式不感兴趣,我只是想将我的网格数据设置为 vtk 非结构化网格 或 vtk 多边形数据集 并渲染它。
我做了一个小测试。下面的代码正确呈现,但这是设置数据集的最有效方法吗?如果我将 N_SQUARES
设置为 1 000 000,它可以工作,但三角形循环似乎很慢。
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
//TEST MESH
int N_SQUARES = 100;
//This creates node coordinates for N_SQUARES amount of squares. (Nodal data would be read from a file later on)
vtkSmartPointer<vtkPoints> nodes = vtkSmartPointer<vtkPoints>::New();
for (int i = 0; i < N_SQUARES; i++){
nodes->InsertNextPoint(0.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 1.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(0.0, 1.0, 0.2 + 0.2f*float(i));
}
//Here two triangles are created for each square. (these indices would later on be read from FEM element data)
vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
for (int j = 0; j < N_SQUARES; j++){
vtkSmartPointer<vtkTriangle> triangle1 = vtkSmartPointer<vtkTriangle>::New();
triangle1->GetPointIds()->SetId(0, 0 + j);
triangle1->GetPointIds()->SetId(1, 1 + j);
triangle1->GetPointIds()->SetId(2, 2 + j);
vtkSmartPointer<vtkTriangle> triangle2 = vtkSmartPointer<vtkTriangle>::New();
triangle2->GetPointIds()->SetId(0, 2 + j);
triangle2->GetPointIds()->SetId(1, 3 + j);
triangle2->GetPointIds()->SetId(2, 0 + j);
triangles->InsertNextCell(triangle1);
triangles->InsertNextCell(triangle2);
}
vtkSmartPointer<vtkPolyData> meshData = vtkSmartPointer<vtkPolyData>::New();
meshData->SetPoints(nodes);
meshData->SetPolys(triangles);
vtkSmartPointer<vtkPolyDataMapper> meshMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
meshMapper->SetInputData(meshData);
vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New();
meshActor->SetMapper(meshMapper);
renderer->AddActor(meshActor);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
您示例中的代码可能由于多种原因而变慢
- 您正在
j
循环中构造和销毁 2 个 vtkTriangle 实例。这很昂贵,并且可能是速度缓慢的最大原因。
既然你构建了 polydata,最好完全避免使用 vtkTriangle。相反,做一些像
for (int j = 0; j < N_SQUARES; ++j)
{
vtkIdType triangle1[3] = {j, j+1, j+2};
vtkIdType triangle2[3] = {j+2, j+3, j};
triangles->InsertNextCell(3, triangle1);
triangles->InsertNextCell(3, triangle2);
// ... or better yet, create a single quad:
vtkIdType quad[4] = {j, j+1, j+2, j+3};
triangles->InsertNextCell(4, quad);
}
您不会提前告诉 VTK 数组(点坐标或连通性)有多大。这意味着 VTK 必须在您增加数组大小时重新分配和复制数组。尝试在第一个循环之前添加 nodes->GetData()->Allocate(4 * N_SQUARES);
(超过 i
)。同样,您可以告诉 vtkCellArray 提前分配适量的内存(有点棘手;它是一个整数数组,格式如下:nptsPerPoly0 ptId0Poly0 ptId1Poly0 ... ptIdNPoly0 nPtsPerPoly1 ...)。对于三角形,你会调用 triangles->Allocate((1 + 3) * 2 * N_SQUARES);
。对于前面示例中的四边形,它将是 triangles->Allocate((1 + 4) * N_SQUARES);
.
- 您的示例没有重复使用多个方块共享的点。这使得
nodes
和 triangles
都消耗了比必要更多的内存。
- 对于中等大小的网格(适合单台计算机的内存),您可以使用线程来准备
nodes
和 triangles
数组。对于大型网格,VTK 被构建为跨多台计算机工作,其中每台计算机仅包含网格的一部分(分布式内存并行性)。
- 如果您已经在内存中拥有网格,最新版本的 VTK 允许您编写特殊的 类 将网格暴露给 VTK 而无需任何副本,但这超出了本问题的范围。但是,它会将给定网格消耗的内存量减半,因此根据网格和计算机的内存,它可能很重要。
- 根据您制作的大小
N_SQUARES
,您可能会导致计算机使用交换文件或分区。在那种情况下,您应该减小网格的大小或使用分布式内存并行性。
我正在制作一个更简单的查看器来读取和可视化网格。
VTK 对我来说是新手,我首先尝试找出 best/most 为查看器设置网格数据的有效方法。我看到有很多使用 C++ 的 VTK 示例,但是其中很多都是转换为 vtk 格式或渲染原语。
我对转换为 vtk 格式不感兴趣,我只是想将我的网格数据设置为 vtk 非结构化网格 或 vtk 多边形数据集 并渲染它。
我做了一个小测试。下面的代码正确呈现,但这是设置数据集的最有效方法吗?如果我将 N_SQUARES
设置为 1 000 000,它可以工作,但三角形循环似乎很慢。
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
//TEST MESH
int N_SQUARES = 100;
//This creates node coordinates for N_SQUARES amount of squares. (Nodal data would be read from a file later on)
vtkSmartPointer<vtkPoints> nodes = vtkSmartPointer<vtkPoints>::New();
for (int i = 0; i < N_SQUARES; i++){
nodes->InsertNextPoint(0.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 1.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(0.0, 1.0, 0.2 + 0.2f*float(i));
}
//Here two triangles are created for each square. (these indices would later on be read from FEM element data)
vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
for (int j = 0; j < N_SQUARES; j++){
vtkSmartPointer<vtkTriangle> triangle1 = vtkSmartPointer<vtkTriangle>::New();
triangle1->GetPointIds()->SetId(0, 0 + j);
triangle1->GetPointIds()->SetId(1, 1 + j);
triangle1->GetPointIds()->SetId(2, 2 + j);
vtkSmartPointer<vtkTriangle> triangle2 = vtkSmartPointer<vtkTriangle>::New();
triangle2->GetPointIds()->SetId(0, 2 + j);
triangle2->GetPointIds()->SetId(1, 3 + j);
triangle2->GetPointIds()->SetId(2, 0 + j);
triangles->InsertNextCell(triangle1);
triangles->InsertNextCell(triangle2);
}
vtkSmartPointer<vtkPolyData> meshData = vtkSmartPointer<vtkPolyData>::New();
meshData->SetPoints(nodes);
meshData->SetPolys(triangles);
vtkSmartPointer<vtkPolyDataMapper> meshMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
meshMapper->SetInputData(meshData);
vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New();
meshActor->SetMapper(meshMapper);
renderer->AddActor(meshActor);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
您示例中的代码可能由于多种原因而变慢
- 您正在
j
循环中构造和销毁 2 个 vtkTriangle 实例。这很昂贵,并且可能是速度缓慢的最大原因。 既然你构建了 polydata,最好完全避免使用 vtkTriangle。相反,做一些像
for (int j = 0; j < N_SQUARES; ++j) { vtkIdType triangle1[3] = {j, j+1, j+2}; vtkIdType triangle2[3] = {j+2, j+3, j}; triangles->InsertNextCell(3, triangle1); triangles->InsertNextCell(3, triangle2); // ... or better yet, create a single quad: vtkIdType quad[4] = {j, j+1, j+2, j+3}; triangles->InsertNextCell(4, quad); }
您不会提前告诉 VTK 数组(点坐标或连通性)有多大。这意味着 VTK 必须在您增加数组大小时重新分配和复制数组。尝试在第一个循环之前添加
nodes->GetData()->Allocate(4 * N_SQUARES);
(超过i
)。同样,您可以告诉 vtkCellArray 提前分配适量的内存(有点棘手;它是一个整数数组,格式如下:nptsPerPoly0 ptId0Poly0 ptId1Poly0 ... ptIdNPoly0 nPtsPerPoly1 ...)。对于三角形,你会调用triangles->Allocate((1 + 3) * 2 * N_SQUARES);
。对于前面示例中的四边形,它将是triangles->Allocate((1 + 4) * N_SQUARES);
.- 您的示例没有重复使用多个方块共享的点。这使得
nodes
和triangles
都消耗了比必要更多的内存。 - 对于中等大小的网格(适合单台计算机的内存),您可以使用线程来准备
nodes
和triangles
数组。对于大型网格,VTK 被构建为跨多台计算机工作,其中每台计算机仅包含网格的一部分(分布式内存并行性)。 - 如果您已经在内存中拥有网格,最新版本的 VTK 允许您编写特殊的 类 将网格暴露给 VTK 而无需任何副本,但这超出了本问题的范围。但是,它会将给定网格消耗的内存量减半,因此根据网格和计算机的内存,它可能很重要。
- 根据您制作的大小
N_SQUARES
,您可能会导致计算机使用交换文件或分区。在那种情况下,您应该减小网格的大小或使用分布式内存并行性。