mirror of https://github.com/axmolengine/axmol.git
284 lines
13 KiB
C
284 lines
13 KiB
C
/* Copyright (c) 2007 Scott Lembcke
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
/// @defgroup cpSpace cpSpace
|
|
/// @{
|
|
|
|
typedef struct cpContactBufferHeader cpContactBufferHeader;
|
|
typedef void (*cpSpaceArbiterApplyImpulseFunc)(cpArbiter *arb);
|
|
|
|
/// Basic Unit of Simulation in Chipmunk
|
|
struct cpSpace {
|
|
/// Number of iterations to use in the impulse solver to solve contacts.
|
|
int iterations;
|
|
|
|
/// Gravity to pass to rigid bodies when integrating velocity.
|
|
cpVect gravity;
|
|
|
|
/// Damping rate expressed as the fraction of velocity bodies retain each second.
|
|
/// A value of 0.9 would mean that each body's velocity will drop 10% per second.
|
|
/// The default value is 1.0, meaning no damping is applied.
|
|
/// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring.
|
|
cpFloat damping;
|
|
|
|
/// Speed threshold for a body to be considered idle.
|
|
/// The default value of 0 means to let the space guess a good threshold based on gravity.
|
|
cpFloat idleSpeedThreshold;
|
|
|
|
/// Time a group of bodies must remain idle in order to fall asleep.
|
|
/// Enabling sleeping also implicitly enables the the contact graph.
|
|
/// The default value of INFINITY disables the sleeping algorithm.
|
|
cpFloat sleepTimeThreshold;
|
|
|
|
/// Amount of encouraged penetration between colliding shapes.
|
|
/// Used to reduce oscillating contacts and keep the collision cache warm.
|
|
/// Defaults to 0.1. If you have poor simulation quality,
|
|
/// increase this number as much as possible without allowing visible amounts of overlap.
|
|
cpFloat collisionSlop;
|
|
|
|
/// Determines how fast overlapping shapes are pushed apart.
|
|
/// Expressed as a fraction of the error remaining after each second.
|
|
/// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz.
|
|
cpFloat collisionBias;
|
|
|
|
/// Number of frames that contact information should persist.
|
|
/// Defaults to 3. There is probably never a reason to change this value.
|
|
cpTimestamp collisionPersistence;
|
|
|
|
/// Rebuild the contact graph during each step. Must be enabled to use the cpBodyEachArbiter() function.
|
|
/// Disabled by default for a small performance boost. Enabled implicitly when the sleeping feature is enabled.
|
|
cpBool enableContactGraph;
|
|
|
|
/// User definable data pointer.
|
|
/// Generally this points to your game's controller or game state
|
|
/// class so you can access it when given a cpSpace reference in a callback.
|
|
cpDataPointer data;
|
|
|
|
/// The designated static body for this space.
|
|
/// You can modify this body, or replace it with your own static body.
|
|
/// By default it points to a statically allocated cpBody in the cpSpace struct.
|
|
cpBody *staticBody;
|
|
|
|
CP_PRIVATE(cpTimestamp stamp);
|
|
CP_PRIVATE(cpFloat curr_dt);
|
|
|
|
CP_PRIVATE(cpArray *bodies);
|
|
CP_PRIVATE(cpArray *rousedBodies);
|
|
CP_PRIVATE(cpArray *sleepingComponents);
|
|
|
|
CP_PRIVATE(cpSpatialIndex *staticShapes);
|
|
CP_PRIVATE(cpSpatialIndex *activeShapes);
|
|
|
|
CP_PRIVATE(cpArray *arbiters);
|
|
CP_PRIVATE(cpContactBufferHeader *contactBuffersHead);
|
|
CP_PRIVATE(cpHashSet *cachedArbiters);
|
|
CP_PRIVATE(cpArray *pooledArbiters);
|
|
CP_PRIVATE(cpArray *constraints);
|
|
|
|
CP_PRIVATE(cpArray *allocatedBuffers);
|
|
CP_PRIVATE(int locked);
|
|
|
|
CP_PRIVATE(cpHashSet *collisionHandlers);
|
|
CP_PRIVATE(cpCollisionHandler defaultHandler);
|
|
|
|
CP_PRIVATE(cpBool skipPostStep);
|
|
CP_PRIVATE(cpArray *postStepCallbacks);
|
|
|
|
CP_PRIVATE(cpBody _staticBody);
|
|
};
|
|
|
|
/// Allocate a cpSpace.
|
|
cpSpace* cpSpaceAlloc(void);
|
|
/// Initialize a cpSpace.
|
|
cpSpace* cpSpaceInit(cpSpace *space);
|
|
/// Allocate and initialize a cpSpace.
|
|
cpSpace* cpSpaceNew(void);
|
|
|
|
/// Destroy a cpSpace.
|
|
void cpSpaceDestroy(cpSpace *space);
|
|
/// Destroy and free a cpSpace.
|
|
void cpSpaceFree(cpSpace *space);
|
|
|
|
#define CP_DefineSpaceStructGetter(type, member, name) \
|
|
static inline type cpSpaceGet##name(const cpSpace *space){return space->member;}
|
|
|
|
#define CP_DefineSpaceStructSetter(type, member, name) \
|
|
static inline void cpSpaceSet##name(cpSpace *space, type value){space->member = value;}
|
|
|
|
#define CP_DefineSpaceStructProperty(type, member, name) \
|
|
CP_DefineSpaceStructGetter(type, member, name) \
|
|
CP_DefineSpaceStructSetter(type, member, name)
|
|
|
|
CP_DefineSpaceStructProperty(int, iterations, Iterations)
|
|
CP_DefineSpaceStructProperty(cpVect, gravity, Gravity)
|
|
CP_DefineSpaceStructProperty(cpFloat, damping, Damping)
|
|
CP_DefineSpaceStructProperty(cpFloat, idleSpeedThreshold, IdleSpeedThreshold)
|
|
CP_DefineSpaceStructProperty(cpFloat, sleepTimeThreshold, SleepTimeThreshold)
|
|
CP_DefineSpaceStructProperty(cpFloat, collisionSlop, CollisionSlop)
|
|
CP_DefineSpaceStructProperty(cpFloat, collisionBias, CollisionBias)
|
|
CP_DefineSpaceStructProperty(cpTimestamp, collisionPersistence, CollisionPersistence)
|
|
CP_DefineSpaceStructProperty(cpBool, enableContactGraph, EnableContactGraph)
|
|
CP_DefineSpaceStructProperty(cpDataPointer, data, UserData)
|
|
CP_DefineSpaceStructGetter(cpBody*, staticBody, StaticBody)
|
|
CP_DefineSpaceStructGetter(cpFloat, CP_PRIVATE(curr_dt), CurrentTimeStep)
|
|
|
|
/// returns true from inside a callback and objects cannot be added/removed.
|
|
static inline cpBool
|
|
cpSpaceIsLocked(cpSpace *space)
|
|
{
|
|
return space->CP_PRIVATE(locked);
|
|
}
|
|
|
|
/// Set a default collision handler for this space.
|
|
/// The default collision handler is invoked for each colliding pair of shapes
|
|
/// that isn't explicitly handled by a specific collision handler.
|
|
/// You can pass NULL for any function you don't want to implement.
|
|
void cpSpaceSetDefaultCollisionHandler(
|
|
cpSpace *space,
|
|
cpCollisionBeginFunc begin,
|
|
cpCollisionPreSolveFunc preSolve,
|
|
cpCollisionPostSolveFunc postSolve,
|
|
cpCollisionSeparateFunc separate,
|
|
void *data
|
|
);
|
|
|
|
/// Set a collision handler to be used whenever the two shapes with the given collision types collide.
|
|
/// You can pass NULL for any function you don't want to implement.
|
|
void cpSpaceAddCollisionHandler(
|
|
cpSpace *space,
|
|
cpCollisionType a, cpCollisionType b,
|
|
cpCollisionBeginFunc begin,
|
|
cpCollisionPreSolveFunc preSolve,
|
|
cpCollisionPostSolveFunc postSolve,
|
|
cpCollisionSeparateFunc separate,
|
|
void *data
|
|
);
|
|
|
|
/// Unset a collision handler.
|
|
void cpSpaceRemoveCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b);
|
|
|
|
/// Add a collision shape to the simulation.
|
|
/// If the shape is attached to a static body, it will be added as a static shape.
|
|
cpShape* cpSpaceAddShape(cpSpace *space, cpShape *shape);
|
|
/// Explicity add a shape as a static shape to the simulation.
|
|
cpShape* cpSpaceAddStaticShape(cpSpace *space, cpShape *shape);
|
|
/// Add a rigid body to the simulation.
|
|
cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);
|
|
/// Add a constraint to the simulation.
|
|
cpConstraint* cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint);
|
|
|
|
/// Remove a collision shape from the simulation.
|
|
void cpSpaceRemoveShape(cpSpace *space, cpShape *shape);
|
|
/// Remove a collision shape added using cpSpaceAddStaticShape() from the simulation.
|
|
void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape);
|
|
/// Remove a rigid body from the simulation.
|
|
void cpSpaceRemoveBody(cpSpace *space, cpBody *body);
|
|
/// Remove a constraint from the simulation.
|
|
void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint);
|
|
|
|
/// Test if a collision shape has been added to the space.
|
|
cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape);
|
|
/// Test if a rigid body has been added to the space.
|
|
cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body);
|
|
/// Test if a constraint has been added to the space.
|
|
cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint);
|
|
|
|
/// Convert a dynamic rogue body to a static one.
|
|
/// If the body is active, you must remove it from the space first.
|
|
void cpSpaceConvertBodyToStatic(cpSpace *space, cpBody *body);
|
|
/// Convert a body to a dynamic rogue body.
|
|
/// If you want the body to be active after the transition, you must add it to the space also.
|
|
void cpSpaceConvertBodyToDynamic(cpSpace *space, cpBody *body, cpFloat mass, cpFloat moment);
|
|
|
|
/// Post Step callback function type.
|
|
typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data);
|
|
/// Schedule a post-step callback to be called when cpSpaceStep() finishes.
|
|
/// You can only register one callback per unique value for @c key.
|
|
/// Returns true only if @c key has never been scheduled before.
|
|
/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used.
|
|
cpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data);
|
|
|
|
/// Point query callback function type.
|
|
typedef void (*cpSpacePointQueryFunc)(cpShape *shape, void *data);
|
|
/// Query the space at a point and call @c func for each shape found.
|
|
void cpSpacePointQuery(cpSpace *space, cpVect point, cpLayers layers, cpGroup group, cpSpacePointQueryFunc func, void *data);
|
|
/// Query the space at a point and return the first shape found. Returns NULL if no shapes were found.
|
|
cpShape *cpSpacePointQueryFirst(cpSpace *space, cpVect point, cpLayers layers, cpGroup group);
|
|
|
|
/// Nearest point query callback function type.
|
|
typedef void (*cpSpaceNearestPointQueryFunc)(cpShape *shape, cpFloat distance, cpVect point, void *data);
|
|
/// Query the space at a point and call @c func for each shape found.
|
|
void cpSpaceNearestPointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpSpaceNearestPointQueryFunc func, void *data);
|
|
/// Query the space at a point and return the nearest shape found. Returns NULL if no shapes were found.
|
|
cpShape *cpSpaceNearestPointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpLayers layers, cpGroup group, cpNearestPointQueryInfo *out);
|
|
|
|
/// Segment query callback function type.
|
|
typedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpFloat t, cpVect n, void *data);
|
|
/// Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected.
|
|
void cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSpaceSegmentQueryFunc func, void *data);
|
|
/// Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit.
|
|
cpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpLayers layers, cpGroup group, cpSegmentQueryInfo *out);
|
|
|
|
/// Rectangle Query callback function type.
|
|
typedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data);
|
|
/// Perform a fast rectangle query on the space calling @c func for each shape found.
|
|
/// Only the shape's bounding boxes are checked for overlap, not their full shape.
|
|
void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpLayers layers, cpGroup group, cpSpaceBBQueryFunc func, void *data);
|
|
|
|
/// Shape query callback function type.
|
|
typedef void (*cpSpaceShapeQueryFunc)(cpShape *shape, cpContactPointSet *points, void *data);
|
|
/// Query a space for any shapes overlapping the given shape and call @c func for each shape found.
|
|
cpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data);
|
|
|
|
/// Call cpBodyActivate() for any shape that is overlaps the given shape.
|
|
void cpSpaceActivateShapesTouchingShape(cpSpace *space, cpShape *shape);
|
|
|
|
|
|
/// Space/body iterator callback function type.
|
|
typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);
|
|
/// Call @c func for each body in the space.
|
|
void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);
|
|
|
|
/// Space/body iterator callback function type.
|
|
typedef void (*cpSpaceShapeIteratorFunc)(cpShape *shape, void *data);
|
|
/// Call @c func for each shape in the space.
|
|
void cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data);
|
|
|
|
/// Space/constraint iterator callback function type.
|
|
typedef void (*cpSpaceConstraintIteratorFunc)(cpConstraint *constraint, void *data);
|
|
/// Call @c func for each shape in the space.
|
|
void cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data);
|
|
|
|
/// Update the collision detection info for the static shapes in the space.
|
|
void cpSpaceReindexStatic(cpSpace *space);
|
|
/// Update the collision detection data for a specific shape in the space.
|
|
void cpSpaceReindexShape(cpSpace *space, cpShape *shape);
|
|
/// Update the collision detection data for all shapes attached to a body.
|
|
void cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body);
|
|
|
|
/// Switch the space to use a spatial has as it's spatial index.
|
|
void cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count);
|
|
|
|
/// Step the space forward in time by @c dt.
|
|
void cpSpaceStep(cpSpace *space, cpFloat dt);
|
|
|
|
/// @}
|