Different jitter on different shape types?

pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Different jitter on different shape types?

Post by pico »

Erwin Coumans wrote:
pico wrote: It seems the effect only happens when the box crosses a triangle edge.
In that case, the sliding box is hitting an internal edge indeed.

We can add some option/workaround for static triangle meshes, to always return the triangle normal. This will eliminate the effect of hitting internal triangle edges, at the cost of some side effect. It might help you.

I'll add it to the todo, and try to add it before next release,
Thanks,
Erwin
I tested this now also with a sphere. The behaviour is the same. The spheres movement gets affected by polygon edges.
I would be really thankful for a fix.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Different jitter on different shape types?

Post by Erwin Coumans »

pico wrote: I tested this now also with a sphere. The behaviour is the same. The spheres movement gets affected by polygon edges.
I would be really thankful for a fix.
We'll try to provide the option to use triangle normals for triangle meshes in Bullet 2.67 (avoiding hitting internal edges), but the Game Developers Conference preparations are primary focus right now.

Thanks,
Erwin
AlexSilverman
Posts: 141
Joined: Mon Jul 02, 2007 5:12 pm

Re: Different jitter on different shape types?

Post by AlexSilverman »

I believe I'm avoiding this (or maybe just not paying close enough attention) by using the following callback funtion when a contact has been added (search for ContactAddedCallback in the demo suite for how to use).

Code: Select all

