diff --git a/include/box2d/box2d.h b/include/box2d/box2d.h index 9709ee55..d39993e0 100644 --- a/include/box2d/box2d.h +++ b/include/box2d/box2d.h @@ -15,8 +15,8 @@ typedef struct b2Capsule b2Capsule; typedef struct b2Circle b2Circle; -typedef struct b2Polygon b2Polygon; typedef struct b2DebugDraw b2DebugDraw; +typedef struct b2Polygon b2Polygon; typedef struct b2Segment b2Segment; /** @@ -151,6 +151,9 @@ B2_API b2BodyType b2Body_GetType(b2BodyId bodyId); /// Set the type of a body. This has a similar cost to re-creating the body. B2_API void b2Body_SetType(b2BodyId bodyId, b2BodyType type); +/// Set the user data for a body +B2_API void b2Body_SetUserData(b2BodyId bodyId, void* userData); + /// Get the user data stored in a body B2_API void* b2Body_GetUserData(b2BodyId bodyId); @@ -286,6 +289,12 @@ B2_API bool b2Body_IsAwake(b2BodyId bodyId); /// Wake a body from sleep. This wakes the entire island the body is touching. B2_API void b2Body_Wake(b2BodyId bodyId); +/// Enable or disable sleeping this body. If sleeping is disabled the body will wake. +B2_API void b2Body_EnableSleep(b2BodyId bodyId, bool enableSleep); + +/// @return is sleeping enabled for this body? +B2_API bool b2Body_IsSleepEnabled(b2BodyId bodyId); + /// Is this body enabled? B2_API bool b2Body_IsEnabled(b2BodyId bodyId); @@ -343,16 +352,6 @@ B2_API void b2DestroyShape(b2ShapeId shapeId); /// Shape identifier validation. Provides validation for up to 64K allocations. B2_API bool b2Shape_IsValid(b2ShapeId id); -/// Create a chain shape -/// @see b2ChainDef for details -B2_API b2ChainId b2CreateChain(b2BodyId bodyId, const b2ChainDef* def); - -/// Destroy a chain shape -B2_API void b2DestroyChain(b2ChainId chainId); - -/// Chain identifier validation. Provides validation for up to 64K allocations. -B2_API bool b2Chain_IsValid(b2ChainId id); - /// Get the type of a shape. B2_API b2ShapeType b2Shape_GetType(b2ShapeId shapeId); @@ -362,8 +361,11 @@ B2_API b2BodyId b2Shape_GetBody(b2ShapeId shapeId); /// Is this shape a sensor? See b2ShapeDef. B2_API bool b2Shape_IsSensor(b2ShapeId shapeId); +/// Set the user data for a shape. +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 density on a shape. Normally this is specified in b2ShapeDef. @@ -396,7 +398,7 @@ B2_API void b2Shape_SetFilter(b2ShapeId shapeId, b2Filter filter); B2_API bool b2Shape_TestPoint(b2ShapeId shapeId, b2Vec2 point); /// Ray cast a shape directly -B2_API b2RayResult b2Shape_RayCast(b2ShapeId shapeId, b2Vec2 origin, b2Vec2 translation); +B2_API b2CastOutput b2Shape_RayCast(b2ShapeId shapeId, b2Vec2 origin, b2Vec2 translation); /// Access the circle geometry of a shape. Asserts the type is correct. B2_API const b2Circle b2Shape_GetCircle(b2ShapeId shapeId); @@ -416,16 +418,16 @@ B2_API const 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. -B2_API const void b2Shape_SetCircle(b2ShapeId shapeId, b2Circle circle); +B2_API void b2Shape_SetCircle(b2ShapeId shapeId, b2Circle circle); /// Allows you to change a shape to be a capsule or update the current capsule. -B2_API const void b2Shape_SetCapsule(b2ShapeId shapeId, b2Capsule capsule); +B2_API void b2Shape_SetCapsule(b2ShapeId shapeId, b2Capsule capsule); /// Allows you to change a shape to be a segment or update the current segment. -B2_API const void b2Shape_SetSegment(b2ShapeId shapeId, b2Segment segment); +B2_API void b2Shape_SetSegment(b2ShapeId shapeId, b2Segment segment); /// Allows you to change a shape to be a segment or update the current segment. -B2_API const void b2Shape_SetPolygon(b2ShapeId shapeId, b2Polygon polygon); +B2_API void b2Shape_SetPolygon(b2ShapeId shapeId, b2Polygon polygon); /// If the type is b2_smoothSegmentShape then you can get the parent chain id. /// If the shape is not a smooth segment then this will return b2_nullChainId. @@ -446,6 +448,18 @@ B2_API int32_t b2Shape_GetContactData(b2ShapeId shapeId, b2ContactData* contactD /// Get the current world AABB B2_API b2AABB b2Shape_GetAABB(b2ShapeId shapeId); +/// Chain Shape + +/// Create a chain shape +/// @see b2ChainDef for details +B2_API b2ChainId b2CreateChain(b2BodyId bodyId, const b2ChainDef* def); + +/// Destroy a chain shape +B2_API void b2DestroyChain(b2ChainId chainId); + +/// Chain identifier validation. Provides validation for up to 64K allocations. +B2_API bool b2Chain_IsValid(b2ChainId id); + /** @} */ /** @@ -497,129 +511,252 @@ B2_API b2BodyId b2Joint_GetBodyA(b2JointId jointId); /// Get body B on a joint B2_API b2BodyId b2Joint_GetBodyB(b2JointId jointId); +/// Get local anchor on bodyA +B2_API b2Vec2 b2Joint_GetLocalAnchorA(b2JointId jointId); + +/// Get local anchor on bodyB +B2_API b2Vec2 b2Joint_GetLocalAnchorB(b2JointId jointId); + /// Toggle collision between connected bodies B2_API void b2Joint_SetCollideConnected(b2JointId jointId, bool shouldCollide); /// Is collision allowed between connected bodies? B2_API bool b2Joint_GetCollideConnected(b2JointId jointId); +/// Set the user data on a joint +B2_API void b2Joint_SetUserData(b2JointId jointId, void* userData); + +/// Get the user data on a joint +B2_API void* b2Joint_GetUserData(b2JointId jointId); + +/// Distance Joint + /// Get the constraint force on a distance joint B2_API float b2DistanceJoint_GetConstraintForce(b2JointId jointId, float timeStep); -/// Set the length parameters of a distance joint -/// @see b2DistanceJointDef for details -B2_API void b2DistanceJoint_SetLength(b2JointId jointId, float length, float minLength, float maxLength); +/// Set the rest length of a distance joint +B2_API void b2DistanceJoint_SetLength(b2JointId jointId, float length); + +/// Get the rest length of a distance joint +B2_API float b2DistanceJoint_GetLength(b2JointId jointId); + +/// Set the minimum and maximum length parameters of a distance joint +B2_API void b2DistanceJoint_SetLengthRange(b2JointId jointId, float minLength, float maxLength); + +/// Get the minimum distance joint length +B2_API float b2DistanceJoint_GetMinLength(b2JointId jointId); + +/// Get the maximum distance joint length +B2_API float b2DistanceJoint_GetMaxLength(b2JointId jointId); /// Get the current length of a distance joint B2_API float b2DistanceJoint_GetCurrentLength(b2JointId jointId); -/// Adjust the softness of a distance joint -/// @see b2DistanceJointDef for details +/// Adjust the softness parameters of a distance joint B2_API void b2DistanceJoint_SetTuning(b2JointId jointId, float hertz, float dampingRatio); -/// Set the linear offset target for a motor joint +/// Get the Hertz of a distance joint +B2_API float b2DistanceJoint_GetHertz(b2JointId jointId); + +/// Get the damping ratio of a distance joint +B2_API float b2DistanceJoint_GetDampingRatio(b2JointId jointId); + +/// Motor Joint + +/// Set/Get the linear offset target for a motor joint B2_API void b2MotorJoint_SetLinearOffset(b2JointId jointId, b2Vec2 linearOffset); +/// @return the linear offset target for a motor joint +B2_API b2Vec2 b2MotorJoint_GetLinearOffset(b2JointId jointId); + /// Set the angular offset target for a motor joint in radians B2_API void b2MotorJoint_SetAngularOffset(b2JointId jointId, float angularOffset); +/// @return the angular offset target for a motor joint in radians +B2_API float b2MotorJoint_GetAngularOffset(b2JointId jointId); + /// Set the maximum force for a motor joint B2_API void b2MotorJoint_SetMaxForce(b2JointId jointId, float maxForce); +/// @return the maximum force for a motor joint +B2_API float b2MotorJoint_GetMaxForce(b2JointId jointId); + /// Set the maximum torque for a motor joint B2_API void b2MotorJoint_SetMaxTorque(b2JointId jointId, float maxTorque); +/// @return the maximum torque for a motor joint +B2_API float b2MotorJoint_GetMaxTorque(b2JointId jointId); + /// Set the correction factor for a motor joint B2_API void b2MotorJoint_SetCorrectionFactor(b2JointId jointId, float correctionFactor); +/// @return the correction factor for a motor joint +B2_API float b2MotorJoint_GetCorrectionFactor(b2JointId jointId); + /// Get the current constraint force for a motor joint B2_API b2Vec2 b2MotorJoint_GetConstraintForce(b2JointId jointId); /// Get the current constraint torque for a motor joint B2_API float b2MotorJoint_GetConstraintTorque(b2JointId jointId); +/// Mouse Joint + /// Set the target for a mouse joint B2_API void b2MouseJoint_SetTarget(b2JointId jointId, b2Vec2 target); +/// @return the target for a mouse joint +B2_API b2Vec2 b2MouseJoint_GetTarget(b2JointId jointId); + +/// Adjust the softness parameters of a mouse joint +B2_API void b2MouseJoint_SetTuning(b2JointId jointId, float hertz, float dampingRatio); + +/// Get the Hertz of a mouse joint +B2_API float b2MouseJoint_GetHertz(b2JointId jointId); + +/// Get the damping ratio of a mouse joint +B2_API float b2MouseJoint_GetDampingRatio(b2JointId jointId); + +/// Prismatic Joint + /// Enable/disable a prismatic joint limit B2_API void b2PrismaticJoint_EnableLimit(b2JointId jointId, bool enableLimit); +/// @return is the prismatic joint limit enabled +B2_API bool b2PrismaticJoint_IsLimitEnabled(b2JointId jointId); + /// Enable/disable a prismatic joint motor B2_API void b2PrismaticJoint_EnableMotor(b2JointId jointId, bool enableMotor); +/// @return is the prismatic joint motor enabled +B2_API bool b2PrismaticJoint_IsMotorEnabled(b2JointId jointId); + /// Set the motor speed for a prismatic joint B2_API void b2PrismaticJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); +/// @return the motor speed for a prismatic joint +B2_API float b2PrismaticJoint_GetMotorSpeed(b2JointId jointId); + /// Get the current motor force for a prismatic joint B2_API float b2PrismaticJoint_GetMotorForce(b2JointId jointId); /// Set the maximum force for a prismatic joint motor B2_API void b2PrismaticJoint_SetMaxMotorForce(b2JointId jointId, float force); +/// @return the maximum force for a prismatic joint motor +B2_API float b2PrismaticJoint_GetMaxMotorForce(b2JointId jointId); + /// Get the current constraint force for a prismatic joint B2_API b2Vec2 b2PrismaticJoint_GetConstraintForce(b2JointId jointId); /// Get the current constraint torque for a prismatic joint B2_API float b2PrismaticJoint_GetConstraintTorque(b2JointId jointId); +/// Revolute Joint + /// Enable/disable a revolute joint limit B2_API void b2RevoluteJoint_EnableLimit(b2JointId jointId, bool enableLimit); +/// @return is the revolute joint limit enabled +B2_API bool b2RevoluteJoint_IsLimitEnabled(b2JointId jointId); + /// Enable/disable a revolute joint motor B2_API void b2RevoluteJoint_EnableMotor(b2JointId jointId, bool enableMotor); +/// @return is the revolute joint motor enabled +B2_API bool b2RevoluteJoint_IsMotorEnabled(b2JointId jointId); + /// Set the motor speed for a revolute joint in radians per second B2_API void b2RevoluteJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); +/// @return the motor speed for a revolute joint in radians per second +B2_API float b2RevoluteJoint_GetMotorSpeed(b2JointId jointId); + /// Get the current motor torque for a revolute joint B2_API float b2RevoluteJoint_GetMotorTorque(b2JointId jointId); /// Set the maximum torque for a revolute joint motor B2_API void b2RevoluteJoint_SetMaxMotorTorque(b2JointId jointId, float torque); +/// @return the maximum torque for a revolute joint motor +B2_API float b2RevoluteJoint_GetMaxMotorTorque(b2JointId jointId); + /// Get the current constraint force for a revolute joint B2_API b2Vec2 b2RevoluteJoint_GetConstraintForce(b2JointId jointId); /// Get the current constraint torque for a revolute joint B2_API float b2RevoluteJoint_GetConstraintTorque(b2JointId jointId); +/// Wheel Joint + /// Set the wheel joint stiffness in Hertz B2_API void b2WheelJoint_SetSpringHertz(b2JointId jointId, float hertz); +/// @return the wheel joint stiffness in Hertz +B2_API float b2WheelJoint_GetSpringHertz(b2JointId jointId); + /// Set the wheel joint damping ratio (non-dimensional) B2_API void b2WheelJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio); +/// @return the wheel joint damping ratio (non-dimensional) +B2_API float b2WheelJoint_GetSpringDampingRatio(b2JointId jointId); + /// Enable/disable the wheel joint limit B2_API void b2WheelJoint_EnableLimit(b2JointId jointId, bool enableLimit); +/// @return is the wheel joint limit enabled +B2_API bool b2WheelJoint_IsLimitEnabled(b2JointId jointId); + /// Enable/disable the wheel joint motor B2_API void b2WheelJoint_EnableMotor(b2JointId jointId, bool enableMotor); +/// @return is the wheel joint motor enabled +B2_API bool b2WheelJoint_IsMotorEnabled(b2JointId jointId); + /// Set the wheel joint motor speed in radians per second B2_API void b2WheelJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed); +/// @return the wheel joint motor speed in radians per second +B2_API float b2WheelJoint_GetMotorSpeed(b2JointId jointId); + /// Get the wheel joint current motor torque B2_API float b2WheelJoint_GetMotorTorque(b2JointId jointId); /// Set the wheel joint maximum motor torque B2_API void b2WheelJoint_SetMaxMotorTorque(b2JointId jointId, float torque); +/// @return the wheel joint maximum motor torque +B2_API float b2WheelJoint_GetMaxMotorTorque(b2JointId jointId); + /// Get the current wheel joint constraint force B2_API b2Vec2 b2WheelJoint_GetConstraintForce(b2JointId jointId); /// Get the current wheel joint constraint torque B2_API float b2WheelJoint_GetConstraintTorque(b2JointId jointId); +/// Weld Joint + /// Set weld joint linear stiffness in Hertz. 0 is rigid. B2_API void b2WeldJoint_SetLinearHertz(b2JointId jointId, float hertz); +/// @return the weld joint linear stiffness in Hertz. +B2_API float b2WeldJoint_GetLinearHertz(b2JointId jointId); + /// Set weld joint linear damping ratio (non-dimensional) B2_API void b2WeldJoint_SetLinearDampingRatio(b2JointId jointId, float dampingRatio); +/// @return the weld joint linear damping ratio (non-dimensional) +B2_API float b2WeldJoint_GetLinearDampingRatio(b2JointId jointId); + /// Set weld joint angular stiffness in Hertz. 0 is rigid. B2_API void b2WeldJoint_SetAngularHertz(b2JointId jointId, float hertz); +/// @return the weld joint angular stiffness in Hertz. +B2_API float b2WeldJoint_GetAngularHertz(b2JointId jointId); + /// Set weld joint angular damping ratio (non-dimensional) B2_API void b2WeldJoint_SetAngularDampingRatio(b2JointId jointId, float dampingRatio); +/// @return the weld joint angular damping ratio (non-dimensional) +B2_API float b2WeldJoint_GetAngularDampingRatio(b2JointId jointId); + /** @} */ diff --git a/include/box2d/joint_types.h b/include/box2d/joint_types.h index 43910115..0285ff5f 100644 --- a/include/box2d/joint_types.h +++ b/include/box2d/joint_types.h @@ -52,6 +52,9 @@ typedef struct b2DistanceJointDef /// Set this flag to true if the attached bodies should collide. bool collideConnected; + /// User data pointer + void* userData; + } b2DistanceJointDef; /// Use this to initialize your joint definition @@ -82,6 +85,13 @@ typedef struct b2MotorJointDef /// Position correction factor in the range [0,1]. float correctionFactor; + + /// Set this flag to true if the attached bodies should collide. + bool collideConnected; + + /// User data pointer + void* userData; + } b2MotorJointDef; /// Use this to initialize your joint definition @@ -106,6 +116,13 @@ typedef struct b2MouseJointDef /// Damping ratio, non-dimensional float dampingRatio; + + /// Set this flag to true if the attached bodies should collide. + bool collideConnected; + + /// User data pointer + void* userData; + } b2MouseJointDef; /// Use this to initialize your joint definition @@ -156,6 +173,9 @@ typedef struct b2PrismaticJointDef /// Set this flag to true if the attached bodies should collide. bool collideConnected; + + /// User data pointer + void* userData; } b2PrismaticJointDef; /// Use this to initialize your joint definition @@ -213,6 +233,9 @@ typedef struct b2RevoluteJointDef /// Set this flag to true if the attached bodies should collide. bool collideConnected; + + /// User data pointer + void* userData; } b2RevoluteJointDef; /// Use this to initialize your joint definition @@ -252,6 +275,9 @@ typedef struct b2WeldJointDef /// Set this flag to true if the attached bodies should collide. bool collideConnected; + + /// User data pointer + void* userData; } b2WeldJointDef; /// Use this to initialize your joint definition @@ -306,6 +332,9 @@ typedef struct b2WheelJointDef /// Set this flag to true if the attached bodies should collide. bool collideConnected; + + /// User data pointer + void* userData; } b2WheelJointDef; /// Use this to initialize your joint definition diff --git a/include/box2d/types.h b/include/box2d/types.h index 632b769d..7674eefe 100644 --- a/include/box2d/types.h +++ b/include/box2d/types.h @@ -191,10 +191,10 @@ typedef struct b2QueryFilter /// Shape type typedef enum b2ShapeType { - b2_capsuleShape, b2_circleShape, - b2_polygonShape, + b2_capsuleShape, b2_segmentShape, + b2_polygonShape, b2_smoothSegmentShape, b2_shapeTypeCount } b2ShapeType; diff --git a/samples/collection/sample_events.cpp b/samples/collection/sample_events.cpp index 76cb0897..81cd3bf2 100644 --- a/samples/collection/sample_events.cpp +++ b/samples/collection/sample_events.cpp @@ -582,7 +582,7 @@ class ContactEvent : public Sample { case b2_circleShape: { - b2Circle circle = *b2Shape_GetCircle(shapeId); + b2Circle circle = b2Shape_GetCircle(shapeId); circle.point = b2TransformPoint(relativeTransform, circle.point); b2CreateCircleShape(m_playerId, &shapeDef, &circle); @@ -591,7 +591,7 @@ class ContactEvent : public Sample case b2_capsuleShape: { - b2Capsule capsule = *b2Shape_GetCapsule(shapeId); + b2Capsule capsule = b2Shape_GetCapsule(shapeId); capsule.point1 = b2TransformPoint(relativeTransform, capsule.point1); capsule.point2 = b2TransformPoint(relativeTransform, capsule.point2); @@ -601,7 +601,8 @@ class ContactEvent : public Sample case b2_polygonShape: { - b2Polygon polygon = b2TransformPolygon(relativeTransform, b2Shape_GetPolygon(shapeId)); + b2Polygon originalPolygon = b2Shape_GetPolygon(shapeId); + b2Polygon polygon = b2TransformPolygon(relativeTransform, &originalPolygon); b2CreatePolygonShape(m_playerId, &shapeDef, &polygon); } diff --git a/samples/collection/sample_joints.cpp b/samples/collection/sample_joints.cpp index 29429ea3..6f39ac89 100644 --- a/samples/collection/sample_joints.cpp +++ b/samples/collection/sample_joints.cpp @@ -44,7 +44,6 @@ class DistanceJoint : public Sample m_minLength = m_length; m_maxLength = m_length; m_fixedLength = true; - m_collideConnected = true; for (int i = 0; i < e_maxCount; ++i) { @@ -102,7 +101,6 @@ class DistanceJoint : public Sample jointDef.length = m_length; jointDef.minLength = m_minLength; jointDef.maxLength = m_maxLength; - jointDef.collideConnected = m_collideConnected; m_jointIds[i] = b2CreateDistanceJoint(m_worldId, &jointDef); prevBodyId = m_bodyIds[i]; @@ -117,15 +115,19 @@ class DistanceJoint : public Sample if (ImGui::SliderFloat("length", &m_length, 0.1f, 4.0f, "%3.1f")) { - if (m_fixedLength) + for (int32_t i = 0; i < m_count; ++i) { - m_minLength = m_length; - m_maxLength = m_length; + b2DistanceJoint_SetLength(m_jointIds[i], m_length); } - for (int32_t i = 0; i < m_count; ++i) + if (m_fixedLength) { - b2DistanceJoint_SetLength(m_jointIds[i], m_length, m_minLength, m_maxLength); + m_minLength = m_length; + m_maxLength = m_length; + for (int32_t i = 0; i < m_count; ++i) + { + b2DistanceJoint_SetLengthRange(m_jointIds[i], m_minLength, m_maxLength); + } } } @@ -137,7 +139,8 @@ class DistanceJoint : public Sample m_maxLength = m_length; for (int32_t i = 0; i < m_count; ++i) { - b2DistanceJoint_SetLength(m_jointIds[i], m_length, m_minLength, m_maxLength); + b2DistanceJoint_SetLength(m_jointIds[i], m_length); + b2DistanceJoint_SetLengthRange(m_jointIds[i], m_minLength, m_maxLength); } } } @@ -148,7 +151,7 @@ class DistanceJoint : public Sample { for (int32_t i = 0; i < m_count; ++i) { - b2DistanceJoint_SetLength(m_jointIds[i], m_length, m_minLength, m_maxLength); + b2DistanceJoint_SetLengthRange(m_jointIds[i], m_minLength, m_maxLength); } } @@ -156,7 +159,7 @@ class DistanceJoint : public Sample { for (int32_t i = 0; i < m_count; ++i) { - b2DistanceJoint_SetLength(m_jointIds[i], m_length, m_minLength, m_maxLength); + b2DistanceJoint_SetLengthRange(m_jointIds[i], m_minLength, m_maxLength); } } @@ -183,14 +186,6 @@ class DistanceJoint : public Sample CreateScene(count); } - if (ImGui::Checkbox("collide connected", &m_collideConnected)) - { - for (int32_t i = 0; i < m_count; ++i) - { - b2Joint_SetCollideConnected(m_jointIds[i], m_collideConnected); - } - } - ImGui::End(); } @@ -209,7 +204,6 @@ class DistanceJoint : public Sample float m_minLength; float m_maxLength; bool m_fixedLength; - bool m_collideConnected; }; static int sampleDistanceJoint = RegisterSample("Joints", "Distance Joint", DistanceJoint::Create); diff --git a/samples/collection/sample_shapes.cpp b/samples/collection/sample_shapes.cpp index 4f5d84b9..a42c5376 100644 --- a/samples/collection/sample_shapes.cpp +++ b/samples/collection/sample_shapes.cpp @@ -364,7 +364,7 @@ class CompoundShapes : public Sample bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_ship1Id); bodyDef.angle = b2Body_GetAngle(m_ship1Id); - //bodyDef.gravityScale = 0.0f; + // bodyDef.gravityScale = 0.0f; b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2Circle circle = {{0.0f, 2.0f}, 0.5f}; @@ -377,7 +377,7 @@ class CompoundShapes : public Sample bodyDef.type = b2_dynamicBody; bodyDef.position = b2Body_GetPosition(m_ship2Id); bodyDef.angle = b2Body_GetAngle(m_ship2Id); - //bodyDef.gravityScale = 0.0f; + // bodyDef.gravityScale = 0.0f; b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); b2Circle circle = {{0.0f, 2.0f}, 0.5f}; @@ -413,20 +413,18 @@ class CompoundShapes : public Sample aabb = b2Body_ComputeAABB(m_table1Id); g_draw.DrawAABB(aabb, yellow); - + aabb = b2Body_ComputeAABB(m_table2Id); g_draw.DrawAABB(aabb, yellow); - + aabb = b2Body_ComputeAABB(m_ship1Id); g_draw.DrawAABB(aabb, yellow); - + aabb = b2Body_ComputeAABB(m_ship2Id); g_draw.DrawAABB(aabb, yellow); } } - - static Sample* Create(const Settings& settings) { return new CompoundShapes(settings); @@ -444,7 +442,6 @@ static int sampleCompoundShape = RegisterSample("Shapes", "Compound Shapes", Com class ShapeFilter : public Sample { public: - enum CollisionBits { GROUND = 0x00000001, @@ -479,7 +476,7 @@ class ShapeFilter : public Sample { b2BodyDef bodyDef = b2DefaultBodyDef(); bodyDef.type = b2_dynamicBody; - + bodyDef.position = {0.0f, 4.0f}; m_player1Id = b2CreateBody(m_worldId, &bodyDef); @@ -488,7 +485,7 @@ class ShapeFilter : public Sample bodyDef.position = {0.0f, 12.0f}; m_player3Id = b2CreateBody(m_worldId, &bodyDef); - + b2Polygon box = b2MakeBox(2.0f, 1.0f); b2ShapeDef shapeDef = b2DefaultShapeDef(); @@ -833,3 +830,162 @@ class Friction : public Sample }; static int sampleIndex3 = RegisterSample("Shapes", "Friction", Friction::Create); + +// This sample shows how to modify the geometry on an existing shape. This is only supported on +// dynamic and kinematic shapes because static shapes don't look for new collisions. +class ModifyGeometry : public Sample +{ +public: + ModifyGeometry(const Settings& settings) + : Sample(settings) + { + if (settings.restart == false) + { + g_camera.m_zoom = 0.25f; + g_camera.m_center = {0.0f, 5.0f}; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody(m_worldId, &bodyDef); + b2Polygon box = b2MakeOffsetBox(10.0f, 1.0f, {0.0f, -1.0f}, 0.0f); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape(groundId, &shapeDef, &box); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = {0.0f, 4.0f}; + b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox(1.0f, 1.0f); + b2CreatePolygonShape(bodyId, &shapeDef, &box); + } + + { + m_shapeType = b2_circleShape; + m_scale = 1.0f; + m_circle = {{0.0f, 0.0f}, 0.5f}; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position = {0.0f, 1.0f}; + b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + m_shapeId = b2CreateCircleShape(bodyId, &shapeDef, &m_circle); + } + } + + void UpdateShape() + { + switch (m_shapeType) + { + case b2_circleShape: + m_circle = {{0.0f, 0.0f}, 0.5f * m_scale}; + b2Shape_SetCircle(m_shapeId, m_circle); + break; + + case b2_capsuleShape: + m_capsule = {{-0.5f * m_scale, 0.0f}, {0.0f, 0.5f * m_scale}, 0.5f * m_scale}; + b2Shape_SetCapsule(m_shapeId, m_capsule); + break; + + case b2_segmentShape: + m_segment = {{-0.5f * m_scale, 0.0f}, {0.75f * m_scale, 0.0f}}; + b2Shape_SetSegment(m_shapeId, m_segment); + break; + + case b2_polygonShape: + m_polygon = b2MakeBox(0.5f * m_scale, 0.75f * m_scale); + b2Shape_SetPolygon(m_shapeId, m_polygon); + break; + + default: + assert(false); + break; + } + + b2BodyId bodyId = b2Shape_GetBody(m_shapeId); + b2Body_ResetMassData(bodyId); + } + + void UpdateUI() override + { + ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); + ImGui::SetNextWindowSize(ImVec2(250.0f, 240.0f)); + ImGui::Begin("Modify Geometry", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + + if (ImGui::RadioButton("Circle", m_shapeType == b2_circleShape)) + { + m_shapeType = b2_circleShape; + UpdateShape(); + } + + if (ImGui::RadioButton("Capsule", m_shapeType == b2_capsuleShape)) + { + m_shapeType = b2_capsuleShape; + UpdateShape(); + } + + if (ImGui::RadioButton("Segment", m_shapeType == b2_segmentShape)) + { + m_shapeType = b2_segmentShape; + UpdateShape(); + } + + if (ImGui::RadioButton("Polygon", m_shapeType == b2_polygonShape)) + { + m_shapeType = b2_polygonShape; + UpdateShape(); + } + + if (ImGui::SliderFloat("Scale", &m_scale, 0.1f, 10.0f, "%.2f")) + { + UpdateShape(); + } + + b2BodyId bodyId = b2Shape_GetBody(m_shapeId); + b2BodyType bodyType = b2Body_GetType(bodyId); + + if (ImGui::RadioButton("Static", bodyType == b2_staticBody)) + { + b2Body_SetType(bodyId, b2_staticBody); + } + + if (ImGui::RadioButton("Kinematic", bodyType == b2_kinematicBody)) + { + b2Body_SetType(bodyId, b2_kinematicBody); + } + + if (ImGui::RadioButton("Dynamic", bodyType == b2_dynamicBody)) + { + b2Body_SetType(bodyId, b2_dynamicBody); + } + + ImGui::End(); + } + + void Step(Settings& settings) override + { + Sample::Step(settings); + } + + static Sample* Create(const Settings& settings) + { + return new ModifyGeometry(settings); + } + + b2ShapeId m_shapeId; + b2ShapeType m_shapeType; + float m_scale; + + union + { + b2Circle m_circle; + b2Capsule m_capsule; + b2Segment m_segment; + b2Polygon m_polygon; + }; +}; + +static int sampleModifyGeometry = RegisterSample("Shapes", "Modify Geometry", ModifyGeometry::Create); diff --git a/samples/settings.h b/samples/settings.h index c0450a0f..67b7a9b3 100644 --- a/samples/settings.h +++ b/samples/settings.h @@ -28,7 +28,7 @@ struct Settings bool drawProfile = false; bool enableWarmStarting = true; bool enableContinuous = true; - bool enableSleep = false; + bool enableSleep = true; bool pause = false; bool singleStep = false; bool restart = false; diff --git a/src/body.c b/src/body.c index 38f69842..b35f72d8 100644 --- a/src/body.c +++ b/src/body.c @@ -25,7 +25,7 @@ b2Body* b2GetBody(b2World* world, b2BodyId id) { B2_ASSERT(1 <= id.index && id.index <= world->bodyPool.capacity); b2Body* body = world->bodies + (id.index - 1); - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); B2_ASSERT(id.revision == body->object.revision); return body; } @@ -281,7 +281,7 @@ bool b2IsBodyAwake(b2World* world, b2Body* body) return false; } -static void b2WakeBody(b2World* world, b2Body* body) +void b2WakeBody(b2World* world, b2Body* body) { if (body->islandIndex != B2_NULL_INDEX) { @@ -1155,6 +1155,13 @@ void b2Body_SetType(b2BodyId bodyId, b2BodyType type) b2UpdateBodyMassData(world, body); } +void b2Body_SetUserData(b2BodyId bodyId, void* userData) +{ + b2World* world = b2GetWorldFromIndex(bodyId.world); + b2Body* body = b2GetBody(world, bodyId); + body->userData = userData; +} + void* b2Body_GetUserData(b2BodyId bodyId) { b2World* world = b2GetWorldFromIndex(bodyId.world); @@ -1330,6 +1337,30 @@ bool b2Body_IsEnabled(b2BodyId bodyId) return body->isEnabled; } +bool b2Body_IsSleepEnabled(b2BodyId bodyId) +{ + b2World* world = b2GetWorldFromIndex(bodyId.world); + b2Body* body = b2GetBody(world, bodyId); + return body->enableSleep; +} + +void b2Body_EnableSleep(b2BodyId bodyId, bool enableSleep) +{ + b2World* world = b2GetWorldFromIndexLocked(bodyId.world); + if (world == NULL) + { + return; + } + + b2Body* body = b2GetBody(world, bodyId); + body->enableSleep = enableSleep; + + if (enableSleep == false) + { + b2WakeBody(world, body); + } +} + void b2Body_Disable(b2BodyId bodyId) { b2World* world = b2GetWorldFromIndexLocked(bodyId.world); diff --git a/src/body.h b/src/body.h index 4ed651fd..69e7e5af 100644 --- a/src/body.h +++ b/src/body.h @@ -124,6 +124,7 @@ typedef struct b2Body b2Body* b2GetBody(b2World* world, b2BodyId id); bool b2ShouldBodiesCollide(b2World* world, b2Body* bodyA, b2Body* bodyB); bool b2IsBodyAwake(b2World* world, b2Body* body); +void b2WakeBody(b2World* world, b2Body* body); void b2UpdateBodyMassData(b2World* world, b2Body* body); static inline b2Transform b2MakeTransform(const b2Body* body) diff --git a/src/contact.c b/src/contact.c index 48004603..f4de7fee 100644 --- a/src/contact.c +++ b/src/contact.c @@ -382,6 +382,9 @@ void b2DestroyContact(b2World* world, b2Contact* contact) world->contactAwakeIndexArray[contactIndex] = B2_NULL_INDEX; } + b2WakeBody(world, bodyA); + b2WakeBody(world, bodyB); + b2FreeObject(&world->contactPool, &contact->object); } diff --git a/src/core.h b/src/core.h index 5ba96fe2..589ff24b 100644 --- a/src/core.h +++ b/src/core.h @@ -15,6 +15,8 @@ #define B2_DEBUG 1 #endif +#define B2_VALIDATE B2_DEBUG + // Define platform #if defined(_WIN64) #define B2_PLATFORM_WINDOWS @@ -83,5 +85,3 @@ extern b2AssertFcn* b2AssertHandler; #else #define B2_ASSERT(...) ((void)0) #endif - -#define B2_VALIDATE B2_DEBUG diff --git a/src/distance_joint.c b/src/distance_joint.c index 52d7e672..bde253e1 100644 --- a/src/distance_joint.c +++ b/src/distance_joint.c @@ -40,8 +40,8 @@ void b2PrepareDistanceJoint(b2Joint* base, b2StepContext* context) b2Body* bodyA = context->bodies + indexA; b2Body* bodyB = context->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); float mA = bodyA->invMass; float iA = bodyA->invI; @@ -279,23 +279,52 @@ float b2DistanceJoint_GetConstraintForce(b2JointId jointId, float inverseTimeSte return (joint->impulse + joint->lowerImpulse - joint->upperImpulse) * inverseTimeStep; } -void b2DistanceJoint_SetLength(b2JointId jointId, float length, float minLength, float maxLength) +void b2DistanceJoint_SetLength(b2JointId jointId, float length) { b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); b2DistanceJoint* joint = &base->distanceJoint; joint->length = B2_CLAMP(length, b2_linearSlop, b2_huge); + joint->impulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; +} + +float b2DistanceJoint_GetLength(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->length; +} + +void b2DistanceJoint_SetLengthRange(b2JointId jointId, float minLength, float maxLength) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; minLength = B2_CLAMP(minLength, b2_linearSlop, b2_huge); maxLength = B2_CLAMP(maxLength, b2_linearSlop, b2_huge); joint->minLength = B2_MIN(minLength, maxLength); joint->maxLength = B2_MAX(minLength, maxLength); - joint->impulse = 0.0f; joint->lowerImpulse = 0.0f; joint->upperImpulse = 0.0f; } +float b2DistanceJoint_GetMinLength(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->minLength; +} + +float b2DistanceJoint_GetMaxLength(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->maxLength; +} + float b2DistanceJoint_GetCurrentLength(b2JointId jointId) { b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); @@ -312,8 +341,8 @@ float b2DistanceJoint_GetCurrentLength(b2JointId jointId) b2Body* bodyA = world->bodies + indexA; b2Body* bodyB = world->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Vec2 pA = b2TransformPoint(b2MakeTransform(bodyA), base->localOriginAnchorA); b2Vec2 pB = b2TransformPoint(b2MakeTransform(bodyB), base->localOriginAnchorB); @@ -330,6 +359,20 @@ void b2DistanceJoint_SetTuning(b2JointId jointId, float hertz, float dampingRati joint->dampingRatio = dampingRatio; } +float b2DistanceJoint_GetHertz(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->hertz; +} + +float b2DistanceJoint_GetDampingRatio(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_distanceJoint); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->dampingRatio; +} + #if 0 void b2DistanceJoint::Dump() { diff --git a/src/joint.c b/src/joint.c index 18339a04..cb62d359 100644 --- a/src/joint.c +++ b/src/joint.c @@ -95,7 +95,7 @@ b2Joint* b2GetJoint(b2World* world, b2JointId jointId) { B2_ASSERT(1 <= jointId.index && jointId.index <= world->jointPool.capacity); b2Joint* joint = world->joints + (jointId.index - 1); - B2_ASSERT(b2ObjectValid(&joint->object)); + B2_ASSERT(b2IsValidObject(&joint->object)); B2_ASSERT(joint->object.revision == jointId.revision); return joint; } @@ -209,8 +209,8 @@ b2JointId b2CreateDistanceJoint(b2WorldId worldId, const b2DistanceJointDef* def b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -218,6 +218,7 @@ b2JointId b2CreateDistanceJoint(b2WorldId worldId, const b2DistanceJointDef* def joint->localOriginAnchorA = def->localAnchorA; joint->localOriginAnchorB = def->localAnchorB; joint->collideConnected = def->collideConnected; + joint->userData = def->userData; b2DistanceJoint empty = {0}; joint->distanceJoint = empty; @@ -256,15 +257,16 @@ b2JointId b2CreateMotorJoint(b2WorldId worldId, const b2MotorJointDef* def) b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); joint->type = b2_motorJoint; joint->localOriginAnchorA = (b2Vec2){0.0f, 0.0f}; joint->localOriginAnchorB = (b2Vec2){0.0f, 0.0f}; - joint->collideConnected = true; + joint->collideConnected = def->collideConnected; + joint->userData = def->userData; joint->motorJoint = (b2MotorJoint){0}; joint->motorJoint.linearOffset = def->linearOffset; @@ -273,6 +275,12 @@ b2JointId b2CreateMotorJoint(b2WorldId worldId, const b2MotorJointDef* def) joint->motorJoint.maxTorque = def->maxTorque; joint->motorJoint.correctionFactor = B2_CLAMP(def->correctionFactor, 0.0f, 1.0f); + // If the joint prevents collisions, then destroy all contacts between attached bodies + if (def->collideConnected == false) + { + b2DestroyContactsBetweenBodies(world, bodyA, bodyB); + } + b2JointId jointId = {joint->object.index + 1, world->poolIndex, joint->object.revision}; return jointId; } @@ -293,8 +301,8 @@ b2JointId b2CreateMouseJoint(b2WorldId worldId, const b2MouseJointDef* def) b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -302,6 +310,7 @@ b2JointId b2CreateMouseJoint(b2WorldId worldId, const b2MouseJointDef* def) joint->localOriginAnchorA = b2InvTransformPoint(b2MakeTransform(bodyA), def->target); joint->localOriginAnchorB = b2InvTransformPoint(b2MakeTransform(bodyB), def->target); joint->collideConnected = true; + joint->userData = def->userData; b2MouseJoint empty = {0}; joint->mouseJoint = empty; @@ -329,8 +338,8 @@ b2JointId b2CreateRevoluteJoint(b2WorldId worldId, const b2RevoluteJointDef* def b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -338,6 +347,7 @@ b2JointId b2CreateRevoluteJoint(b2WorldId worldId, const b2RevoluteJointDef* def joint->localOriginAnchorA = def->localAnchorA; joint->localOriginAnchorB = def->localAnchorB; joint->collideConnected = def->collideConnected; + joint->userData = def->userData; joint->drawSize = def->drawSize; b2RevoluteJoint empty = {0}; @@ -382,8 +392,8 @@ b2JointId b2CreatePrismaticJoint(b2WorldId worldId, const b2PrismaticJointDef* d b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -391,6 +401,7 @@ b2JointId b2CreatePrismaticJoint(b2WorldId worldId, const b2PrismaticJointDef* d joint->localOriginAnchorA = def->localAnchorA; joint->localOriginAnchorB = def->localAnchorB; joint->collideConnected = def->collideConnected; + joint->userData = def->userData; b2PrismaticJoint empty = {0}; joint->prismaticJoint = empty; @@ -435,8 +446,8 @@ b2JointId b2CreateWeldJoint(b2WorldId worldId, const b2WeldJointDef* def) b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -444,6 +455,7 @@ b2JointId b2CreateWeldJoint(b2WorldId worldId, const b2WeldJointDef* def) joint->localOriginAnchorA = def->localAnchorA; joint->localOriginAnchorB = def->localAnchorB; joint->collideConnected = def->collideConnected; + joint->userData = def->userData; b2WeldJoint empty = {0}; joint->weldJoint = empty; @@ -481,8 +493,8 @@ b2JointId b2CreateWheelJoint(b2WorldId worldId, const b2WheelJointDef* def) b2Body* bodyA = world->bodies + (def->bodyIdA.index - 1); b2Body* bodyB = world->bodies + (def->bodyIdB.index - 1); - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); b2Joint* joint = b2CreateJoint(world, bodyA, bodyB); @@ -490,6 +502,7 @@ b2JointId b2CreateWheelJoint(b2WorldId worldId, const b2WheelJointDef* def) joint->localOriginAnchorA = def->localAnchorA; joint->localOriginAnchorB = def->localAnchorB; joint->collideConnected = def->collideConnected; + joint->userData = def->userData; // todo test this joint->wheelJoint = (b2WheelJoint){0}; @@ -526,8 +539,8 @@ void b2DestroyJointInternal(b2World* world, b2Joint* joint) b2Body* bodyA = world->bodies + edgeA->bodyIndex; b2Body* bodyB = world->bodies + edgeB->bodyIndex; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); // Remove from body A if (edgeA->prevKey != B2_NULL_INDEX) @@ -599,8 +612,8 @@ void b2DestroyJoint(b2JointId jointId) b2Body* bodyA = world->bodies + edgeA->bodyIndex; b2Body* bodyB = world->bodies + edgeB->bodyIndex; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); // Remove from body A if (edgeA->prevKey != B2_NULL_INDEX) @@ -669,7 +682,7 @@ b2BodyId b2Joint_GetBodyA(b2JointId jointId) int32_t bodyIndex = joint->edges[0].bodyIndex; b2Body* body = world->bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2BodyId bodyId = {bodyIndex + 1, jointId.world, body->object.revision}; return bodyId; } @@ -681,11 +694,25 @@ b2BodyId b2Joint_GetBodyB(b2JointId jointId) int32_t bodyIndex = joint->edges[1].bodyIndex; b2Body* body = world->bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2BodyId bodyId = {bodyIndex + 1, jointId.world, body->object.revision}; return bodyId; } +b2Vec2 b2Joint_GetLocalAnchorA(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + return joint->localOriginAnchorA; +} + +b2Vec2 b2Joint_GetLocalAnchorB(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + return joint->localOriginAnchorB; +} + void b2Joint_SetCollideConnected(b2JointId jointId, bool shouldCollide) { b2World* world = b2GetWorldFromIndexLocked(jointId.world); @@ -762,6 +789,20 @@ bool b2Joint_GetCollideConnected(b2JointId jointId) return joint->collideConnected; } +void b2Joint_SetUserData(b2JointId jointId, void* userData) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + joint->userData = userData; +} + +void* b2Joint_GetUserData(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + return joint->userData; +} + extern void b2PrepareDistanceJoint(b2Joint* base, b2StepContext* context); extern void b2PrepareMotorJoint(b2Joint* base, b2StepContext* context); extern void b2PrepareMouseJoint(b2Joint* base, b2StepContext* context); @@ -914,7 +955,7 @@ void b2PrepareOverflowJoints(b2StepContext* context) B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2PrepareJoint(joint, context); } @@ -938,7 +979,7 @@ void b2WarmStartOverflowJoints(b2StepContext* context) B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2WarmStartJoint(joint, context); } @@ -962,7 +1003,7 @@ void b2SolveOverflowJoints(b2StepContext* context, bool useBias) B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2SolveJoint(joint, context, useBias); } diff --git a/src/joint.h b/src/joint.h index 0804b6fa..d3a0c067 100644 --- a/src/joint.h +++ b/src/joint.h @@ -220,6 +220,8 @@ typedef struct b2Joint b2WheelJoint wheelJoint; }; + void* userData; + float drawSize; bool isMarked; bool collideConnected; diff --git a/src/motor_joint.c b/src/motor_joint.c index 5cd637d7..76a2bc09 100644 --- a/src/motor_joint.c +++ b/src/motor_joint.c @@ -180,79 +180,64 @@ void b2SolveMotorJoint(b2Joint* base, const b2StepContext* context, bool useBias void b2MotorJoint_SetLinearOffset(b2JointId jointId, b2Vec2 linearOffset) { - b2World* world = b2GetWorldFromIndex(jointId.world); - B2_ASSERT(world->locked == false); - if (world->locked) - { - return; - } - - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_motorJoint); - + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); joint->motorJoint.linearOffset = linearOffset; } -void b2MotorJoint_SetAngularOffset(b2JointId jointId, float angularOffset) +b2Vec2 b2MotorJoint_GetLinearOffset(b2JointId jointId) { - b2World* world = b2GetWorldFromIndex(jointId.world); - B2_ASSERT(world->locked == false); - if (world->locked) - { - return; - } - - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_motorJoint); + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); + return joint->motorJoint.linearOffset; +} +void b2MotorJoint_SetAngularOffset(b2JointId jointId, float angularOffset) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); joint->motorJoint.angularOffset = angularOffset; } -void b2MotorJoint_SetMaxForce(b2JointId jointId, float maxForce) +float b2MotorJoint_GetAngularOffset(b2JointId jointId) { - b2World* world = b2GetWorldFromIndex(jointId.world); - B2_ASSERT(world->locked == false); - if (world->locked) - { - return; - } - - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_motorJoint); + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); + return joint->motorJoint.angularOffset; +} +void b2MotorJoint_SetMaxForce(b2JointId jointId, float maxForce) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); joint->motorJoint.maxForce = B2_MAX(0.0f, maxForce); } -void b2MotorJoint_SetMaxTorque(b2JointId jointId, float maxTorque) +float b2MotorJoint_GetMaxForce(b2JointId jointId) { - b2World* world = b2GetWorldFromIndex(jointId.world); - B2_ASSERT(world->locked == false); - if (world->locked) - { - return; - } - - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_motorJoint); + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); + return joint->motorJoint.maxForce; +} +void b2MotorJoint_SetMaxTorque(b2JointId jointId, float maxTorque) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); joint->motorJoint.maxTorque = B2_MAX(0.0f, maxTorque); } -void b2MotorJoint_SetCorrectionFactor(b2JointId jointId, float correctionFactor) +float b2MotorJoint_GetMaxTorque(b2JointId jointId) { - b2World* world = b2GetWorldFromIndex(jointId.world); - B2_ASSERT(world->locked == false); - if (world->locked) - { - return; - } - - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_motorJoint); + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); + return joint->motorJoint.maxTorque; +} +void b2MotorJoint_SetCorrectionFactor(b2JointId jointId, float correctionFactor) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); joint->motorJoint.correctionFactor = B2_CLAMP(correctionFactor, 0.0f, 1.0f); } +float b2MotorJoint_GetCorrectionFactor(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_motorJoint); + return joint->motorJoint.correctionFactor; +} + b2Vec2 b2MotorJoint_GetConstraintForce(b2JointId jointId) { b2World* world = b2GetWorldFromIndex(jointId.world); diff --git a/src/mouse_joint.c b/src/mouse_joint.c index 78e6a70b..4d701054 100644 --- a/src/mouse_joint.c +++ b/src/mouse_joint.c @@ -16,6 +16,31 @@ void b2MouseJoint_SetTarget(b2JointId jointId, b2Vec2 target) base->mouseJoint.targetA = target; } +b2Vec2 b2MouseJoint_GetTarget(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_mouseJoint); + return base->mouseJoint.targetA; +} + +void b2MouseJoint_SetTuning(b2JointId jointId, float hertz, float dampingRatio) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_mouseJoint); + base->mouseJoint.hertz = hertz; + base->mouseJoint.dampingRatio = dampingRatio; +} + +float b2MouseJoint_GetHertz(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_mouseJoint); + return base->mouseJoint.hertz; +} + +float b2MouseJoint_GetDampingRatio(b2JointId jointId) +{ + b2Joint* base = b2GetJointCheckType(jointId, b2_mouseJoint); + return base->mouseJoint.dampingRatio; +} + void b2PrepareMouseJoint(b2Joint* base, b2StepContext* context) { B2_ASSERT(base->type == b2_mouseJoint); diff --git a/src/pool.h b/src/pool.h index fe7cbdae..720fd4de 100644 --- a/src/pool.h +++ b/src/pool.h @@ -35,7 +35,7 @@ void b2FreeObject(b2Pool* pool, b2Object* object); void b2GrowPool(b2Pool* pool, int32_t capacity); -static inline bool b2ObjectValid(const b2Object* object) +static inline bool b2IsValidObject(const b2Object* object) { // this means the object is not on the free list return object->index == object->next; diff --git a/src/prismatic_joint.c b/src/prismatic_joint.c index 40fa6213..461bb4aa 100644 --- a/src/prismatic_joint.c +++ b/src/prismatic_joint.c @@ -13,6 +13,94 @@ #include +void b2PrismaticJoint_EnableLimit(b2JointId jointId, bool enableLimit) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + joint->prismaticJoint.enableLimit = enableLimit; +} + +bool b2PrismaticJoint_IsLimitEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + return joint->prismaticJoint.enableLimit; +} + +void b2PrismaticJoint_EnableMotor(b2JointId jointId, bool enableMotor) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + joint->prismaticJoint.enableMotor = enableMotor; +} + +bool b2PrismaticJoint_IsMotorEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + return joint->prismaticJoint.enableMotor; +} + +void b2PrismaticJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + joint->prismaticJoint.motorSpeed = motorSpeed; +} + +float b2PrismaticJoint_GetMotorSpeed(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + return joint->prismaticJoint.motorSpeed; +} + +float b2PrismaticJoint_GetMotorForce(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* base = b2GetJoint(world, jointId); + B2_ASSERT(base->type == b2_prismaticJoint); + return world->inv_h * base->prismaticJoint.motorImpulse; +} + +void b2PrismaticJoint_SetMaxMotorForce(b2JointId jointId, float force) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + joint->prismaticJoint.maxMotorForce = force; +} + +float b2PrismaticJoint_GetMaxMotorForce(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); + return joint->prismaticJoint.maxMotorForce; +} + +b2Vec2 b2PrismaticJoint_GetConstraintForce(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* base = b2GetJoint(world, jointId); + B2_ASSERT(base->type == b2_prismaticJoint); + + int32_t indexA = base->edges[0].bodyIndex; + b2Body* bodyA = world->bodies + indexA; + B2_ASSERT(b2IsValidObject(&bodyA->object)); + + b2PrismaticJoint* joint = &base->prismaticJoint; + + b2Vec2 axisA = b2RotateVector(bodyA->rotation, joint->localAxisA); + b2Vec2 perpA = b2LeftPerp(axisA); + + float inv_h = world->inv_h; + float perpForce = inv_h * joint->impulse.x; + float axialForce = inv_h * (joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse); + + b2Vec2 force = b2Add(b2MulSV(perpForce, perpA), b2MulSV(axialForce, axisA)); + return force; +} + +float b2PrismaticJoint_GetConstraintTorque(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_prismaticJoint); + + return world->inv_h * joint->prismaticJoint.impulse.y; +} + // Linear constraint (point-to-line) // d = p2 - p1 = x2 + r2 - x1 - r1 // C = dot(perp, d) @@ -66,8 +154,8 @@ void b2PreparePrismaticJoint(b2Joint* base, b2StepContext* context) int32_t indexB = base->edges[1].bodyIndex; b2Body* bodyA = context->bodies + indexA; b2Body* bodyB = context->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); float mA = bodyA->invMass; float iA = bodyA->invI; @@ -349,70 +437,6 @@ void b2SolvePrismaticJoint(b2Joint* base, b2StepContext* context, bool useBias) stateB->angularVelocity = wB; } -void b2PrismaticJoint_EnableLimit(b2JointId jointId, bool enableLimit) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); - joint->prismaticJoint.enableLimit = enableLimit; -} - -void b2PrismaticJoint_EnableMotor(b2JointId jointId, bool enableMotor) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); - joint->prismaticJoint.enableMotor = enableMotor; -} - -void b2PrismaticJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); - joint->prismaticJoint.motorSpeed = motorSpeed; -} - -float b2PrismaticJoint_GetMotorForce(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* base = b2GetJoint(world, jointId); - B2_ASSERT(base->type == b2_prismaticJoint); - return world->inv_h * base->prismaticJoint.motorImpulse; -} - -void b2PrismaticJoint_SetMaxMotorForce(b2JointId jointId, float force) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_prismaticJoint); - joint->prismaticJoint.maxMotorForce = force; -} - -b2Vec2 b2PrismaticJoint_GetConstraintForce(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* base = b2GetJoint(world, jointId); - B2_ASSERT(base->type == b2_prismaticJoint); - - int32_t indexA = base->edges[0].bodyIndex; - b2Body* bodyA = world->bodies + indexA; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - - b2PrismaticJoint* joint = &base->prismaticJoint; - - b2Vec2 axisA = b2RotateVector(bodyA->rotation, joint->localAxisA); - b2Vec2 perpA = b2LeftPerp(axisA); - - float inv_h = world->inv_h; - float perpForce = inv_h * joint->impulse.x; - float axialForce = inv_h * (joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse); - - b2Vec2 force = b2Add(b2MulSV(perpForce, perpA), b2MulSV(axialForce, axisA)); - return force; -} - -float b2PrismaticJoint_GetConstraintTorque(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_prismaticJoint); - - return world->inv_h * joint->prismaticJoint.impulse.y; -} - #if 0 void b2PrismaticJoint::Dump() { diff --git a/src/revolute_joint.c b/src/revolute_joint.c index ace7064e..75b02d00 100644 --- a/src/revolute_joint.c +++ b/src/revolute_joint.c @@ -15,6 +15,84 @@ #include +void b2RevoluteJoint_EnableLimit(b2JointId jointId, bool enableLimit) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + joint->revoluteJoint.enableLimit = enableLimit; +} + +bool b2RevoluteJoint_IsLimitEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + return joint->revoluteJoint.enableLimit; +} + +void b2RevoluteJoint_EnableMotor(b2JointId jointId, bool enableMotor) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + joint->revoluteJoint.enableMotor = enableMotor; +} + +bool b2RevoluteJoint_IsMotorEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + return joint->revoluteJoint.enableMotor; +} + +void b2RevoluteJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + joint->revoluteJoint.motorSpeed = motorSpeed; +} + +float b2RevoluteJoint_GetMotorSpeed(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + return joint->revoluteJoint.motorSpeed; +} + +float b2RevoluteJoint_GetMotorTorque(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_revoluteJoint); + + return world->inv_h * joint->revoluteJoint.motorImpulse; +} + +void b2RevoluteJoint_SetMaxMotorTorque(b2JointId jointId, float torque) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + joint->revoluteJoint.maxMotorTorque = torque; +} + +float b2RevoluteJoint_GetMaxMotorTorque(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); + return joint->revoluteJoint.maxMotorTorque; +} + +b2Vec2 b2RevoluteJoint_GetConstraintForce(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_revoluteJoint); + + b2Vec2 force = b2MulSV(world->inv_h, joint->revoluteJoint.linearImpulse); + return force; +} + +float b2RevoluteJoint_GetConstraintTorque(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_revoluteJoint); + + const b2RevoluteJoint* revolute = &joint->revoluteJoint; + float torque = world->inv_h * (revolute->motorImpulse + revolute->lowerImpulse - revolute->upperImpulse); + return torque; +} + // Point-to-point constraint // C = p2 - p1 // Cdot = v2 - v1 @@ -52,8 +130,8 @@ void b2PrepareRevoluteJoint(b2Joint* base, b2StepContext* context) int32_t indexB = base->edges[1].bodyIndex; b2Body* bodyA = context->bodies + indexA; b2Body* bodyB = context->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); float mA = bodyA->invMass; float iA = bodyA->invI; @@ -272,60 +350,6 @@ void b2SolveRevoluteJoint(b2Joint* base, b2StepContext* context, bool useBias) stateB->angularVelocity = wB; } -void b2RevoluteJoint_EnableLimit(b2JointId jointId, bool enableLimit) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); - joint->revoluteJoint.enableLimit = enableLimit; -} - -void b2RevoluteJoint_EnableMotor(b2JointId jointId, bool enableMotor) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); - joint->revoluteJoint.enableMotor = enableMotor; -} - -void b2RevoluteJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); - joint->revoluteJoint.motorSpeed = motorSpeed; -} - -float b2RevoluteJoint_GetMotorTorque(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_revoluteJoint); - - return world->inv_h * joint->revoluteJoint.motorImpulse; -} - -void b2RevoluteJoint_SetMaxMotorTorque(b2JointId jointId, float torque) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_revoluteJoint); - joint->revoluteJoint.maxMotorTorque = torque; -} - -b2Vec2 b2RevoluteJoint_GetConstraintForce(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_revoluteJoint); - - b2Vec2 force = b2MulSV(world->inv_h, joint->revoluteJoint.linearImpulse); - return force; -} - -float b2RevoluteJoint_GetConstraintTorque(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_revoluteJoint); - - const b2RevoluteJoint* revolute = &joint->revoluteJoint; - float torque = world->inv_h * (revolute->motorImpulse + revolute->lowerImpulse - revolute->upperImpulse); - return torque; -} - #if 0 void b2RevoluteJoint::Dump() { diff --git a/src/shape.c b/src/shape.c index d83572fd..c25c45f4 100644 --- a/src/shape.c +++ b/src/shape.c @@ -16,7 +16,7 @@ b2Shape* b2GetShape(b2World* world, b2ShapeId shapeId) { B2_ASSERT(1 <= shapeId.index && shapeId.index <= world->shapePool.capacity); b2Shape* shape = world->shapes + (shapeId.index - 1); - B2_ASSERT(b2ObjectValid(&shape->object)); + B2_ASSERT(b2IsValidObject(&shape->object)); B2_ASSERT(shape->object.revision == shapeId.revision); return shape; } @@ -25,7 +25,7 @@ static b2ChainShape* b2GetChainShape(b2World* world, b2ChainId chainId) { B2_ASSERT(1 <= chainId.index && chainId.index <= world->chainPool.capacity); b2ChainShape* chain = world->chains + (chainId.index - 1); - B2_ASSERT(b2ObjectValid(&chain->object)); + B2_ASSERT(b2IsValidObject(&chain->object)); B2_ASSERT(chain->object.revision == chainId.revision); return chain; } @@ -265,12 +265,19 @@ b2BodyId b2Shape_GetBody(b2ShapeId shapeId) b2Shape* shape = b2GetShape(world, shapeId); b2Body* body = world->bodies + shape->bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2BodyId bodyId = {body->object.index + 1, shapeId.world, body->object.revision}; return bodyId; } +void b2Shape_SetUserData(b2ShapeId shapeId, void* userData) +{ + b2World* world = b2GetWorldFromIndex(shapeId.world); + b2Shape* shape = b2GetShape(world, shapeId); + shape->userData = userData; +} + void* b2Shape_GetUserData(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); @@ -291,7 +298,7 @@ bool b2Shape_TestPoint(b2ShapeId shapeId, b2Vec2 point) b2Shape* shape = b2GetShape(world, shapeId); b2Body* body = world->bodies + shape->bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2Vec2 localPoint = b2InvTransformPoint(b2MakeTransform(body), point); @@ -311,6 +318,57 @@ bool b2Shape_TestPoint(b2ShapeId shapeId, b2Vec2 point) } } +b2CastOutput b2Shape_RayCast(b2ShapeId shapeId, b2Vec2 origin, b2Vec2 translation) +{ + b2World* world = b2GetWorldFromIndex(shapeId.world); + b2Shape* shape = b2GetShape(world, shapeId); + + b2Body* body = world->bodies + shape->bodyIndex; + B2_ASSERT(b2IsValidObject(&body->object)); + b2Transform transform = b2MakeTransform(body); + + // input in local coordinates + b2RayCastInput input = {0}; + input.maxFraction = 1.0f; + input.origin = b2InvTransformPoint(transform, origin); + input.translation = b2InvRotateVector(transform.q, translation); + + b2CastOutput output = {0}; + switch (shape->type) + { + case b2_capsuleShape: + output = b2RayCastCapsule(&input, &shape->capsule); + break; + + case b2_circleShape: + output = b2RayCastCircle(&input, &shape->circle); + break; + + case b2_segmentShape: + output = b2RayCastSegment(&input, &shape->segment, false); + break; + + case b2_polygonShape: + output = b2RayCastPolygon(&input, &shape->polygon); + break; + + case b2_smoothSegmentShape: + output = b2RayCastSegment(&input, &shape->smoothSegment.segment, true); + break; + + default: + (b2RayResult){0}; + } + + if (output.hit) + { + // convert to world coordinates + output.normal = b2RotateVector(transform.q, output.normal); + output.point = b2TransformPoint(transform, output.point); + } + return output; +} + void b2Shape_SetDensity(b2ShapeId shapeId, float density) { B2_ASSERT(b2IsValid(density) && density >= 0.0f); @@ -389,15 +447,55 @@ b2Filter b2Shape_GetFilter(b2ShapeId shapeId) return shape->filter; } +static void b2ResetContactsAndProxy(b2World* world, b2Shape* shape) +{ + int32_t shapeIndex = shape->object.index; + + b2Body* body = world->bodies + shape->bodyIndex; + B2_ASSERT(b2IsValidObject(&body->object)); + + // Destroy any contacts associated with the shape + int32_t contactKey = body->contactList; + while (contactKey != B2_NULL_INDEX) + { + int32_t contactIndex = contactKey >> 1; + int32_t edgeIndex = contactKey & 1; + + b2Contact* contact = world->contacts + contactIndex; + contactKey = contact->edges[edgeIndex].nextKey; + + if (contact->shapeIndexA == shapeIndex || contact->shapeIndexB == shapeIndex) + { + b2DestroyContact(world, contact); + } + } + + if (body->isEnabled) + { + // Must recreate proxy due to changed filter bits that exist in the dynamic tree + b2DestroyShapeProxy(shape, &world->broadPhase); + b2CreateShapeProxy(shape, &world->broadPhase, body->type, b2MakeTransform(body)); + } + else + { + B2_ASSERT(shape->proxyKey == B2_NULL_INDEX); + } +} + void b2Shape_SetFilter(b2ShapeId shapeId, b2Filter filter) { - b2World* world = b2GetWorldFromIndex(shapeId.world); + b2World* world = b2GetWorldFromIndexLocked(shapeId.world); + if (world == NULL) + { + return; + } + b2Shape* shape = b2GetShape(world, shapeId); shape->filter = filter; int32_t shapeIndex = shape->object.index; b2Body* body = world->bodies + shape->bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); // Destroy any contacts associated with the shape int32_t contactKey = body->contactList; @@ -434,44 +532,100 @@ b2ShapeType b2Shape_GetType(b2ShapeId shapeId) return shape->type; } -const b2Circle* b2Shape_GetCircle(b2ShapeId shapeId) +const b2Circle b2Shape_GetCircle(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); b2Shape* shape = b2GetShape(world, shapeId); B2_ASSERT(shape->type == b2_circleShape); - return &shape->circle; + return shape->circle; } -const b2Segment* b2Shape_GetSegment(b2ShapeId shapeId) +const b2Segment b2Shape_GetSegment(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); b2Shape* shape = b2GetShape(world, shapeId); B2_ASSERT(shape->type == b2_segmentShape); - return &shape->segment; + return shape->segment; } -const b2SmoothSegment* b2Shape_GetSmoothSegment(b2ShapeId shapeId) +const b2SmoothSegment b2Shape_GetSmoothSegment(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); b2Shape* shape = b2GetShape(world, shapeId); B2_ASSERT(shape->type == b2_smoothSegmentShape); - return &shape->smoothSegment; + return shape->smoothSegment; } -const b2Capsule* b2Shape_GetCapsule(b2ShapeId shapeId) +const b2Capsule b2Shape_GetCapsule(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); b2Shape* shape = b2GetShape(world, shapeId); B2_ASSERT(shape->type == b2_capsuleShape); - return &shape->capsule; + return shape->capsule; } -const b2Polygon* b2Shape_GetPolygon(b2ShapeId shapeId) +const b2Polygon b2Shape_GetPolygon(b2ShapeId shapeId) { b2World* world = b2GetWorldFromIndex(shapeId.world); b2Shape* shape = b2GetShape(world, shapeId); B2_ASSERT(shape->type == b2_polygonShape); - return &shape->polygon; + return shape->polygon; +} + +void b2Shape_SetCircle(b2ShapeId shapeId, b2Circle circle) +{ + b2World* world = b2GetWorldFromIndexLocked(shapeId.world); + if (world == NULL) + { + return; + } + + b2Shape* shape = b2GetShape(world, shapeId); + shape->circle = circle; + shape->type = b2_circleShape; + b2ResetContactsAndProxy(world, shape); +} + +void b2Shape_SetCapsule(b2ShapeId shapeId, b2Capsule capsule) +{ + b2World* world = b2GetWorldFromIndexLocked(shapeId.world); + if (world == NULL) + { + return; + } + + b2Shape* shape = b2GetShape(world, shapeId); + shape->capsule = capsule; + shape->type = b2_capsuleShape; + b2ResetContactsAndProxy(world, shape); +} + +void b2Shape_SetSegment(b2ShapeId shapeId, b2Segment segment) +{ + b2World* world = b2GetWorldFromIndexLocked(shapeId.world); + if (world == NULL) + { + return; + } + + b2Shape* shape = b2GetShape(world, shapeId); + shape->segment = segment; + shape->type = b2_segmentShape; + b2ResetContactsAndProxy(world, shape); +} + +void b2Shape_SetPolygon(b2ShapeId shapeId, b2Polygon polygon) +{ + b2World* world = b2GetWorldFromIndexLocked(shapeId.world); + if (world == NULL) + { + return; + } + + b2Shape* shape = b2GetShape(world, shapeId); + shape->polygon = polygon; + shape->type = b2_polygonShape; + b2ResetContactsAndProxy(world, shape); } b2ChainId b2Shape_GetParentChain(b2ShapeId shapeId) @@ -485,7 +639,7 @@ b2ChainId b2Shape_GetParentChain(b2ShapeId shapeId) { B2_ASSERT(0 <= chainIndex && chainIndex < world->chainPool.capacity); b2ChainShape* chain = world->chains + chainIndex; - B2_ASSERT(b2ObjectValid(&chain->object)); + B2_ASSERT(b2IsValidObject(&chain->object)); b2ChainId chainId = {chainIndex, shapeId.world, chain->object.revision}; return chainId; } @@ -546,6 +700,7 @@ int32_t b2Shape_GetContactCapacity(b2ShapeId shapeId) b2Shape* shape = b2GetShape(world, shapeId); b2Body* body = world->bodies + shape->bodyIndex; + B2_ASSERT(b2IsValidObject(&body->object)); // Conservative and fast return body->contactCount; diff --git a/src/solver.c b/src/solver.c index 36143bff..edeed7ce 100644 --- a/src/solver.c +++ b/src/solver.c @@ -95,7 +95,7 @@ static void b2PrepareJointsTask(int32_t startIndex, int32_t endIndex, b2StepCont B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2PrepareJoint(joint, context); } @@ -117,7 +117,7 @@ static void b2WarmStartJointsTask(int32_t startIndex, int32_t endIndex, b2StepCo B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2WarmStartJoint(joint, context); } @@ -139,7 +139,7 @@ static void b2SolveJointsTask(int32_t startIndex, int32_t endIndex, b2StepContex B2_ASSERT(0 <= index && index < world->jointPool.capacity); b2Joint* joint = joints + index; - B2_ASSERT(b2ObjectValid(&joint->object) == true); + B2_ASSERT(b2IsValidObject(&joint->object) == true); b2SolveJoint(joint, context, useBias); } @@ -200,7 +200,7 @@ static void b2FinalizeBodiesTask(int32_t startIndex, int32_t endIndex, uint32_t int32_t bodyIndex = solverToBodyMap[i]; b2Body* body = bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2Vec2 v = state->linearVelocity; float w = state->angularVelocity; @@ -781,7 +781,7 @@ static bool b2SolveConstraintGraph(b2World* world, b2StepContext* context) while (bodyIndex != B2_NULL_INDEX) { b2Body* body = bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); B2_ASSERT(body->object.index == bodyIndex); awakeBodies[index] = body; @@ -1404,7 +1404,7 @@ static bool b2SolveConstraintGraph(b2World* world, b2StepContext* context) uint32_t ctz = b2CTZ(word); uint32_t islandIndex = 64 * k + ctz; - B2_ASSERT(b2ObjectValid(&islands[islandIndex].object)); + B2_ASSERT(b2IsValidObject(&islands[islandIndex].object)); b2Array_Push(world->awakeIslandArray, islandIndex); @@ -1422,7 +1422,7 @@ static bool b2SolveConstraintGraph(b2World* world, b2StepContext* context) for (int32_t i = 0; i < world->islandPool.capacity; ++i) { b2Island* island = world->islands + i; - if (b2ObjectValid(&island->object) == false) + if (b2IsValidObject(&island->object) == false) { continue; } @@ -1565,7 +1565,7 @@ static bool b2ContinuousQueryCallback(int32_t proxyId, int32_t shapeIndex, void* static void b2SolveContinuous(b2World* world, int32_t bodyIndex) { b2Body* fastBody = world->bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&fastBody->object)); + B2_ASSERT(b2IsValidObject(&fastBody->object)); B2_ASSERT(fastBody->type == b2_dynamicBody && fastBody->isFast); b2Shape* shapes = world->shapes; @@ -1761,7 +1761,7 @@ void b2Solve(b2World* world, b2StepContext* context) uint32_t shapeIndex = 64 * k + ctz; b2Shape* shape = shapes + shapeIndex; - B2_ASSERT(b2ObjectValid(&shape->object)); + B2_ASSERT(b2IsValidObject(&shape->object)); if (shape->isFast == false) { b2BroadPhase_EnlargeProxy(broadPhase, shape->proxyKey, shape->fatAABB); diff --git a/src/weld_joint.c b/src/weld_joint.c index 441b9c97..645ab8df 100644 --- a/src/weld_joint.c +++ b/src/weld_joint.c @@ -10,6 +10,58 @@ // needed for dll export #include "box2d/box2d.h" +void b2WeldJoint_SetLinearHertz(b2JointId jointId, float hertz) +{ + B2_ASSERT(b2IsValid(hertz) && hertz >= 0.0f); + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + joint->weldJoint.linearHertz = hertz; +} + +float b2WeldJoint_GetLinearHertz(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + return joint->weldJoint.linearHertz; +} + +void b2WeldJoint_SetLinearDampingRatio(b2JointId jointId, float dampingRatio) +{ + B2_ASSERT(b2IsValid(dampingRatio) && dampingRatio >= 0.0f); + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + joint->weldJoint.linearDampingRatio = dampingRatio; +} + +float b2WeldJoint_GetLinearDampingRatio(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + return joint->weldJoint.linearDampingRatio; +} + +void b2WeldJoint_SetAngularHertz(b2JointId jointId, float hertz) +{ + B2_ASSERT(b2IsValid(hertz) && hertz >= 0.0f); + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + joint->weldJoint.angularHertz = hertz; +} + +float b2WeldJoint_GetAngularHertz(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + return joint->weldJoint.angularHertz; +} + +void b2WeldJoint_SetAngularDampingRatio(b2JointId jointId, float dampingRatio) +{ + B2_ASSERT(b2IsValid(dampingRatio) && dampingRatio >= 0.0f); + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + joint->weldJoint.angularDampingRatio = dampingRatio; +} + +float b2WeldJoint_GetAngularDampingRatio(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); + return joint->weldJoint.angularDampingRatio; +} + // Point-to-point constraint // C = p2 - p1 // Cdot = v2 - v1 @@ -32,8 +84,8 @@ void b2PrepareWeldJoint(b2Joint* base, b2StepContext* context) int32_t indexB = base->edges[1].bodyIndex; b2Body* bodyA = context->bodies + indexA; b2Body* bodyB = context->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); float mA = bodyA->invMass; float iA = bodyA->invI; @@ -217,32 +269,3 @@ void b2DumpWeldJoint() b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } #endif - -void b2WeldJoint_SetLinearHertz(b2JointId jointId, float hertz) -{ - B2_ASSERT(b2IsValid(hertz) && hertz >= 0.0f); - - b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); - joint->weldJoint.linearHertz = hertz; -} - -void b2WeldJoint_SetLinearDampingRatio(b2JointId jointId, float dampingRatio) -{ - B2_ASSERT(b2IsValid(dampingRatio) && dampingRatio >= 0.0f); - b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); - joint->weldJoint.linearDampingRatio = dampingRatio; -} - -void b2WeldJoint_SetAngularHertz(b2JointId jointId, float hertz) -{ - B2_ASSERT(b2IsValid(hertz) && hertz >= 0.0f); - b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); - joint->weldJoint.angularHertz = hertz; -} - -void b2WeldJoint_SetAngularDampingRatio(b2JointId jointId, float dampingRatio) -{ - B2_ASSERT(b2IsValid(dampingRatio) && dampingRatio >= 0.0f); - b2Joint* joint = b2GetJointCheckType(jointId, b2_weldJoint); - joint->weldJoint.angularDampingRatio = dampingRatio; -} diff --git a/src/wheel_joint.c b/src/wheel_joint.c index ed7cf8cb..9fff7fb3 100644 --- a/src/wheel_joint.c +++ b/src/wheel_joint.c @@ -13,6 +13,128 @@ #include +void b2WheelJoint_SetSpringHertz(b2JointId jointId, float hertz) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + joint->wheelJoint.hertz = hertz; +} + +float b2WheelJoint_GetSpringHertz(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.hertz; +} + +void b2WheelJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + joint->wheelJoint.dampingRatio = dampingRatio; +} + +float b2WheelJoint_GetSpringDampingRatio(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.dampingRatio; +} + +void b2WheelJoint_EnableLimit(b2JointId jointId, bool enableLimit) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + + if (joint->wheelJoint.enableLimit != enableLimit) + { + joint->wheelJoint.lowerImpulse = 0.0f; + joint->wheelJoint.upperImpulse = 0.0f; + } + + joint->wheelJoint.enableLimit = enableLimit; +} + +bool b2WheelJoint_IsLimitEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.enableLimit; +} + +void b2WheelJoint_EnableMotor(b2JointId jointId, bool enableMotor) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + + if (joint->wheelJoint.enableMotor != enableMotor) + { + joint->wheelJoint.motorImpulse = 0.0f; + } + + joint->wheelJoint.enableMotor = enableMotor; +} + +bool b2WheelJoint_IsMotorEnabled(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.enableMotor; +} + +void b2WheelJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + joint->wheelJoint.motorSpeed = motorSpeed; +} + +float b2WheelJoint_GetMotorSpeed(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.motorSpeed; +} + +float b2WheelJoint_GetMotorTorque(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_wheelJoint); + + return world->inv_h * joint->wheelJoint.motorImpulse; +} + +void b2WheelJoint_SetMaxMotorTorque(b2JointId jointId, float torque) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + joint->wheelJoint.maxMotorTorque = torque; +} + +float b2WheelJoint_GetMaxMotorTorque(b2JointId jointId) +{ + b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); + return joint->wheelJoint.maxMotorTorque; +} + +b2Vec2 b2WheelJoint_GetConstraintForce(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* base = b2GetJoint(world, jointId); + B2_ASSERT(base->type == b2_wheelJoint); + + b2WheelJoint* joint = &base->wheelJoint; + + // This is a frame behind + b2Vec2 axisA = joint->axisA; + b2Vec2 perpA = b2LeftPerp(axisA); + + float perpForce = world->inv_h * joint->perpImpulse; + float axialForce = world->inv_h * (joint->springImpulse + joint->lowerImpulse - joint->upperImpulse); + + b2Vec2 force = b2Add(b2MulSV(perpForce, perpA), b2MulSV(axialForce, axisA)); + return force; +} + +float b2WheelJoint_GetConstraintTorque(b2JointId jointId) +{ + b2World* world = b2GetWorldFromIndex(jointId.world); + b2Joint* joint = b2GetJoint(world, jointId); + B2_ASSERT(joint->type == b2_wheelJoint); + + return world->inv_h * joint->wheelJoint.motorImpulse; +} + // Linear constraint (point-to-line) // d = pB - pA = xB + rB - xA - rA // C = dot(ay, d) @@ -37,8 +159,8 @@ void b2PrepareWheelJoint(b2Joint* base, b2StepContext* context) int32_t indexB = base->edges[1].bodyIndex; b2Body* bodyA = context->bodies + indexA; b2Body* bodyB = context->bodies + indexB; - B2_ASSERT(b2ObjectValid(&bodyA->object)); - B2_ASSERT(b2ObjectValid(&bodyB->object)); + B2_ASSERT(b2IsValidObject(&bodyA->object)); + B2_ASSERT(b2IsValidObject(&bodyB->object)); float mA = bodyA->invMass; float iA = bodyA->invI; @@ -329,93 +451,6 @@ void b2SolveWheelJoint(b2Joint* base, b2StepContext* context, bool useBias) stateB->angularVelocity = wB; } -void b2WheelJoint_SetSpringHertz(b2JointId jointId, float hertz) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - joint->wheelJoint.hertz = hertz; -} - -void b2WheelJoint_SetSpringDampingRatio(b2JointId jointId, float dampingRatio) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - joint->wheelJoint.dampingRatio = dampingRatio; -} - -void b2WheelJoint_EnableLimit(b2JointId jointId, bool enableLimit) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - - if (joint->wheelJoint.enableLimit != enableLimit) - { - joint->wheelJoint.lowerImpulse = 0.0f; - joint->wheelJoint.upperImpulse = 0.0f; - } - - joint->wheelJoint.enableLimit = enableLimit; - -} - -void b2WheelJoint_EnableMotor(b2JointId jointId, bool enableMotor) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - - if (joint->wheelJoint.enableMotor != enableMotor) - { - joint->wheelJoint.motorImpulse = 0.0f; - } - - joint->wheelJoint.enableMotor = enableMotor; -} - -void b2WheelJoint_SetMotorSpeed(b2JointId jointId, float motorSpeed) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - joint->wheelJoint.motorSpeed = motorSpeed; -} - -float b2WheelJoint_GetMotorTorque(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_wheelJoint); - - return world->inv_h * joint->wheelJoint.motorImpulse; -} - -void b2WheelJoint_SetMaxMotorTorque(b2JointId jointId, float torque) -{ - b2Joint* joint = b2GetJointCheckType(jointId, b2_wheelJoint); - joint->wheelJoint.maxMotorTorque = torque; -} - -b2Vec2 b2WheelJoint_GetConstraintForce(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* base = b2GetJoint(world, jointId); - B2_ASSERT(base->type == b2_wheelJoint); - - b2WheelJoint* joint = &base->wheelJoint; - - // This is a frame behind - b2Vec2 axisA = joint->axisA; - b2Vec2 perpA = b2LeftPerp(axisA); - - float perpForce = world->inv_h * joint->perpImpulse; - float axialForce = world->inv_h * (joint->springImpulse + joint->lowerImpulse - joint->upperImpulse); - - b2Vec2 force = b2Add(b2MulSV(perpForce, perpA), b2MulSV(axialForce, axisA)); - return force; -} - -float b2WheelJoint_GetConstraintTorque(b2JointId jointId) -{ - b2World* world = b2GetWorldFromIndex(jointId.world); - b2Joint* joint = b2GetJoint(world, jointId); - B2_ASSERT(joint->type == b2_wheelJoint); - - return world->inv_h * joint->wheelJoint.motorImpulse; -} - #if 0 void b2WheelJoint_Dump() { diff --git a/src/world.c b/src/world.c index 641852bb..20cd0575 100644 --- a/src/world.c +++ b/src/world.c @@ -221,7 +221,7 @@ void b2DestroyWorld(b2WorldId id) for (int32_t i = 0; i < chainCapacity; ++i) { b2ChainShape* chain = world->chains + i; - if (b2ObjectValid(&chain->object)) + if (b2IsValidObject(&chain->object)) { b2Free(chain->shapeIndices, chain->count * sizeof(int32_t)); } @@ -795,7 +795,7 @@ void b2World_Draw(b2WorldId worldId, b2DebugDraw* draw) for (int32_t i = 0; i < bodyCapacity; ++i) { b2Body* body = bodies + i; - if (b2ObjectValid(&body->object) == false) + if (b2IsValidObject(&body->object) == false) { continue; } @@ -956,7 +956,7 @@ bool b2Body_IsValid(b2BodyId id) } b2Body* body = world->bodies + (id.index - 1); - if (b2ObjectValid(&body->object) == false) + if (b2IsValidObject(&body->object) == false) { return false; } @@ -979,7 +979,7 @@ bool b2Shape_IsValid(b2ShapeId id) } b2Shape* shape = world->shapes + (id.index - 1); - if (b2ObjectValid(&shape->object) == false) + if (b2IsValidObject(&shape->object) == false) { return false; } @@ -1002,7 +1002,7 @@ bool b2Chain_IsValid(b2ChainId id) } b2ChainShape* chain = world->chains + (id.index - 1); - if (b2ObjectValid(&chain->object) == false) + if (b2IsValidObject(&chain->object) == false) { return false; } @@ -1025,7 +1025,7 @@ bool b2Joint_IsValid(b2JointId id) } b2Joint* joint = world->joints + (id.index - 1); - if (b2ObjectValid(&joint->object) == false) + if (b2IsValidObject(&joint->object) == false) { return false; } @@ -1349,7 +1349,7 @@ static float RayCastCallback(const b2RayCastInput* input, int32_t proxyId, int32 B2_ASSERT(0 <= bodyIndex && bodyIndex < world->bodyPool.capacity); b2Body* body = world->bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2Transform transform = b2MakeTransform(body); b2CastOutput output = b2RayCastShape(input, shape, transform); @@ -1461,7 +1461,7 @@ static float ShapeCastCallback(const b2ShapeCastInput* input, int32_t proxyId, i B2_ASSERT(0 <= bodyIndex && bodyIndex < world->bodyPool.capacity); b2Body* body = world->bodies + bodyIndex; - B2_ASSERT(b2ObjectValid(&body->object)); + B2_ASSERT(b2IsValidObject(&body->object)); b2Transform transform = b2MakeTransform(body); b2CastOutput output = b2ShapeCastShape(input, shape, transform);