VTK - 如何用单个演员渲染多个 3d 文本对象
VTK - How to render multiple 3d text objects with single actor
我正在尝试使用 vtk 对象 vtkVectorText 呈现文本。它适用于单个 3d 位置。我需要的是在一些 3d (vtkPoint) 点上方放置一个 3d 文本。我试着用 vtkTextActor3d 来做,但每个文本对象都需要一个单独的演员,我最终得到了 10k 个演员,当我尝试旋转场景时,这非常糟糕且滞后。
我还尝试应用一些 appendFilter 来创建 vtkVectorText 数组,从 appendFilter 的对象中获取非结构化网格,然后将其转换为多数据,以便使用我想要的点位置渲染非结构化网格。它什么也没显示,因为我不知道什么是最好的方法。
有人可以帮我解决这个问题吗?
这是我最后一部分的代码:
vtkSmartPointer<vtkAppendFilter> appendFilter = vtkSmartPointer<vtkAppendFilter>::New();
//for each point
for (int i = 0; i < N;i++) {
vtkSmartPointer<vtkVectorText> vecText = vtkSmartPointer<vtkVectorText>::New();
vecText->SetText("My text, needs to appear multiple times");
vecText->Update();
appendFilter->AddInputData(vecText->GetOutput());
appendFilter->Update();
}
vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid = appendFilter->GetOutput();
unstructuredGrid->Allocate(N);
unstructuredGrid->SetPoints(points);
vtkSmartPointer<vtkGeometryFilter> geometryFilter = vtkSmartPointer<vtkGeometryFilter>::New();
geometryFilter->SetInputData(unstructuredGrid);
geometryFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
textMapper->SetInputConnection(geometryFilter->GetOutputPort());
vtkSmartPointer<vtkActor> textActor = vtkSmartPointer<vtkActor>::New();
textActor->SetMapper(textMapper);
textActor->GetProperty()->SetColor(0, 1, 0);
renderer->AddActor(textActor);
如果每个点的文本都相同,我建议将其用作字形:
vtkSmartPointer<vtkPolyData> pointsHolder = vtkSmartPointer<vtkPolyData>::New();
pointsHolder->SetPoints(points); // I assume that these are the points where you want the object to be rendered
vtkSmartPointer<vtkGlyph3DMapper> glyphMapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
glyphMapper->SetSourceConnection(vecText->GetOutputPort()); // this says WHAT should be rendered
glyphMapper->SetInputData(pointsHolder); // this says WHERE
textActor->SetMapper(glyphMapper);
这将在 "points" 数组中的所有点呈现文本(我假设这是一个 vtkPoints 数组,其中包含您希望呈现文本的位置)。这样你就可以做各种各样的事情,当你把它附加到一个网格时,你不能做,比如通过提供一个比例数组为每个字形设置不同的大小,或者通过提供一个掩码数组等交互地转动它们 on/off ., 参见 http://www.vtk.org/doc/nightly/html/classvtkGlyph3DMapper.html
如果每个点的文本都不同,您可能必须以追加的方式进行。我可以在您的附加代码中看到一些错误:
1) 首先是一个小的性能 - 调用 appendFilter->Update();仅一次,在您设置所有输入后。
2)
unstructuredGrid->Allocate(N);
unstructuredGrid->SetPoints(points);
通过调用 Allocate,您只是重置了 appendfilter 为您所做的一切。即使没有它,第二行也会重写为文本生成的所有点的位置。附加过滤器的输出只是您应该直接分配给映射器的内容,必须删除这两行。就像 vtkGeometryFilter 一样,我看不出有任何理由(我猜你用它来获取 vtkPolyData 而不是 vtkUnstructuredGrid - 只需使用 vtkAppendPolydata 而不是 vtkAppendFilter,它会直接生成 polydata)。
3) 但是,现在 "points" 数组未被使用,即您的文本将不会位于正确的位置。在将其分配给追加过滤器之前,您必须为每个文本实例转换多数据。最简单的方法是使用 "points" 数组中的点作为平移向量,因此在将点发送到追加过滤器之前,您可以将点的坐标添加到 vecText->GetOutput() 的每个点,所以像这样:
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
//for each point
for (int i = 0; i < N;i++) {
vtkSmartPointer<vtkVectorText> vecText = vtkSmartPointer<vtkVectorText>::New();
vecText->SetText("My text, needs to appear multiple times");
vecText->Update();
vtkPolyData *output = vecText->GetOutput();
double *location = points->GetPoint(i);
for (int j = 0; j < output->GetNumberOfPoints(); j++) {
double *point = output->GetPoint(j);
output->GetPoints()->SetPoint(j, point[0] + location[0], point[1] + location[1], points[2] + location[2]);
}
appendFilter->AddInputData(output);
}
appendFilter->Update();
如果您想将文本居中放置,则需要更聪明的方法。
我正在尝试使用 vtk 对象 vtkVectorText 呈现文本。它适用于单个 3d 位置。我需要的是在一些 3d (vtkPoint) 点上方放置一个 3d 文本。我试着用 vtkTextActor3d 来做,但每个文本对象都需要一个单独的演员,我最终得到了 10k 个演员,当我尝试旋转场景时,这非常糟糕且滞后。
我还尝试应用一些 appendFilter 来创建 vtkVectorText 数组,从 appendFilter 的对象中获取非结构化网格,然后将其转换为多数据,以便使用我想要的点位置渲染非结构化网格。它什么也没显示,因为我不知道什么是最好的方法。
有人可以帮我解决这个问题吗?
这是我最后一部分的代码:
vtkSmartPointer<vtkAppendFilter> appendFilter = vtkSmartPointer<vtkAppendFilter>::New();
//for each point
for (int i = 0; i < N;i++) {
vtkSmartPointer<vtkVectorText> vecText = vtkSmartPointer<vtkVectorText>::New();
vecText->SetText("My text, needs to appear multiple times");
vecText->Update();
appendFilter->AddInputData(vecText->GetOutput());
appendFilter->Update();
}
vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid = appendFilter->GetOutput();
unstructuredGrid->Allocate(N);
unstructuredGrid->SetPoints(points);
vtkSmartPointer<vtkGeometryFilter> geometryFilter = vtkSmartPointer<vtkGeometryFilter>::New();
geometryFilter->SetInputData(unstructuredGrid);
geometryFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
textMapper->SetInputConnection(geometryFilter->GetOutputPort());
vtkSmartPointer<vtkActor> textActor = vtkSmartPointer<vtkActor>::New();
textActor->SetMapper(textMapper);
textActor->GetProperty()->SetColor(0, 1, 0);
renderer->AddActor(textActor);
如果每个点的文本都相同,我建议将其用作字形:
vtkSmartPointer<vtkPolyData> pointsHolder = vtkSmartPointer<vtkPolyData>::New();
pointsHolder->SetPoints(points); // I assume that these are the points where you want the object to be rendered
vtkSmartPointer<vtkGlyph3DMapper> glyphMapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
glyphMapper->SetSourceConnection(vecText->GetOutputPort()); // this says WHAT should be rendered
glyphMapper->SetInputData(pointsHolder); // this says WHERE
textActor->SetMapper(glyphMapper);
这将在 "points" 数组中的所有点呈现文本(我假设这是一个 vtkPoints 数组,其中包含您希望呈现文本的位置)。这样你就可以做各种各样的事情,当你把它附加到一个网格时,你不能做,比如通过提供一个比例数组为每个字形设置不同的大小,或者通过提供一个掩码数组等交互地转动它们 on/off ., 参见 http://www.vtk.org/doc/nightly/html/classvtkGlyph3DMapper.html
如果每个点的文本都不同,您可能必须以追加的方式进行。我可以在您的附加代码中看到一些错误:
1) 首先是一个小的性能 - 调用 appendFilter->Update();仅一次,在您设置所有输入后。
2)
unstructuredGrid->Allocate(N);
unstructuredGrid->SetPoints(points);
通过调用 Allocate,您只是重置了 appendfilter 为您所做的一切。即使没有它,第二行也会重写为文本生成的所有点的位置。附加过滤器的输出只是您应该直接分配给映射器的内容,必须删除这两行。就像 vtkGeometryFilter 一样,我看不出有任何理由(我猜你用它来获取 vtkPolyData 而不是 vtkUnstructuredGrid - 只需使用 vtkAppendPolydata 而不是 vtkAppendFilter,它会直接生成 polydata)。
3) 但是,现在 "points" 数组未被使用,即您的文本将不会位于正确的位置。在将其分配给追加过滤器之前,您必须为每个文本实例转换多数据。最简单的方法是使用 "points" 数组中的点作为平移向量,因此在将点发送到追加过滤器之前,您可以将点的坐标添加到 vecText->GetOutput() 的每个点,所以像这样:
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
//for each point
for (int i = 0; i < N;i++) {
vtkSmartPointer<vtkVectorText> vecText = vtkSmartPointer<vtkVectorText>::New();
vecText->SetText("My text, needs to appear multiple times");
vecText->Update();
vtkPolyData *output = vecText->GetOutput();
double *location = points->GetPoint(i);
for (int j = 0; j < output->GetNumberOfPoints(); j++) {
double *point = output->GetPoint(j);
output->GetPoints()->SetPoint(j, point[0] + location[0], point[1] + location[1], points[2] + location[2]);
}
appendFilter->AddInputData(output);
}
appendFilter->Update();
如果您想将文本居中放置,则需要更聪明的方法。