ofxChipmunk + iPhone + ofNotifyEvent = problems?

This feels like it might belong in the “extend” section, but it seems to be iPhone/iPad specific so here goes.

I added some functionality to the ofxChipmunk addon that Theo made… collision event handling and mouse interaction. I now have it all running nicely for OS X and Windows, but today I’ve been playing with Chipmunk on iPad and discovered that collisions weren’t really happening. I discovered that the problematic line that was screwing up the collisions was in my cpCollisionBeginFunc. Specifically the last line, which is a call to ofNotifyEvent.

Let me explain the setup first…

first, above the ofxChipmunk class declaration in ofxChipmunk.h, I declare an ofxChipmunkEvent class:

class ofxChipmunkEvent : public ofEventArgs {  
	int x;  
	int y;  
	cpShape		*shapeA;  
	cpShape		*shapeB;  
	cpBody		*bodyA;  
	cpBody		*bodyB;  
	cpArbiter	*arbiter;  
	int button;  

I also do a forward declaration of my callback right after that:

static void collisionBeginCallback(cpArbiter *arb, cpSpace *space, void *unused);  

Chipmunk’s collision callbacks have to be static functions so in order for the callback to get a reference to the ofxChipmunk instance, I declare a static member of ofxChipmunk of type ofxChipmunk:

static ofxChipmunk *instance;  

and right below that an event type:

ofEvent<ofxChipmunkEvent> collisionBegin;  

the instance gets set to “this” inside ofxChipmunk::setup(). Anyway, the last line of that setup is where I set up the callback:

cpSpaceSetDefaultCollisionHandler(space, (cpCollisionBeginFunc)collisionBeginCallback, NULL, NULL, NULL, NULL);  

That callback is defined below the ofxChipmunk class:

static void collisionBeginCallback(cpArbiter *arb, cpSpace *space, void *unused)  
	CP_ARBITER_GET_SHAPES(arb, a, b);  
	ofxChipmunkEvent args;  
	args.shapeA = a;  
	args.shapeB = b;  
	args.bodyA = a->body;  
	args.bodyB = b->body;  
	args.arbiter = arb;  
	ofNotifyEvent(ofxChipmunk::instance->collisionBegin, args);  

Anyway, its that ofNotifyEvent line at the end that seems to be the problem. If subscribe testApp to the event and have a printf inside the event handler in testApp, I see the event getting fired properly in the console. However, something about whatever is happening behind the scenes with ofNotifyEvent is disrupting something in Chipmunk that deals with what to do after objects collide.

If I comment out the ofNotifyEvent line, objects collide and react exactly as I expect them to. If the line is left in, objects go right through each other.

Oh… and this is only for testing on the actual device. I do not have this problem when testing in the simulator. I tried debug and release mode… same results. I suspect this has something to do with slightly different OpenFrameworks event code in the iPhone distribution… I noticed that ofEvents.h differs from the version included in the normal OS X distribution, but I don’t really know what significant changes are at play here. Just seems like a clue.

Anyway, I suppose I could devise a clunkier way of dealing with collisions, but I wanted to expand the addon to be in line with OpenFrameworks style, so using the OF event system seemed like the natural thing to do and it works perfectly in OS X / Windows.



can you post the code of the listener method?

also i’ve noticed problems with static variables inside cpp files in the iphone, can you try with something like:

static ofxChipmunk * getInstance(){  
    static ofxChipmunk instance;  
    return instance;  

and using that instead of instancing it from outside.

Hi Arturo,

I’m pretty sure it doesn’t have anything to do with the listener method because in trying to narrow down what the cause was, I just removed the ofAddListener() call from testApp. It doesn’t matter if nothing is listening for the event… I think its something about the ofNotifyEvent method itself.

I tried the static method you posted and that didn’t seem to help either. Since I don’t even have anything listening for the event, I tried changing the callback to this:

static void collisionBeginCallback(cpArbiter *arb, cpSpace *space, void *unused)  
	CP_ARBITER_GET_SHAPES(arb, a, b);  
	ofxChipmunkEvent args;  
	args.shapeA = a;  
	args.shapeB = b;  
	args.bodyA = a->body;  
	args.bodyB = b->body;  
	args.arbiter = arb;  
	ofEvent<ofxChipmunkEvent> collisionBegin;  
	ofNotifyEvent(collisionBegin, args);  

So there its not even using any kind of reference to the ofxChipmunk instance. Of course as far as I understand the OF events system, nothing can really ever receive an event created this way. But the point is, it still causes collisions to fail as described above.

So upon further experimentation, I found that in the code I posted in the immediately preceding post, just the declaration of the event itself can cause the collisions to fail, even if I take out the ofNotifyEvent() call. I suspected this might have something to do with my ofxChipmunkEvent class definition so I tried just declaring an ordinary ofEventArgs object:

ofEvent<ofEventArgs> collisionBegin;  

But the same thing happens and objects fail to collide.

I tried digging a little deeper, but pretty soon I was swimming around in some pretty scary POCO source files full of templates and other stuff like that!

it’s really weird, can’t imagine what’s going on and don’t have an iphone to test.

my only guess is that it has nothing to do with the event but with some wrong memory allocation that only happens after allocating some more memory. can you try declaring an array the same size as an ofEvent and see if the problem happens also with that.

the size of an ofEvent seems to be 152 bytes so try creating an array of chars of that size instead of the event and see if the problem persists.

ok… just tried that…

unsigned char myChars[152];  

but it didn’t cause any problems. just for good measure, i also tried declaring an array of unsigned char with space for 10000(!) and still didn’t cause any collision problems.

I also tried declaring a Poco::FIFOEvent, but not too surprisingly ran into the same problem as with declaring an ofEvent. I agree it is very strange. Any other ideas?