13. Contact reduction

By using contact reduction, the number of contact points later submitted to the solver as contact constraint can be heavily reduced, hence improving performance.

13.1. Motivation

Assume a rigid body has one or several geometries associated to it. When these geometries collide with the geometries from another rigid body, contact points will be generated. Given a complicated geometry or shape, or many overlapping geometries, a lot of contact points will be created. Each contact point will later lead to a contact constraint which must be handled by the solver. Since frictional contacts are relatively expensive to solve, the fewer contact points/constraints, the better from a CPU usage point of view. Also, in some cases too many contacts can lead to an over-determined system and cause the simulation to deliver bad results.

For example: a box on a plane only needs 3-4 contacts to stand stable. Assume you have a height field as a plane, and a trimesh as a box, both being highly tessellated. This scenario could easily generate 100s of contacts, where only 3-4 are necessary.

13.2. Technical details

The reduction is done by the class agxCollide::ContactReducer, where contact points are reduced by a 6-dimensional binning algorithm in [nxp, n]-space. Here, n is the contact normal and p the contact point relative to a reference point (e.g. one body’s center of mass, or the world origin).

In the overall physics pipeline, contacts can get reduced on two levels:

  • Directly in the narrow phase stage, contact reduction is done on each geometry-geometry interaction (can be controlled, see below). Contact points that are reduced get removed immediately.

  • After collision detection and before stepping the Dynamics system (PRE), contact reduction is done on some rigidbody-rigidbody interactions (can be controlled, see below).

The contact reduction within the physics pipeline can be controlled in three ways:

  1. By setting the reduction mode (ContactReductionMode). Either no reduction, or per geometry overlap, or per geometry overlap AND per rigid body overlap.

  2. By setting the bin resolution (number of bins per dimension). Given a bin resolution of n, this could lead to n^6 contacts being left after reduction in worst case. Average case is about n^2. The bin resolution can be set differently for geometry overlaps and rigid body overlaps.

  3. By setting the threshold for doing contact reduction. In order not to waste time on doing contact reduction for contacts with small numbers of contact points, contact reduction is only done on contacts which exceed a certain number of contact points. This threshold can be set separately for geometry-geometry-overlaps and rigidbody-rididbody-overlaps.

It is possible to call agxCollide::ContactReducer::reduce manually.

One obvious use case is wanting to analyze all contact points before sending them to the solver. This can be done by

  • setting the reduction mode to REDUCE_NONE for a contact material as in the example in the next chapter,

  • and then in a ContactEventListener:

  • analyze the contacts as desired

  • do a manual call to contact reduction

  • Note that this might interfere with other ContactEventListeners listening to the same contact!

Note that currently, the only directly supported way to do contact reduction and send the reduced contacts to the solver is in ContactEventListeners.

13.3. ReductionMode

AGX has two steps where contacts are reduced:

  • For a pair of overlapping geometries (with potentially several shapes)

  • For a pair of overlapping rigid bodies (with potentially several geometries).

By default, AGX does one contact reduction pass between each pair of overlapping geometries.

This behavior can be changed to one of the three modes:

/// Specifies the mode for contact reduction
     enum ContactReductionMode {
       REDUCE_NONE,               /**< No contact reduction enabled */
       REDUCE_GEOMETRY,           /**< Default: Reduce contacts between geometries */
       REDUCE_ALL                 /**< Two step reduction: first between geometries, and then between rigid bodies */
     };

The contact reduction mode can be set per contact material. An example:

// We want to reduce contacts not only between each geometry, but between body and other body

// Assume we have a body and five geometries, each with e.g. one or more trimesh shapes.
rigidBody->add( geometry1 );
rigidBody->add( geometry2 );
rigidBody->add( geometry3 );
rigidBody->add( geometry4 );
rigidBody->add( geometry5 );

// Assign a material to the geometries
geometry1->setMaterial( material1 );
geometry2->setmaterial( material1 );

// Assume we also have another body which we also assign a material to
otherBody->add( otherGeometry );
otherGeometry->setMaterial( material2 );

