Consequences of a 0 margin

User avatar
nikki
Posts: 22
Joined: Sat Jun 14, 2008 3:38 pm
Location: Doha, Qatar.

Consequences of a 0 margin

Post by nikki »

What are the consequences of using a 0 margin on a convex hull? This is only for very simple convex hulls (almost as simple as a box).
User avatar
John McCutchan
Posts: 133
Joined: Wed Jul 27, 2005 1:05 pm
Location: Berkeley, CA

Re: Consequences of a 0 margin

Post by John McCutchan »

Hi,

Using the collision shape margin Bullet can avoid performing expensive penetration depth checks when the penetration is smaller than the margins. So, one of the consequences would be decreased performance. I would suggest always using the default margin.

Thanks,
John
User avatar
John McCutchan
Posts: 133
Joined: Wed Jul 27, 2005 1:05 pm
Location: Berkeley, CA

Re: Consequences of a 0 margin

Post by John McCutchan »

Hey,

Another (more important) reason to not use a collision margin of zero comes from how Bullet (GJK) determines the collision normal. GJK is used to determine the closest points on each object to each other. The normal is computed by subtracting closest(A) - closest(B) without a collision margin, the chances that closest(A) == closest(B) are higher. When closest(A) == closest(B) the collision normal will be the zero vector and invalid. Again, you should always use a collision margin.

Thanks,
John
reltham
Posts: 66
Joined: Fri Oct 12, 2007 6:28 pm
Location: San Diego

Re: Consequences of a 0 margin

Post by reltham »

One problem with using a collision margin is that you always have gaps between objects that should be touching.

Like a characters feet not touching the ground, or a box stack with gaps between them.

Of course, this depends a lot on your units, since the hard coded default margin is 0.4. This would be fine if your units are centimeters perhaps, but not when it's meters.

I think the default margin should be some configurable thing at runtime/startup instead of being a define at compile time.
User avatar
John McCutchan
Posts: 133
Joined: Wed Jul 27, 2005 1:05 pm
Location: Berkeley, CA

Re: Consequences of a 0 margin

Post by John McCutchan »

Hi reltham,

This isn't really a problem. Just adjust your rendering geometry so that hides the margin.

Thanks,
John
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Consequences of a 0 margin

Post by Erwin Coumans »

The default margin is 0.04 units, which is 4 centimeter assuming meter units.

For spheres and capsule, the margin is already 'embedded' so there will be no gap. For other shapes, such as boxes you can subtract the margin from the half extents. For convex hull of vertices there is a utility to shrink the shape to encapsulate the margin.

At least one of the collision shapes should have a margin, so as a rule you can safely set the margin for static collision hapes (for example non-moving triangle meshes) to zero.

Hope this helps,
Erwin
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Consequences of a 0 margin

Post by sparkprime »

Erwin Coumans wrote: At least one of the collision shapes should have a margin, so as a rule you can safely set the margin for static collision hapes (for example non-moving triangle meshes) to zero.
Now, that could come in very handy indeed...

An unrelated question: suppose I'm not using metre units, is there a problem with making the collision margin too large? Should it scale with the maximum velocity of the penetrating object?
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Consequences of a 0 margin

Post by sparkprime »

Erwin Coumans wrote: For convex hull of vertices there is a utility to shrink the shape to encapsulate the margin.
Could anyone help me find this utilty?

btConvexHullShape does not modify its vertices, HullLibrary and HullResult don't seem to mention margins, and although btShapeHull::buildHull has a "margin" parameter, this is not used in the code.

I tried to do it myself using two methods - firstly subtracting the margin from the vector (0,0,0)->p for all points p in the hull and secondly subracting the margin from each axis of each point p. Neither produced convex meshes that stacked neatly.

thanks
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Consequences of a 0 margin

Post by Erwin Coumans »

You can try to use btGeometryUtil to convert vertices into plane equations, move the plane equations inwards and create vertices from the intersection of the shifted plane equations. See this code snippet from ConvexDecompositionDemo:

Code: Select all

