Sleeping of Inactive Bodies
Posted: Sat Jul 31, 2010 5:50 pm
I know I've drug me feet on this in the past, but I found a data structure that allowed me to implement sleeping without an unnecessary overhead and without the need to add a lot of extra state tracking to Chipmunk. I'm using a data structure called a disjoint set forest to build groups of objects in the space in nearly O(n) time. The code has been merged with trunk and should be relatively bug free. Sleeping has been enabled on demos c, f, r, and s. Idle bodies are drawn in light grey while sleeping bodies are drawn in dark grey.
I've tried to keep the API additions simple:
cpSpace.idleSpeedThreshold - Threshold velocity for a body to be considered idle. The default value of 0 means to let the space pick the threshold based on gravity.
cpSpace.sleepTimeThreshold - If all objects in a group have been idle for at least this duration, then the group will fall asleep. The default value of INFINITY disables the sleeping feature entirely.
cpSpace.staticBody - The space wide static body. When you add a shape or a constraint to the space with NULL for a body, the space will replace it with a pointer to this static body. You can change the data pointer of this body if you want.
cpBodyIsStatic() - Returns true if the body is static.
cpBodyIsRouge() - Returns true if the body has not been added to a space.
cpBodyIsSleeping() - Return true if the body has fallen asleep.
cpBodyActivate() - Wakes up a body and any other body in the group it fell asleep in.
Most importantly, you no longer need to create a static body yourself to attach your static shapes to. You simply use NULL as the body when creating static shapes. In fact, in order to use the sleeping feature you must use a NULL body instead of a "rouge" static body as was the norm up to this point.
Rouge Bodies:
"Rouge body" is just a new name for an old idea, they are bodies that have not been added to a space, but make have joints or shapes in the space that reference them. Because a cpSpace does not control rouge bodies, it prevents any body that is jointed to or touching a rouge body from falling asleep. This is why you must change your existing code to use the NULL body for static shapes instead of a rouge static body if you want to enable sleeping. Fortunately for most people, this should be as simple as changing staticBody = cpBodyNew(INFINITY, INFINITY) to staticBody = NULL.
Additionally, you now only need to use cpSpaceAddStaticShape() and cpSpaceRemoveStaticShape() when adding or removing static shapes attached to a rouge body. If you add a shape attached to NULL, it will automatically be added as a static shape.
Comments, suggestions, critisism?
I've tried to keep the API additions simple:
cpSpace.idleSpeedThreshold - Threshold velocity for a body to be considered idle. The default value of 0 means to let the space pick the threshold based on gravity.
cpSpace.sleepTimeThreshold - If all objects in a group have been idle for at least this duration, then the group will fall asleep. The default value of INFINITY disables the sleeping feature entirely.
cpSpace.staticBody - The space wide static body. When you add a shape or a constraint to the space with NULL for a body, the space will replace it with a pointer to this static body. You can change the data pointer of this body if you want.
cpBodyIsStatic() - Returns true if the body is static.
cpBodyIsRouge() - Returns true if the body has not been added to a space.
cpBodyIsSleeping() - Return true if the body has fallen asleep.
cpBodyActivate() - Wakes up a body and any other body in the group it fell asleep in.
Most importantly, you no longer need to create a static body yourself to attach your static shapes to. You simply use NULL as the body when creating static shapes. In fact, in order to use the sleeping feature you must use a NULL body instead of a "rouge" static body as was the norm up to this point.
Rouge Bodies:
"Rouge body" is just a new name for an old idea, they are bodies that have not been added to a space, but make have joints or shapes in the space that reference them. Because a cpSpace does not control rouge bodies, it prevents any body that is jointed to or touching a rouge body from falling asleep. This is why you must change your existing code to use the NULL body for static shapes instead of a rouge static body if you want to enable sleeping. Fortunately for most people, this should be as simple as changing staticBody = cpBodyNew(INFINITY, INFINITY) to staticBody = NULL.
Additionally, you now only need to use cpSpaceAddStaticShape() and cpSpaceRemoveStaticShape() when adding or removing static shapes attached to a rouge body. If you add a shape attached to NULL, it will automatically be added as a static shape.
Comments, suggestions, critisism?