// Create a new contact material
agx::ContactMaterialRef cm = simulation->getMaterialManager()->getOrCreateContactMaterial(material1, material2);

// Set contact reduction mode to REDUCE_ALL - now, contacts between rigidBody and otherBody
// get reduced together, not only each contact by itself.
cm->setContactReductionMode( agx::ContactMaterial::REDUCE_ALL );

Note that REDUCE_ALL is not the default for a reason:

Often, bodies are assigned different geometries because one would like to set different materials on these geometries, resulting in different physical behavior (e.g. vary friction, Young’s modulus, …).

Contact reduction with REDUCE_ALL does not take these differences into account, but reduces over all contact points. However, each contact point will remain in the GeometryContact it belongs to, and only GeometryContacts with a contact material with REDUCE_ALL set will be reduced upon.

All geometries without a rigid body will be treated as belonging to the same one when doing contact reduction between rigid bodies. If you want to avoid geometry contacts from several geometries without rigid bodies to end up in the same reduction, move these geometries into separate (static) rigid bodies.

13.3.1. Bin resolution

The bin resolution gives the number of bins per dimension. Given a bin resolution of n, this could lead to n^6 contacts in worst case, where the average case is about c*n^2 (common contact region, like in convex overlaps).

The bin resolution can be set differently for geometry overlaps and rigid body overlaps, as well as for manual contact reduction.

In the general case, a bin resolution of between 1 and 10 is allowed, where typical values are 2 or 3.

Below is a more detailed description.

13.3.1.1. Geometry overlaps

The bin resolution for contact reduction for rigid body overlaps can only be given for the whole simulation by setting the value like in this example:

// Set contact reduction bin size to 3 for simulation (rigid body overlaps).
sim->setContactReductionBinResolution( 3 );

The bin resolution for contact reduction for geometry overlaps can be set per contact material:

// Create a new contact material
agx::ContactMaterialRef cm = simulation->getMaterialManager()->getOrCreateContactMaterial(material1, material2);

// Set contact reduction bin size to 3 for contact material (all geometry overlaps with this contact material).
cm->setContactReductionBinResolution( 3 );

If the bin resolution is set to zero (not allowed in other contexts, see above) in the contact material or if no contact material is used, a fallback value from agxCollide::Space is used which can be specified like in this example:

// Set contact reduction bin size to 3 for space (fallback value for geometry overlaps).
agxCollide:;SpaceRef = sim->getSpace();
space->setContactReductionBinResolution( 3 );

13.3.1.2. Rigid body overlaps

The bin resolution for contact reduction for rigid body overlaps can only be given for the whole simulation by setting the value like in this example:

// Set contact reduction bin size to 3 for simulation (rigid body overlaps).
sim->setContactReductionBinResolution( 3 );

13.3.1.3. Manual contact reduction

The bin resolution for manual contact reduction can be given in the reduce-call to contact reducer (a static method):

// Set contact reduction bin size to 3 for simulation (rigid body overlaps).
size_t binResolution = 3;
agxCollide::ContactReducer::reduce(contactPoints, binResolution);

13.3.2. ContactReductionThreshold

The contact reduction between overlapping geometries is enabled by default (otherwise dependent on the material’s reduction mode, see chapter above) and will be activated when the number of contact points between two geometries is larger than a specified threshold. This threshold is set globally in agxCollide::Space (since space is responsible for geometries):

agxCollide::SpaceRef space = new agxCollide::Space();
// More than 10 contact points will trigger contact reduction
space-> setContactReductionThreshold( 10 );

The additional contact reduction between overlapping rigid bodies is disabled by default (otherwise dependent on the material’s reduction mode, see chapter above) and will be activated when the number of contact points between two rigid bodies is larger than a specified threshold. This threshold is set globally in agxSDK::Simulation:

agxSDK::SimulationRef sim = new agxSDK::Simulation();
// More than 10 contact points will trigger contact reduction
sim-> setContactReductionThreshold( 10 );