Skip to content

DepthSortPolyData

vtk-examples/Cxx/Visualization/DepthSortPolyData


Description

  • Contributed by: Lars Friedrich

This is a C++-port of the VTK example '''DepthSort.py''' found in [VTKSourceDir/Examples/VisualizationAlgorithms/Python(https://gitlab.kitware.com/vtk/vtk/blob/master/Examples/VisualizationAlgorithms/Python/DepthSort.py). It was slightly modified. It generates 5 spheres with configurable PHI and THETA resolution. The spheres overlap. Therefore, correct blending and visualization in general requires depth sorting of the underlying polygons which will not happen when simply using a poly data mapper. Depth sorting can be achieved by connecting a vtkDepthSortPolyData filter to the mapper instead of the pure poly data.

Program Usage

Usage: ./DepthSortPolyData DepthSortFlag ThetaResolution  PhiResolution ScalarVisibilityFlag*

DepthSortFlag ... activate/deactivate the depth sorting algorithm

ThetaResolution ... THETA resolution for the spheres

PhiResolution ... PHI resolution for the spheres

ScalarVisibilityFlag ... show/hide the found depth values as scalars

Example calls:

./DepthSortPolyData 0 100 100 0
... will render the spheres 'as usual' (without depth sorting); in general you will be confronted with situations (specific view directions) where you cannot determine whether a small sphere is behind or in front of the big center sphere
./DepthSortPolyData 1 100 100 0
... will render the spheres using depth sorting; the sphere depth order should now be visually traceable
./DepthSortPolyData 1 100 100 1
... will render the spheres using depth sorting; the depth values are mapped to the spheres and renderd on the surfaces

Using higher PHI/THETA resolutions shows how depth sorting reduces the frame rate.

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

DepthSortPolyData.cxx

#include <vtkActor.h>
#include <vtkAppendPolyData.h>
#include <vtkCamera.h>
#include <vtkDepthSortPolyData.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>

int main(int argc, char* argv[])
{
  if (argc != 5)
  {
    std::cerr << "Usage: " << argv[0] << " DepthSortFlag ThetaResolution "
              << " PhiResolution ScalarVisibilityFlag" << std::endl;
    std::cerr << "1 100 100 0" << std::endl;
    return EXIT_FAILURE;
  }

  bool doDepthSort = atoi(argv[1]) == 1;
  int theta = atoi(argv[2]);
  int phi = atoi(argv[3]);
  bool scalarVisibility = atoi(argv[4]) == 1;

  vtkNew<vtkNamedColors> colors;

  // Create a bunch of spheres that overlap and cannot be easily arranged
  // so that the blending works without sorting. They are appended into a
  // single vtkPolyData because the filter only sorts within a single
  // vtkPolyData input.
  vtkNew<vtkAppendPolyData> appendData;

  for (int i = 0; i < 5; i++)
  {
    vtkNew<vtkSphereSource> sphereSource;
    sphereSource->SetThetaResolution(theta);
    sphereSource->SetPhiResolution(phi);
    sphereSource->SetRadius(
        0.5); // all sphere except the center one should have radius = 0.5
    switch (i)
    {
    case 0:
      sphereSource->SetRadius(1);
      sphereSource->SetCenter(0, 0, 0);
      break;
    case 1:
      sphereSource->SetCenter(1, 0, 0);
      break;
    case 2:
      sphereSource->SetCenter(-1, 0, 0);
      break;
    case 3:
      sphereSource->SetCenter(0, 1, 0);
      break;
    case 4:
      sphereSource->SetCenter(0, -1, 0);
      break;
    }
    sphereSource->Update();
    appendData->AddInputConnection(sphereSource->GetOutputPort());
  }

  // The dephSort object is set up to generate scalars representing
  // the sort depth.  A camera is assigned for the sorting. The camera
  // defines the sort vector (position and focal point).
  vtkNew<vtkCamera> camera;
  vtkNew<vtkDepthSortPolyData> depthSort;

  depthSort->SetInputConnection(appendData->GetOutputPort());
  depthSort->SetDirectionToBackToFront();
  depthSort->SetVector(1, 1, 1);
  depthSort->SetCamera(camera);
  depthSort->SortScalarsOn();
  depthSort->Update();

  vtkNew<vtkPolyDataMapper> mapper;
  if (doDepthSort)
  {
    mapper->SetInputConnection(depthSort->GetOutputPort());
  }
  else
  {
    mapper->SetInputConnection(appendData->GetOutputPort());
  }

  mapper->SetScalarVisibility(scalarVisibility);
  if (scalarVisibility)
  {
    mapper->SetScalarRange(0, depthSort->GetOutput()->GetNumberOfCells());
  }

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetOpacity(0.5);
  actor->GetProperty()->SetColor(colors->GetColor3d("Crimson").GetData());
  actor->RotateX(-72); // put the object in a position where it is easy
  // to see different overlapping regions

  // If an Prop3D is supplied, then its transformation matrix is taken
  // into account during sorting.
  depthSort->SetProp3D(actor);

  // Create the RenderWindow, Renderer and both Actors
  vtkNew<vtkRenderer> renderer;
  renderer->SetActiveCamera(camera);
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->AddRenderer(renderer);
  renderWindow->SetWindowName("DepthSortPolyData");

  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  renderWindowInteractor->SetRenderWindow(renderWindow);

  // Add the actors to the renderer, set the background and size
  renderer->AddActor(actor);
  renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
  renderWindow->SetSize(600, 400);

  renderer->ResetCamera();
  renderer->GetActiveCamera()->Zoom(2.2); // so the object is larger

  renderWindowInteractor->Initialize();
  renderWindow->Render();
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(DepthSortPolyData)

find_package(VTK COMPONENTS 
  CommonColor
  CommonCore
  FiltersCore
  FiltersHybrid
  FiltersSources
  InteractionStyle
  RenderingContextOpenGL2
  RenderingCore
  RenderingFreeType
  RenderingGL2PSOpenGL2
  RenderingOpenGL2
)

if (NOT VTK_FOUND)
  message(FATAL_ERROR "DepthSortPolyData: Unable to find the VTK build folder.")
endif()

# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
add_executable(DepthSortPolyData MACOSX_BUNDLE DepthSortPolyData.cxx )
  target_link_libraries(DepthSortPolyData PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
  TARGETS DepthSortPolyData
  MODULES ${VTK_LIBRARIES}
)

Download and Build DepthSortPolyData

Click here to download DepthSortPolyData and its CMakeLists.txt file. Once the tarball DepthSortPolyData.tar has been downloaded and extracted,

cd DepthSortPolyData/build

If VTK is installed:

cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

make

and run it:

./DepthSortPolyData

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.