//Input is a set of vertices (point cloud)
#define SHRINK_OBJECT_INWARDS 1
#ifdef SHRINK_OBJECT_INWARDS
                                        std::vector<btVector3> planeEquations;
                                        btGeometryUtil::getPlaneEquationsFromVertices(vertices,planeEquations);

                                        std::vector<btVector3> shiftedPlaneEquations;
                                        for (int p=0;p<planeEquations.size();p++)
                                        {
                                                btVector3 plane = planeEquations[p];
                                                plane[3] += collisionMargin;
                                                shiftedPlaneEquations.push_back(plane);
                                        }
                                        std::vector<btVector3> shiftedVertices;
                                        btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,shiftedVertices);


                                        btCollisionShape* convexShape = new btConvexHullShape(&(shiftedVertices[0].getX()),shiftedVertices.size());

Hope this helps,
Erwin
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Consequences of a 0 margin

Post by sparkprime »

That function works nicely, thanks.
I changed the code slightly because I already had a btConvexHull object I wanted to populate and std::vector didn't work.

For the benefit of anyone else in this situation:

Code: Select all

#include <LinearMath/btGeometryUtil.h>

...

        btAlignedObjectArray<btVector3> vertexes = ...; // put all the hull vertexes in here

        btAlignedObjectArray<btVector3> planes;
        btGeometryUtil::getPlaneEquationsFromVertices(vertexes, planes);
        int sz = planes.size();
        for (int i=0 ; i<sz ; ++i) {
                planes[i][3] += s->getMargin();
        }
        vertexes.clear();
        btGeometryUtil::getVerticesFromPlaneEquations(planes, vertexes);

        sz = vertexes.size();
        for (int i=0 ; i<sz ; ++i) {
                s->addPoint(vertexes[i]);
        }
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Consequences of a 0 margin

Post by dphil »

Sparkprime, thanks for posting your code (and thanks to Erwin for the original version). It's very helpful when people post their solutions for those who may have the same problem. It indeed helped me as I had the same issue.

One additional problem I have though... the convex hulls I am dealing with are ones that are generated automatically by convex decomposition of a mesh. If I set the level of decomposition high enough, I was sometimes getting strange memory access errors during collisions. I traced this down to an issue with a margin, and I believe what is happening is that some of the generated convex hulls were so small that the shrinking of their vertices (via the code you/Erwin posted) was causing their shapes to shrink to nothing (all vertices shrunk to the same centre point?) or perhaps even turned inside out.

So I'm wondering how I would go about ensuring that the convex hull is not too small to be shrunk by. Perhaps if the value of planes[3] is less than or greater than some value?
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Consequences of a 0 margin

Post by dphil »

Ok, I think I figured it out. plane[3] values should be negative, and problems occur when they pass 0 and become positive (indicating that the shape is essentially flipping inside out, or something like that). So I modified sparkprime's code to ensure shrinking only occurs if the shape is large enough to avoid errors when shrinking objects smaller than the margin.

Code: Select all

btAlignedObjectArray<btVector3> vertices = ...;

btConvexHullShape convexShape = new btConvexHullShape();
convexShape->setMargin(someValue);

btAlignedObjectArray<btVector3> planes;
btGeometryUtil::getPlaneEquationsFromVertices(vertices, planes);

int sz = planes.size();
bool tooSmall = false;
for (int i=0 ; i<sz ; ++i) {
	if ((planes[i][3] += convexShape->getMargin()) >= 0) {
		tooSmall = true;
		break;
	}
}

if (!tooSmall) {
	vertices.clear();
	btGeometryUtil::getVerticesFromPlaneEquations(planes, vertices);
}

sz = vertices.size();
for (int i=0 ; i<sz ; ++i) {
	convexShape->addPoint(vertices[i]);
}
This is probably not necessary for most people, but is a good safety check anyway, particularly when dealing with convex hulls of unknown, potentially small size (like I am).
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Consequences of a 0 margin

Post by sparkprime »

Interesting, I'll add that to my code too.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Consequences of a 0 margin

Post by sparkprime »

Does this mean it only works when the convex hull is defined such that (0,0,0) in object space is within the bounds of the hull? I have several where this is not true, because they form part of a compound.
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Consequences of a 0 margin

Post by dphil »

I have some hulls in the same situation (not enclosing {0,0,0} in object space), but it doesn't seem to be an issue. The code has stood up to several preliminary tests I've done. If some erroneous case comes up, I'll post it.