#include <vtkSmartPointer.h>
#include <vtkGlyph3DMapper.h>
#include <vtkSphereSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkCubeSource.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPointSource.h>
#include <vtkRenderWindowInteractor.h>
#include <iostream>
#include <vector>

#define VTK_CREATE(type, name) \
    vtkSmartPointer<type> name = vtkSmartPointer<type>::New();

#define REUSE_SOURCES

int main()
{
    VTK_CREATE(vtkPointSource, pointSource);
    pointSource->SetNumberOfPoints(1);

    VTK_CREATE(vtkGlyph3DMapper, glyphMapper);
    glyphMapper->SetInputConnection(pointSource->GetOutputPort());

    VTK_CREATE(vtkActor, glyphActor);
    glyphActor->SetMapper(glyphMapper);

    VTK_CREATE(vtkRenderer, renderer);
    renderer->AddActor(glyphActor);

    VTK_CREATE(vtkRenderWindow, renderWindow);
    renderWindow->AddRenderer(renderer);

    std::vector<vtkSmartPointer<vtkPolyDataAlgorithm> > sources;
    sources.push_back(vtkSmartPointer<vtkSphereSource>::New());
    sources.push_back(vtkSmartPointer<vtkCubeSource>::New());

    for (int i = 0; i < 3; ++i)
    {
        if (i%2)
        {
#if defined REUSE_SOURCES
            glyphMapper->SetSourceConnection(sources.at(0)->GetOutputPort());
#else
            VTK_CREATE(vtkSphereSource, sphereSource);
            glyphMapper->SetSourceConnection(sphereSource->GetOutputPort());
#endif
            std::cout << "Sphere" << std::endl;
        }
        else
        {
#if defined REUSE_SOURCES
            glyphMapper->SetSourceConnection(sources.at(1)->GetOutputPort());
#else
            VTK_CREATE(vtkCubeSource, cubeSource);
            glyphMapper->SetSourceConnection(cubeSource->GetOutputPort());
#endif
            std::cout << "Cube" << std::endl;
        }

        renderWindow->Render();
    }

    VTK_CREATE(vtkRenderWindowInteractor, interactor);
    renderWindow->SetInteractor(interactor);
    interactor->Initialize();
    interactor->Start();
}