Collision Begin / End Reference Counting

Discuss any Chipmunk bugs here.
Post Reply
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Collision Begin / End Reference Counting

Post by trevarthan »

I started to implement a reference counter yesterday for collisions between my player and the ground. I attached the begin callback to the increment function and the end callback to the decrement function. I quickly noticed that the number would gradually creep up and never return to zero.

The documentation does not specifically state that this is a bug. It sort of avoids the subject. I'd like to understand why this is happening. Do collisions begin multiple times per contact?

And finally, what is the generally accepted way to tell, definitively, if one object is colliding with any other? I was expecting a boolean, "isBodyColliding" query, but I don't see one.

I'm using Chipmunk 6.0.1.
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

Hmmm... this seems related: Chipmunk 4.1 - Only get initial collision
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

Yeah, I still don't get it. The only objects we really get references to in the collision begin/end handlers are the arbiter and space objects. However, body_a and body_b are private properties of the arbiter, so I can't access them. The only thing I do have access to are the contact point sets. This leaves me... what? Making an AARB query for objects in the general vicinity, then running a point query against each object to see if the contact set matches? Seems very inefficient, especially considering that I *know* the bodies are right there in the arbiter and annoyingly private. There has to be a better way.

How is everyone else doing this? I must just be missing something.
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

Oh. I attacked it from a different angle and found cpBodyEachArbiter(). Maybe that is what everyone is using.
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Collision Begin / End Reference Counting

Post by slembcke »

You get the bodies from the arbiter using these functions: http://chipmunk-physics.net/release/Chi ... rFunctions

Begin/Separate should always happen in pairs. Even removing objects from the space should trigger a separate callback to prevent them from being unbalanced. I've often used the counter trick and never had a problem with it. If you can make a simple example to replicate it as a bug I can fix it.

Lastly, cpBodyEachArbiter() is a good way to write an is-it-touching-something routine. I have an example of that called "Contact Graph" that is part of the Chipmunk demo application: https://github.com/slembcke/Chipmunk-Ph ... actGraph.c
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

I downloaded the latest git this morning and started modifying Demo/Player.c in an attempt to recreate the reference counting issue. Worst case, I think I can learn a lot from the way you are handling Player movement. It feels a lot more natural than the way I'm doing it.

I could not reproduce the reference counting bug. Perhaps it's the slightly different newer version of Chipmunk, or the fact that my ground tiles are not quite as elaborate in the Player.c as in my game. More likely, I think, it is something about the way I am handling movement, steps, or iterations.

However, I did find a fairly reproducible dangling pointer error:
Aborting due to Chipmunk error: Internal Error: Dangling contact graph pointers detected. (A)
Failed condition: cpArbiterThreadForBody(arb, body)->next == NULL
Source:/Users/jesse/Documents/Chipmunk-Physics/macosx/../src/cpSpaceComponent.c:164
Aborting due to Chipmunk error: Internal Error: Dangling contact graph pointers detected. (C)
Failed condition: next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL
Source:/Users/jesse/Documents/Chipmunk-Physics/macosx/../src/cpSpaceComponent.c:168
Aborting due to Chipmunk error: Internal Error: Dangling contact graph pointers detected. (C)
Failed condition: next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL
Source:/Users/jesse/Documents/Chipmunk-Physics/macosx/../src/cpSpaceComponent.c:168
I've attached the patch to Planet.c in case you're interested. To reproduce, build it, drag a block to the ground, then jump/walk on it for a minute or two. Eventually the error will crop up.

Here's the patch (the forum doesn't accept diff attachments):
http://pastebin.com/kbq6LBie

To install, something like this will probably work:
patch -p1 <dangling_contact_graph_pointers.diff
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

I figured out what is causing it. With a little work, I can probably duplicate the problem in the example patch against Player.c.

I think the reference counting discrepancy happens when I update the angle of the player's body too dramatically WHILE the player is contacting the ground. In the example diff, you can see that I am updating the angle of the player's body to coincide with the ground's normal. Sometimes this can cause the player's shape to overlap with the ground shape too much. I think this is when the reference counting issue happens.

This highlights something I've noticed about Chipmunk (you even mention it yourself in the documentation a few versions back): Chipmunk has a hard time with mutable shapes. For example, if I change the shape of the player for each frame of animation, the simulation tends to break down and become unreliable.

What is the best way to handle that? Set the angle AND the position so the Player is just barely touching the ground?
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Collision Begin / End Reference Counting

Post by slembcke »

Well, it's not that Chipmunk has a hard time with mutable shapes or moving shapes around like that, but that there isn't a correct way to handle it.

What you basically doing is "teleporting" your player a small distance so that they are ending up inside of a wall or the ground with no context of how it got there (velocity) and expecting it to still act like physics. When objects overlap, Chipmunk fixes it using sort-of-physics. You can mostly fix the problems by changing the velocity to match the position change, but that doesn't fix some of the issues. It's the same problem with mutable shapes. If you modify a shape, Chipmunk has no way to even recognize how the new shape is related to the old one or how things moved. They simply changed between frames.

Now, that said it causes problems with the solver, but it definitely shouldn't be causing problems with the collision detection. If you were able to trigger those dangling pointer errors, that is bad indeed. :-\ Looking at your patch now.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: Collision Begin / End Reference Counting

Post by slembcke »

Ah, well. I see the first problem right away. You are modifying the position/angle of the object and calling cpSpaceReindexShapesForBody(). Changing the position data isn't really that bad. It will mess up the collision slightly, but probably not in a way that causes stability problems. Trying to reindex the spatial index while it's currently being used is very very bad (like pretty much every data structure), and I can guarantee that it's causing crashes. I guess I should add assertions for those. I assume you are trying to force the object into it's new position so that you get collisions listed for it's new position, but it simply won't work.

I expanded on the Player Demo when I made, Your Story (https://github.com/maximile/Your-Story). One of the things that I did was to save the most relevant ground contact and use it to draw the player sprite so it didn't ever overlap the ground even if the physics did by a pixel or two (https://github.com/maximile/Your-Story/ ... ter.m#L151). You could do something similar to fix the rotation after cpSpaceStep() returns.

I've also seen a lot of games that use a circle for the player (like N) that always use a circle for the player collider and simply rotate the graphics when there is a collision. It's a really subtle implementation trick, but the end result looks really nice.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
trevarthan
Posts: 9
Joined: Thu Nov 10, 2011 7:39 am
Location: USA
Contact:

Re: Collision Begin / End Reference Counting

Post by trevarthan »

Well, that's definitely good to know about cpSpaceReindexShapesForBody. I guess I was trying to be too clever for my own good. I'll take a look at Your Story and mull over some of the other comments you've made and get back to you if anything jumps out at me. I have a feeling you've said enough to nudge me in the right direction.

Thanks for the help! Chipmunk FTW.
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests