gContactDestroyedCallback not being called?

Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

gContactDestroyedCallback not being called?

Post by Wavesonics »

I just started implementing bullet's custom collision callbacks and have been having some trouble:

Code: Select all

extern ContactDestroyedCallback		gContactDestroyedCallback;
extern ContactAddedCallback			gContactAddedCallback;

bool customContactDestroyedCallback( void* userData ) {
   cout << "custom destroyed callback!" << endl;
   return false;
}

bool customContactAddedCallback( btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,
                              int index0,const btCollisionObject* colObj1,int partId1,int index1 ) {
   cout << "custom added callback!" << endl;
   return false;
}

void physicsInit() {

   // Create physics solvers and such here
   ...................

   // Set the custom collision callback
   gContactDestroyedCallback = customContactDestroyedCallback;
   gContactAddedCallback = customContactAddedCallback;

   ..................

    // Tell the physics system to use our custom callback
    physObj->body->setCollisionFlags( physObj->body->getCollisionFlags() | 
btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK );

      // Associate the body with our physical body structure
      physObj->body->setUserPointer( physObj );

    m_dynamicsWorld->addCollisionObject( physObj->body, collisionGroup, collidesWith );
}
But I only get output from the custom "added" callback. If two objects collide and bounce off each other, shouldn't the contact point be destroyed, and thus call my callback?

Now, the reason I am doing this is because when two specific types of objects collide I want to destroy one of them (delete it). I figured the deleted call back was optimal because removing an object mid collision is warned against in the things I have read. So, assuming I can get this callback to work, what would be the best way of associating the collided bodies with my game objects? I've read a little about user data pointers but havent seen anyway to set them, is this what they are for?
Last edited by Wavesonics on Thu Jun 12, 2008 7:09 pm, edited 2 times in total.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: gContactDestroyedCallback not being called?

Post by Erwin Coumans »

Can it be reproduced in a Bullet demo?
I've read a little about user data pointers but havent seen anyway to set them
Check out btCollisionObject

Code: Select all

	///users can point to their objects, userPointer is not used by Bullet
	void*	getUserPointer() const
	{
		return m_userObjectPointer;
	}
	
	///users can point to their objects, userPointer is not used by Bullet
	void	setUserPointer(void* userPointer)
	{
		m_userObjectPointer = userPointer;
	}
Hope this helps,
Erwin
Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

Re: gContactDestroyedCallback not being called?

Post by Wavesonics »

thanks for the reply :)

I'm running this code on the Wii, so I cant very easily try the demos,
and I very seriously doubt that it is a porting issue.

So I will try to do some more digging and fiddling and post back here, this is a fairly critical thing to get working for the project im working on to progress so thanks for the reply.

Also, is it just me or does btCollisionObject not show up in the doxygen documentation?
Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

Re: gContactDestroyedCallback not being called?

Post by Wavesonics »

moved the content of this post into the first post.
Last edited by Wavesonics on Thu Jun 12, 2008 7:05 pm, edited 2 times in total.
Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

Re: gContactDestroyedCallback not being called?

Post by Wavesonics »

// =======
// UPDATE 3:
// =======
I traced it through and found where the destroy callback should be called, but it is not being called in: clearUserCache(btManifoldPoint& pt) because the m_userPersistentData of the btManifoldPoint is NULL.

In my set up code I set the user data pointer like so:

Code: Select all

		// Associate the body with our physical body structure
		physObj->body->setUserPointer( physObj );
Is this the same user data we are discussing in the collision callbacks?
Is there anything special I need to do to get the user data to propagate through the collision system?

// =======
// UPDATE 2:
// =======

I modified btSequentialImpulseConstraintSolver.cpp:

Code: Select all

#include <iostream>
bool  MyContactDestroyedCallback(void* userPersistentData);
bool  MyContactDestroyedCallback(void* userPersistentData)
{

std::cout << "default detroy callback" << std::endl;
	assert (userPersistentData);
	btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData;
	btAlignedFree(cpd);
	totalCpd--;
	//printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData);
	return true;
}
and removed my custom assignment, and this never gets called either.


// =======
// UPDATE:
// =======

I just looked and on line: 111 of btSequentialImpulseConstraintSolver.cpp
is the following line:

Code: Select all

gContactDestroyedCallback = &MyContactDestroyedCallback;
Which is in the constructor for btSequentialImpulseConstraintSolver();

So I set my custom callback after the solver in constructed and it is no longer being lost. But it's still not being called :/

// =======
// ORIGINAL:
// =======
*sorry for the post spam*

I did some more testing, and each time I loop I do a pointer check:

Code: Select all

if( gContactDestroyedCallback != &customContactDestroyedCallback )
cout << "delete lost!" << endl;
if( gContactAddedCallback != &customContactAddedCallback )
cout << "add lost!" << endl;
and delete is being lost once I leave the scope of the init function.
Is there any part of Bullet that sets it somewhere?
Bbilz
Posts: 26
Joined: Wed Feb 27, 2008 9:55 am

Re: gContactDestroyedCallback not being called?

Post by Bbilz »

I have had similar problems.
I ended up tackling it in a different way, but I found that having SOLVER_CACHE_FRIENDLY set in your btSequentialImpulseSolver means it skips the section of code that would normally call the delete callback..

To disable:

Code: Select all

solver->setSolverMode( SOLVER_RANDMIZE_ORDER | SOLVER_USE_WARMSTARTING );
Cache friendly solver sounded like something I would want to keep though, hence I did something different.
Could anyone shed light on whether this is intended? Is there a reason why the callback is not called in the cache friendly case?

Cheers!

-david
Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

Re: gContactDestroyedCallback not being called?

Post by Wavesonics »

talks for the info!

I assume you are talking about:

Code: Select all

btSequentialImpulseConstraintSolver ?
I couldn't find a function named setSolverMode() in it, But I looked around in the API and found the dynamics world had something simular, so I did this:

Code: Select all

m_dynamicsWorld->getSolverInfo().m_solverMode = SOLVER_RANDMIZE_ORDER | SOLVER_USE_WARMSTARTING;
And it worked!!

So thank you everyone so much for helping!

Bullet is awesome but god DAMN does it need some better documentation.
Wavesonics
Posts: 71
Joined: Thu May 22, 2008 8:03 pm

Re: gContactDestroyedCallback not being called?

Post by Wavesonics »

So it turns out that yes, my destroy callback gets a pointer, but it doesn't seem to be the one that I put in as user data when I was making the object :/

Anyone know why it would get changed and/or what it would get changed to?
Bbilz
Posts: 26
Joined: Wed Feb 27, 2008 9:55 am

Re: gContactDestroyedCallback not being called?

Post by Bbilz »

The steps to reproduce this in the bullet demos:

1) run appBasicDemo
2) put a break in MyContactDestroyedCallback (the default destroyed callback)
3) note how it is never called


Further testing:

1) add the following to BasicDemo.cpp:

Code: Select all

int gGlobalValue = 42;

static bool DestroyedCallback(void* userPersistentData)
{
	btAssert( userPersistentData == &gGlobalValue );
	return TRUE;
}

static bool AddedCallback(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
{
	cp.m_userPersistentData = &gGlobalValue;	
	return TRUE;
}
2) Also add this after the world has been initialised:

Code: Select all

gContactAddedCallback = AddedCallback;
gContactDestroyedCallback = DestroyedCallback;
3) finally add this in the for loop that initialies the box stack:

Code: Select all

body->setCollisionFlags( body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK );
4) Run the game and note how the ContactAdded callback is correctly called, but the destroyed callback is never called.

5) Now add this line after the dynamics world has been intialised:

Code: Select all

m_dynamicsWorld->getSolverInfo().m_solverMode &= ~( SOLVER_CACHE_FRIENDLY );
6) Note how the destroyed callback is now called, but unfortunately the user data has since been trampled over and fires off the assert. This is because the btManifoldPoint that is passed into the ContactAddedCallback has local scope and is copied off into a persistant manifold before the callback, thus meaning that anything you try and do to it will not be stored in the persistant manifold. I believe this problem has already been talked about elsewhere in the forums.


Phew!
Hope that helps. The main thing i want to learn is whether you are supposed to turn off SOLVER_CACHE_FRIENDLY in order to get destroy callbacks, and what kind of impact that will have on performance etc..
Also would be nice to fix it so that the manifold point passed into the AddedCallback gets saved into the persistant manifold

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

Re: gContactDestroyedCallback not being called?

Post by AlexSilverman »

Bbliz,

I posted a bug (with an attached fix) to the Google Code issue database (http://code.google.com/p/bullet/issues/detail?id=53). The patch is for an old revision of the repository, as it's been a while, but I'd think the overall gist of what's being done in the patch is the same. Worst case scenario, you can just implement the changes yourself, as I tried to detail what was done pretty thoroughly. Hopefully this fixes the problem with the persistent data in the contact destroyed callback.

- Alex
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: gContactDestroyedCallback not being called?

Post by sparkprime »

Wavesonics wrote:thanks for the reply :)
Also, is it just me or does btCollisionObject not show up in the doxygen documentation?
Me either, also neither does btConvexShape.

Could this have something to do with ATTRIBUTE_ALIGNED16(class) ?
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: gContactDestroyedCallback not being called?

Post by sparkprime »

You can fix the doxygen output by changing the include dir to "src" in Doxyfile
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: gContactDestroyedCallback not being called?

Post by Erwin Coumans »

AlexSilverman wrote: I posted a bug (with an attached fix) to the Google Code issue database (http://code.google.com/p/bullet/issues/detail?id=53).
Hi Alex,

Thanks a lot for the patch, it has been applied in latest SVN, so it will be in Bullet 2.70.

Sorry for the delay: too much travel and too little time...
Erwin
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: gContactDestroyedCallback not being called?

Post by Erwin Coumans »

sparkprime wrote:
Wavesonics wrote: Could this have something to do with ATTRIBUTE_ALIGNED16(class) ?
Yes, this is probably a bug in doxygen, feel free to report it to doxygen developers,
Thanks,
Erwin
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: gContactDestroyedCallback not being called?

Post by sparkprime »

It's not doxygen, as I said, it can be fixed by giving the correct include path to doxygen via Doxyfile