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

标签 3d vtk vector-graphics

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

我还尝试应用一些 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);

最佳答案

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

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 数组,其中包含你想要渲染文本的位置)。通过这种方式,您可以执行将其附加到一个网格中时无法执行的各种操作,例如通过提供缩放数组为每个字形设置不同的大小,或者通过提供 mask 数组等交互地打开/关闭它们,见 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)但是,现在不使用“点”数组,即您的文本将不在正确的位置。您必须先转换每个文本实例的 polydata,然后再将其分配给附加过滤器。最简单的方法是使用“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();

例如,如果您想将文本居中放置,则需要更聪明的方法。

关于3d - VTK - 如何使用单个 actor 渲染多个 3d 文本对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40788572/

相关文章:

ios - Scenekit - SCNNode 的多次旋转和轴的方向

c++ - 将 2D 位图转换为 3D 立方体模型的有效方法?

c++ - QVTKWidget中的renderWindowInteractor

java - 为什么在 Java Applet 中使用 vector 坐标时多边形会变形?

image - 如何创建矢量图形,然后从中生成图标?

java - 我可以在 Android 上使用 jmonkeyengine 吗?

java - 在 3D 结构中添加新顶点

computational-geometry - vtk中顶点和点的区别

python - 使用 Numpy 将 VTK 转换为 Matplotlib

c# - 如何正确地在 wpf 中重用矢量图