1
votes

I use VTK-6.2, C++ (gcc-4.7.2) on Linux and I have the following VTK pipeline setup (please ignore implementation, details and focus on the pipeline: cone->filter->mapper->actor):

// cone/initialize
vtkConeSource cone;

// add cone(s) to filter
vtkAppendFilter filter;
filter.AddInputData(cone.GetOutput());

// add filter to mapper
vtkDataSetMapper mapper;
mapper.SetInputData(filter->GetOutput());

// actor
vtkActor actor;
actor.SetMapper(mapper);

The scene renders fine.

The Problem

I want to update the original data (i.e. the cones) and the actor to be rendered correctly.

  • How do I access the original cone data if I have just the actors? Does this guarantee that the actors will be updated too? Because when I decided to keep track of the original data (via pointers: the whole implementation is with vtkSmartPointers) and then change some of their attributes, the pipeline did not update. Shouldn't it update automatically?

  • (When I change the actor (e.g. their visibility), the scene renders fine)

Forgive me, I am not a VTK expert and the pipelines are confusing. Maybe one approach would be to simplify my pipeline.

Thanks

[update]

According to this answer to a similar post, the original data (vtkConeSource) are transformed (to vtkUnstructuredGrid when added in the vtkAppendFilter) so even if I keep track of the original data, changing them is useless.

1

1 Answers

1
votes

VTK pipelines are demand-driven pipelines. They do not update automatically even if one of the elements of the pipeline is modified. We need to explicitly call the Update() function on the last vtkAlgorithm( or its derived class object) of the pipeline to update the entire pipeline. The correct way to set up a pipeline is when we are connecting two objects which are derived from vtkAlgorithm type is to use

currAlgoObj->SetInputConnection( prevAlgoObj->GetOutputPort() )

instead of

currAlgoObj->SetInputData( prevAlgo->GetOutput() )

Then we can update the pipeline using the pointer to the actor object by doing actor->GetMapper()->Update() like shown in the example below.

In this example, we will create a cone from a cone source, pass it through vtkAppendFilter and then change the height of the original cone source and render it in another window to see the updated cone. (You will have to close the first render window to see the updated cone in second window.)

#include <vtkConeSource.h>
#include <vtkDataSetMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkAppendFilter.h>

int main(int, char *[])
{
    // Set up the data pipeline
    auto cone = vtkSmartPointer<vtkConeSource>::New();
    cone->SetHeight( 1.0 );

    auto appf = vtkSmartPointer<vtkAppendFilter>::New();
    appf->SetInputConnection( cone->GetOutputPort() );

    auto coneMapper = vtkSmartPointer<vtkDataSetMapper>::New();
    coneMapper->SetInputConnection( appf->GetOutputPort() );

    auto coneActor = vtkSmartPointer<vtkActor>::New();
    coneActor->SetMapper( coneMapper );

    // We need to update the pipeline otherwise nothing will be rendered
    coneActor->GetMapper()->Update();

    // Connect to the rendering portion of the pipeline
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor( coneActor );
    renderer->SetBackground( 0.1, 0.2, 0.4 );

    auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize( 200, 200 );
    renderWindow->AddRenderer(renderer);

    auto renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);
    renderWindowInteractor->Start();

    // Change cone property
    cone->SetHeight( 10.0 );

    //Update the pipeline using the actor object
    coneActor->GetMapper()->Update();

    auto renderer2 = vtkSmartPointer<vtkRenderer>::New();
    renderer2->AddActor( coneActor );
    renderer2->SetBackground( 0.1, 0.2, 0.4 );

    auto renderWindow2 = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow2->SetSize( 200, 200 );
    renderWindow2->AddRenderer(renderer2);

    auto renderWindowInteractor2 =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor2->SetRenderWindow(renderWindow2);

    renderWindowInteractor2->Start();

    return EXIT_SUCCESS;
}