1
\$\begingroup\$

I'm looking for ways to calculate the degree of contact between two objects in a scene. I was thinking that calculating the hausdorff distance would be a useful approximation if it is then normalized somehow using the surface area/volume of the objects. Does anyone have any experience calculating this in Unity? Or have any suggestions for other ways to approximate this?

Edit: For some context, I'm working on a project which involves looking at the relationship between geometric properties and relations of objects, and what language/words people use to describe objects and I am using scenes in unity to test this. The notion of 'contact' appears to be an important one and it would be useful to be able to quantify the amount of contact between two objects in a scene

\$\endgroup\$
  • \$\begingroup\$ Can you give us a bit of context about what you want to use this measure for? That might give us clues about what kinds of approximation are appropriate for your needs. \$\endgroup\$ – DMGregory May 23 '19 at 13:24
  • \$\begingroup\$ Good point! I've added some context \$\endgroup\$ – A. Bollans May 23 '19 at 18:33
1
\$\begingroup\$

I don't think Hausdorff distance is an appropriate measure of "contact".

Imagine we have two objects, finite in extent, touching at one point, with neither fully enclosed by the other. I can increase the Hausdorff distance to be arbitrarily great by taking part of one object's surface on the far side from the contact point, and extruding it into a spike or tendril that escapes to a great distance from the other object. I haven't changed the nature of the contact, I've just changed the shape of a part of the object nowhere near the contact, and yet I've completely distorted the measure.

So I think what you want is something more like the closest distance / penetration distance, or a measure of the volume of space sandwiched "between" the objects.


If your objects are, or can be well approximated by, collision primitives, then you may be able to use the physics engine to estimate the smallest distance between them:

  • If a collider of one object intersects a collider of the other, Physics.ComputePenetration will tell you how deeply it penetrates (ie. what is the minimal translation vector we'd need to apply to separate them?)

  • If none of the first object's colliders intersect any of the other's, then you can use Physics.ClosestPoint to find the closest separations between them. If your shapes are convex, then it suffices to find the closest point on each collider to the center of each of the other object's colliders, then finding the closest point on the other object's collider to that point. If your shapes can be concave, then you may be forced to scatter sampling points along the surface of the concave shape and try to find closest points to those samples.


Another strategy you may be able to use if your contacts are "plane-ish" (ie. not wrapped around, like entwined chain links) is to use the rendering system to convert the 3D space to a raster image you can more easily analyze.

  • First, identify the approximate axis of approach - this might be as simple as a line drawn through each object's centres, or determined using crude collider approximations as above.

  • Position an orthographic camera so that it looks along this axis, scaled so at least one of the objects just fills its view (it's OK if the other extends out of frame - since we're looking for contacts, we only need the pixels that overlap both objects)

  • Render the further object's front faces, with depth-testing set to "less", drawing the depth of each rendered pixel to one render target.

  • Render the nearer object's back faces, with depth-testing set to "greater", drawing the depth of each rendered pixel to a second render target.

  • Subtract one render target from the other: this is the depth of separation between the objects at this point, along your chosen axis. It will be negative where the objects intersect (a penetration depth).

Now you can apply any image analysis technique you can imagine to this separation depth map. You could look for its local minima (near-contact points or deepest intersections). You could sum areas of pixels to compute the volume of space in the sandwich. You could form a histogram of separation distances to categorize things that approach at only a few points vs objects that stay closely parallel/lapped over a large area...

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the input. The methods you describe in the first part will certainly be helpful in ascertaining if two objects are touching, or if not how close they are to touching. \$\endgroup\$ – A. Bollans Jul 13 '19 at 16:00
  • \$\begingroup\$ The issue I have though is that I would like to calculate the amount of contact between two surfaces, e.g. imagine a pencil is on a table, there would be more contact between the pencil and the table if it were laying flat compared to if it were stood on its end. I guess the way to do this would be to find how many vertices of one object are within some threshold distance from the other object, but this seems quite intensive? I also need to do this automatically for lots of pairs, so your second method doesn't seem feasible. \$\endgroup\$ – A. Bollans Jul 13 '19 at 16:07
  • \$\begingroup\$ A voxel-based approach may be better for your situation then. \$\endgroup\$ – DMGregory Jul 13 '19 at 16:14
0
\$\begingroup\$

Initially I thought iterating over all vertices in a mesh would be too computationally expensive to do for each pair of objects but it turns out not to be, especially since my meshes are relatively simple.

To calculate the proportion of contact between two gameobjects, e1 and e2, I iterate through all vertices, v1, in the instantiated mesh of e1 and find the closest point on the mesh collider of e2: v2= e2.meshColl.ClosestPoint(v1). If the distance from v1 to v2 is under some threshold distance (0.01f appears to be the default in unity), then the vertex v1 is deemed to be in contact with the object e2. The proportion of contact between e1 and e2 is the number of vertices of e1 in contact with e2 divided by the total number of vertices in e1. Note that this is not a symmetric measure i.e. in general contact(e1,e2) != contact(e2,e1)

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This can be problematic if the first object e1 has large surfaces of straight lines without many vertices e.g. tabletops. It would be ideal to normalize meshes somehow beforehand to add vertices in such instances and/or remove vertices from overly dense meshes \$\endgroup\$ – A. Bollans Nov 10 '19 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.