VTK - 如何使用单个actor渲染多个3d文本对象

时间:2016-11-24 14:12:26

标签: 3d vtk vector-graphics

我正在尝试使用vtk对象vtkVectorText呈现文本。它适用于单个3d位置。我需要的是在一些3d(vtkPoint)点上方放置一个3d文本。我尝试用vtkTextActor3d做这个,但是每个文本对象都需要一个单独的actor,我最终得到了10k演员,当我试图旋转场景时,这是非常糟糕和滞后的。

我还尝试应用一些appendFilter来创建一个vtkVectorText数组,从appendFilter对象获取非结构化网格,然后将其转换为polydata,以便使用我想要的点位置渲染非结构化网格。它没有显示任何内容,因为我无法弄清楚这是最好的方法。

有人可以帮我这个吗?

以下是我上一部分的代码:

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);

1 个答案:

答案 0 :(得分:1)

如果每个点的文本相同,我建议将其用作字形:

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);

这将在&#34;点&#34;中的所有点处呈现文本。数组(我假设是一个vtkPoints数组,其中包含您希望呈现文本的位置)。通过这种方式,您可以在将其附加到一个网格中时执行各种操作,例如通过提供缩放数组为每个字形设置不同的大小,或者通过提供掩模数组等以交互方式打开/关闭它们。,见http://www.vtk.org/doc/nightly/html/classvtkGlyph3DMapper.html

如果每个点的文本可能不同,您可能必须以附加的方式进行。我可以在你的附加代码中看到一些错误:

1)首先是一个小的性能 - 调用appendFilter-&gt; Update();在设置完所有输入后,只有一次。

2)

unstructuredGrid->Allocate(N);
unstructuredGrid->SetPoints(points);

通过调用Allocate,您只需重置appendfilter为您完成的所有操作。即使没有它,第二行也会重写为文本生成的所有点的位置。附加过滤器的输出就是您应该直接分配给映射器的输出,这两行必须删除。和vtkGeometryFilter一样,我没有看到它的任何原因(我猜你用它来获取vtkPolyData而不是vtkUnstructuredGrid - 只需使用vtkAppendPolydata而不是vtkAppendFilter,它将直接产生polydata)。

3)然而,现在&#34;点&#34;未使用数组,即您的文本将不在正确的位置。在将其分配给追加过滤器之前,您必须为每个文本实例转换polydata。最简单的方法是使用你的&#34;点&#34;数组作为转换向量,所以你要将点的坐标添加到vecText-&gt; 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();

如果您想要将文本置于中心位置,则需要更聪明的东西。