diff --git a/include/box2d/base.h b/include/box2d/base.h index 5d8a7deb3..7f83f8bac 100644 --- a/include/box2d/base.h +++ b/include/box2d/base.h @@ -44,26 +44,26 @@ */ /// Prototype for user allocation function -/// @param size the allocation size in bytes -/// @param alignment the required alignment, guaranteed to be a power of 2 +/// @param size the allocation size in bytes +/// @param alignment the required alignment, guaranteed to be a power of 2 typedef void* b2AllocFcn( unsigned int size, int alignment ); /// Prototype for user free function -/// @param mem the memory previously allocated through `b2AllocFcn` +/// @param mem the memory previously allocated through `b2AllocFcn` typedef void b2FreeFcn( void* mem ); /// Prototype for the user assert callback. Return 0 to skip the debugger break. typedef int b2AssertFcn( const char* condition, const char* fileName, int lineNumber ); /// This allows the user to override the allocation functions. These should be -/// set during application startup. +/// set during application startup. B2_API void b2SetAllocator( b2AllocFcn* allocFcn, b2FreeFcn* freeFcn ); /// @return the total bytes allocated by Box2D B2_API int b2GetByteCount( void ); /// Override the default assert callback -/// @param assertFcn a non-null assert callback +/// @param assertFcn a non-null assert callback B2_API void b2SetAssertFcn( b2AssertFcn* assertFcn ); /// Version numbering scheme. diff --git a/include/box2d/box2d.h b/include/box2d/box2d.h index acc980d19..7b65841b5 100644 --- a/include/box2d/box2d.h +++ b/include/box2d/box2d.h @@ -22,8 +22,8 @@ */ /// Create a world for rigid body simulation. A world contains bodies, shapes, and constraints. You make create -/// up to 128 worlds. Each world is completely independent and may be simulated in parallel. -/// @return the world id. +/// up to 128 worlds. Each world is completely independent and may be simulated in parallel. +/// @return the world id. B2_API b2WorldId b2CreateWorld( const b2WorldDef* def ); /// Destroy a world @@ -68,13 +68,13 @@ B2_API void b2World_OverlapPolygon( b2WorldId worldId, const b2Polygon* polygon, /// Cast a ray into the world to collect shapes in the path of the ray. /// Your callback function controls whether you get the closest point, any point, or n-points. /// The ray-cast ignores shapes that contain the starting point. -/// @param worldId The world to cast the ray against -/// @param origin The start point of the ray -/// @param translation The translation of the ray from the start point to the end point -/// @param filter Contains bit flags to filter unwanted shapes from the results +/// @param worldId The world to cast the ray against +/// @param origin The start point of the ray +/// @param translation The translation of the ray from the start point to the end point +/// @param filter Contains bit flags to filter unwanted shapes from the results /// @param fcn A user implemented callback function /// @param context A user context that is passed along to the callback function -/// @note The callback function may receive shapes in any order +/// @note The callback function may receive shapes in any order B2_API void b2World_CastRay( b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter, b2CastResultFcn* fcn, void* context ); @@ -95,8 +95,8 @@ B2_API void b2World_CastPolygon( b2WorldId worldId, const b2Polygon* polygon, b2 b2QueryFilter filter, b2CastResultFcn* fcn, void* context ); /// Enable/disable sleep. If your application does not need sleeping, you can gain some performance -/// by disabling sleep completely at the world level. -/// @see b2WorldDef +/// by disabling sleep completely at the world level. +/// @see b2WorldDef B2_API void b2World_EnableSleeping( b2WorldId worldId, bool flag ); /// Is body sleeping enabled? @@ -104,16 +104,16 @@ B2_API bool b2World_IsSleepingEnabled( b2WorldId worldId ); /// Enable/disable continuous collision between dynamic and static bodies. Generally you should keep continuous /// collision enabled to prevent fast moving objects from going through static objects. The performance gain from -/// disabling continuous collision is minor. -/// @see b2WorldDef +/// disabling continuous collision is minor. +/// @see b2WorldDef B2_API void b2World_EnableContinuous( b2WorldId worldId, bool flag ); /// Is continuous collision enabled? B2_API bool b2World_IsContinuousEnabled( b2WorldId worldId ); /// Adjust the restitution threshold. It is recommended not to make this value very small -/// because it will prevent bodies from sleeping. Typically in meters per second. -/// @see b2WorldDef +/// because it will prevent bodies from sleeping. Typically in meters per second. +/// @see b2WorldDef B2_API void b2World_SetRestitutionThreshold( b2WorldId worldId, float value ); /// Get the the restitution speed threshold. Typically in meters per second. @@ -121,7 +121,7 @@ B2_API float b2World_GetRestitutionThreshold( b2WorldId worldId ); /// Adjust the hit event threshold. This controls the collision velocity needed to generate a b2ContactHitEvent. /// Typically in meters per second. -/// @see b2WorldDef::hitEventThreshold +/// @see b2WorldDef::hitEventThreshold B2_API void b2World_SetHitEventThreshold( b2WorldId worldId, float value ); /// Get the the hit event speed threshold. Typically in meters per second. @@ -135,34 +135,40 @@ B2_API void b2World_SetPreSolveCallback( b2WorldId worldId, b2PreSolveFcn* fcn, /// Set the gravity vector for the entire world. Box2D has no concept of an up direction and this /// is left as a decision for the application. Typically in m/s^2. -/// @see b2WorldDef +/// @see b2WorldDef B2_API void b2World_SetGravity( b2WorldId worldId, b2Vec2 gravity ); /// Get the gravity vector B2_API b2Vec2 b2World_GetGravity( b2WorldId worldId ); /// Apply a radial explosion -/// @param worldId The world id -/// @param explosionDef The explosion definition +/// @param worldId The world id +/// @param explosionDef The explosion definition B2_API void b2World_Explode( b2WorldId worldId, const b2ExplosionDef* explosionDef ); /// Adjust contact tuning parameters -/// @param worldId The world id +/// @param worldId The world id /// @param hertz The contact stiffness (cycles per second) /// @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) /// @param pushVelocity The maximum contact constraint push out velocity (meters per second) -/// @note Advanced feature +/// @note Advanced feature B2_API void b2World_SetContactTuning( b2WorldId worldId, float hertz, float dampingRatio, float pushVelocity ); /// Adjust joint tuning parameters -/// @param worldId The world id +/// @param worldId The world id /// @param hertz The contact stiffness (cycles per second) /// @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) -/// @note Advanced feature +/// @note Advanced feature B2_API void b2World_SetJointTuning( b2WorldId worldId, float hertz, float dampingRatio ); +/// Set the maximum linear velocity. Typically in m/s. +B2_API void b2World_SetMaximumLinearVelocity( b2WorldId worldId, float maximumLinearVelocity ); + +/// Get the maximum linear velocity. Typically in m/s. +B2_API float b2World_GetMaximumLinearVelocity( b2WorldId worldId ); + /// Enable/disable constraint warm starting. Advanced feature for testing. Disabling -/// sleeping greatly reduces stability and provides no performance gain. +/// sleeping greatly reduces stability and provides no performance gain. B2_API void b2World_EnableWarmStarting( b2WorldId worldId, bool flag ); /// Is constraint warm starting enabled? @@ -186,16 +192,16 @@ B2_API void b2World_DumpMemoryStats( b2WorldId worldId ); */ /// Create a rigid body given a definition. No reference to the definition is retained. So you can create the definition -/// on the stack and pass it as a pointer. -/// @code{.c} -/// b2BodyDef bodyDef = b2DefaultBodyDef(); -/// b2BodyId myBodyId = b2CreateBody(myWorldId, &bodyDef); -/// @endcode +/// on the stack and pass it as a pointer. +/// @code{.c} +/// b2BodyDef bodyDef = b2DefaultBodyDef(); +/// b2BodyId myBodyId = b2CreateBody(myWorldId, &bodyDef); +/// @endcode /// @warning This function is locked during callbacks. B2_API b2BodyId b2CreateBody( b2WorldId worldId, const b2BodyDef* def ); /// Destroy a rigid body given an id. This destroys all shapes and joints attached to the body. -/// Do not keep references to the associated shapes and joints. +/// Do not keep references to the associated shapes and joints. B2_API void b2DestroyBody( b2BodyId bodyId ); /// Body identifier validation. Can be used to detect orphaned ids. Provides validation for up to 64K allocations. @@ -205,7 +211,7 @@ B2_API bool b2Body_IsValid( b2BodyId id ); B2_API b2BodyType b2Body_GetType( b2BodyId bodyId ); /// Change the body type. This is an expensive operation. This automatically updates the mass -/// properties regardless of the automatic mass setting. +/// properties regardless of the automatic mass setting. B2_API void b2Body_SetType( b2BodyId bodyId, b2BodyType type ); /// Set the user data for a body @@ -225,7 +231,7 @@ B2_API b2Transform b2Body_GetTransform( b2BodyId bodyId ); /// Set the world transform of a body. This acts as a teleport and is fairly expensive. /// @note Generally you should create a body with then intended transform. -/// @see b2BodyDef::position and b2BodyDef::angle +/// @see b2BodyDef::position and b2BodyDef::angle B2_API void b2Body_SetTransform( b2BodyId bodyId, b2Vec2 position, b2Rot rotation ); /// Get a local point on a body given a world point @@ -254,23 +260,23 @@ B2_API void b2Body_SetAngularVelocity( b2BodyId bodyId, float angularVelocity ); /// Apply a force at a world point. If the force is not applied at the center of mass, /// it will generate a torque and affect the angular velocity. This optionally wakes up the body. -/// The force is ignored if the body is not awake. -/// @param bodyId The body id +/// The force is ignored if the body is not awake. +/// @param bodyId The body id /// @param force The world force vector, typically in newtons (N) /// @param point The world position of the point of application /// @param wake Option to wake up the body B2_API void b2Body_ApplyForce( b2BodyId bodyId, b2Vec2 force, b2Vec2 point, bool wake ); /// Apply a force to the center of mass. This optionally wakes up the body. -/// The force is ignored if the body is not awake. -/// @param bodyId The body id +/// The force is ignored if the body is not awake. +/// @param bodyId The body id /// @param force the world force vector, usually in newtons (N). /// @param wake also wake up the body B2_API void b2Body_ApplyForceToCenter( b2BodyId bodyId, b2Vec2 force, bool wake ); /// Apply a torque. This affects the angular velocity without affecting the linear velocity. -/// This optionally wakes the body. The torque is ignored if the body is not awake. -/// @param bodyId The body id +/// This optionally wakes the body. The torque is ignored if the body is not awake. +/// @param bodyId The body id /// @param torque about the z-axis (out of the screen), typically in N*m. /// @param wake also wake up the body B2_API void b2Body_ApplyTorque( b2BodyId bodyId, float torque, bool wake ); @@ -279,29 +285,29 @@ B2_API void b2Body_ApplyTorque( b2BodyId bodyId, float torque, bool wake ); /// It also modifies the angular velocity if the point of application /// is not at the center of mass. This optionally wakes the body. /// The impulse is ignored if the body is not awake. -/// @param bodyId The body id +/// @param bodyId The body id /// @param impulse the world impulse vector, typically in N*s or kg*m/s. /// @param point the world position of the point of application. /// @param wake also wake up the body -/// @warning This should be used for one-shot impulses. If you need a steady force, +/// @warning This should be used for one-shot impulses. If you need a steady force, /// use a force instead, which will work better with the sub-stepping solver. B2_API void b2Body_ApplyLinearImpulse( b2BodyId bodyId, b2Vec2 impulse, b2Vec2 point, bool wake ); /// Apply an impulse to the center of mass. This immediately modifies the velocity. /// The impulse is ignored if the body is not awake. This optionally wakes the body. -/// @param bodyId The body id +/// @param bodyId The body id /// @param impulse the world impulse vector, typically in N*s or kg*m/s. /// @param wake also wake up the body -/// @warning This should be used for one-shot impulses. If you need a steady force, +/// @warning This should be used for one-shot impulses. If you need a steady force, /// use a force instead, which will work better with the sub-stepping solver. B2_API void b2Body_ApplyLinearImpulseToCenter( b2BodyId bodyId, b2Vec2 impulse, bool wake ); /// Apply an angular impulse. The impulse is ignored if the body is not awake. /// This optionally wakes the body. -/// @param bodyId The body id +/// @param bodyId The body id /// @param impulse the angular impulse, typically in units of kg*m*m/s /// @param wake also wake up the body -/// @warning This should be used for one-shot impulses. If you need a steady force, +/// @warning This should be used for one-shot impulses. If you need a steady force, /// use a force instead, which will work better with the sub-stepping solver. B2_API void b2Body_ApplyAngularImpulse( b2BodyId bodyId, float impulse, bool wake ); @@ -318,8 +324,8 @@ B2_API b2Vec2 b2Body_GetLocalCenterOfMass( b2BodyId bodyId ); B2_API b2Vec2 b2Body_GetWorldCenterOfMass( b2BodyId bodyId ); /// Override the body's mass properties. Normally this is computed automatically using the -/// shape geometry and density. This information is lost if a shape is added or removed or if the -/// body type changes. +/// shape geometry and density. This information is lost if a shape is added or removed or if the +/// body type changes. B2_API void b2Body_SetMassData( b2BodyId bodyId, b2MassData massData ); /// Get the mass data for a body @@ -328,12 +334,12 @@ B2_API b2MassData b2Body_GetMassData( b2BodyId bodyId ); /// This update the mass properties to the sum of the mass properties of the shapes. /// This normally does not need to be called unless you called SetMassData to override /// the mass and you later want to reset the mass. -/// You may also use this when automatic mass computation has been disabled. -/// You should call this regardless of body type. +/// You may also use this when automatic mass computation has been disabled. +/// You should call this regardless of body type. B2_API void b2Body_ApplyMassFromShapes( b2BodyId bodyId ); /// Set the automatic mass setting. Normally this is set in b2BodyDef before creation. -/// @see b2BodyDef::automaticMass +/// @see b2BodyDef::automaticMass B2_API void b2Body_SetAutomaticMass( b2BodyId bodyId, bool automaticMass ); /// Get the automatic mass setting @@ -352,7 +358,7 @@ B2_API void b2Body_SetAngularDamping( b2BodyId bodyId, float angularDamping ); B2_API float b2Body_GetAngularDamping( b2BodyId bodyId ); /// Adjust the gravity scale. Normally this is set in b2BodyDef before creation. -/// @see b2BodyDef::gravityScale +/// @see b2BodyDef::gravityScale B2_API void b2Body_SetGravityScale( b2BodyId bodyId, float gravityScale ); /// Get the current gravity scale @@ -362,8 +368,8 @@ B2_API float b2Body_GetGravityScale( b2BodyId bodyId ); B2_API bool b2Body_IsAwake( b2BodyId bodyId ); /// Wake a body from sleep. This wakes the entire island the body is touching. -/// @warning Putting a body to sleep will put the entire island of bodies touching this body to sleep, -/// which can be expensive and possibly unintuitive. +/// @warning Putting a body to sleep will put the entire island of bodies touching this body to sleep, +/// which can be expensive and possibly unintuitive. B2_API void b2Body_SetAwake( b2BodyId bodyId, bool awake ); /// Enable or disable sleeping for this body. If sleeping is disabled the body will wake. @@ -401,7 +407,7 @@ B2_API void b2Body_SetBullet( b2BodyId bodyId, bool flag ); B2_API bool b2Body_IsBullet( b2BodyId bodyId ); /// Enable/disable hit events on all shapes -/// @see b2ShapeDef::enableHitEvents +/// @see b2ShapeDef::enableHitEvents B2_API void b2Body_EnableHitEvents( b2BodyId bodyId, bool enableHitEvents ); /// Get the world that owns this body @@ -411,14 +417,14 @@ B2_API b2WorldId b2Body_GetWorld( b2BodyId bodyId ); B2_API int b2Body_GetShapeCount( b2BodyId bodyId ); /// Get the shape ids for all shapes on this body, up to the provided capacity. -/// @returns the number of shape ids stored in the user array +/// @returns the number of shape ids stored in the user array B2_API int b2Body_GetShapes( b2BodyId bodyId, b2ShapeId* shapeArray, int capacity ); /// Get the number of joints on this body B2_API int b2Body_GetJointCount( b2BodyId bodyId ); /// Get the joint ids for all joints on this body, up to the provided capacity -/// @returns the number of joint ids stored in the user array +/// @returns the number of joint ids stored in the user array B2_API int b2Body_GetJoints( b2BodyId bodyId, b2JointId* jointArray, int capacity ); /// Get the maximum capacity required for retrieving all the touching contacts on a body @@ -428,7 +434,7 @@ B2_API int b2Body_GetContactCapacity( b2BodyId bodyId ); B2_API int b2Body_GetContactData( b2BodyId bodyId, b2ContactData* contactData, int capacity ); /// Get the current world AABB that contains all the attached shapes. Note that this may not encompass the body origin. -/// If there are no shapes attached then the returned AABB is empty and centered on the body origin. +/// If there are no shapes attached then the returned AABB is empty and centered on the body origin. B2_API b2AABB b2Body_ComputeAABB( b2BodyId bodyId ); /** @} */ @@ -442,22 +448,22 @@ B2_API b2AABB b2Body_ComputeAABB( b2BodyId bodyId ); /// Create a circle shape and attach it to a body. The shape definition and geometry are fully cloned. /// Contacts are not created until the next time step. -/// @return the shape id for accessing the shape +/// @return the shape id for accessing the shape B2_API b2ShapeId b2CreateCircleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Circle* circle ); /// Create a line segment shape and attach it to a body. The shape definition and geometry are fully cloned. /// Contacts are not created until the next time step. -/// @return the shape id for accessing the shape +/// @return the shape id for accessing the shape B2_API b2ShapeId b2CreateSegmentShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Segment* segment ); /// Create a capsule shape and attach it to a body. The shape definition and geometry are fully cloned. /// Contacts are not created until the next time step. -/// @return the shape id for accessing the shape +/// @return the shape id for accessing the shape B2_API b2ShapeId b2CreateCapsuleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Capsule* capsule ); /// Create a polygon shape and attach it to a body. The shape definition and geometry are fully cloned. /// Contacts are not created until the next time step. -/// @return the shape id for accessing the shape +/// @return the shape id for accessing the shape B2_API b2ShapeId b2CreatePolygonShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Polygon* polygon ); /// Destroy a shape @@ -482,26 +488,26 @@ B2_API bool b2Shape_IsSensor( b2ShapeId shapeId ); B2_API void b2Shape_SetUserData( b2ShapeId shapeId, void* userData ); /// Get the user data for a shape. This is useful when you get a shape id -/// from an event or query. +/// from an event or query. B2_API void* b2Shape_GetUserData( b2ShapeId shapeId ); /// Set the mass density of a shape, typically in kg/m^2. -/// This will not update the mass properties on the parent body. -/// @see b2ShapeDef::density, b2Body_ApplyMassFromShapes +/// This will not update the mass properties on the parent body. +/// @see b2ShapeDef::density, b2Body_ApplyMassFromShapes B2_API void b2Shape_SetDensity( b2ShapeId shapeId, float density ); /// Get the density of a shape, typically in kg/m^2 B2_API float b2Shape_GetDensity( b2ShapeId shapeId ); /// Set the friction on a shape -/// @see b2ShapeDef::friction +/// @see b2ShapeDef::friction B2_API void b2Shape_SetFriction( b2ShapeId shapeId, float friction ); /// Get the friction of a shape B2_API float b2Shape_GetFriction( b2ShapeId shapeId ); /// Set the shape restitution (bounciness) -/// @see b2ShapeDef::restitution +/// @see b2ShapeDef::restitution B2_API void b2Shape_SetRestitution( b2ShapeId shapeId, float restitution ); /// Get the shape restitution @@ -511,33 +517,33 @@ B2_API float b2Shape_GetRestitution( b2ShapeId shapeId ); B2_API b2Filter b2Shape_GetFilter( b2ShapeId shapeId ); /// Set the current filter. This is almost as expensive as recreating the shape. -/// @see b2ShapeDef::filter +/// @see b2ShapeDef::filter B2_API void b2Shape_SetFilter( b2ShapeId shapeId, b2Filter filter ); /// Enable sensor events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. -/// @see b2ShapeDef::isSensor +/// @see b2ShapeDef::isSensor B2_API void b2Shape_EnableSensorEvents( b2ShapeId shapeId, bool flag ); /// Returns true if sensor events are enabled B2_API bool b2Shape_AreSensorEventsEnabled( b2ShapeId shapeId ); /// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. -/// @see b2ShapeDef::enableContactEvents +/// @see b2ShapeDef::enableContactEvents B2_API void b2Shape_EnableContactEvents( b2ShapeId shapeId, bool flag ); /// Returns true if contact events are enabled B2_API bool b2Shape_AreContactEventsEnabled( b2ShapeId shapeId ); /// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive -/// and must be carefully handled due to multithreading. Ignored for sensors. -/// @see b2PreSolveFcn +/// and must be carefully handled due to multithreading. Ignored for sensors. +/// @see b2PreSolveFcn B2_API void b2Shape_EnablePreSolveEvents( b2ShapeId shapeId, bool flag ); /// Returns true if pre-solve events are enabled B2_API bool b2Shape_ArePreSolveEventsEnabled( b2ShapeId shapeId ); /// Enable contact hit events for this shape. Ignored for sensors. -/// @see b2WorldDef.hitEventThreshold +/// @see b2WorldDef.hitEventThreshold B2_API void b2Shape_EnableHitEvents( b2ShapeId shapeId, bool flag ); /// Returns true if hit events are enabled @@ -567,12 +573,12 @@ B2_API b2Polygon b2Shape_GetPolygon( b2ShapeId shapeId ); /// Allows you to change a shape to be a circle or update the current circle. /// This does not modify the mass properties. -/// @see b2Body_ApplyMassFromShapes +/// @see b2Body_ApplyMassFromShapes B2_API void b2Shape_SetCircle( b2ShapeId shapeId, const b2Circle* circle ); /// Allows you to change a shape to be a capsule or update the current capsule. /// This does not modify the mass properties. -/// @see b2Body_ApplyMassFromShapes +/// @see b2Body_ApplyMassFromShapes B2_API void b2Shape_SetCapsule( b2ShapeId shapeId, const b2Capsule* capsule ); /// Allows you to change a shape to be a segment or update the current segment. @@ -580,7 +586,7 @@ B2_API void b2Shape_SetSegment( b2ShapeId shapeId, const b2Segment* segment ); /// Allows you to change a shape to be a polygon or update the current polygon. /// This does not modify the mass properties. -/// @see b2Body_ApplyMassFromShapes +/// @see b2Body_ApplyMassFromShapes B2_API void b2Shape_SetPolygon( b2ShapeId shapeId, const b2Polygon* polygon ); /// Get the parent chain id if the shape type is a chain segment, otherwise @@ -602,7 +608,7 @@ B2_API b2Vec2 b2Shape_GetClosestPoint( b2ShapeId shapeId, b2Vec2 target ); /// Chain Shape /// Create a chain shape -/// @see b2ChainDef for details +/// @see b2ChainDef for details B2_API b2ChainId b2CreateChain( b2BodyId bodyId, const b2ChainDef* def ); /// Destroy a chain shape @@ -615,7 +621,7 @@ B2_API b2WorldId b2Chain_GetWorld( b2ChainId chainId ); B2_API int b2Chain_GetSegmentCount( b2ChainId chainId ); /// Fill a user array with chain segment shape ids up to the specified capacity. Returns -/// the actual number of segments returned. +/// the actual number of segments returned. B2_API int b2Chain_GetSegments( b2ChainId chainId, b2ShapeId* segmentArray, int capacity ); /// Set the chain friction @@ -689,7 +695,7 @@ B2_API float b2Joint_GetConstraintTorque( b2JointId jointId ); */ /// Create a distance joint -/// @see b2DistanceJointDef for details +/// @see b2DistanceJointDef for details B2_API b2JointId b2CreateDistanceJoint( b2WorldId worldId, const b2DistanceJointDef* def ); /// Set the rest length of a distance joint @@ -719,7 +725,7 @@ B2_API float b2DistanceJoint_GetSpringHertz( b2JointId jointId ); B2_API float b2DistanceJoint_GetSpringDampingRatio( b2JointId jointId ); /// Enable joint limit. The limit only works if the joint spring is enabled. Otherwise the joint is rigid -/// and the limit has no effect. +/// and the limit has no effect. B2_API void b2DistanceJoint_EnableLimit( b2JointId jointId, bool enableLimit ); /// Is the distance joint limit enabled? @@ -771,7 +777,7 @@ B2_API float b2DistanceJoint_GetMotorForce( b2JointId jointId ); */ /// Create a motor joint -/// @see b2MotorJointDef for details +/// @see b2MotorJointDef for details B2_API b2JointId b2CreateMotorJoint( b2WorldId worldId, const b2MotorJointDef* def ); /// Set the motor joint linear offset target @@ -816,7 +822,7 @@ B2_API float b2MotorJoint_GetCorrectionFactor( b2JointId jointId ); */ /// Create a mouse joint -/// @see b2MouseJointDef for details +/// @see b2MouseJointDef for details B2_API b2JointId b2CreateMouseJoint( b2WorldId worldId, const b2MouseJointDef* def ); /// Set the mouse joint target @@ -855,7 +861,7 @@ B2_API float b2MouseJoint_GetMaxForce( b2JointId jointId ); */ /// Create a prismatic (slider) joint. -/// @see b2PrismaticJointDef for details +/// @see b2PrismaticJointDef for details B2_API b2JointId b2CreatePrismaticJoint( b2WorldId worldId, const b2PrismaticJointDef* def ); /// Enable/disable the joint spring. @@ -926,7 +932,7 @@ B2_API float b2PrismaticJoint_GetMotorForce( b2JointId jointId ); */ /// Create a revolute joint -/// @see b2RevoluteJointDef for details +/// @see b2RevoluteJointDef for details B2_API b2JointId b2CreateRevoluteJoint( b2WorldId worldId, const b2RevoluteJointDef* def ); /// Enable/disable the revolute joint spring @@ -948,7 +954,7 @@ B2_API void b2RevoluteJoint_SetSpringDampingRatio( b2JointId jointId, float damp B2_API float b2RevoluteJoint_GetSpringDampingRatio( b2JointId jointId ); /// Get the revolute joint current angle in radians relative to the reference angle -/// @see b2RevoluteJointDef::referenceAngle +/// @see b2RevoluteJointDef::referenceAngle B2_API float b2RevoluteJoint_GetAngle( b2JointId jointId ); /// Enable/disable the revolute joint limit @@ -1001,7 +1007,7 @@ B2_API float b2RevoluteJoint_GetMaxMotorTorque( b2JointId jointId ); */ /// Create a weld joint -/// @see b2WeldJointDef for details +/// @see b2WeldJointDef for details B2_API b2JointId b2CreateWeldJoint( b2WorldId worldId, const b2WeldJointDef* def ); /// Get the weld joint reference angle in radians @@ -1047,7 +1053,7 @@ B2_API float b2WeldJoint_GetAngularDampingRatio( b2JointId jointId ); */ /// Create a wheel joint -/// @see b2WheelJointDef for details +/// @see b2WheelJointDef for details B2_API b2JointId b2CreateWheelJoint( b2WorldId worldId, const b2WheelJointDef* def ); /// Enable/disable the wheel joint spring diff --git a/include/box2d/collision.h b/include/box2d/collision.h index 6c2c1628c..0e55b9aa3 100644 --- a/include/box2d/collision.h +++ b/include/box2d/collision.h @@ -26,7 +26,7 @@ typedef struct b2Hull b2Hull; */ /// The maximum number of vertices on a convex polygon. Changing this affects performance even if you -/// don't use more vertices. +/// don't use more vertices. #define b2_maxPolygonVertices 8 /// Low level ray-cast input data @@ -43,8 +43,8 @@ typedef struct b2RayCastInput } b2RayCastInput; /// Low level shape cast input in generic form. This allows casting an arbitrary point -/// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius. -/// A capsule is two points with a non-zero radius. A box is four points with a zero radius. +/// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius. +/// A capsule is two points with a non-zero radius. A box is four points with a zero radius. typedef struct b2ShapeCastInput { /// A point cloud to cast @@ -106,7 +106,7 @@ typedef struct b2Circle } b2Circle; /// A solid capsule can be viewed as two semicircles connected -/// by a rectangle. +/// by a rectangle. typedef struct b2Capsule { /// Local center of the first semicircle @@ -123,8 +123,8 @@ typedef struct b2Capsule /// the left of each edge. /// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. /// In most cases you should not need many vertices for a convex polygon. -/// @warning DO NOT fill this out manually, instead use a helper function like -/// b2MakePolygon or b2MakeBox. +/// @warning DO NOT fill this out manually, instead use a helper function like +/// b2MakePolygon or b2MakeBox. typedef struct b2Polygon { /// The polygon vertices @@ -263,7 +263,7 @@ B2_API b2CastOutput b2ShapeCastSegment( const b2ShapeCastInput* input, const b2S B2_API b2CastOutput b2ShapeCastPolygon( const b2ShapeCastInput* input, const b2Polygon* shape ); /// A convex hull. Used to create convex polygons. -/// @warning Do not modify these values directly, instead use b2ComputeHull() +/// @warning Do not modify these values directly, instead use b2ComputeHull() typedef struct b2Hull { /// The final points of the hull @@ -280,7 +280,7 @@ typedef struct b2Hull /// - less than 3 points /// - more than b2_maxPolygonVertices points /// This welds close points and removes collinear points. -/// @warning Do not modify a hull once it has been computed +/// @warning Do not modify a hull once it has been computed B2_API b2Hull b2ComputeHull( const b2Vec2* points, int32_t count ); /// This determines if a hull is valid. Checks for: @@ -337,7 +337,7 @@ typedef struct b2DistanceProxy } b2DistanceProxy; /// Used to warm start b2Distance. Set count to zero on first call or -/// use zero initialization. +/// use zero initialization. typedef struct b2DistanceCache { /// The number of stored simplex points @@ -401,7 +401,7 @@ typedef struct b2Simplex /// Compute the closest points between two shapes represented as point clouds. /// b2DistanceCache cache is input/output. On the first call set b2DistanceCache.count to zero. -/// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these. +/// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these. B2_API b2DistanceOutput b2ShapeDistance( b2DistanceCache* cache, const b2DistanceInput* input, b2Simplex* simplexes, int simplexCapacity ); @@ -484,15 +484,15 @@ B2_API b2TOIOutput b2TimeOfImpact( const b2TOIInput* input ); typedef struct b2ManifoldPoint { /// Location of the contact point in world space. Subject to precision loss at large coordinates. - /// @note Should only be used for debugging. + /// @note Should only be used for debugging. b2Vec2 point; /// Location of the contact point relative to bodyA's origin in world space - /// @note When used internally to the Box2D solver, this is relative to the center of mass. + /// @note When used internally to the Box2D solver, this is relative to the center of mass. b2Vec2 anchorA; /// Location of the contact point relative to bodyB's origin in world space - /// @note When used internally to the Box2D solver, this is relative to the center of mass. + /// @note When used internally to the Box2D solver, this is relative to the center of mass. b2Vec2 anchorB; /// The separation of the contact point, negative if penetrating @@ -505,7 +505,7 @@ typedef struct b2ManifoldPoint float tangentImpulse; /// The maximum normal impulse applied during sub-stepping - /// This could be a bool to indicate the point is confirmed (may be a speculative point) + /// This could be a bool to indicate the point is confirmed (may be a speculative point) float maxNormalImpulse; /// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is @@ -603,7 +603,7 @@ B2_API b2Manifold b2CollideChainSegmentAndPolygon( const b2ChainSegment* segment #define b2_defaultCategoryBits ( 1 ) /// Convenience mask bits to use when you don't need collision filtering and just want -/// all results. +/// all results. #define b2_defaultMaskBits ( UINT64_MAX ) /// A node in the dynamic tree. This is private data placed here for performance reasons. @@ -720,12 +720,12 @@ typedef float b2TreeRayCastCallbackFcn( const b2RayCastInput* input, int32_t pro /// The callback also performs the any collision filtering. This has performance /// roughly equal to k * log(n), where k is the number of collisions and n is the /// number of proxies in the tree. -/// Bit-wise filtering using mask bits can greatly improve performance in some scenarios. -/// @param tree the dynamic tree to ray cast +/// Bit-wise filtering using mask bits can greatly improve performance in some scenarios. +/// @param tree the dynamic tree to ray cast /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1) -/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` /// @param callback a callback class that is called for each proxy that is hit by the ray -/// @param context user context that is passed to the callback +/// @param context user context that is passed to the callback B2_API void b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInput* input, uint64_t maskBits, b2TreeRayCastCallbackFcn* callback, void* context ); @@ -741,11 +741,11 @@ typedef float b2TreeShapeCastCallbackFcn( const b2ShapeCastInput* input, int32_t /// The callback also performs the any collision filtering. This has performance /// roughly equal to k * log(n), where k is the number of collisions and n is the /// number of proxies in the tree. -/// @param tree the dynamic tree to ray cast +/// @param tree the dynamic tree to ray cast /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). -/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` /// @param callback a callback class that is called for each proxy that is hit by the shape -/// @param context user context that is passed to the callback +/// @param context user context that is passed to the callback B2_API void b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCastInput* input, uint64_t maskBits, b2TreeShapeCastCallbackFcn* callback, void* context ); diff --git a/include/box2d/math_functions.h b/include/box2d/math_functions.h index 495595347..a5218c172 100644 --- a/include/box2d/math_functions.h +++ b/include/box2d/math_functions.h @@ -78,7 +78,7 @@ static const b2Mat22 b2Mat22_zero = { { 0.0f, 0.0f }, { 0.0f, 0.0f } }; /// Compute an approximate arctangent in the range [-pi, pi] /// This is hand coded for cross platform determinism. The atan2f -/// function in the standard library is not cross platform deterministic. +/// function in the standard library is not cross platform deterministic. B2_API float b2Atan2( float y, float x ); /// @return the minimum of two floats @@ -279,7 +279,7 @@ B2_INLINE b2Vec2 b2Normalize( b2Vec2 v ) } /// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also -/// outputs the length. +/// outputs the length. B2_INLINE b2Vec2 b2GetLengthAndNormalize( float* length, b2Vec2 v ) { *length = b2Length( v ); @@ -303,8 +303,8 @@ B2_INLINE b2Rot b2NormalizeRot( b2Rot q ) } /// Integration rotation from angular velocity -/// @param q1 initial rotation -/// @param deltaAngle the angular displacement in radians +/// @param q1 initial rotation +/// @param deltaAngle the angular displacement in radians B2_INLINE b2Rot b2IntegrateRotation( b2Rot q1, float deltaAngle ) { // dc/dt = -omega * sin(t) @@ -363,9 +363,9 @@ B2_INLINE b2Rot b2NLerp( b2Rot q1, b2Rot q2, float t ) } /// Compute the angular velocity necessary to rotate between two rotations over a give time -/// @param q1 initial rotation -/// @param q2 final rotation -/// @param inv_h inverse time step +/// @param q1 initial rotation +/// @param q2 final rotation +/// @param inv_h inverse time step B2_INLINE float b2ComputeAngularVelocity( b2Rot q1, b2Rot q2, float inv_h ) { // ds/dt = omega * cos(t) @@ -609,8 +609,8 @@ B2_API bool b2AABB_IsValid( b2AABB aabb ); /// Box2D bases all length units on meters, but you may need different units for your game. /// You can set this value to use different units. This should be done at application startup -/// and only modified once. Default value is 1. -/// @warning This must be modified before any calls to Box2D +/// and only modified once. Default value is 1. +/// @warning This must be modified before any calls to Box2D B2_API void b2SetLengthUnitsPerMeter( float lengthUnits ); /// Get the current length units per meter. diff --git a/include/box2d/types.h b/include/box2d/types.h index 6d324ed04..9faf6b84c 100644 --- a/include/box2d/types.h +++ b/include/box2d/types.h @@ -14,40 +14,40 @@ #define B2_DEFAULT_CATEGORY_BITS 0x0001ULL #define B2_DEFAULT_MASK_BITS UINT64_MAX - /// Task interface +/// Task interface /// This is prototype for a Box2D task. Your task system is expected to invoke the Box2D task with these arguments. /// The task spans a range of the parallel-for: [startIndex, endIndex) /// The worker index must correctly identify each worker in the user thread pool, expected in [0, workerCount). -/// A worker must only exist on only one thread at a time and is analogous to the thread index. +/// A worker must only exist on only one thread at a time and is analogous to the thread index. /// The task context is the context pointer sent from Box2D when it is enqueued. -/// The startIndex and endIndex are expected in the range [0, itemCount) where itemCount is the argument to b2EnqueueTaskCallback +/// The startIndex and endIndex are expected in the range [0, itemCount) where itemCount is the argument to b2EnqueueTaskCallback /// below. Box2D expects startIndex < endIndex and will execute a loop like this: /// -/// @code{.c} +/// @code{.c} /// for (int i = startIndex; i < endIndex; ++i) -/// { -/// DoWork(); -/// } -/// @endcode -/// @ingroup world +/// { +/// DoWork(); +/// } +/// @endcode +/// @ingroup world typedef void b2TaskCallback( int32_t startIndex, int32_t endIndex, uint32_t workerIndex, void* taskContext ); /// These functions can be provided to Box2D to invoke a task system. These are designed to work well with enkiTS. /// Returns a pointer to the user's task object. May be nullptr. A nullptr indicates to Box2D that the work was executed -/// serially within the callback and there is no need to call b2FinishTaskCallback. -/// The itemCount is the number of Box2D work items that are to be partitioned among workers by the user's task system. -/// This is essentially a parallel-for. The minRange parameter is a suggestion of the minimum number of items to assign -/// per worker to reduce overhead. For example, suppose the task is small and that itemCount is 16. A minRange of 8 suggests -/// that your task system should split the work items among just two workers, even if you have more available. -/// In general the range [startIndex, endIndex) send to b2TaskCallback should obey: -/// endIndex - startIndex >= minRange -/// The exception of course is when itemCount < minRange. -/// @ingroup world +/// serially within the callback and there is no need to call b2FinishTaskCallback. +/// The itemCount is the number of Box2D work items that are to be partitioned among workers by the user's task system. +/// This is essentially a parallel-for. The minRange parameter is a suggestion of the minimum number of items to assign +/// per worker to reduce overhead. For example, suppose the task is small and that itemCount is 16. A minRange of 8 suggests +/// that your task system should split the work items among just two workers, even if you have more available. +/// In general the range [startIndex, endIndex) send to b2TaskCallback should obey: +/// endIndex - startIndex >= minRange +/// The exception of course is when itemCount < minRange. +/// @ingroup world typedef void* b2EnqueueTaskCallback( b2TaskCallback* task, int32_t itemCount, int32_t minRange, void* taskContext, void* userContext ); /// Finishes a user task object that wraps a Box2D task. -/// @ingroup world +/// @ingroup world typedef void b2FinishTaskCallback( void* userTask, void* userContext ); /// Result from b2World_RayCastClosest @@ -61,6 +61,16 @@ typedef struct b2RayResult bool hit; } b2RayResult; +/// Mixing rules for friction and restitution +typedef enum b2MixingRule +{ + b2_mixAverage, + b2_mixGeometricMean, + b2_mixMultiply, + b2_mixMinimum, + b2_mixMaximum +} b2MixingRule; + /// World definition used to create a simulation world. /// Must be initialized using b2DefaultWorldDef(). /// @ingroup world @@ -94,6 +104,12 @@ typedef struct b2WorldDef /// Maximum linear velocity. Usually meters per second. float maximumLinearVelocity; + /// Mixing rule for friction. Default is b2_mixGeometricMean. + b2MixingRule frictionMixingRule; + + /// Mixing rule for restitution. Default is b2_mixMaximum. + b2MixingRule restitutionMixingRule; + /// Can bodies go to sleep to improve performance bool enableSleep; @@ -101,8 +117,8 @@ typedef struct b2WorldDef bool enableContinuous; /// Number of workers to use with the provided task system. Box2D performs best when using only - /// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide - /// little benefit and may even harm performance. + /// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide + /// little benefit and may even harm performance. int32_t workerCount; /// Function to spawn tasks @@ -142,7 +158,7 @@ typedef enum b2BodyType /// A body definition holds all the data needed to construct a rigid body. /// You can safely re-use body definitions. Shapes are added to a body after construction. -/// Body definitions are temporary objects used to bundle creation parameters. +/// Body definitions are temporary objects used to bundle creation parameters. /// Must be initialized using b2DefaultBodyDef(). /// @ingroup body typedef struct b2BodyDef @@ -152,7 +168,7 @@ typedef struct b2BodyDef /// The initial world position of the body. Bodies should be created with the desired position. /// @note Creating bodies at the origin and then moving them nearly doubles the cost of body creation, especially - /// if the body is moved after shapes have been added. + /// if the body is moved after shapes have been added. b2Vec2 position; /// The initial world rotation of the body. Use b2MakeRot() if you have an angle. @@ -167,14 +183,14 @@ typedef struct b2BodyDef /// Linear damping is use to reduce the linear velocity. The damping parameter /// can be larger than 1 but the damping effect becomes sensitive to the /// time step when the damping parameter is large. - /// Generally linear damping is undesirable because it makes objects move slowly - /// as if they are floating. + /// Generally linear damping is undesirable because it makes objects move slowly + /// as if they are floating. float linearDamping; /// Angular damping is use to reduce the angular velocity. The damping parameter /// can be larger than 1.0f but the damping effect becomes sensitive to the /// time step when the damping parameter is large. - /// Angular damping can be use slow down rotating bodies. + /// Angular damping can be use slow down rotating bodies. float angularDamping; /// Scale the gravity applied to this body. Non-dimensional. @@ -197,8 +213,8 @@ typedef struct b2BodyDef /// Treat this body as high speed object that performs continuous collision detection /// against dynamic and kinematic bodies, but not other bullet bodies. - /// @warning Bullets should be used sparingly. They are not a solution for general dynamic-versus-dynamic - /// continuous collision. They may interfere with joint constraints. + /// @warning Bullets should be used sparingly. They are not a solution for general dynamic-versus-dynamic + /// continuous collision. They may interfere with joint constraints. bool isBullet; /// Used to disable a body. A disabled body does not move or collide. @@ -209,7 +225,7 @@ typedef struct b2BodyDef bool automaticMass; /// This allows this body to bypass rotational speed limits. Should only be used - /// for circular objects, like wheels. + /// for circular objects, like wheels. bool allowFastRotation; /// Used internally to detect a valid definition. DO NOT SET. @@ -221,39 +237,39 @@ typedef struct b2BodyDef B2_API b2BodyDef b2DefaultBodyDef( void ); /// This is used to filter collision on shapes. It affects shape-vs-shape collision -/// and shape-versus-query collision (such as b2World_CastRay). +/// and shape-versus-query collision (such as b2World_CastRay). /// @ingroup shape typedef struct b2Filter { /// The collision category bits. Normally you would just set one bit. The category bits should - /// represent your application object types. For example: - /// @code{.cpp} - /// enum MyCategories - /// { - /// Static = 0x00000001, - /// Dynamic = 0x00000002, - /// Debris = 0x00000004, - /// Player = 0x00000008, - /// // etc + /// represent your application object types. For example: + /// @code{.cpp} + /// enum MyCategories + /// { + /// Static = 0x00000001, + /// Dynamic = 0x00000002, + /// Debris = 0x00000004, + /// Player = 0x00000008, + /// // etc /// }; - /// @endcode + /// @endcode uint64_t categoryBits; /// The collision mask bits. This states the categories that this /// shape would accept for collision. - /// For example, you may want your player to only collide with static objects - /// and other players. - /// @code{.c} - /// maskBits = Static | Player; - /// @endcode + /// For example, you may want your player to only collide with static objects + /// and other players. + /// @code{.c} + /// maskBits = Static | Player; + /// @endcode uint64_t maskBits; /// Collision groups allow a certain group of objects to never collide (negative) /// or always collide (positive). A group index of zero has no effect. Non-zero group filtering /// always wins against the mask bits. - /// For example, you may want ragdolls to collide with other ragdolls but you don't want - /// ragdoll self-collision. In this case you would give each ragdoll a unique negative group index - /// and apply that group index to all shapes on the ragdoll. + /// For example, you may want ragdolls to collide with other ragdolls but you don't want + /// ragdoll self-collision. In this case you would give each ragdoll a unique negative group index + /// and apply that group index to all shapes on the ragdoll. int32_t groupIndex; } b2Filter; @@ -262,8 +278,8 @@ typedef struct b2Filter B2_API b2Filter b2DefaultFilter( void ); /// The query filter is used to filter collisions between queries and shapes. For example, -/// you may want a ray-cast representing a projectile to hit players and the static environment -/// but not debris. +/// you may want a ray-cast representing a projectile to hit players and the static environment +/// but not debris. /// @ingroup shape typedef struct b2QueryFilter { @@ -304,7 +320,7 @@ typedef enum b2ShapeType /// Used to create a shape. /// This is a temporary object used to bundle shape creation parameters. You may use -/// the same shape definition to create multiple shapes. +/// the same shape definition to create multiple shapes. /// Must be initialized using b2DefaultShapeDef(). /// @ingroup shape typedef struct b2ShapeDef @@ -328,8 +344,8 @@ typedef struct b2ShapeDef uint32_t customColor; /// A sensor shape generates overlap events but never generates a collision response. - /// Sensors do not collide with other sensors and do not have continuous collision. - /// Instead use a ray or shape cast for those scenarios. + /// Sensors do not collide with other sensors and do not have continuous collision. + /// Instead use a ray or shape cast for those scenarios. bool isSensor; /// Enable sensor events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. @@ -342,12 +358,12 @@ typedef struct b2ShapeDef bool enableHitEvents; /// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive - /// and must be carefully handled due to threading. Ignored for sensors. + /// and must be carefully handled due to threading. Ignored for sensors. bool enablePreSolveEvents; /// Normally shapes on static bodies don't invoke contact creation when they are added to the world. This overrides - /// that behavior and causes contact creation. This significantly slows down static body creation which can be important - /// when there are many static shapes. + /// that behavior and causes contact creation. This significantly slows down static body creation which can be important + /// when there are many static shapes. /// This is implicitly always true for sensors. bool forceContactCreation; @@ -360,19 +376,19 @@ typedef struct b2ShapeDef B2_API b2ShapeDef b2DefaultShapeDef( void ); /// Used to create a chain of line segments. This is designed to eliminate ghost collisions with some limitations. -/// - chains are one-sided -/// - chains have no mass and should be used on static bodies -/// - chains have a counter-clockwise winding order -/// - chains are either a loop or open +/// - chains are one-sided +/// - chains have no mass and should be used on static bodies +/// - chains have a counter-clockwise winding order +/// - chains are either a loop or open /// - a chain must have at least 4 points -/// - the distance between any two points must be greater than b2_linearSlop -/// - a chain shape should not self intersect (this is not validated) -/// - an open chain shape has NO COLLISION on the first and final edge -/// - you may overlap two open chains on their first three and/or last three points to get smooth collision -/// - a chain shape creates multiple line segment shapes on the body +/// - the distance between any two points must be greater than b2_linearSlop +/// - a chain shape should not self intersect (this is not validated) +/// - an open chain shape has NO COLLISION on the first and final edge +/// - you may overlap two open chains on their first three and/or last three points to get smooth collision +/// - a chain shape creates multiple line segment shapes on the body /// https://en.wikipedia.org/wiki/Polygonal_chain /// Must be initialized using b2DefaultChainDef(). -/// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature. +/// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature. /// @ingroup shape typedef struct b2ChainDef { @@ -494,7 +510,7 @@ typedef struct b2DistanceJointDef float length; /// Enable the distance constraint to behave like a spring. If false - /// then the distance joint will be rigid, overriding the limit and motor. + /// then the distance joint will be rigid, overriding the limit and motor. bool enableSpring; /// The spring linear stiffness Hertz, cycles per second @@ -760,7 +776,7 @@ B2_API b2RevoluteJointDef b2DefaultRevoluteJointDef( void ); /// Weld joint definition /// /// A weld joint connect to bodies together rigidly. This constraint provides springs to mimic -/// soft-body simulation. +/// soft-body simulation. /// @note The approximate solver in Box2D cannot hold many bodies together rigidly /// @ingroup weld_joint typedef struct b2WeldJointDef @@ -872,8 +888,8 @@ typedef struct b2WheelJointDef B2_API b2WheelJointDef b2DefaultWheelJointDef( void ); /// The explosion definition is used to configure options for explosions. Explosions -/// consider shape geometry when computing the impulse. -/// @ingroup world +/// consider shape geometry when computing the impulse. +/// @ingroup world typedef struct b2ExplosionDef { /// Mask bits to filter shapes @@ -889,13 +905,13 @@ typedef struct b2ExplosionDef float falloff; /// Impulse per unit length. This applies an impulse according to the shape perimeter that - /// is facing the explosion. Explosions only apply to circles, capsules, and polygons. This - /// may be negative for implosions. + /// is facing the explosion. Explosions only apply to circles, capsules, and polygons. This + /// may be negative for implosions. float impulsePerLength; } b2ExplosionDef; /// Use this to initialize your explosion definition -/// @ingroup world +/// @ingroup world B2_API b2ExplosionDef b2DefaultExplosionDef( void ); /** @@ -936,8 +952,8 @@ typedef struct b2SensorEndTouchEvent } b2SensorEndTouchEvent; /// Sensor events are buffered in the Box2D world and are available -/// as begin/end overlap event arrays after the time step is complete. -/// Note: these may become invalid if bodies and/or shapes are destroyed +/// as begin/end overlap event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed typedef struct b2SensorEvents { /// Array of sensor begin touch events @@ -996,8 +1012,8 @@ typedef struct b2ContactHitEvent } b2ContactHitEvent; /// Contact events are buffered in the Box2D world and are available -/// as event arrays after the time step is complete. -/// Note: these may become invalid if bodies and/or shapes are destroyed +/// as event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed typedef struct b2ContactEvents { /// Array of begin touch events @@ -1025,10 +1041,10 @@ typedef struct b2ContactEvents /// sleep that actor/entity/object associated with the body. /// On the other hand if the flag does not indicate the body went to sleep then the application /// can treat the actor/entity/object associated with the body as awake. -/// This is an efficient way for an application to update game object transforms rather than -/// calling functions such as b2Body_GetTransform() because this data is delivered as a contiguous array -/// and it is only populated with bodies that have moved. -/// @note If sleeping is disabled all dynamic and kinematic bodies will trigger move events. +/// This is an efficient way for an application to update game object transforms rather than +/// calling functions such as b2Body_GetTransform() because this data is delivered as a contiguous array +/// and it is only populated with bodies that have moved. +/// @note If sleeping is disabled all dynamic and kinematic bodies will trigger move events. typedef struct b2BodyMoveEvent { b2Transform transform; @@ -1038,8 +1054,8 @@ typedef struct b2BodyMoveEvent } b2BodyMoveEvent; /// Body events are buffered in the Box2D world and are available -/// as event arrays after the time step is complete. -/// Note: this data becomes invalid if bodies are destroyed +/// as event arrays after the time step is complete. +/// Note: this data becomes invalid if bodies are destroyed typedef struct b2BodyEvents { /// Array of move events @@ -1050,8 +1066,8 @@ typedef struct b2BodyEvents } b2BodyEvents; /// The contact data for two shapes. By convention the manifold normal points -/// from shape A to shape B. -/// @see b2Shape_GetContactData() and b2Body_GetContactData() +/// from shape A to shape B. +/// @see b2Shape_GetContactData() and b2Body_GetContactData() typedef struct b2ContactData { b2ShapeId shapeIdA; @@ -1063,15 +1079,15 @@ typedef struct b2ContactData /// Prototype for a contact filter callback. /// This is called when a contact pair is considered for collision. This allows you to -/// perform custom logic to prevent collision between shapes. This is only called if -/// one of the two shapes has custom filtering enabled. @see b2ShapeDef. +/// perform custom logic to prevent collision between shapes. This is only called if +/// one of the two shapes has custom filtering enabled. @see b2ShapeDef. /// Notes: -/// - this function must be thread-safe -/// - this is only called if one of the two shapes has enabled custom filtering +/// - this function must be thread-safe +/// - this is only called if one of the two shapes has enabled custom filtering /// - this is called only for awake dynamic bodies -/// Return false if you want to disable the collision -/// @warning Do not attempt to modify the world inside this callback -/// @ingroup world +/// Return false if you want to disable the collision +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world typedef bool b2CustomFilterFcn( b2ShapeId shapeIdA, b2ShapeId shapeIdB, void* context ); /// Prototype for a pre-solve callback. @@ -1079,21 +1095,21 @@ typedef bool b2CustomFilterFcn( b2ShapeId shapeIdA, b2ShapeId shapeIdB, void* co /// contact before it goes to the solver. If you are careful, you can modify the /// contact manifold (e.g. modify the normal). /// Notes: -/// - this function must be thread-safe -/// - this is only called if the shape has enabled pre-solve events +/// - this function must be thread-safe +/// - this is only called if the shape has enabled pre-solve events /// - this is called only for awake dynamic bodies /// - this is not called for sensors /// - the supplied manifold has impulse values from the previous step -/// Return false if you want to disable the contact this step -/// @warning Do not attempt to modify the world inside this callback -/// @ingroup world +/// Return false if you want to disable the contact this step +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world typedef bool b2PreSolveFcn( b2ShapeId shapeIdA, b2ShapeId shapeIdB, b2Manifold* manifold, void* context ); /// Prototype callback for overlap queries. /// Called for each shape found in the query. /// @see b2World_QueryAABB /// @return false to terminate the query. -/// @ingroup world +/// @ingroup world typedef bool b2OverlapResultFcn( b2ShapeId shapeId, void* context ); /// Prototype callback for ray casts. @@ -1107,14 +1123,14 @@ typedef bool b2OverlapResultFcn( b2ShapeId shapeId, void* context ); /// @param point the point of initial intersection /// @param normal the normal vector at the point of intersection /// @param fraction the fraction along the ray at the point of intersection -/// @param context the user context +/// @param context the user context /// @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue /// @see b2World_CastRay -/// @ingroup world +/// @ingroup world typedef float b2CastResultFcn( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ); /// These colors are used for debug draw. -/// See https://www.rapidtables.com/web/color/index.html +/// See https://www.rapidtables.com/web/color/index.html typedef enum b2HexColor { b2_colorAliceBlue = 0xf0f8ff, @@ -1274,8 +1290,8 @@ typedef enum b2HexColor } b2HexColor; /// This struct holds callbacks you can implement to draw a Box2D world. -/// This structure should be zero initialized. -/// @ingroup world +/// This structure should be zero initialized. +/// @ingroup world typedef struct b2DebugDraw { /// Draw a closed polygon provided in CCW order. diff --git a/samples/sample_joints.cpp b/samples/sample_joints.cpp index ace8c2808..9727fea6d 100644 --- a/samples/sample_joints.cpp +++ b/samples/sample_joints.cpp @@ -223,8 +223,8 @@ static int sampleDistanceJoint = RegisterSample( "Joints", "Distance Joint", Dis /// This test shows how to use a motor joint. A motor joint /// can be used to animate a dynamic body. With finite motor forces /// the body can be blocked by collision with other bodies. -/// By setting the correction factor to zero, the motor joint acts -/// like top-down dry friction. +/// By setting the correction factor to zero, the motor joint acts +/// like top-down dry friction. class MotorJoint : public Sample { public: diff --git a/src/contact.c b/src/contact.c index 24049b7cb..6d44f0e65 100644 --- a/src/contact.c +++ b/src/contact.c @@ -40,18 +40,29 @@ B2_ARRAY_SOURCE( b2ContactSim, b2ContactSim ); // - As long as contacts are created in deterministic order, island link order is deterministic. // - This keeps the order of contacts in islands deterministic -// Friction mixing law. The idea is to allow either shape to drive the friction to zero. -// For example, anything slides on ice. -static inline float b2MixFriction( float friction1, float friction2 ) +static inline float b2MixFloats( float value1, float value2, b2MixingRule mixingRule ) { - return sqrtf( friction1 * friction2 ); -} - -// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface. -// For example, a superball bounces on anything. -static inline float b2MixRestitution( float restitution1, float restitution2 ) -{ - return restitution1 > restitution2 ? restitution1 : restitution2; + switch (mixingRule) + { + case b2_mixAverage: + return 0.5f * ( value1 + value2 ); + + case b2_mixGeometricMean: + return sqrtf( value1 * value2 ); + + case b2_mixMultiply: + return value1 * value2; + + case b2_mixMinimum: + return value1 < value2 ? value1 : value2; + + case b2_mixMaximum: + return value1 > value2 ? value1 : value2; + + default: + B2_ASSERT( false ); + return 0.0f; + } } // todo make relative for all @@ -323,8 +334,8 @@ void b2CreateContact( b2World* world, b2Shape* shapeA, b2Shape* shapeB ) contactSim->shapeIdB = shapeIdB; contactSim->cache = b2_emptyDistanceCache; contactSim->manifold = ( b2Manifold ){ 0 }; - contactSim->friction = b2MixFriction( shapeA->friction, shapeB->friction ); - contactSim->restitution = b2MixRestitution( shapeA->restitution, shapeB->restitution ); + contactSim->friction = b2MixFloats( shapeA->friction, shapeB->friction, world->frictionMixingRule ); + contactSim->restitution = b2MixFloats( shapeA->restitution, shapeB->restitution, world->restitutionMixingRule ); contactSim->tangentSpeed = 0.0f; contactSim->simFlags = 0; diff --git a/src/core.h b/src/core.h index ea5148cc9..a37ec42a0 100644 --- a/src/core.h +++ b/src/core.h @@ -115,7 +115,7 @@ #endif /// Tracy profiler instrumentation -/// https://github.com/wolfpld/tracy +/// https://github.com/wolfpld/tracy #ifdef BOX2D_PROFILE #include #define b2TracyCZoneC( ctx, color, active ) TracyCZoneC( ctx, color, active ) diff --git a/src/types.c b/src/types.c index 227945968..42556d4fe 100644 --- a/src/types.c +++ b/src/types.c @@ -19,6 +19,8 @@ b2WorldDef b2DefaultWorldDef( void ) def.jointDampingRatio = 2.0f; // 400 meters per second, faster than the speed of sound def.maximumLinearVelocity = 400.0f * b2_lengthUnitsPerMeter; + def.frictionMixingRule = b2_mixGeometricMean; + def.restitutionMixingRule = b2_mixMaximum; def.enableSleep = true; def.enableContinuous = true; def.internalValue = B2_SECRET_COOKIE; diff --git a/src/world.c b/src/world.c index 9494b10a0..68be3286e 100644 --- a/src/world.c +++ b/src/world.c @@ -179,6 +179,8 @@ b2WorldId b2CreateWorld( const b2WorldDef* def ) world->contactDampingRatio = def->contactDampingRatio; world->jointHertz = def->jointHertz; world->jointDampingRatio = def->jointDampingRatio; + world->frictionMixingRule = def->frictionMixingRule; + world->restitutionMixingRule = def->restitutionMixingRule; world->enableSleep = def->enableSleep; world->locked = false; world->enableWarmStarting = true; @@ -1697,6 +1699,26 @@ void b2World_SetJointTuning(b2WorldId worldId, float hertz, float dampingRatio) world->jointDampingRatio = b2ClampFloat( dampingRatio, 0.0f, FLT_MAX ); } +void b2World_SetMaximumLinearVelocity(b2WorldId worldId, float maximumLinearVelocity) +{ + B2_ASSERT( b2IsValid( maximumLinearVelocity ) && maximumLinearVelocity > 0.0f ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->maxLinearVelocity = maximumLinearVelocity; +} + +float b2World_GetMaximumLinearVelocity(b2WorldId worldId) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->maxLinearVelocity; +} + b2Profile b2World_GetProfile( b2WorldId worldId ) { b2World* world = b2GetWorldFromId( worldId ); diff --git a/src/world.h b/src/world.h index 8bba9ef52..7b0281623 100644 --- a/src/world.h +++ b/src/world.h @@ -132,6 +132,9 @@ typedef struct b2World float jointHertz; float jointDampingRatio; + b2MixingRule frictionMixingRule; + b2MixingRule restitutionMixingRule; + uint16_t revision; b2Profile profile;