Click or drag to resize
DigitalRuneHow To: Compute Contacts between Objects

This topic will demonstrate how to use a collision domain to compute contacts between several objects.

This topic contains the following sections:

Add DigitalRune namespaces

The following example will use data types from DigitalRune Geometry and Mathematics. The following namespaces must be imported at the beginning of the source code file:

C#
using DigitalRune.Geometry;
using DigitalRune.Geometry.Collisions;
using DigitalRune.Geometry.Shapes;
using DigitalRune.Mathematics.Algebra;
using DigitalRune.Mathematics.Statistics;
Create a collision domain and collision objects

A collision domain manages a group of collision objects. It is not necessary to use a collision domain to compute contacts between objects. CollisionDetection can compute this as well. But it is strongly recommended to use a collision domain because it is much faster. The domain can optimize the contact computation because all relevant objects must be registered in the domain beforehand and the domain can re-use old contact information. A collision domain is created with

C#
CollisionDomain domain = new CollisionDomain();

Most games will use one collision domain for all collision objects.

Next, we add a couple of box-shaped collision objects with random positions and random orientations.

C#
for (int i = 0; i < 100; i++)
{
  // Define position/orientation and shape.
  GeometricObject geometricObject = new GeometricObject()
  {
    Shape = new BoxShape(1, 2, 3),
    Pose = new Pose(RandomHelper.Random.NextVector3F(-20, 20),
    RandomHelper.Random.NextQuaternionF())),
  };

  // Create collision object.
  CollisionObject collisionObject = new CollisionObject(geometricObject);

  // Add collision object to collision domain.
  domain.CollisionObjects.Add(collisionObject);
}
Compute contacts

The collision domains computes all contacts by calling

C#
domain.Update(1.0f / 60.0f);

The method argument is the size of the time step, which is 1/60 s (60 Hz) for most games. This method is usually called once per frame. After this call the collision domain contains up-to-date contact information for all collision objects. Following code enumerates all pairs of touching objects:

C#
foreach (ContactSet contactSet in domain.ContactSets)
{
  // Get touching object pair.
  CollisionObject objectA = contactSet.ObjectA;
  CollisionObject objectB = contactSet.ObjectB;

  // Handle contact of the objects, for example:
  // - play a sound,
  // - reduce "health" of objects,
  // - move objects,
  // - ...
}

The contact set also contains contacts that describe the contact details, including penetration depth, normal vector, contact position, age of the contact, etc.

If you are only interested in the contact of a specific object or a specific object pair, you can call:

C#
// Check if object 21 touches any other object.
bool object21HasContact = domain.HasContact(domain.CollisionObjects[21]);

// Check if object 10 touches object 20.
bool object10And20HaveContact = domain.HaveContact(domain.CollisionObjects[10], domain.CollisionObjects[20]);

// Get all contact sets for object 73.
// (Each contact set describes the contacts between a pair of collision objects.)
IEnumerable<ContactSet> contactsWithObject73 = domain.GetContacts(domain.CollisionObjects[73]);
Note Note

In a typical main loop of a game the following steps will usually be performed:

  1. Get the contacts of the objects from the collision domain.

  2. Change the poses of the collision objects according to the contact information. For example, let objects stop or bounce if they hit a wall.

  3. Update the collision domain to compute new contacts.