bool NotifyOnCollision(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
{
    if(((CENGutil_PhysicsEntry *)(colObj0->getUserPointer()))->GetType() == PHYS_TRI_MESH)
    {
        btTriangleShape* triangle = (btTriangleShape*)colObj0->getCollisionShape();
    	const btVector3* vertices = &triangle->getVertexPtr(0);
    
    	cp.m_normalWorldOnB = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
    }
    else if(((CENGutil_PhysicsEntry *)(colObj1->getUserPointer()))->GetType() == PHYS_TRI_MESH)
    {
        btTriangleShape* triangle = (btTriangleShape*)colObj1->getCollisionShape();
    	const btVector3* vertices = &triangle->getVertexPtr(0);
    
    	cp.m_normalWorldOnB = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
    }
	return true;
}
Ignore the bit about CENGutil_PhysicsEntry, as that's just a part of the engine we're using, but I basically see if either colliding object is a triangle, and if so I overwrite the collision normal with the triangle normal. Since implementing this I haven't seen edge collisions anymore. There's probably a much better way to integrate this into Bullet someplace deeper down, but this was my solution.

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

Re: Different jitter on different shape types?

Post by Erwin Coumans »

Good point Alex, it is a good idea to deal with this in a ContactAddedCallback. That way you can add some more heuristic, in case the general case isn't working out for certain triangles (at a cliff for example).

pico, can you try Alex' suggestion?
Thanks,
Erwin
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Different jitter on different shape types?

Post by pico »

Erwin Coumans wrote:Good point Alex, it is a good idea to deal with this in a ContactAddedCallback. That way you can add some more heuristic, in case the general case isn't working out for certain triangles (at a cliff for example).

pico, can you try Alex' suggestion?
Thanks,
Erwin
I added the callback and it got executed. There was no visible difference in behavior.

I have now a more simple testcase:
- I generate a sphere
- I generate a subdivided xz aligned trimesh plane
- I give the sphere a single central impulse on Z direction
Observation: Instead of rolling straight the sphere gets slightly bounced by the normal of the crossed edges

Any pool, football, bowling or golf game should suffer from this.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Different jitter on different shape types?

Post by Erwin Coumans »

pico wrote: I added the callback and it got executed. There was no visible difference in behavior.
Did you double-check that your callback is actually executed?

You should enable the callback, only for the objects that need it (triangle mesh).

Code: Select all

//enable custom material callback
staticBody->setCollisionFlags(staticBody->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
See the ConcaveDemo.

Hope this helps,
Erwin
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Different jitter on different shape types?

Post by Dirk Gregorius »

Just an idea, but I could imagine that you also need to correct the penetration depth. Basically I would simply project the penetration depth vector onto the new normal. E.g.

float d_new = dot( d_old * n_old, n_new )

Here d is the penetration depth and n the normal.


Cheers,
-Dirk
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Different jitter on different shape types?

Post by pico »

Erwin Coumans wrote:
pico wrote: I added the callback and it got executed. There was no visible difference in behavior.
Did you double-check that your callback is actually executed?

You should enable the callback, only for the objects that need it (triangle mesh).

Code: Select all

//enable custom material callback
staticBody->setCollisionFlags(staticBody->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
See the ConcaveDemo.

Hope this helps,
Erwin
Yes, i double checked as i had a breakpoint in the callback. I also have the callback only for the trimesh.
The cp.m_normalWorldOnA/B got changed but the visual result was still wrong.

I was also expecting this should work. Tho I think Dirk is right that penetration depth may matter.
I actually don't know the inner Bullet workings and how penetration depth is handled.
Maybe you could modify the below code to reflect PD?
Then i could try right away:

static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
{
btCollisionShape* col0Shape= (btCollisionShape*)colObj0->getCollisionShape();
btCollisionShape* col1Shape= (btCollisionShape*)colObj1->getCollisionShape();

if (col0Shape->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
{
btTriangleShape* triangle = (btTriangleShape*)col0Shape;
const btVector3* vertices = &triangle->getVertexPtr(0);

cp.m_normalWorldOnB = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
}
else if (col1Shape->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
{
btTriangleShape* triangle = (btTriangleShape*)col1Shape;
const btVector3* vertices = &triangle->getVertexPtr(0);

cp.m_normalWorldOnB = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
}

return true;
}
Dirk Gregorius
Posts: 861
Joined: Sun Jul 03, 2005 4:06 pm
Location: Kirkland, WA

Re: Different jitter on different shape types?

Post by Dirk Gregorius »

Conceptually you could try this. Note that I just quickly looked into Bullet and didn't compile anything. Please let me know how it works and even if not how the behavior changed.

Code: Select all

static bool CustomMaterialCombinerCallback(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
    {
    btCollisionShape* col0Shape= (btCollisionShape*)colObj0->getCollisionShape();
    btCollisionShape* col1Shape= (btCollisionShape*)colObj1->getCollisionShape();

    if (col0Shape->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
        {
        btTriangleShape* triangle = (btTriangleShape*)col0Shape;
        const btVector3* vertices = &triangle->getVertexPtr(0);

        btVector3 normal =  (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
        float distance =  ( cp.m_distance1 * cp.m_normalWorldOnB ).dot( normal );
   
        cp.m_normalWorldOnB = normal;
        cp.m_distance1 =  distance;
        }
    else if (col1Shape->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
        {
        btTriangleShape* triangle = (btTriangleShape*)col1Shape;
        const btVector3* vertices = &triangle->getVertexPtr(0);

        btVector3 normal =  (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
        float distance =  ( cp.m_distance1 * cp.m_normalWorldOnB ).dot( normal );
   
        cp.m_normalWorldOnB = normal;
        cp.m_distance1 =  distance;
        }

    return true;
    }
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Different jitter on different shape types?

Post by pico »

[quote="Dirk Gregorius"]Conceptually you could try this. Note that I just quickly looked into Bullet and didn't compile anything. Please let me know how it works and even if not how the behavior changed.

Hi,

thanks for that.

The behavior didn't changed. I think now the problem hides somewhere else. Check out my reply to Erwin.
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Re: Different jitter on different shape types?

Post by pico »

Erwin Coumans wrote:
pico wrote: I added the callback and it got executed. There was no visible difference in behavior.
Did you double-check that your callback is actually executed?

You should enable the callback, only for the objects that need it (triangle mesh).

Code: Select all

//enable custom material callback
staticBody->setCollisionFlags(staticBody->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
See the ConcaveDemo.

Hope this helps,
Erwin
Hi Erwin & Dirk,

the behaviour is still the same when using Dirks code. The spheres' direction gets changed when rolling over a subdivided plane.

When i examined the generated normal in the CustomMaterialCombinerCallback i have seen there was never a X or Z component. Only the Y component was !=0, although the sphere changed its direction.

Where else, beside the CustomMaterialCombinerCallback, could the spheres' direction be affected?
helicase
Posts: 5
Joined: Tue Feb 26, 2008 3:53 am

Re: Different jitter on different shape types?

Post by helicase »

I am having a similar problem (2.66)

I have a box sliding along a heightfield mesh. The mesh is flat. The box will occasionally veer off to the side, or worse, flip suddenly.

Upon rendering the contactnormals I see that they are unstable! They sometimes (seemingly randomly) go off to the side. I tried using a ContactAddedCallback to force the normals to be the face normal as above. This had no effect. I then iterated through the manifold points after each step, looked for terrain contacts, and forced their normals the same way. This also had no effect. I believe the contact normals are being recalculated and modified inside the simulation step, making these normal changes moot.

Also, when the box slides fast enough, there aren't any persistent contacts at all because the orthogonal velocity is too great. The fact remains that response impulses are being generated with the wrong normals every now and then. I spent a few hours trying to find out what could be causing this and I'm stumped.

Note: when using a groundplane, it works perfectly, so the problem is with the calculation of triangle collision normals.

Here's a screenshot.
normal_prob.png
You do not have the required permissions to view the files attached to this post.
helicase
Posts: 5
Joined: Tue Feb 26, 2008 3:53 am

Re: Different jitter on different shape types?

Post by helicase »

OK, this obviously isn't a general solution to the problem as you'd need to provide an option for this somewhere, but I added this to btConvexConvexAlgorithm.cpp in processCollision

Code: Select all

	input.m_transformA = body0->getWorldTransform();
	input.m_transformB = body1->getWorldTransform();
	
	m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);

	// added VVVVV
	btCollisionShape *useTriangleNormal = NULL;

	if ( (body0->getCollisionShape()->getShapeType()) == TRIANGLE_SHAPE_PROXYTYPE )
	  useTriangleNormal = (btCollisionShape*)(body0->getCollisionShape());
	else if ( (body1->getCollisionShape()->getShapeType()) == TRIANGLE_SHAPE_PROXYTYPE )
	  useTriangleNormal = (btCollisionShape*)(body1->getCollisionShape());


	if (useTriangleNormal) {
	  int numContacts = resultOut->getPersistentManifold()->getNumContacts();

	  for (int j = 0; j < numContacts; j++) {
	    btManifoldPoint &cp = resultOut->getPersistentManifold()->getContactPoint(j);
	    const btVector3 *vertices = &(((btTriangleShape*)useTriangleNormal)->getVertexPtr(0));
	    btVector3 normal = (vertices[2]-vertices[0]).cross(vertices[1]-vertices[0]);
	    cp.m_normalWorldOnB = normal;
	    cp.m_distance1 = ( cp.m_distance1 * cp.m_normalWorldOnB ).dot( normal );
	  }
	}
This succeeded in forcing the collision normals to be the face normals of the trimesh. The jumping around/jittering is now gone - no more flipping around just when going straight. However, I still have the veering issue. My box, despite going straight forward across flat terrain, still veers off gradually to one side, whereas it goes straight on a static plane shape.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Different jitter on different shape types?

Post by Erwin Coumans »

We'll try to address this issue for Bullet 2.68.

You can track the status here:
http://code.google.com/p/bullet/issues/detail?id=27

Thanks for the feedback,
Erwin
pico
Posts: 229
Joined: Sun Sep 30, 2007 7:58 am

Issue 27: Provide solution to filter out unwanted collision

Post by pico »

> We need some good reproduction cases. Will ask for them on the forum.

To reproduce:

-Generate a flat subdivided triangle mesh.
-Place a sphere slightly above.
-Give the sphere a high gravity and let it drop down to the mesh.
-The sphere will spin away when its dropped on a triangle edge instead of pushed upward