mirror of https://github.com/axmolengine/axmol.git
229 lines
8.0 KiB
C
229 lines
8.0 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 cpShape cpShape
|
|
/// The cpShape struct defines the shape of a rigid body.
|
|
/// @{
|
|
|
|
typedef struct cpShapeClass cpShapeClass;
|
|
|
|
/// Nearest point query info struct.
|
|
typedef struct cpNearestPointQueryInfo {
|
|
/// The nearest shape, NULL if no shape was within range.
|
|
cpShape *shape;
|
|
/// The closest point on the shape's surface. (in world space coordinates)
|
|
cpVect p;
|
|
/// The distance to the point. The distance is negative if the point is inside the shape.
|
|
cpFloat d;
|
|
} cpNearestPointQueryInfo;
|
|
|
|
/// Segment query info struct.
|
|
typedef struct cpSegmentQueryInfo {
|
|
/// The shape that was hit, NULL if no collision occured.
|
|
cpShape *shape;
|
|
/// The normalized distance along the query segment in the range [0, 1].
|
|
cpFloat t;
|
|
/// The normal of the surface hit.
|
|
cpVect n;
|
|
} cpSegmentQueryInfo;
|
|
|
|
/// @private
|
|
typedef enum cpShapeType{
|
|
CP_CIRCLE_SHAPE,
|
|
CP_SEGMENT_SHAPE,
|
|
CP_POLY_SHAPE,
|
|
CP_NUM_SHAPES
|
|
} cpShapeType;
|
|
|
|
typedef cpBB (*cpShapeCacheDataImpl)(cpShape *shape, cpVect p, cpVect rot);
|
|
typedef void (*cpShapeDestroyImpl)(cpShape *shape);
|
|
typedef void (*cpShapeNearestPointQueryImpl)(cpShape *shape, cpVect p, cpNearestPointQueryInfo *info);
|
|
typedef void (*cpShapeSegmentQueryImpl)(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
|
|
|
|
/// @private
|
|
struct cpShapeClass {
|
|
cpShapeType type;
|
|
|
|
cpShapeCacheDataImpl cacheData;
|
|
cpShapeDestroyImpl destroy;
|
|
cpShapeNearestPointQueryImpl nearestPointQuery;
|
|
cpShapeSegmentQueryImpl segmentQuery;
|
|
};
|
|
|
|
/// Opaque collision shape struct.
|
|
struct cpShape {
|
|
CP_PRIVATE(const cpShapeClass *klass);
|
|
|
|
/// The rigid body this collision shape is attached to.
|
|
cpBody *body;
|
|
|
|
/// The current bounding box of the shape.
|
|
cpBB bb;
|
|
|
|
/// Sensor flag.
|
|
/// Sensor shapes call collision callbacks but don't produce collisions.
|
|
cpBool sensor;
|
|
|
|
/// Coefficient of restitution. (elasticity)
|
|
cpFloat e;
|
|
/// Coefficient of friction.
|
|
cpFloat u;
|
|
/// Surface velocity used when solving for friction.
|
|
cpVect surface_v;
|
|
|
|
/// User definable data pointer.
|
|
/// Generally this points to your the game object class so you can access it
|
|
/// when given a cpShape reference in a callback.
|
|
cpDataPointer data;
|
|
|
|
/// Collision type of this shape used when picking collision handlers.
|
|
cpCollisionType collision_type;
|
|
/// Group of this shape. Shapes in the same group don't collide.
|
|
cpGroup group;
|
|
// Layer bitmask for this shape. Shapes only collide if the bitwise and of their layers is non-zero.
|
|
cpLayers layers;
|
|
|
|
CP_PRIVATE(cpSpace *space);
|
|
|
|
CP_PRIVATE(cpShape *next);
|
|
CP_PRIVATE(cpShape *prev);
|
|
|
|
CP_PRIVATE(cpHashValue hashid);
|
|
};
|
|
|
|
/// Destroy a shape.
|
|
void cpShapeDestroy(cpShape *shape);
|
|
/// Destroy and Free a shape.
|
|
void cpShapeFree(cpShape *shape);
|
|
|
|
/// Update, cache and return the bounding box of a shape based on the body it's attached to.
|
|
cpBB cpShapeCacheBB(cpShape *shape);
|
|
/// Update, cache and return the bounding box of a shape with an explicit transformation.
|
|
cpBB cpShapeUpdate(cpShape *shape, cpVect pos, cpVect rot);
|
|
|
|
/// Test if a point lies within a shape.
|
|
cpBool cpShapePointQuery(cpShape *shape, cpVect p);
|
|
|
|
/// Perform a nearest point query. It finds the closest point on the surface of shape to a specific point.
|
|
/// The value returned is the distance between the points. A negative distance means the point is inside the shape.
|
|
cpFloat cpShapeNearestPointQuery(cpShape *shape, cpVect p, cpNearestPointQueryInfo *out);
|
|
|
|
/// Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure.
|
|
cpBool cpShapeSegmentQuery(cpShape *shape, cpVect a, cpVect b, cpSegmentQueryInfo *info);
|
|
|
|
/// Get the hit point for a segment query.
|
|
static inline cpVect cpSegmentQueryHitPoint(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
|
|
{
|
|
return cpvlerp(start, end, info.t);
|
|
}
|
|
|
|
/// Get the hit distance for a segment query.
|
|
static inline cpFloat cpSegmentQueryHitDist(const cpVect start, const cpVect end, const cpSegmentQueryInfo info)
|
|
{
|
|
return cpvdist(start, end)*info.t;
|
|
}
|
|
|
|
#define CP_DefineShapeStructGetter(type, member, name) \
|
|
static inline type cpShapeGet##name(const cpShape *shape){return shape->member;}
|
|
|
|
#define CP_DefineShapeStructSetter(type, member, name, activates) \
|
|
static inline void cpShapeSet##name(cpShape *shape, type value){ \
|
|
if(activates && shape->body) cpBodyActivate(shape->body); \
|
|
shape->member = value; \
|
|
}
|
|
|
|
#define CP_DefineShapeStructProperty(type, member, name, activates) \
|
|
CP_DefineShapeStructGetter(type, member, name) \
|
|
CP_DefineShapeStructSetter(type, member, name, activates)
|
|
|
|
CP_DefineShapeStructGetter(cpSpace*, CP_PRIVATE(space), Space)
|
|
|
|
CP_DefineShapeStructGetter(cpBody*, body, Body)
|
|
void cpShapeSetBody(cpShape *shape, cpBody *body);
|
|
|
|
CP_DefineShapeStructGetter(cpBB, bb, BB)
|
|
CP_DefineShapeStructProperty(cpBool, sensor, Sensor, cpTrue)
|
|
CP_DefineShapeStructProperty(cpFloat, e, Elasticity, cpFalse)
|
|
CP_DefineShapeStructProperty(cpFloat, u, Friction, cpTrue)
|
|
CP_DefineShapeStructProperty(cpVect, surface_v, SurfaceVelocity, cpTrue)
|
|
CP_DefineShapeStructProperty(cpDataPointer, data, UserData, cpFalse)
|
|
CP_DefineShapeStructProperty(cpCollisionType, collision_type, CollisionType, cpTrue)
|
|
CP_DefineShapeStructProperty(cpGroup, group, Group, cpTrue)
|
|
CP_DefineShapeStructProperty(cpLayers, layers, Layers, cpTrue)
|
|
|
|
/// When initializing a shape, it's hash value comes from a counter.
|
|
/// Because the hash value may affect iteration order, you can reset the shape ID counter
|
|
/// when recreating a space. This will make the simulation be deterministic.
|
|
void cpResetShapeIdCounter(void);
|
|
|
|
#define CP_DeclareShapeGetter(struct, type, name) type struct##Get##name(const cpShape *shape)
|
|
|
|
/// @}
|
|
/// @defgroup cpCircleShape cpCircleShape
|
|
|
|
/// @private
|
|
typedef struct cpCircleShape {
|
|
cpShape shape;
|
|
|
|
cpVect c, tc;
|
|
cpFloat r;
|
|
} cpCircleShape;
|
|
|
|
/// Allocate a circle shape.
|
|
cpCircleShape* cpCircleShapeAlloc(void);
|
|
/// Initialize a circle shape.
|
|
cpCircleShape* cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset);
|
|
/// Allocate and initialize a circle shape.
|
|
cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset);
|
|
|
|
CP_DeclareShapeGetter(cpCircleShape, cpVect, Offset);
|
|
CP_DeclareShapeGetter(cpCircleShape, cpFloat, Radius);
|
|
|
|
/// @}
|
|
/// @defgroup cpSegmentShape cpSegmentShape
|
|
|
|
/// @private
|
|
typedef struct cpSegmentShape {
|
|
cpShape shape;
|
|
|
|
cpVect a, b, n;
|
|
cpVect ta, tb, tn;
|
|
cpFloat r;
|
|
|
|
cpVect a_tangent, b_tangent;
|
|
} cpSegmentShape;
|
|
|
|
/// Allocate a segment shape.
|
|
cpSegmentShape* cpSegmentShapeAlloc(void);
|
|
/// Initialize a segment shape.
|
|
cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius);
|
|
/// Allocate and initialize a segment shape.
|
|
cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius);
|
|
|
|
void cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next);
|
|
|
|
CP_DeclareShapeGetter(cpSegmentShape, cpVect, A);
|
|
CP_DeclareShapeGetter(cpSegmentShape, cpVect, B);
|
|
CP_DeclareShapeGetter(cpSegmentShape, cpVect, Normal);
|
|
CP_DeclareShapeGetter(cpSegmentShape, cpFloat, Radius);
|
|
|
|
/// @}
|