Collision Detection in ODA Visualize (Part 1 of 3)

Egor Slupko

October 12, 2018

ODA Visualize contains a graphics system with a collision detection mechanism. It also contains an API that allows developers to create custom collision detection functionality. The current collision detection implementation processes triangular representations of entities and does not detect collisions between line primitives (lines, curves, etc.).

ODA’s collision detection functionality is carried out by OdGsView::collide. This call modifies a geometry conveyor by adding a new collision detection conveyor node that implements an OdGiCollideProc interface:

image1

This node collects triangular representations of entities and detects collisions between them using OdGiCollisionDetector. All detected collisions are processed by implementation of OdGsCollisionDetectionReactor.

Triangle collection goes through a vectorization process. However, if a device supports the useMetafileAsGeometry option, triangles are collected from metafiles which increases performance.

Overview of OdGsView::collide

The main collision detection method is described in Gs.h:

virtual void collide( OdGiPathNode const*const* pInputList, OdUInt32 nInputListSize, OdGsCollisionDetectionReactor* pReactor, OdGiPathNode const*const* pCollisionWithList = NULL, OdUInt32 nCollisionWithListSize = 0, const OdGsCollisionDetectionContext* pCtx = NULL ) = 0;
  • OdGiPathNode const*const* pInputList — List of GiPathNode that represents input entities; can be NULL.
  • OdUInt32 nInputListSize — Size of input list; can be 0.
  • OdGsCollisionDetectionReactor* pReactor — Pointer to the reactor that processes detected collisions; cannot be NULL.
  • OdGiPathNode const*const* pCollisionWithList — List of GiPathNode that represents entities to check with the input list for collisions; can be NULL.
  • OdUInt32 nCollisionWithListSize — Size of list; can be NULL.
  • const OdGsCollisionDetectionContext* — Pointer to the context that provides additional collision detection properties; can be NULL.

Based on this there are three possible ways to use the OdGsView::collide method:

  1. Detect collisions between all entities in the view:
    pView->collide( NULL, 0, &reactor );
  2. Detect collisions between specified entities and all other entities:
    pView->collide( pList, nListSize, &reactor );
  3. Detect collisions between entities from two different lists:
    pView->collide( pList1, nList1Size, &reactor, pList2, nList2Size );

Overview of OdGsCollisionDetectionReactor

The reactor interface is described in Gs.h and contains only one method:

virtual OdUInt32 collisionDetected(const OdGiPathNode* pPathNode1, const OdGiPathNode* pPathNode2)

This method is called for each detected collision. The input parameters are two OdGiPathNode values that represent colliding entities. The return value must be one of two values:

  • OdGsCollisionDetectionReactor::kContinue continues collision detection between other entities.
  • OdGsCollisionDetectionReactor::kBreak interrupts the collision detection process. This can be useful for checking only whether collisions exist but not which entities collide.

Note that transferred pointers to OdGiPathNode may be destroyed after the OdGsView::collide call is complete, so paths should be copied if processing them is postponed.

Overview of OdGsCollisionDetectionContext

The context is described in Gs.h. Currently it supports only one option: OdGsCollisionDetectionContext::kIntersectOnly. If this option is enabled, entities that touch each other are not detected as a collision. Such entities are detected as a collision if this option is disabled or if a pointer to the context in the OdGsView::collide call is NULL.

The next article in this series will describe how to try out OdGsView::collide.