Skip to content


# CollisionDetection

VTKEx/Cxx/Visualization/CollisionDetection

### Description

This examples uses vtkCollisionDetectionFilter to find the intersection between a fixed (solid white) and moving (red wireframe) sphere. The animation places the moving sphere some distance from the fixed sphere and moves the moving sphere until it contacts the fixed sphere.

Three collision modes are available and can be set as the first argument on the command line.

1. All contacts (0) finds all the contacting cell pairs with two points per collision.
2. First contact (1) quickly find the first contact point.
3. Half contacts (2) finds all the contacting cell pairs with one points per collision.

The animation pauses between each frame. The total animation should be 3 seconds.

Three videos on the VTK Examples Project youtube playlist show each of the collision modes.

Other languages

See (Python)

Question

If you have a simple question about this example contact us at VTKExProject If your question is more complex and may require extended discussion, please use the VTK Discourse Forum

### Code

CollisionDetection.cxx

    #include "vtkActor.h"
    #include "vtkCamera.h"
    #include "vtkCollisionDetectionFilter.h"
    #include "vtkMatrix4x4.h"
    #include "vtkNamedColors.h"
    #include "vtkPolyDataMapper.h"
    #include "vtkProperty.h"
    #include "vtkRenderWindow.h"
    #include "vtkRenderWindowInteractor.h"
    #include "vtkRenderer.h"
    #include "vtkSmartPointer.h"
    #include "vtkSphereSource.h"
    #include "vtkTextActor.h"
    #include "vtkTextProperty.h"
    #include "vtkTransform.h"

    #include <chrono>
    #include <sstream>
    #include <string>
    #include <thread>

    int main(int argc, char* argv[])
    {
      int contactMode = 0;
      if (argc > 1)
      {
        contactMode = std::stoi(std::string(argv[1]));
      }
      auto sphere0 = vtkSmartPointer<vtkSphereSource>::New();
      sphere0->SetRadius(.29);
      sphere0->SetPhiResolution(31);
      sphere0->SetThetaResolution(31);
      sphere0->SetCenter(0.0, 0, 0);

      auto sphere1 = vtkSmartPointer<vtkSphereSource>::New();
      sphere1->SetPhiResolution(30);
      sphere1->SetThetaResolution(30);
      sphere1->SetRadius(0.3);

      auto matrix1 = vtkSmartPointer<vtkMatrix4x4>::New();
      auto transform0 = vtkSmartPointer<vtkTransform>::New();

      auto collide = vtkSmartPointer<vtkCollisionDetectionFilter>::New();
      collide->SetInputConnection(0, sphere0->GetOutputPort());
      collide->SetTransform(0, transform0);
      collide->SetInputConnection(1, sphere1->GetOutputPort());
      collide->SetMatrix(1, matrix1);
      collide->SetBoxTolerance(0.0);
      collide->SetCellTolerance(0.0);
      collide->SetNumberOfCellsPerNode(2);
      if (contactMode == 0)
      {
        collide->SetCollisionModeToAllContacts();
      }
      else if (contactMode == 1)
      {
        collide->SetCollisionModeToFirstContact();
      }
      else
      {
        collide->SetCollisionModeToHalfContacts();
      }
      collide->GenerateScalarsOn();

      // Visualize
      auto colors = vtkSmartPointer<vtkNamedColors>::New();
      auto mapper1 = vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper1->SetInputConnection(collide->GetOutputPort(0));
      mapper1->ScalarVisibilityOff();
      auto actor1 = vtkSmartPointer<vtkActor>::New();
      actor1->SetMapper(mapper1);
      actor1->GetProperty()->BackfaceCullingOn();
      actor1->SetUserTransform(transform0);
      actor1->GetProperty()->SetDiffuseColor(
          colors->GetColor3d("Tomato").GetData());
      actor1->GetProperty()->SetRepresentationToWireframe();

      auto mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper2->SetInputConnection(collide->GetOutputPort(1));

      auto actor2 = vtkSmartPointer<vtkActor>::New();
      actor2->SetMapper(mapper2);
      actor2->GetProperty()->BackfaceCullingOn();
      actor2->SetUserMatrix(matrix1);

      auto mapper3 = vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper3->SetInputConnection(collide->GetContactsOutputPort());
      mapper3->SetResolveCoincidentTopologyToPolygonOffset();

      auto actor3 = vtkSmartPointer<vtkActor>::New();
      actor3->SetMapper(mapper3);
      actor3->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());
      actor3->GetProperty()->SetLineWidth(3.0);

      auto txt = vtkSmartPointer<vtkTextActor>::New();
      txt->GetTextProperty()->SetFontSize(18);

      auto renderer = vtkSmartPointer<vtkRenderer>::New();
      renderer->UseHiddenLineRemovalOn();
      renderer->AddActor(actor1);
      renderer->AddActor(actor2);
      renderer->AddActor(actor3);
      renderer->AddActor(txt);
      renderer->SetBackground(colors->GetColor3d("Gray").GetData());
      renderer->UseHiddenLineRemovalOn();

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

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

      // Move the first object
      int numSteps = 100;
      double dx = 1.0 / static_cast<double>(numSteps) * 2.0;
      transform0->Translate(-numSteps * dx - .3, 0.0, 0.0);
      renderWindow->Render();
      renderer->GetActiveCamera()->Azimuth(-60);
      renderer->GetActiveCamera()->Elevation(45);
      renderer->GetActiveCamera()->Dolly(1.2);

      renderWindow->SetWindowName("CollisionDetection");
      renderWindow->Render();

      for (int i = 0; i < numSteps; ++i)
      {
        transform0->Translate(dx, 0.0, 0.0);
        renderer->ResetCameraClippingRange();
        std::ostringstream textStream;
        textStream << collide->GetCollisionModeAsString()
                   << ": Number of contact cells is "
                   << collide->GetNumberOfContacts();
        txt->SetInput(textStream.str().c_str());
        renderWindow->Render();
        if (collide->GetNumberOfContacts() > 0)
        {
          break;
        }
        // The total animation time is 3 seconds
        std::this_thread::sleep_for(std::chrono::milliseconds(3000 / numSteps));
      }
      renderer->ResetCamera();
      renderWindow->Render();
      interactor->Start();
      // In Field Data there will be an array named "ContactCells".
      // This array indexes contacting cells (e.g.) index 50 of array 0
      //  points to a cell (triangle) which contacts/intersects a cell
      //  at index 50 of array 1.
      // You can directly obtain these, see GetContactCells(int i)
      //  in the documentation.
      // collide->GetOutput(0)->Print(std::cout);
      //collide->GetOutput(1)->Print(std::cout);
      return EXIT_SUCCESS;
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(CollisionDetection)

    find_package(VTK COMPONENTS
      vtkvtkCommonColor
      vtkvtkCommonCore
      vtkvtkCommonMath
      vtkvtkCommonTransforms
      vtkvtkFiltersModeling
      vtkvtkFiltersSources
      vtkvtkInteractionStyle
      vtkvtkRenderingContextOpenGL2
      vtkvtkRenderingCore
      vtkvtkRenderingFreeType
      vtkvtkRenderingGL2PSOpenGL2
      vtkvtkRenderingOpenGL2 QUIET)
    if (NOT VTK_FOUND)
      message("Skipping CollisionDetection: ${VTK_NOT_FOUND_MESSAGE}")
      return ()
    endif()
    message (STATUS "VTK_VERSION: ${VTK_VERSION}")
    if (VTK_VERSION VERSION_LESS "8.90.0")
      # old system
      include(${VTK_USE_FILE})
      add_executable(CollisionDetection MACOSX_BUNDLE CollisionDetection.cxx )
      target_link_libraries(CollisionDetection PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      add_executable(CollisionDetection MACOSX_BUNDLE CollisionDetection.cxx )
      target_link_libraries(CollisionDetection PRIVATE ${VTK_LIBRARIES})
      # vtk_module_autoinit is needed
      vtk_module_autoinit(
        TARGETS CollisionDetection
        MODULES ${VTK_LIBRARIES}
        )
    endif ()

### Download and Build CollisionDetection

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

    cd CollisionDetection/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:

    ./CollisionDetection

WINDOWS USERS

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