2016-11-24 92 views
5

Próbuję renderować tekst za pomocą obiektu vtk vtkVectorText. Działa dobrze dla pojedynczej lokalizacji 3d. Potrzebne jest umieszczenie tekstu 3d powyżej niektórych punktów 3d (vtkPoint). Próbowałem to zrobić za pomocą vtkTextActor3d, ale każdy obiekt tekstowy wymaga oddzielnego aktora i skończyłem z 10 tys. Aktorów, co jest dość złe i opóźnione, gdy próbuję na przykład obrócić scenę.VTK - Jak renderować wiele obiektów tekstowych 3D z jednym aktorem

Próbowałem także zastosować appendFilter, aby utworzyć tablicę vtkVectorText, pobrać nieuporządkowaną siatkę z obiektu appendFilter, a następnie przekonwertować ją na polydata w celu renderowania niestrukturowanej siatki z wybranymi lokalizacjami punktów. Nic nie pokazuje, ponieważ nie wiem, jaki jest najlepszy sposób na zrobienie tego.

Czy ktoś może mi pomóc z tym?

Oto mój kod z ostatniej strony:

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

Odpowiedz

1

Jeśli tekst jest taki sam dla każdego punktu, chciałbym zaproponować wykorzystanie go jako glif:

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

ta uniemożliwiała tekst we wszystkich punktach w tablicy "points" (zakładam, że jest to tablica vtkPoints z pozycjami, w których tekst ma być renderowany). W ten sposób możesz robić różne rzeczy, których nie możesz, kiedy dodajesz je do jednej siatki, np. Ustawiając inny rozmiar dla każdego glifu, zapewniając tablicę skali lub włączając je/wyłączając interaktywnie, zapewniając macierz maskową itp. zobacz http://www.vtk.org/doc/nightly/html/classvtkGlyph3DMapper.html

Jeśli tekst może być inny dla każdego punktu, prawdopodobnie będziesz musiał zrobić to w sposób dopisywania. Widzę kilka błędów w kodzie jako załączniki:

1) Najpierw jeden mały performance - wywołanie appendFilter-> Update(); tylko raz, po ustawieniu wszystkich wejść.

2)

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

Dzwoniąc Przeznaczyć, po prostu wszystko, co appendFilter resetują zrobił dla ciebie. Nawet bez tego druga linia przepisałaby pozycje dla wszystkich punktów, które zostały wygenerowane dla tekstu. Dane wyjściowe filtra dołączania są po prostu tym, co należy bezpośrednio przypisać do programu odwzorowującego, te dwie linie muszą zostać usunięte. Podobnie jak w przypadku vtkGeometryFilter, nie widzę żadnego powodu (domyślam się, że użyłeś go do uzyskania vtkPolyData zamiast vtkUnstructuredGrid - po prostu użyj vtkAppendPolydata zamiast vtkAppendFilter, będzie bezpośrednio tworzyć polydata).

3) Jednak teraz tablica "punktów" nie jest używana, tzn. Tekst nie będzie we właściwej pozycji. Konieczne będzie przekształcenie polydanych dla każdej instancji tekstu przed przypisaniem jej do filtru dołączania. Najprościej byłoby użyć punktów z twojej tablicy "punktów" jako wektorów translacji, aby dodać współrzędne punktu do każdego punktu w vecText-> GetOutput() przed wysłaniem go do filtra dołączania, więc coś takiego:

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

Potrzebne byłoby coś bardziej sprytnego, jeśli chcesz na przykład wyśrodkować tam tekst.