From 77f238767f50bcafc099973fd2494398227e4434 Mon Sep 17 00:00:00 2001 From: Garrett Brown Date: Sat, 17 Oct 2020 22:15:18 -0400 Subject: [PATCH] Update to box2d 2.4.1 --- src/libraries/box2d/b2_api.h | 52 ++++ src/libraries/box2d/b2_block_allocator.h | 5 +- src/libraries/box2d/b2_body.h | 31 ++- src/libraries/box2d/b2_broad_phase.h | 5 +- src/libraries/box2d/b2_chain_shape.h | 3 +- src/libraries/box2d/b2_circle_shape.h | 3 +- src/libraries/box2d/b2_collision.h | 38 +-- src/libraries/box2d/b2_common.h | 138 +++++++++++ src/libraries/box2d/b2_contact.h | 39 ++- src/libraries/box2d/b2_contact_manager.h | 5 +- src/libraries/box2d/b2_distance.h | 21 +- src/libraries/box2d/b2_distance_joint.h | 64 +++-- src/libraries/box2d/b2_draw.h | 11 +- src/libraries/box2d/b2_dynamic_tree.h | 8 +- src/libraries/box2d/b2_edge_shape.h | 7 +- src/libraries/box2d/b2_fixture.h | 47 +++- src/libraries/box2d/b2_friction_joint.h | 5 +- src/libraries/box2d/b2_gear_joint.h | 5 +- src/libraries/box2d/b2_growable_stack.h | 3 +- src/libraries/box2d/b2_joint.h | 28 +-- src/libraries/box2d/b2_math.h | 31 +-- src/libraries/box2d/b2_motor_joint.h | 7 +- src/libraries/box2d/b2_mouse_joint.h | 7 +- src/libraries/box2d/b2_polygon_shape.h | 3 +- src/libraries/box2d/b2_prismatic_joint.h | 5 +- src/libraries/box2d/b2_pulley_joint.h | 7 +- src/libraries/box2d/b2_revolute_joint.h | 7 +- src/libraries/box2d/b2_rope.h | 15 +- src/libraries/box2d/b2_settings.h | 208 ++++++++-------- src/libraries/box2d/b2_shape.h | 7 +- src/libraries/box2d/b2_stack_allocator.h | 5 +- src/libraries/box2d/b2_time_of_impact.h | 7 +- src/libraries/box2d/b2_time_step.h | 11 +- src/libraries/box2d/b2_timer.h | 3 +- src/libraries/box2d/b2_types.h | 33 +++ src/libraries/box2d/b2_weld_joint.h | 7 +- src/libraries/box2d/b2_wheel_joint.h | 5 +- src/libraries/box2d/b2_world.h | 7 +- src/libraries/box2d/b2_world_callbacks.h | 13 +- src/libraries/box2d/collision/b2_distance.cpp | 2 +- .../box2d/collision/b2_dynamic_tree.cpp | 2 - .../box2d/collision/b2_time_of_impact.cpp | 6 +- src/libraries/box2d/common/b2_settings.cpp | 17 +- src/libraries/box2d/dynamics/b2_body.cpp | 3 + src/libraries/box2d/dynamics/b2_contact.cpp | 1 + .../box2d/dynamics/b2_contact_solver.cpp | 5 +- .../box2d/dynamics/b2_contact_solver.h | 1 + .../box2d/dynamics/b2_distance_joint.cpp | 225 +++++++++++++++--- src/libraries/box2d/dynamics/b2_fixture.cpp | 3 +- .../box2d/dynamics/b2_gear_joint.cpp | 6 + src/libraries/box2d/dynamics/b2_joint.cpp | 12 - .../box2d/dynamics/b2_prismatic_joint.cpp | 3 +- .../box2d/dynamics/b2_revolute_joint.cpp | 2 +- .../box2d/dynamics/b2_wheel_joint.cpp | 2 +- src/libraries/box2d/rope/b2_rope.cpp | 40 ++++ src/modules/physics/box2d/Body.cpp | 4 +- src/modules/physics/box2d/Fixture.cpp | 4 +- src/modules/physics/box2d/Joint.cpp | 2 +- 58 files changed, 879 insertions(+), 367 deletions(-) create mode 100644 src/libraries/box2d/b2_api.h create mode 100644 src/libraries/box2d/b2_common.h create mode 100644 src/libraries/box2d/b2_types.h diff --git a/src/libraries/box2d/b2_api.h b/src/libraries/box2d/b2_api.h new file mode 100644 index 000000000..6730203c6 --- /dev/null +++ b/src/libraries/box2d/b2_api.h @@ -0,0 +1,52 @@ +// MIT License + +// Copyright (c) 2019 Erin Catto + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef B2_API_H +#define B2_API_H + +#ifdef B2_SHARED + #if defined _WIN32 || defined __CYGWIN__ + #ifdef box2d_EXPORTS + #ifdef __GNUC__ + #define B2_API __attribute__ ((dllexport)) + #else + #define B2_API __declspec(dllexport) + #endif + #else + #ifdef __GNUC__ + #define B2_API __attribute__ ((dllimport)) + #else + #define B2_API __declspec(dllimport) + #endif + #endif + #else + #if __GNUC__ >= 4 + #define B2_API __attribute__ ((visibility ("default"))) + #else + #define B2_API + #endif + #endif +#else + #define B2_API +#endif + +#endif diff --git a/src/libraries/box2d/b2_block_allocator.h b/src/libraries/box2d/b2_block_allocator.h index 48957343e..95c12de89 100644 --- a/src/libraries/box2d/b2_block_allocator.h +++ b/src/libraries/box2d/b2_block_allocator.h @@ -23,7 +23,8 @@ #ifndef B2_BLOCK_ALLOCATOR_H #define B2_BLOCK_ALLOCATOR_H -#include "box2d/b2_settings.h" +#include "b2_api.h" +#include "b2_settings.h" const int32 b2_blockSizeCount = 14; @@ -33,7 +34,7 @@ struct b2Chunk; /// This is a small object allocator used for allocating small /// objects that persist for more than one time step. /// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp -class b2BlockAllocator +class B2_API b2BlockAllocator { public: b2BlockAllocator(); diff --git a/src/libraries/box2d/b2_body.h b/src/libraries/box2d/b2_body.h index 6ba8574de..565f23898 100644 --- a/src/libraries/box2d/b2_body.h +++ b/src/libraries/box2d/b2_body.h @@ -23,6 +23,7 @@ #ifndef B2_BODY_H #define B2_BODY_H +#include "b2_api.h" #include "b2_math.h" #include "b2_shape.h" @@ -44,19 +45,15 @@ enum b2BodyType b2_staticBody = 0, b2_kinematicBody, b2_dynamicBody - - // TODO_ERIN - //b2_bulletBody, }; /// 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. -struct b2BodyDef +struct B2_API b2BodyDef { /// This constructor sets the body definition default values. b2BodyDef() { - userData = nullptr; position.Set(0.0f, 0.0f); angle = 0.0f; linearVelocity.Set(0.0f, 0.0f); @@ -121,14 +118,14 @@ struct b2BodyDef bool enabled; /// Use this to store application specific body data. - void* userData; + b2BodyUserData userData; /// Scale the gravity applied to this body. float gravityScale; }; /// A rigid body. These are created via b2World::CreateBody. -class b2Body +class B2_API b2Body { public: /// Creates a fixture and attach it to this body. Use this function if you need @@ -379,10 +376,10 @@ public: const b2Body* GetNext() const; /// Get the user data pointer that was provided in the body definition. - void* GetUserData() const; + b2BodyUserData& GetUserData(); /// Set the user data. Use this to store your application specific data. - void SetUserData(void* data); + void SetUserData(b2BodyUserData& data); /// Get the parent world of this body. b2World* GetWorld(); @@ -398,7 +395,7 @@ private: friend class b2ContactManager; friend class b2ContactSolver; friend class b2Contact; - + friend class b2DistanceJoint; friend class b2FrictionJoint; friend class b2GearJoint; @@ -471,7 +468,7 @@ private: float m_sleepTime; - void* m_userData; + b2BodyUserData m_userData; }; inline b2BodyType b2Body::GetType() const @@ -734,16 +731,16 @@ inline const b2Body* b2Body::GetNext() const return m_next; } -inline void b2Body::SetUserData(void* data) -{ - m_userData = data; -} - -inline void* b2Body::GetUserData() const +inline b2BodyUserData& b2Body::GetUserData() { return m_userData; } +inline void b2Body::SetUserData(b2BodyUserData& userData) +{ + m_userData = userData; +} + inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake) { if (m_type != b2_dynamicBody) diff --git a/src/libraries/box2d/b2_broad_phase.h b/src/libraries/box2d/b2_broad_phase.h index cf1cf6773..cc882ab47 100644 --- a/src/libraries/box2d/b2_broad_phase.h +++ b/src/libraries/box2d/b2_broad_phase.h @@ -23,11 +23,12 @@ #ifndef B2_BROAD_PHASE_H #define B2_BROAD_PHASE_H +#include "b2_api.h" #include "b2_settings.h" #include "b2_collision.h" #include "b2_dynamic_tree.h" -struct b2Pair +struct B2_API b2Pair { int32 proxyIdA; int32 proxyIdB; @@ -36,7 +37,7 @@ struct b2Pair /// The broad-phase is used for computing pairs and performing volume queries and ray casts. /// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. /// It is up to the client to consume the new pairs and to track subsequent overlap. -class b2BroadPhase +class B2_API b2BroadPhase { public: diff --git a/src/libraries/box2d/b2_chain_shape.h b/src/libraries/box2d/b2_chain_shape.h index 9ba0b8b1c..da2605d62 100644 --- a/src/libraries/box2d/b2_chain_shape.h +++ b/src/libraries/box2d/b2_chain_shape.h @@ -23,6 +23,7 @@ #ifndef B2_CHAIN_SHAPE_H #define B2_CHAIN_SHAPE_H +#include "b2_api.h" #include "b2_shape.h" class b2EdgeShape; @@ -32,7 +33,7 @@ class b2EdgeShape; /// This provides a counter-clockwise winding like the polygon shape. /// Connectivity information is used to create smooth collisions. /// @warning the chain will not collide properly if there are self-intersections. -class b2ChainShape : public b2Shape +class B2_API b2ChainShape : public b2Shape { public: b2ChainShape(); diff --git a/src/libraries/box2d/b2_circle_shape.h b/src/libraries/box2d/b2_circle_shape.h index 009d77db5..5e330f5a7 100644 --- a/src/libraries/box2d/b2_circle_shape.h +++ b/src/libraries/box2d/b2_circle_shape.h @@ -23,10 +23,11 @@ #ifndef B2_CIRCLE_SHAPE_H #define B2_CIRCLE_SHAPE_H +#include "b2_api.h" #include "b2_shape.h" /// A solid circle shape -class b2CircleShape : public b2Shape +class B2_API b2CircleShape : public b2Shape { public: b2CircleShape(); diff --git a/src/libraries/box2d/b2_collision.h b/src/libraries/box2d/b2_collision.h index aaa207b35..4c4592061 100644 --- a/src/libraries/box2d/b2_collision.h +++ b/src/libraries/box2d/b2_collision.h @@ -23,9 +23,11 @@ #ifndef B2_COLLISION_H #define B2_COLLISION_H -#include "b2_math.h" #include +#include "b2_api.h" +#include "b2_math.h" + /// @file /// Structures and functions used for computing contact points, distance /// queries, and TOI queries. @@ -39,7 +41,7 @@ const uint8 b2_nullFeature = UCHAR_MAX; /// The features that intersect to form the contact point /// This must be 4 bytes or less. -struct b2ContactFeature +struct B2_API b2ContactFeature { enum Type { @@ -54,7 +56,7 @@ struct b2ContactFeature }; /// Contact ids to facilitate warm starting. -union b2ContactID +union B2_API b2ContactID { b2ContactFeature cf; uint32 key; ///< Used to quickly compare contact ids. @@ -70,7 +72,7 @@ union b2ContactID /// This structure is stored across time steps, so we keep it small. /// Note: the impulses are used for internal caching and may not /// provide reliable contact forces, especially for high speed collisions. -struct b2ManifoldPoint +struct B2_API b2ManifoldPoint { b2Vec2 localPoint; ///< usage depends on manifold type float normalImpulse; ///< the non-penetration impulse @@ -94,7 +96,7 @@ struct b2ManifoldPoint /// account for movement, which is critical for continuous physics. /// All contact scenarios must be expressed in one of these types. /// This structure is stored across time steps, so we keep it small. -struct b2Manifold +struct B2_API b2Manifold { enum Type { @@ -111,7 +113,7 @@ struct b2Manifold }; /// This is used to compute the current state of a contact manifold. -struct b2WorldManifold +struct B2_API b2WorldManifold { /// Evaluate the manifold with supplied transforms. This assumes /// modest motion from the original state. This does not change the @@ -137,18 +139,18 @@ enum b2PointState /// Compute the point states given two manifolds. The states pertain to the transition from manifold1 /// to manifold2. So state1 is either persist or remove while state2 is either add or persist. -void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], +B2_API void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], const b2Manifold* manifold1, const b2Manifold* manifold2); /// Used for computing contact manifolds. -struct b2ClipVertex +struct B2_API b2ClipVertex { b2Vec2 v; b2ContactID id; }; /// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). -struct b2RayCastInput +struct B2_API b2RayCastInput { b2Vec2 p1, p2; float maxFraction; @@ -156,14 +158,14 @@ struct b2RayCastInput /// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2 /// come from b2RayCastInput. -struct b2RayCastOutput +struct B2_API b2RayCastOutput { b2Vec2 normal; float fraction; }; /// An axis aligned bounding box. -struct b2AABB +struct B2_API b2AABB { /// Verify that the bounds are sorted. bool IsValid() const; @@ -220,36 +222,36 @@ struct b2AABB }; /// Compute the collision manifold between two circles. -void b2CollideCircles(b2Manifold* manifold, +B2_API void b2CollideCircles(b2Manifold* manifold, const b2CircleShape* circleA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between a polygon and a circle. -void b2CollidePolygonAndCircle(b2Manifold* manifold, +B2_API void b2CollidePolygonAndCircle(b2Manifold* manifold, const b2PolygonShape* polygonA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between two polygons. -void b2CollidePolygons(b2Manifold* manifold, +B2_API void b2CollidePolygons(b2Manifold* manifold, const b2PolygonShape* polygonA, const b2Transform& xfA, const b2PolygonShape* polygonB, const b2Transform& xfB); /// Compute the collision manifold between an edge and a circle. -void b2CollideEdgeAndCircle(b2Manifold* manifold, +B2_API void b2CollideEdgeAndCircle(b2Manifold* manifold, const b2EdgeShape* polygonA, const b2Transform& xfA, const b2CircleShape* circleB, const b2Transform& xfB); /// Compute the collision manifold between an edge and a polygon. -void b2CollideEdgeAndPolygon(b2Manifold* manifold, +B2_API void b2CollideEdgeAndPolygon(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA, const b2PolygonShape* circleB, const b2Transform& xfB); /// Clipping for contact manifolds. -int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], +B2_API int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], const b2Vec2& normal, float offset, int32 vertexIndexA); /// Determine if two generic shapes overlap. -bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, +B2_API bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, const b2Shape* shapeB, int32 indexB, const b2Transform& xfA, const b2Transform& xfB); diff --git a/src/libraries/box2d/b2_common.h b/src/libraries/box2d/b2_common.h new file mode 100644 index 000000000..dfca8af1b --- /dev/null +++ b/src/libraries/box2d/b2_common.h @@ -0,0 +1,138 @@ +// MIT License + +// Copyright (c) 2019 Erin Catto + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef B2_COMMON_H +#define B2_COMMON_H + +#include "b2_settings.h" + +#include +#include +#include + +#if !defined(NDEBUG) + #define b2DEBUG +#endif + +#define B2_NOT_USED(x) ((void)(x)) +#define b2Assert(A) assert(A) + +#define b2_maxFloat FLT_MAX +#define b2_epsilon FLT_EPSILON +#define b2_pi 3.14159265359f + +/// @file +/// Global tuning constants based on meters-kilograms-seconds (MKS) units. +/// + +// Collision + +/// The maximum number of contact points between two convex shapes. Do +/// not change this value. +#define b2_maxManifoldPoints 2 + +/// This is used to fatten AABBs in the dynamic tree. This allows proxies +/// to move by a small amount without triggering a tree adjustment. +/// This is in meters. +#define b2_aabbExtension (0.1f * b2_lengthUnitsPerMeter) + +/// This is used to fatten AABBs in the dynamic tree. This is used to predict +/// the future position based on the current displacement. +/// This is a dimensionless multiplier. +#define b2_aabbMultiplier 4.0f + +/// A small length used as a collision and constraint tolerance. Usually it is +/// chosen to be numerically significant, but visually insignificant. In meters. +#define b2_linearSlop (0.005f * b2_lengthUnitsPerMeter) + +/// A small angle used as a collision and constraint tolerance. Usually it is +/// chosen to be numerically significant, but visually insignificant. +#define b2_angularSlop (2.0f / 180.0f * b2_pi) + +/// The radius of the polygon/edge shape skin. This should not be modified. Making +/// this smaller means polygons will have an insufficient buffer for continuous collision. +/// Making it larger may create artifacts for vertex collision. +#define b2_polygonRadius (2.0f * b2_linearSlop) + +/// Maximum number of sub-steps per contact in continuous physics simulation. +#define b2_maxSubSteps 8 + + +// Dynamics + +/// Maximum number of contacts to be handled to solve a TOI impact. +#define b2_maxTOIContacts 32 + +/// The maximum linear position correction used when solving constraints. This helps to +/// prevent overshoot. Meters. +#define b2_maxLinearCorrection (0.2f * b2_lengthUnitsPerMeter) + +/// The maximum angular position correction used when solving constraints. This helps to +/// prevent overshoot. +#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi) + +/// The maximum linear translation of a body per step. This limit is very large and is used +/// to prevent numerical problems. You shouldn't need to adjust this. Meters. +#define b2_maxTranslation (2.0f * b2_lengthUnitsPerMeter) +#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation) + +/// The maximum angular velocity of a body. This limit is very large and is used +/// to prevent numerical problems. You shouldn't need to adjust this. +#define b2_maxRotation (0.5f * b2_pi) +#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation) + +/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so +/// that overlap is removed in one time step. However using values close to 1 often lead +/// to overshoot. +#define b2_baumgarte 0.2f +#define b2_toiBaumgarte 0.75f + + +// Sleep + +/// The time that a body must be still before it will go to sleep. +#define b2_timeToSleep 0.5f + +/// A body cannot sleep if its linear velocity is above this tolerance. +#define b2_linearSleepTolerance (0.01f * b2_lengthUnitsPerMeter) + +/// A body cannot sleep if its angular velocity is above this tolerance. +#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi) + +/// Dump to a file. Only one dump file allowed at a time. +void b2OpenDump(const char* fileName); +void b2Dump(const char* string, ...); +void b2CloseDump(); + +/// Version numbering scheme. +/// See http://en.wikipedia.org/wiki/Software_versioning +struct b2Version +{ + int32 major; ///< significant changes + int32 minor; ///< incremental changes + int32 revision; ///< bug fixes +}; + +/// Current version. +extern B2_API b2Version b2_version; + +#endif diff --git a/src/libraries/box2d/b2_contact.h b/src/libraries/box2d/b2_contact.h index d4c59c620..de7541f13 100644 --- a/src/libraries/box2d/b2_contact.h +++ b/src/libraries/box2d/b2_contact.h @@ -23,6 +23,7 @@ #ifndef B2_CONTACT_H #define B2_CONTACT_H +#include "b2_api.h" #include "b2_collision.h" #include "b2_fixture.h" #include "b2_math.h" @@ -50,12 +51,18 @@ inline float b2MixRestitution(float restitution1, float restitution2) return restitution1 > restitution2 ? restitution1 : restitution2; } +/// Restitution mixing law. This picks the lowest value. +inline float b2MixRestitutionThreshold(float threshold1, float threshold2) +{ + return threshold1 < threshold2 ? threshold1 : threshold2; +} + typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); -struct b2ContactRegister +struct B2_API b2ContactRegister { b2ContactCreateFcn* createFcn; b2ContactDestroyFcn* destroyFcn; @@ -67,7 +74,7 @@ struct b2ContactRegister /// is an edge. A contact edge belongs to a doubly linked list /// maintained in each attached body. Each contact has two contact /// nodes, one for each attached body. -struct b2ContactEdge +struct B2_API b2ContactEdge { b2Body* other; ///< provides quick access to the other body attached. b2Contact* contact; ///< the contact @@ -78,7 +85,7 @@ struct b2ContactEdge /// The class manages contact between two shapes. A contact exists for each overlapping /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist /// that has no contact points. -class b2Contact +class B2_API b2Contact { public: @@ -139,6 +146,16 @@ public: /// Reset the restitution to the default value. void ResetRestitution(); + /// Override the default restitution velocity threshold mixture. You can call this in b2ContactListener::PreSolve. + /// The value persists until you set or reset. + void SetRestitutionThreshold(float threshold); + + /// Get the restitution threshold. + float GetRestitutionThreshold() const; + + /// Reset the restitution threshold to the default value. + void ResetRestitutionThreshold(); + /// Set the desired tangent speed for a conveyor belt behavior. In meters per second. void SetTangentSpeed(float speed); @@ -219,6 +236,7 @@ protected: float m_friction; float m_restitution; + float m_restitutionThreshold; float m_tangentSpeed; }; @@ -340,6 +358,21 @@ inline void b2Contact::ResetRestitution() m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); } +inline void b2Contact::SetRestitutionThreshold(float threshold) +{ + m_restitutionThreshold = threshold; +} + +inline float b2Contact::GetRestitutionThreshold() const +{ + return m_restitutionThreshold; +} + +inline void b2Contact::ResetRestitutionThreshold() +{ + m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold); +} + inline void b2Contact::SetTangentSpeed(float speed) { m_tangentSpeed = speed; diff --git a/src/libraries/box2d/b2_contact_manager.h b/src/libraries/box2d/b2_contact_manager.h index efa156847..fbd3b4d40 100644 --- a/src/libraries/box2d/b2_contact_manager.h +++ b/src/libraries/box2d/b2_contact_manager.h @@ -23,6 +23,7 @@ #ifndef B2_CONTACT_MANAGER_H #define B2_CONTACT_MANAGER_H +#include "b2_api.h" #include "b2_broad_phase.h" class b2Contact; @@ -31,7 +32,7 @@ class b2ContactListener; class b2BlockAllocator; // Delegate of b2World. -class b2ContactManager +class B2_API b2ContactManager { public: b2ContactManager(); @@ -44,7 +45,7 @@ public: void Destroy(b2Contact* c); void Collide(); - + b2BroadPhase m_broadPhase; b2Contact* m_contactList; int32 m_contactCount; diff --git a/src/libraries/box2d/b2_distance.h b/src/libraries/box2d/b2_distance.h index 3fcefc413..3e05773de 100644 --- a/src/libraries/box2d/b2_distance.h +++ b/src/libraries/box2d/b2_distance.h @@ -23,13 +23,14 @@ #ifndef B2_DISTANCE_H #define B2_DISTANCE_H +#include "b2_api.h" #include "b2_math.h" class b2Shape; /// A distance proxy is used by the GJK algorithm. /// It encapsulates any shape. -struct b2DistanceProxy +struct B2_API b2DistanceProxy { b2DistanceProxy() : m_vertices(nullptr), m_count(0), m_radius(0.0f) {} @@ -61,7 +62,7 @@ struct b2DistanceProxy /// Used to warm start b2Distance. /// Set count to zero on first call. -struct b2SimplexCache +struct B2_API b2SimplexCache { float metric; ///< length or area uint16 count; @@ -71,8 +72,8 @@ struct b2SimplexCache /// Input for b2Distance. /// You have to option to use the shape radii -/// in the computation. Even -struct b2DistanceInput +/// in the computation. Even +struct B2_API b2DistanceInput { b2DistanceProxy proxyA; b2DistanceProxy proxyB; @@ -82,7 +83,7 @@ struct b2DistanceInput }; /// Output for b2Distance. -struct b2DistanceOutput +struct B2_API b2DistanceOutput { b2Vec2 pointA; ///< closest point on shapeA b2Vec2 pointB; ///< closest point on shapeB @@ -93,12 +94,12 @@ struct b2DistanceOutput /// Compute the closest points between two shapes. Supports any combination of: /// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output. /// On the first call set b2SimplexCache.count to zero. -void b2Distance(b2DistanceOutput* output, - b2SimplexCache* cache, +B2_API void b2Distance(b2DistanceOutput* output, + b2SimplexCache* cache, const b2DistanceInput* input); /// Input parameters for b2ShapeCast -struct b2ShapeCastInput +struct B2_API b2ShapeCastInput { b2DistanceProxy proxyA; b2DistanceProxy proxyB; @@ -108,7 +109,7 @@ struct b2ShapeCastInput }; /// Output results for b2ShapeCast -struct b2ShapeCastOutput +struct B2_API b2ShapeCastOutput { b2Vec2 point; b2Vec2 normal; @@ -118,7 +119,7 @@ struct b2ShapeCastOutput /// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. /// @returns true if hit, false if there is no hit or an initial overlap -bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input); +B2_API bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input); ////////////////////////////////////////////////////////////////////////// diff --git a/src/libraries/box2d/b2_distance_joint.h b/src/libraries/box2d/b2_distance_joint.h index b339e9239..cfc75fefb 100644 --- a/src/libraries/box2d/b2_distance_joint.h +++ b/src/libraries/box2d/b2_distance_joint.h @@ -23,14 +23,14 @@ #ifndef B2_DISTANCE_JOINT_H #define B2_DISTANCE_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Distance joint definition. This requires defining an anchor point on both -/// bodies and the non-zero length of the distance joint. The definition uses local anchor points -/// so that the initial configuration can violate the constraint -/// slightly. This helps when saving and loading a game. -/// @warning Do not use a zero or short length. -struct b2DistanceJointDef : public b2JointDef +/// bodies and the non-zero distance of the distance joint. The definition uses +/// local anchor points so that the initial configuration can violate the +/// constraint slightly. This helps when saving and loading a game. +struct B2_API b2DistanceJointDef : public b2JointDef { b2DistanceJointDef() { @@ -38,12 +38,14 @@ struct b2DistanceJointDef : public b2JointDef localAnchorA.Set(0.0f, 0.0f); localAnchorB.Set(0.0f, 0.0f); length = 1.0f; + minLength = 0.0f; + maxLength = FLT_MAX; stiffness = 0.0f; damping = 0.0f; } - /// Initialize the bodies, anchors, and length using the world - /// anchors. + /// Initialize the bodies, anchors, and rest length using world space anchors. + /// The minimum and maximum lengths are set to the rest length. void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchorA, const b2Vec2& anchorB); @@ -53,10 +55,16 @@ struct b2DistanceJointDef : public b2JointDef /// The local anchor point relative to bodyB's origin. b2Vec2 localAnchorB; - /// The natural length between the anchor points. + /// The rest length of this joint. Clamped to a stable minimum value. float length; - /// The linear stiffness in N/m. A value of 0 disables softness. + /// Minimum length. Clamped to a stable minimum value. + float minLength; + + /// Maximum length. Must be greater than or equal to the minimum length. + float maxLength; + + /// The linear stiffness in N/m. float stiffness; /// The linear damping in N*s/m. @@ -65,7 +73,7 @@ struct b2DistanceJointDef : public b2JointDef /// A distance joint constrains two points on two bodies to remain at a fixed /// distance from each other. You can view this as a massless, rigid rod. -class b2DistanceJoint : public b2Joint +class B2_API b2DistanceJoint : public b2Joint { public: @@ -86,11 +94,30 @@ public: /// The local anchor point relative to bodyB's origin. const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - /// Set/get the natural length. - /// Manipulating the length can lead to non-physical behavior when the frequency is zero. - void SetLength(float length) { m_length = length; } + /// Get the rest length float GetLength() const { return m_length; } + /// Set the rest length + /// @returns clamped rest length + float SetLength(float length); + + /// Get the minimum length + float GetMinLength() const { return m_minLength; } + + /// Set the minimum length + /// @returns the clamped minimum length + float SetMinLength(float minLength); + + /// Get the maximum length + float GetMaxLength() const { return m_maxLength; } + + /// Set the maximum length + /// @returns the clamped maximum length + float SetMaxLength(float maxLength); + + /// Get the current length + float GetCurrentLength() const; + /// Set/get the linear stiffness in N/m void SetStiffness(float stiffness) { m_stiffness = stiffness; } float GetStiffness() const { return m_stiffness; } @@ -102,6 +129,9 @@ public: /// Dump joint to dmLog void Dump() override; + /// + void Draw(b2Draw* draw) const override; + protected: friend class b2Joint; @@ -114,13 +144,17 @@ protected: float m_stiffness; float m_damping; float m_bias; + float m_length; + float m_minLength; + float m_maxLength; // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; float m_gamma; float m_impulse; - float m_length; + float m_lowerImpulse; + float m_upperImpulse; // Solver temp int32 m_indexA; @@ -130,10 +164,12 @@ protected: b2Vec2 m_rB; b2Vec2 m_localCenterA; b2Vec2 m_localCenterB; + float m_currentLength; float m_invMassA; float m_invMassB; float m_invIA; float m_invIB; + float m_softMass; float m_mass; }; diff --git a/src/libraries/box2d/b2_draw.h b/src/libraries/box2d/b2_draw.h index 10cbf866f..a4d171187 100644 --- a/src/libraries/box2d/b2_draw.h +++ b/src/libraries/box2d/b2_draw.h @@ -23,10 +23,11 @@ #ifndef B2_DRAW_H #define B2_DRAW_H +#include "b2_api.h" #include "b2_math.h" /// Color for debug drawing. Each value has the range [0,1]. -struct b2Color +struct B2_API b2Color { b2Color() {} b2Color(float rIn, float gIn, float bIn, float aIn = 1.0f) @@ -44,7 +45,7 @@ struct b2Color /// Implement and register this class with a b2World to provide debug drawing of physics /// entities in your game. -class b2Draw +class B2_API b2Draw { public: b2Draw(); @@ -65,7 +66,7 @@ public: /// Get the drawing flags. uint32 GetFlags() const; - + /// Append flags to the current flags. void AppendFlags(uint32 flags); @@ -80,10 +81,10 @@ public: /// Draw a circle. virtual void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) = 0; - + /// Draw a solid circle. virtual void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) = 0; - + /// Draw a line segment. virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0; diff --git a/src/libraries/box2d/b2_dynamic_tree.h b/src/libraries/box2d/b2_dynamic_tree.h index b3ddb97ca..b85491915 100644 --- a/src/libraries/box2d/b2_dynamic_tree.h +++ b/src/libraries/box2d/b2_dynamic_tree.h @@ -23,13 +23,14 @@ #ifndef B2_DYNAMIC_TREE_H #define B2_DYNAMIC_TREE_H +#include "b2_api.h" #include "b2_collision.h" #include "b2_growable_stack.h" #define b2_nullNode (-1) /// A node in the dynamic tree. The client does not interact with this directly. -struct b2TreeNode +struct B2_API b2TreeNode { bool IsLeaf() const { @@ -64,7 +65,7 @@ struct b2TreeNode /// object to move by small amounts without triggering a tree update. /// /// Nodes are pooled and relocatable, so we use node indices rather than pointers. -class b2DynamicTree +class B2_API b2DynamicTree { public: /// Constructing the tree initializes the node pool. @@ -156,9 +157,6 @@ private: int32 m_freeList; - /// This is used to incrementally traverse the tree for re-balancing. - uint32 m_path; - int32 m_insertionCount; }; diff --git a/src/libraries/box2d/b2_edge_shape.h b/src/libraries/box2d/b2_edge_shape.h index ed79b43e2..b930ee872 100644 --- a/src/libraries/box2d/b2_edge_shape.h +++ b/src/libraries/box2d/b2_edge_shape.h @@ -23,12 +23,13 @@ #ifndef B2_EDGE_SHAPE_H #define B2_EDGE_SHAPE_H +#include "b2_api.h" #include "b2_shape.h" /// A line segment (edge) shape. These can be connected in chains or loops /// to other edge shapes. Edges created independently are two-sided and do -/// no provide smooth movement across junctions. -class b2EdgeShape : public b2Shape +/// no provide smooth movement across junctions. +class B2_API b2EdgeShape : public b2Shape { public: b2EdgeShape(); @@ -60,7 +61,7 @@ public: /// @see b2Shape::ComputeMass void ComputeMass(b2MassData* massData, float density) const override; - + /// These are the edge vertices b2Vec2 m_vertex1, m_vertex2; diff --git a/src/libraries/box2d/b2_fixture.h b/src/libraries/box2d/b2_fixture.h index 4cdde74d8..989dc6bd0 100644 --- a/src/libraries/box2d/b2_fixture.h +++ b/src/libraries/box2d/b2_fixture.h @@ -23,6 +23,7 @@ #ifndef B2_FIXTURE_H #define B2_FIXTURE_H +#include "b2_api.h" #include "b2_body.h" #include "b2_collision.h" #include "b2_shape.h" @@ -33,7 +34,7 @@ class b2BroadPhase; class b2Fixture; /// This holds contact filtering data. -struct b2Filter +struct B2_API b2Filter { b2Filter() { @@ -57,15 +58,15 @@ struct b2Filter /// A fixture definition is used to create a fixture. This class defines an /// abstract fixture definition. You can reuse fixture definitions safely. -struct b2FixtureDef +struct B2_API b2FixtureDef { /// The constructor sets the default fixture definition values. b2FixtureDef() { shape = nullptr; - userData = nullptr; friction = 0.2f; restitution = 0.0f; + restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter; density = 0.0f; isSensor = false; } @@ -75,7 +76,7 @@ struct b2FixtureDef const b2Shape* shape; /// Use this to store application specific fixture data. - void* userData; + b2FixtureUserData userData; /// The friction coefficient, usually in the range [0,1]. float friction; @@ -83,6 +84,10 @@ struct b2FixtureDef /// The restitution (elasticity) usually in the range [0,1]. float restitution; + /// Restitution velocity threshold, usually in m/s. Collisions above this + /// speed have restitution applied (will bounce). + float restitutionThreshold; + /// The density, usually in kg/m^2. float density; @@ -95,7 +100,7 @@ struct b2FixtureDef }; /// This proxy is used internally to connect fixtures to the broad-phase. -struct b2FixtureProxy +struct B2_API b2FixtureProxy { b2AABB aabb; b2Fixture* fixture; @@ -108,7 +113,7 @@ struct b2FixtureProxy /// such as friction, collision filters, etc. /// Fixtures are created via b2Body::CreateFixture. /// @warning you cannot reuse fixtures. -class b2Fixture +class B2_API b2Fixture { public: /// Get the type of the child shape. You can use this to down cast to the concrete shape. @@ -151,10 +156,10 @@ public: /// Get the user data that was assigned in the fixture definition. Use this to /// store your application specific data. - void* GetUserData() const; + b2FixtureUserData& GetUserData(); /// Set the user data. Use this to store your application specific data. - void SetUserData(void* data); + void SetUserData(b2FixtureUserData& userData); /// Test a point for containment in this fixture. /// @param p a point in world coordinates. @@ -192,6 +197,13 @@ public: /// existing contacts. void SetRestitution(float restitution); + /// Get the restitution velocity threshold. + float GetRestitutionThreshold() const; + + /// Set the restitution threshold. This will _not_ change the restitution threshold of + /// existing contacts. + void SetRestitutionThreshold(float threshold); + /// Get the fixture's AABB. This AABB may be enlarge and/or stale. /// If you need a more accurate AABB, compute it using the shape and /// the body transform. @@ -229,6 +241,7 @@ protected: float m_friction; float m_restitution; + float m_restitutionThreshold; b2FixtureProxy* m_proxies; int32 m_proxyCount; @@ -237,7 +250,7 @@ protected: bool m_isSensor; - void* m_userData; + b2FixtureUserData m_userData; }; inline b2Shape::Type b2Fixture::GetType() const @@ -265,14 +278,14 @@ inline const b2Filter& b2Fixture::GetFilterData() const return m_filter; } -inline void* b2Fixture::GetUserData() const +inline b2FixtureUserData& b2Fixture::GetUserData() { return m_userData; } -inline void b2Fixture::SetUserData(void* data) +inline void b2Fixture::SetUserData(b2FixtureUserData& userData) { - m_userData = data; + m_userData = userData; } inline b2Body* b2Fixture::GetBody() @@ -326,6 +339,16 @@ inline void b2Fixture::SetRestitution(float restitution) m_restitution = restitution; } +inline float b2Fixture::GetRestitutionThreshold() const +{ + return m_restitutionThreshold; +} + +inline void b2Fixture::SetRestitutionThreshold(float threshold) +{ + m_restitutionThreshold = threshold; +} + inline bool b2Fixture::TestPoint(const b2Vec2& p) const { return m_shape->TestPoint(m_body->GetTransform(), p); diff --git a/src/libraries/box2d/b2_friction_joint.h b/src/libraries/box2d/b2_friction_joint.h index d7b88245e..99922c3a3 100644 --- a/src/libraries/box2d/b2_friction_joint.h +++ b/src/libraries/box2d/b2_friction_joint.h @@ -23,10 +23,11 @@ #ifndef B2_FRICTION_JOINT_H #define B2_FRICTION_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Friction joint definition. -struct b2FrictionJointDef : public b2JointDef +struct B2_API b2FrictionJointDef : public b2JointDef { b2FrictionJointDef() { @@ -56,7 +57,7 @@ struct b2FrictionJointDef : public b2JointDef /// Friction joint. This is used for top-down friction. /// It provides 2D translational friction and angular friction. -class b2FrictionJoint : public b2Joint +class B2_API b2FrictionJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_gear_joint.h b/src/libraries/box2d/b2_gear_joint.h index 69e67a199..1c40687a0 100644 --- a/src/libraries/box2d/b2_gear_joint.h +++ b/src/libraries/box2d/b2_gear_joint.h @@ -27,7 +27,8 @@ /// Gear joint definition. This definition requires two existing /// revolute or prismatic joints (any combination will work). -struct b2GearJointDef : public b2JointDef +/// @warning bodyB on the input joints must both be dynamic +struct B2_API b2GearJointDef : public b2JointDef { b2GearJointDef() { @@ -57,7 +58,7 @@ struct b2GearJointDef : public b2JointDef /// of length or units of 1/length. /// @warning You have to manually destroy the gear joint if joint1 or joint2 /// is destroyed. -class b2GearJoint : public b2Joint +class B2_API b2GearJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_growable_stack.h b/src/libraries/box2d/b2_growable_stack.h index a24984f0c..ec42e5e9e 100644 --- a/src/libraries/box2d/b2_growable_stack.h +++ b/src/libraries/box2d/b2_growable_stack.h @@ -23,9 +23,10 @@ #ifndef B2_GROWABLE_STACK_H #define B2_GROWABLE_STACK_H -#include "b2_settings.h" #include +#include "b2_settings.h" + /// This is a growable LIFO stack with an initial capacity of N. /// If the stack size exceeds the initial capacity, the heap is used /// to increase the size of the stack. diff --git a/src/libraries/box2d/b2_joint.h b/src/libraries/box2d/b2_joint.h index c33ec90af..c6546663d 100644 --- a/src/libraries/box2d/b2_joint.h +++ b/src/libraries/box2d/b2_joint.h @@ -23,6 +23,7 @@ #ifndef B2_JOINT_H #define B2_JOINT_H +#include "b2_api.h" #include "b2_math.h" class b2Body; @@ -47,7 +48,7 @@ enum b2JointType e_motorJoint }; -struct b2Jacobian +struct B2_API b2Jacobian { b2Vec2 linear; float angularA; @@ -59,7 +60,7 @@ struct b2Jacobian /// is an edge. A joint edge belongs to a doubly linked list /// maintained in each attached body. Each joint has two joint /// nodes, one for each attached body. -struct b2JointEdge +struct B2_API b2JointEdge { b2Body* other; ///< provides quick access to the other body attached. b2Joint* joint; ///< the joint @@ -68,12 +69,11 @@ struct b2JointEdge }; /// Joint definitions are used to construct joints. -struct b2JointDef +struct B2_API b2JointDef { b2JointDef() { type = e_unknownJoint; - userData = nullptr; bodyA = nullptr; bodyB = nullptr; collideConnected = false; @@ -83,7 +83,7 @@ struct b2JointDef b2JointType type; /// Use this to attach application specific data to your joints. - void* userData; + b2JointUserData userData; /// The first attached body. b2Body* bodyA; @@ -96,18 +96,18 @@ struct b2JointDef }; /// Utility to compute linear stiffness values from frequency and damping ratio -void b2LinearStiffness(float& stiffness, float& damping, +B2_API void b2LinearStiffness(float& stiffness, float& damping, float frequencyHertz, float dampingRatio, const b2Body* bodyA, const b2Body* bodyB); /// Utility to compute rotational stiffness values frequency and damping ratio -void b2AngularStiffness(float& stiffness, float& damping, +B2_API void b2AngularStiffness(float& stiffness, float& damping, float frequencyHertz, float dampingRatio, const b2Body* bodyA, const b2Body* bodyB); /// The base joint class. Joints are used to constraint two bodies together in /// various fashions. Some joints also feature limits and motors. -class b2Joint +class B2_API b2Joint { public: @@ -137,10 +137,10 @@ public: const b2Joint* GetNext() const; /// Get the user data pointer. - void* GetUserData() const; + b2JointUserData& GetUserData(); /// Set the user data pointer. - void SetUserData(void* data); + void SetUserData(b2JointUserData& userData); /// Short-cut function to determine if either body is enabled. bool IsEnabled() const; @@ -190,7 +190,7 @@ protected: bool m_islandFlag; bool m_collideConnected; - void* m_userData; + b2JointUserData m_userData; }; inline b2JointType b2Joint::GetType() const @@ -218,14 +218,14 @@ inline const b2Joint* b2Joint::GetNext() const return m_next; } -inline void* b2Joint::GetUserData() const +inline b2JointUserData& b2Joint::GetUserData() { return m_userData; } -inline void b2Joint::SetUserData(void* data) +inline void b2Joint::SetUserData(b2JointUserData& userData) { - m_userData = data; + m_userData = userData; } inline bool b2Joint::GetCollideConnected() const diff --git a/src/libraries/box2d/b2_math.h b/src/libraries/box2d/b2_math.h index f3042ec22..479e667be 100644 --- a/src/libraries/box2d/b2_math.h +++ b/src/libraries/box2d/b2_math.h @@ -23,20 +23,22 @@ #ifndef B2_MATH_H #define B2_MATH_H +#include + +#include "b2_api.h" #include "b2_settings.h" -#include /// This function is used to ensure that a floating point number is not a NaN or infinity. inline bool b2IsValid(float x) { - return std::isfinite(x); + return isfinite(x); } #define b2Sqrt(x) sqrtf(x) #define b2Atan2(y, x) atan2f(y, x) /// A 2D column vector. -struct b2Vec2 +struct B2_API b2Vec2 { /// Default constructor does nothing (for performance). b2Vec2() {} @@ -52,7 +54,7 @@ struct b2Vec2 /// Negate this vector. b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } - + /// Read from and indexed element. float operator () (int32 i) const { @@ -70,7 +72,7 @@ struct b2Vec2 { x += v.x; y += v.y; } - + /// Subtract a vector from this vector. void operator -= (const b2Vec2& v) { @@ -127,7 +129,7 @@ struct b2Vec2 }; /// A 2D column vector with 3 elements. -struct b2Vec3 +struct B2_API b2Vec3 { /// Default constructor does nothing (for performance). b2Vec3() {} @@ -166,7 +168,7 @@ struct b2Vec3 }; /// A 2-by-2 matrix. Stored in column-major order. -struct b2Mat22 +struct B2_API b2Mat22 { /// The default constructor does nothing (for performance). b2Mat22() {} @@ -240,7 +242,7 @@ struct b2Mat22 }; /// A 3-by-3 matrix. Stored in column-major order. -struct b2Mat33 +struct B2_API b2Mat33 { /// The default constructor does nothing (for performance). b2Mat33() {} @@ -282,7 +284,7 @@ struct b2Mat33 }; /// Rotation -struct b2Rot +struct B2_API b2Rot { b2Rot() {} @@ -333,7 +335,7 @@ struct b2Rot /// A transform contains translation and rotation. It is used to represent /// the position and orientation of rigid frames. -struct b2Transform +struct B2_API b2Transform { /// The default constructor does nothing. b2Transform() {} @@ -363,7 +365,7 @@ struct b2Transform /// Shapes are defined with respect to the body origin, which may /// no coincide with the center of mass. However, to support dynamics /// we must interpolate the center of mass position. -struct b2Sweep +struct B2_API b2Sweep { /// Get the interpolated transform at a specific time. /// @param transform the output transform @@ -387,7 +389,7 @@ struct b2Sweep }; /// Useful constant -extern const b2Vec2 b2Vec2_zero; +extern B2_API const b2Vec2 b2Vec2_zero; /// Perform the dot product on two vectors. inline float b2Dot(const b2Vec2& a, const b2Vec2& b) @@ -681,10 +683,11 @@ inline bool b2IsPowerOfTwo(uint32 x) return result; } +// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ inline void b2Sweep::GetTransform(b2Transform* xf, float beta) const { - xf->p = c0 + beta * (c - c0); - float angle = a0 + beta * (a - a0); + xf->p = (1.0f - beta) * c0 + beta * c; + float angle = (1.0f - beta) * a0 + beta * a; xf->q.Set(angle); // Shift to origin diff --git a/src/libraries/box2d/b2_motor_joint.h b/src/libraries/box2d/b2_motor_joint.h index c3f1adcbb..c88115f20 100644 --- a/src/libraries/box2d/b2_motor_joint.h +++ b/src/libraries/box2d/b2_motor_joint.h @@ -23,10 +23,11 @@ #ifndef B2_MOTOR_JOINT_H #define B2_MOTOR_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Motor joint definition. -struct b2MotorJointDef : public b2JointDef +struct B2_API b2MotorJointDef : public b2JointDef { b2MotorJointDef() { @@ -46,7 +47,7 @@ struct b2MotorJointDef : public b2JointDef /// The bodyB angle minus bodyA angle in radians. float angularOffset; - + /// The maximum motor force in N. float maxForce; @@ -60,7 +61,7 @@ struct b2MotorJointDef : public b2JointDef /// A motor joint is used to control the relative motion /// between two bodies. A typical usage is to control the movement /// of a dynamic body with respect to the ground. -class b2MotorJoint : public b2Joint +class B2_API b2MotorJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_mouse_joint.h b/src/libraries/box2d/b2_mouse_joint.h index ebaa02592..fcbc56a70 100644 --- a/src/libraries/box2d/b2_mouse_joint.h +++ b/src/libraries/box2d/b2_mouse_joint.h @@ -23,11 +23,12 @@ #ifndef B2_MOUSE_JOINT_H #define B2_MOUSE_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Mouse joint definition. This requires a world target point, /// tuning parameters, and the time step. -struct b2MouseJointDef : public b2JointDef +struct B2_API b2MouseJointDef : public b2JointDef { b2MouseJointDef() { @@ -61,7 +62,7 @@ struct b2MouseJointDef : public b2JointDef /// NOTE: this joint is not documented in the manual because it was /// developed to be used in the testbed. If you want to learn how to /// use the mouse joint, look at the testbed. -class b2MouseJoint : public b2Joint +class B2_API b2MouseJoint : public b2Joint { public: @@ -113,7 +114,7 @@ protected: float m_stiffness; float m_damping; float m_beta; - + // Solver shared b2Vec2 m_impulse; float m_maxForce; diff --git a/src/libraries/box2d/b2_polygon_shape.h b/src/libraries/box2d/b2_polygon_shape.h index 52f4cc0ec..5a4e563f8 100644 --- a/src/libraries/box2d/b2_polygon_shape.h +++ b/src/libraries/box2d/b2_polygon_shape.h @@ -22,13 +22,14 @@ #ifndef B2_POLYGON_SHAPE_H #define B2_POLYGON_SHAPE_H +#include "b2_api.h" #include "b2_shape.h" /// A solid convex polygon. It is assumed that the interior of the polygon is to /// 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. -class b2PolygonShape : public b2Shape +class B2_API b2PolygonShape : public b2Shape { public: b2PolygonShape(); diff --git a/src/libraries/box2d/b2_prismatic_joint.h b/src/libraries/box2d/b2_prismatic_joint.h index 09cbad540..9d12d2126 100644 --- a/src/libraries/box2d/b2_prismatic_joint.h +++ b/src/libraries/box2d/b2_prismatic_joint.h @@ -23,6 +23,7 @@ #ifndef B2_PRISMATIC_JOINT_H #define B2_PRISMATIC_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Prismatic joint definition. This requires defining a line of @@ -31,7 +32,7 @@ /// can violate the constraint slightly. The joint translation is zero /// when the local anchor points coincide in world space. Using local /// anchors and a local axis helps when saving and loading a game. -struct b2PrismaticJointDef : public b2JointDef +struct B2_API b2PrismaticJointDef : public b2JointDef { b2PrismaticJointDef() { @@ -87,7 +88,7 @@ struct b2PrismaticJointDef : public b2JointDef /// along an axis fixed in bodyA. Relative rotation is prevented. You can /// use a joint limit to restrict the range of motion and a joint motor to /// drive the motion or to model joint friction. -class b2PrismaticJoint : public b2Joint +class B2_API b2PrismaticJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_pulley_joint.h b/src/libraries/box2d/b2_pulley_joint.h index 14f12c41f..6b1445641 100644 --- a/src/libraries/box2d/b2_pulley_joint.h +++ b/src/libraries/box2d/b2_pulley_joint.h @@ -23,13 +23,14 @@ #ifndef B2_PULLEY_JOINT_H #define B2_PULLEY_JOINT_H +#include "b2_api.h" #include "b2_joint.h" const float b2_minPulleyLength = 2.0f; /// Pulley joint definition. This requires two ground anchors, /// two dynamic body anchor points, and a pulley ratio. -struct b2PulleyJointDef : public b2JointDef +struct B2_API b2PulleyJointDef : public b2JointDef { b2PulleyJointDef() { @@ -80,7 +81,7 @@ struct b2PulleyJointDef : public b2JointDef /// work better when combined with prismatic joints. You should also cover the /// the anchor points with static shapes to prevent one side from going to /// zero length. -class b2PulleyJoint : public b2Joint +class B2_API b2PulleyJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; @@ -129,7 +130,7 @@ protected: b2Vec2 m_groundAnchorB; float m_lengthA; float m_lengthB; - + // Solver shared b2Vec2 m_localAnchorA; b2Vec2 m_localAnchorB; diff --git a/src/libraries/box2d/b2_revolute_joint.h b/src/libraries/box2d/b2_revolute_joint.h index f202e3551..36ad5314e 100644 --- a/src/libraries/box2d/b2_revolute_joint.h +++ b/src/libraries/box2d/b2_revolute_joint.h @@ -23,6 +23,7 @@ #ifndef B2_REVOLUTE_JOINT_H #define B2_REVOLUTE_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Revolute joint definition. This requires defining an anchor point where the @@ -35,7 +36,7 @@ /// 1. you might not know where the center of mass will be. /// 2. if you add/remove shapes from a body and recompute the mass, /// the joints will be broken. -struct b2RevoluteJointDef : public b2JointDef +struct B2_API b2RevoluteJointDef : public b2JointDef { b2RevoluteJointDef() { @@ -90,7 +91,7 @@ struct b2RevoluteJointDef : public b2JointDef /// a joint limit that specifies a lower and upper angle. You can use a motor /// to drive the relative rotation about the shared point. A maximum motor torque /// is provided so that infinite forces are not generated. -class b2RevoluteJoint : public b2Joint +class B2_API b2RevoluteJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; @@ -161,7 +162,7 @@ public: void Draw(b2Draw* draw) const override; protected: - + friend class b2Joint; friend class b2GearJoint; diff --git a/src/libraries/box2d/b2_rope.h b/src/libraries/box2d/b2_rope.h index 5f1cc4073..47f5fc442 100644 --- a/src/libraries/box2d/b2_rope.h +++ b/src/libraries/box2d/b2_rope.h @@ -23,6 +23,7 @@ #ifndef B2_ROPE_H #define B2_ROPE_H +#include "b2_api.h" #include "b2_math.h" class b2Draw; @@ -41,11 +42,12 @@ enum b2BendingModel b2_pbdAngleBendingModel, b2_xpbdAngleBendingModel, b2_pbdDistanceBendingModel, - b2_pbdHeightBendingModel + b2_pbdHeightBendingModel, + b2_pbdTriangleBendingModel }; /// -struct b2RopeTuning +struct B2_API b2RopeTuning { b2RopeTuning() { @@ -75,8 +77,8 @@ struct b2RopeTuning bool warmStart; }; -/// -struct b2RopeDef +/// +struct B2_API b2RopeDef { b2RopeDef() { @@ -95,8 +97,8 @@ struct b2RopeDef b2RopeTuning tuning; }; -/// -class b2Rope +/// +class B2_API b2Rope { public: b2Rope(); @@ -125,6 +127,7 @@ private: void SolveBend_XPBD_Angle(float dt); void SolveBend_PBD_Distance(); void SolveBend_PBD_Height(); + void SolveBend_PBD_Triangle(); void ApplyBendForces(float dt); b2Vec2 m_position; diff --git a/src/libraries/box2d/b2_settings.h b/src/libraries/box2d/b2_settings.h index 8695980e1..ccdcac519 100644 --- a/src/libraries/box2d/b2_settings.h +++ b/src/libraries/box2d/b2_settings.h @@ -23,143 +23,123 @@ #ifndef B2_SETTINGS_H #define B2_SETTINGS_H -#include -#include -#include - -void loveAssert(bool test, const char* teststr); - -#if !defined(NDEBUG) - #define b2DEBUG -#endif - -#define B2_NOT_USED(x) ((void)(x)) -//#define b2Assert(A) assert(A) -#define b2Assert(A) loveAssert((A), #A) - -typedef signed char int8; -typedef signed short int16; -typedef signed int int32; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; - -#define b2_maxFloat FLT_MAX -#define b2_epsilon FLT_EPSILON -#define b2_pi 3.14159265359f +#include "b2_types.h" +#include "b2_api.h" /// @file -/// Global tuning constants based on meters-kilograms-seconds (MKS) units. +/// Settings that can be overriden for your application /// -// Collision +/// Define this macro in your build if you want to override settings +#ifdef B2_USER_SETTINGS -/// The maximum number of contact points between two convex shapes. Do -/// not change this value. -#define b2_maxManifoldPoints 2 +/// This is a user file that includes custom definitions of the macros, structs, and functions +/// defined below. +#include "b2_user_settings.h" + +#else + +#include +#include + +// Tunable Constants + +/// You can use this to change the length scale used by your game. +/// For example for inches you could use 39.4. +#define b2_lengthUnitsPerMeter 1.0f /// The maximum number of vertices on a convex polygon. You cannot increase /// this too much because b2BlockAllocator has a maximum object size. #define b2_maxPolygonVertices 8 -/// This is used to fatten AABBs in the dynamic tree. This allows proxies -/// to move by a small amount without triggering a tree adjustment. -/// This is in meters. -#define b2_aabbExtension 0.1f +// User data -/// This is used to fatten AABBs in the dynamic tree. This is used to predict -/// the future position based on the current displacement. -/// This is a dimensionless multiplier. -#define b2_aabbMultiplier 4.0f +/// You can define this to inject whatever data you want in b2Body +struct B2_API b2BodyUserData +{ + b2BodyUserData() + { + pointer = 0; + } -/// A small length used as a collision and constraint tolerance. Usually it is -/// chosen to be numerically significant, but visually insignificant. -#define b2_linearSlop 0.005f + /// For legacy compatibility + uintptr_t pointer; +}; -/// A small angle used as a collision and constraint tolerance. Usually it is -/// chosen to be numerically significant, but visually insignificant. -#define b2_angularSlop (2.0f / 180.0f * b2_pi) +/// You can define this to inject whatever data you want in b2Fixture +struct B2_API b2FixtureUserData +{ + b2FixtureUserData() + { + pointer = 0; + } -/// The radius of the polygon/edge shape skin. This should not be modified. Making -/// this smaller means polygons will have an insufficient buffer for continuous collision. -/// Making it larger may create artifacts for vertex collision. -#define b2_polygonRadius (2.0f * b2_linearSlop) + /// For legacy compatibility + uintptr_t pointer; +}; -/// Maximum number of sub-steps per contact in continuous physics simulation. -#define b2_maxSubSteps 8 +/// You can define this to inject whatever data you want in b2Joint +struct B2_API b2JointUserData +{ + b2JointUserData() + { + pointer = 0; + } - -// Dynamics - -/// Maximum number of contacts to be handled to solve a TOI impact. -#define b2_maxTOIContacts 32 - -/// A velocity threshold for elastic collisions. Any collision with a relative linear -/// velocity below this threshold will be treated as inelastic. -#define b2_velocityThreshold 1.0f - -/// The maximum linear position correction used when solving constraints. This helps to -/// prevent overshoot. -#define b2_maxLinearCorrection 0.2f - -/// The maximum angular position correction used when solving constraints. This helps to -/// prevent overshoot. -#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi) - -/// The maximum linear velocity of a body. This limit is very large and is used -/// to prevent numerical problems. You shouldn't need to adjust this. -#define b2_maxTranslation 2.0f -#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation) - -/// The maximum angular velocity of a body. This limit is very large and is used -/// to prevent numerical problems. You shouldn't need to adjust this. -#define b2_maxRotation (0.5f * b2_pi) -#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation) - -/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so -/// that overlap is removed in one time step. However using values close to 1 often lead -/// to overshoot. -#define b2_baumgarte 0.2f -#define b2_toiBaumgarte 0.75f - - -// Sleep - -/// The time that a body must be still before it will go to sleep. -#define b2_timeToSleep 0.5f - -/// A body cannot sleep if its linear velocity is above this tolerance. -#define b2_linearSleepTolerance 0.01f - -/// A body cannot sleep if its angular velocity is above this tolerance. -#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi) + /// For legacy compatibility + uintptr_t pointer; +}; // Memory Allocation +/// Default allocation functions +B2_API void* b2Alloc_Default(int32 size); +B2_API void b2Free_Default(void* mem); + /// Implement this function to use your own memory allocator. -void* b2Alloc(int32 size); +inline void* b2Alloc(int32 size) +{ + return b2Alloc_Default(size); +} /// If you implement b2Alloc, you should also implement this function. -void b2Free(void* mem); - -/// Logging function. -void b2Log(const char* string, ...); - -/// Dump to a file. Only one dump file allowed at a time. -void b2OpenDump(const char* fileName); -void b2Dump(const char* string, ...); -void b2CloseDump(); - -/// Version numbering scheme. -/// See http://en.wikipedia.org/wiki/Software_versioning -struct b2Version +inline void b2Free(void* mem) { - int32 major; ///< significant changes - int32 minor; ///< incremental changes - int32 revision; ///< bug fixes -}; + b2Free_Default(mem); +} -/// Current version. -extern b2Version b2_version; +/// Default logging function +B2_API void b2Log_Default(const char* string, va_list args); + +/// Implement this to use your own logging. +inline void b2Log(const char* string, ...) +{ + va_list args; + va_start(args, string); + b2Log_Default(string, args); + va_end(args); +} + +#endif // B2_USER_SETTINGS + +void loveAssert(bool test, const char* teststr); + +#define b2Assert(A) loveAssert((A), #A) + +namespace love { + namespace physics { + namespace box2d { + struct bodyudata; + struct fixtureudata; + struct jointudata; + } + } +} + +#define b2BodyUserData love::physics::box2d::bodyudata* +#define b2FixtureUserData love::physics::box2d::fixtureudata* +#define b2JointUserData love::physics::box2d::jointudata* + +#include "b2_common.h" #endif diff --git a/src/libraries/box2d/b2_shape.h b/src/libraries/box2d/b2_shape.h index 27e3d14bc..cbed2b863 100644 --- a/src/libraries/box2d/b2_shape.h +++ b/src/libraries/box2d/b2_shape.h @@ -23,13 +23,14 @@ #ifndef B2_SHAPE_H #define B2_SHAPE_H +#include "b2_api.h" #include "b2_math.h" #include "b2_collision.h" class b2BlockAllocator; /// This holds the mass data computed for a shape. -struct b2MassData +struct B2_API b2MassData { /// The mass of the shape, usually in kilograms. float mass; @@ -44,10 +45,10 @@ struct b2MassData /// A shape is used for collision detection. You can create a shape however you like. /// Shapes used for simulation in b2World are created automatically when a b2Fixture /// is created. Shapes may encapsulate a one or more child shapes. -class b2Shape +class B2_API b2Shape { public: - + enum Type { e_circle = 0, diff --git a/src/libraries/box2d/b2_stack_allocator.h b/src/libraries/box2d/b2_stack_allocator.h index 780ab7945..1db2af5d9 100644 --- a/src/libraries/box2d/b2_stack_allocator.h +++ b/src/libraries/box2d/b2_stack_allocator.h @@ -23,12 +23,13 @@ #ifndef B2_STACK_ALLOCATOR_H #define B2_STACK_ALLOCATOR_H +#include "b2_api.h" #include "b2_settings.h" const int32 b2_stackSize = 100 * 1024; // 100k const int32 b2_maxStackEntries = 32; -struct b2StackEntry +struct B2_API b2StackEntry { char* data; int32 size; @@ -38,7 +39,7 @@ struct b2StackEntry // This is a stack allocator used for fast per step allocations. // You must nest allocate/free pairs. The code will assert // if you try to interleave multiple allocate/free pairs. -class b2StackAllocator +class B2_API b2StackAllocator { public: b2StackAllocator(); diff --git a/src/libraries/box2d/b2_time_of_impact.h b/src/libraries/box2d/b2_time_of_impact.h index bb3031fcb..04d46262e 100644 --- a/src/libraries/box2d/b2_time_of_impact.h +++ b/src/libraries/box2d/b2_time_of_impact.h @@ -23,11 +23,12 @@ #ifndef B2_TIME_OF_IMPACT_H #define B2_TIME_OF_IMPACT_H +#include "b2_api.h" #include "b2_math.h" #include "b2_distance.h" /// Input parameters for b2TimeOfImpact -struct b2TOIInput +struct B2_API b2TOIInput { b2DistanceProxy proxyA; b2DistanceProxy proxyB; @@ -37,7 +38,7 @@ struct b2TOIInput }; /// Output parameters for b2TimeOfImpact. -struct b2TOIOutput +struct B2_API b2TOIOutput { enum State { @@ -57,6 +58,6 @@ struct b2TOIOutput /// non-tunneling collisions. If you change the time interval, you should call this function /// again. /// Note: use b2Distance to compute the contact point and normal at the time of impact. -void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); +B2_API void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); #endif diff --git a/src/libraries/box2d/b2_time_step.h b/src/libraries/box2d/b2_time_step.h index f0304a300..13d6292ec 100644 --- a/src/libraries/box2d/b2_time_step.h +++ b/src/libraries/box2d/b2_time_step.h @@ -22,10 +22,11 @@ #ifndef B2_TIME_STEP_H #define B2_TIME_STEP_H +#include "b2_api.h" #include "b2_math.h" /// Profiling data. Times are in milliseconds. -struct b2Profile +struct B2_API b2Profile { float step; float collide; @@ -38,7 +39,7 @@ struct b2Profile }; /// This is an internal structure. -struct b2TimeStep +struct B2_API b2TimeStep { float dt; // time step float inv_dt; // inverse time step (0 if dt == 0). @@ -49,21 +50,21 @@ struct b2TimeStep }; /// This is an internal structure. -struct b2Position +struct B2_API b2Position { b2Vec2 c; float a; }; /// This is an internal structure. -struct b2Velocity +struct B2_API b2Velocity { b2Vec2 v; float w; }; /// Solver Data -struct b2SolverData +struct B2_API b2SolverData { b2TimeStep step; b2Position* positions; diff --git a/src/libraries/box2d/b2_timer.h b/src/libraries/box2d/b2_timer.h index a664de833..7893c3270 100644 --- a/src/libraries/box2d/b2_timer.h +++ b/src/libraries/box2d/b2_timer.h @@ -23,11 +23,12 @@ #ifndef B2_TIMER_H #define B2_TIMER_H +#include "b2_api.h" #include "b2_settings.h" /// Timer for profiling. This has platform specific code and may /// not work on every platform. -class b2Timer +class B2_API b2Timer { public: diff --git a/src/libraries/box2d/b2_types.h b/src/libraries/box2d/b2_types.h new file mode 100644 index 000000000..e0d437759 --- /dev/null +++ b/src/libraries/box2d/b2_types.h @@ -0,0 +1,33 @@ +// MIT License + +// Copyright (c) 2020 Erin Catto + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef B2_TYPES_H +#define B2_TYPES_H + +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +#endif diff --git a/src/libraries/box2d/b2_weld_joint.h b/src/libraries/box2d/b2_weld_joint.h index fd5537f34..f226c8a46 100644 --- a/src/libraries/box2d/b2_weld_joint.h +++ b/src/libraries/box2d/b2_weld_joint.h @@ -23,12 +23,13 @@ #ifndef B2_WELD_JOINT_H #define B2_WELD_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Weld joint definition. You need to specify local anchor points /// where they are attached and the relative body angle. The position /// of the anchor points is important for computing the reaction torque. -struct b2WeldJointDef : public b2JointDef +struct B2_API b2WeldJointDef : public b2JointDef { b2WeldJointDef() { @@ -54,7 +55,7 @@ struct b2WeldJointDef : public b2JointDef /// The bodyB angle minus bodyA angle in the reference state (radians). float referenceAngle; - + /// The rotational stiffness in N*m /// Disable softness with a value of 0 float stiffness; @@ -65,7 +66,7 @@ struct b2WeldJointDef : public b2JointDef /// A weld joint essentially glues two bodies together. A weld joint may /// distort somewhat because the island constraint solver is approximate. -class b2WeldJoint : public b2Joint +class B2_API b2WeldJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_wheel_joint.h b/src/libraries/box2d/b2_wheel_joint.h index 1b8f43739..8576adbd2 100644 --- a/src/libraries/box2d/b2_wheel_joint.h +++ b/src/libraries/box2d/b2_wheel_joint.h @@ -23,6 +23,7 @@ #ifndef B2_WHEEL_JOINT_H #define B2_WHEEL_JOINT_H +#include "b2_api.h" #include "b2_joint.h" /// Wheel joint definition. This requires defining a line of @@ -31,7 +32,7 @@ /// can violate the constraint slightly. The joint translation is zero /// when the local anchor points coincide in world space. Using local /// anchors and a local axis helps when saving and loading a game. -struct b2WheelJointDef : public b2JointDef +struct B2_API b2WheelJointDef : public b2JointDef { b2WheelJointDef() { @@ -91,7 +92,7 @@ struct b2WheelJointDef : public b2JointDef /// along an axis fixed in bodyA and rotation in the plane. In other words, it is a point to /// line constraint with a rotational motor and a linear spring/damper. The spring/damper is /// initialized upon creation. This joint is designed for vehicle suspensions. -class b2WheelJoint : public b2Joint +class B2_API b2WheelJoint : public b2Joint { public: b2Vec2 GetAnchorA() const override; diff --git a/src/libraries/box2d/b2_world.h b/src/libraries/box2d/b2_world.h index 3ddc136e3..57d37096c 100644 --- a/src/libraries/box2d/b2_world.h +++ b/src/libraries/box2d/b2_world.h @@ -23,6 +23,7 @@ #ifndef B2_WORLD_H #define B2_WORLD_H +#include "b2_api.h" #include "b2_block_allocator.h" #include "b2_contact_manager.h" #include "b2_math.h" @@ -42,7 +43,7 @@ class b2Joint; /// The world class manages all physics entities, dynamic simulation, /// and asynchronous queries. The world also contains efficient memory /// management facilities. -class b2World +class B2_API b2World { public: /// Construct a world object. @@ -58,7 +59,7 @@ public: /// Register a contact filter to provide specific control over collision. /// Otherwise the default filter is used (b2_defaultFilter). The listener is - /// owned by you and must remain in scope. + /// owned by you and must remain in scope. void SetContactFilter(b2ContactFilter* filter); /// Register a contact event listener. The listener is owned by you and must @@ -185,7 +186,7 @@ public: /// Change the global gravity vector. void SetGravity(const b2Vec2& gravity); - + /// Get the global gravity vector. b2Vec2 GetGravity() const; diff --git a/src/libraries/box2d/b2_world_callbacks.h b/src/libraries/box2d/b2_world_callbacks.h index e1e75c9e9..da45640e2 100644 --- a/src/libraries/box2d/b2_world_callbacks.h +++ b/src/libraries/box2d/b2_world_callbacks.h @@ -23,6 +23,7 @@ #ifndef B2_WORLD_CALLBACKS_H #define B2_WORLD_CALLBACKS_H +#include "b2_api.h" #include "b2_settings.h" struct b2Vec2; @@ -37,7 +38,7 @@ struct b2Manifold; /// Joints and fixtures are destroyed when their associated /// body is destroyed. Implement this listener so that you /// may nullify references to these joints and shapes. -class b2DestructionListener +class B2_API b2DestructionListener { public: virtual ~b2DestructionListener() {} @@ -53,7 +54,7 @@ public: /// Implement this class to provide collision filtering. In other words, you can implement /// this class if you want finer control over contact creation. -class b2ContactFilter +class B2_API b2ContactFilter { public: virtual ~b2ContactFilter() {} @@ -66,7 +67,7 @@ public: /// Contact impulses for reporting. Impulses are used instead of forces because /// sub-step forces may approach infinity for rigid body collisions. These /// match up one-to-one with the contact points in b2Manifold. -struct b2ContactImpulse +struct B2_API b2ContactImpulse { float normalImpulses[b2_maxManifoldPoints]; float tangentImpulses[b2_maxManifoldPoints]; @@ -82,7 +83,7 @@ struct b2ContactImpulse /// You should strive to make your callbacks efficient because there may be /// many callbacks per time step. /// @warning You cannot create/destroy Box2D entities inside these callbacks. -class b2ContactListener +class B2_API b2ContactListener { public: virtual ~b2ContactListener() {} @@ -124,7 +125,7 @@ public: /// Callback class for AABB queries. /// See b2World::Query -class b2QueryCallback +class B2_API b2QueryCallback { public: virtual ~b2QueryCallback() {} @@ -136,7 +137,7 @@ public: /// Callback class for ray casts. /// See b2World::RayCast -class b2RayCastCallback +class B2_API b2RayCastCallback { public: virtual ~b2RayCastCallback() {} diff --git a/src/libraries/box2d/collision/b2_distance.cpp b/src/libraries/box2d/collision/b2_distance.cpp index e2a27abd0..244132408 100644 --- a/src/libraries/box2d/collision/b2_distance.cpp +++ b/src/libraries/box2d/collision/b2_distance.cpp @@ -27,7 +27,7 @@ #include "box2d/b2_polygon_shape.h" // GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates. -int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; +B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; void b2DistanceProxy::Set(const b2Shape* shape, int32 index) { diff --git a/src/libraries/box2d/collision/b2_dynamic_tree.cpp b/src/libraries/box2d/collision/b2_dynamic_tree.cpp index 45e093320..55a9d3246 100644 --- a/src/libraries/box2d/collision/b2_dynamic_tree.cpp +++ b/src/libraries/box2d/collision/b2_dynamic_tree.cpp @@ -41,8 +41,6 @@ b2DynamicTree::b2DynamicTree() m_nodes[m_nodeCapacity-1].height = -1; m_freeList = 0; - m_path = 0; - m_insertionCount = 0; } diff --git a/src/libraries/box2d/collision/b2_time_of_impact.cpp b/src/libraries/box2d/collision/b2_time_of_impact.cpp index ca61a31f7..7a1011b7e 100644 --- a/src/libraries/box2d/collision/b2_time_of_impact.cpp +++ b/src/libraries/box2d/collision/b2_time_of_impact.cpp @@ -29,9 +29,9 @@ #include -float b2_toiTime, b2_toiMaxTime; -int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; -int32 b2_toiRootIters, b2_toiMaxRootIters; +B2_API float b2_toiTime, b2_toiMaxTime; +B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; +B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; // struct b2SeparationFunction diff --git a/src/libraries/box2d/common/b2_settings.cpp b/src/libraries/box2d/common/b2_settings.cpp index 2b8565c9e..9b66769ac 100644 --- a/src/libraries/box2d/common/b2_settings.cpp +++ b/src/libraries/box2d/common/b2_settings.cpp @@ -27,28 +27,23 @@ #include #include -#include "common/Exception.h" - b2Version b2_version = {2, 4, 0}; // Memory allocators. Modify these to use your own allocator. -void* b2Alloc(int32 size) +void* b2Alloc_Default(int32 size) { return malloc(size); } -void b2Free(void* mem) +void b2Free_Default(void* mem) { free(mem); } // You can modify this to use your logging facility. -void b2Log(const char* string, ...) +void b2Log_Default(const char* string, va_list args) { - va_list args; - va_start(args, string); vprintf(string, args); - va_end(args); } FILE* b2_dumpFile = nullptr; @@ -77,9 +72,3 @@ void b2CloseDump() fclose(b2_dumpFile); b2_dumpFile = nullptr; } - -void loveAssert(bool test, const char* teststr) -{ - if (!test) - throw love::Exception("Box2D assertion failed: %s", teststr); -} diff --git a/src/libraries/box2d/dynamics/b2_body.cpp b/src/libraries/box2d/dynamics/b2_body.cpp index 39851c4cb..574666442 100644 --- a/src/libraries/box2d/dynamics/b2_body.cpp +++ b/src/libraries/box2d/dynamics/b2_body.cpp @@ -434,6 +434,9 @@ void b2Body::SetTransform(const b2Vec2& position, float angle) { f->Synchronize(broadPhase, m_xf, m_xf); } + + // Check for new contacts the next step + m_world->m_newContacts = true; } void b2Body::SynchronizeFixtures() diff --git a/src/libraries/box2d/dynamics/b2_contact.cpp b/src/libraries/box2d/dynamics/b2_contact.cpp index 7c95649d0..1c65bc895 100644 --- a/src/libraries/box2d/dynamics/b2_contact.cpp +++ b/src/libraries/box2d/dynamics/b2_contact.cpp @@ -156,6 +156,7 @@ b2Contact::b2Contact(b2Fixture* fA, int32 indexA, b2Fixture* fB, int32 indexB) m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); + m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold); m_tangentSpeed = 0.0f; } diff --git a/src/libraries/box2d/dynamics/b2_contact_solver.cpp b/src/libraries/box2d/dynamics/b2_contact_solver.cpp index f60a2086e..e6f432a23 100644 --- a/src/libraries/box2d/dynamics/b2_contact_solver.cpp +++ b/src/libraries/box2d/dynamics/b2_contact_solver.cpp @@ -31,7 +31,7 @@ // Solver debugging is normally disabled because the block solver sometimes has to deal with a poorly conditioned effective mass matrix. #define B2_DEBUG_SOLVER 0 -bool g_blockSolve = true; +B2_API bool g_blockSolve = true; struct b2ContactPositionConstraint { @@ -80,6 +80,7 @@ b2ContactSolver::b2ContactSolver(b2ContactSolverDef* def) b2ContactVelocityConstraint* vc = m_velocityConstraints + i; vc->friction = contact->m_friction; vc->restitution = contact->m_restitution; + vc->threshold = contact->m_restitutionThreshold; vc->tangentSpeed = contact->m_tangentSpeed; vc->indexA = bodyA->m_islandIndex; vc->indexB = bodyB->m_islandIndex; @@ -213,7 +214,7 @@ void b2ContactSolver::InitializeVelocityConstraints() // Setup a velocity bias for restitution. vcp->velocityBias = 0.0f; float vRel = b2Dot(vc->normal, vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA)); - if (vRel < -b2_velocityThreshold) + if (vRel < -vc->threshold) { vcp->velocityBias = -vc->restitution * vRel; } diff --git a/src/libraries/box2d/dynamics/b2_contact_solver.h b/src/libraries/box2d/dynamics/b2_contact_solver.h index bef5e819c..1064738ef 100644 --- a/src/libraries/box2d/dynamics/b2_contact_solver.h +++ b/src/libraries/box2d/dynamics/b2_contact_solver.h @@ -55,6 +55,7 @@ struct b2ContactVelocityConstraint float invIA, invIB; float friction; float restitution; + float threshold; float tangentSpeed; int32 pointCount; int32 contactIndex; diff --git a/src/libraries/box2d/dynamics/b2_distance_joint.cpp b/src/libraries/box2d/dynamics/b2_distance_joint.cpp index 9eea08559..e54dbaf4f 100644 --- a/src/libraries/box2d/dynamics/b2_distance_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_distance_joint.cpp @@ -21,6 +21,7 @@ // SOFTWARE. #include "box2d/b2_body.h" +#include "box2d/b2_draw.h" #include "box2d/b2_distance_joint.h" #include "box2d/b2_time_step.h" @@ -48,7 +49,9 @@ void b2DistanceJointDef::Initialize(b2Body* b1, b2Body* b2, localAnchorA = bodyA->GetLocalPoint(anchor1); localAnchorB = bodyB->GetLocalPoint(anchor2); b2Vec2 d = anchor2 - anchor1; - length = d.Length(); + length = b2Max(d.Length(), b2_linearSlop); + minLength = length; + maxLength = length; } b2DistanceJoint::b2DistanceJoint(const b2DistanceJointDef* def) @@ -56,13 +59,18 @@ b2DistanceJoint::b2DistanceJoint(const b2DistanceJointDef* def) { m_localAnchorA = def->localAnchorA; m_localAnchorB = def->localAnchorB; - m_length = def->length; + m_length = b2Max(def->length, b2_linearSlop); + m_minLength = b2Max(def->minLength, b2_linearSlop); + m_maxLength = b2Max(def->maxLength, m_minLength); m_stiffness = def->stiffness; m_damping = def->damping; - m_impulse = 0.0f; m_gamma = 0.0f; m_bias = 0.0f; + m_impulse = 0.0f; + m_lowerImpulse = 0.0f; + m_upperImpulse = 0.0f; + m_currentLength = 0.0f; } void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data) @@ -93,23 +101,29 @@ void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data) m_u = cB + m_rB - cA - m_rA; // Handle singularity. - float length = m_u.Length(); - if (length > b2_linearSlop) + m_currentLength = m_u.Length(); + if (m_currentLength > b2_linearSlop) { - m_u *= 1.0f / length; + m_u *= 1.0f / m_currentLength; } else { m_u.Set(0.0f, 0.0f); + m_mass = 0.0f; + m_impulse = 0.0f; + m_lowerImpulse = 0.0f; + m_upperImpulse = 0.0f; } float crAu = b2Cross(m_rA, m_u); float crBu = b2Cross(m_rB, m_u); float invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu; + m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; - if (m_stiffness > 0.0f) + if (m_stiffness > 0.0f && m_minLength < m_maxLength) { - float C = length - m_length; + // soft + float C = m_currentLength - m_length; float d = m_damping; float k = m_stiffness; @@ -117,27 +131,31 @@ void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data) // magic formulas float h = data.step.dt; - // gamma = 1 / (h * (d + h * k)), the extra factor of h in the denominator is since the lambda is an impulse, not a force + // gamma = 1 / (h * (d + h * k)) + // the extra factor of h in the denominator is since the lambda is an impulse, not a force m_gamma = h * (d + h * k); m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f; m_bias = C * h * k * m_gamma; invMass += m_gamma; - m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; + m_softMass = invMass != 0.0f ? 1.0f / invMass : 0.0f; } else { + // rigid m_gamma = 0.0f; m_bias = 0.0f; - m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; + m_softMass = m_mass; } if (data.step.warmStarting) { // Scale the impulse to support a variable time step. m_impulse *= data.step.dtRatio; + m_lowerImpulse *= data.step.dtRatio; + m_upperImpulse *= data.step.dtRatio; - b2Vec2 P = m_impulse * m_u; + b2Vec2 P = (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u; vA -= m_invMassA * P; wA -= m_invIA * b2Cross(m_rA, P); vB += m_invMassB * P; @@ -161,19 +179,85 @@ void b2DistanceJoint::SolveVelocityConstraints(const b2SolverData& data) b2Vec2 vB = data.velocities[m_indexB].v; float wB = data.velocities[m_indexB].w; - // Cdot = dot(u, v + cross(w, r)) - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - float Cdot = b2Dot(m_u, vpB - vpA); + if (m_minLength < m_maxLength) + { + if (m_stiffness > 0.0f) + { + // Cdot = dot(u, v + cross(w, r)) + b2Vec2 vpA = vA + b2Cross(wA, m_rA); + b2Vec2 vpB = vB + b2Cross(wB, m_rB); + float Cdot = b2Dot(m_u, vpB - vpA); - float impulse = -m_mass * (Cdot + m_bias + m_gamma * m_impulse); - m_impulse += impulse; + float impulse = -m_softMass * (Cdot + m_bias + m_gamma * m_impulse); + m_impulse += impulse; - b2Vec2 P = impulse * m_u; - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); + b2Vec2 P = impulse * m_u; + vA -= m_invMassA * P; + wA -= m_invIA * b2Cross(m_rA, P); + vB += m_invMassB * P; + wB += m_invIB * b2Cross(m_rB, P); + } + + // lower + { + float C = m_currentLength - m_minLength; + float bias = b2Max(0.0f, C) * data.step.inv_dt; + + b2Vec2 vpA = vA + b2Cross(wA, m_rA); + b2Vec2 vpB = vB + b2Cross(wB, m_rB); + float Cdot = b2Dot(m_u, vpB - vpA); + + float impulse = -m_mass * (Cdot + bias); + float oldImpulse = m_lowerImpulse; + m_lowerImpulse = b2Max(0.0f, m_lowerImpulse + impulse); + impulse = m_lowerImpulse - oldImpulse; + b2Vec2 P = impulse * m_u; + + vA -= m_invMassA * P; + wA -= m_invIA * b2Cross(m_rA, P); + vB += m_invMassB * P; + wB += m_invIB * b2Cross(m_rB, P); + } + + // upper + { + float C = m_maxLength - m_currentLength; + float bias = b2Max(0.0f, C) * data.step.inv_dt; + + b2Vec2 vpA = vA + b2Cross(wA, m_rA); + b2Vec2 vpB = vB + b2Cross(wB, m_rB); + float Cdot = b2Dot(m_u, vpA - vpB); + + float impulse = -m_mass * (Cdot + bias); + float oldImpulse = m_upperImpulse; + m_upperImpulse = b2Max(0.0f, m_upperImpulse + impulse); + impulse = m_upperImpulse - oldImpulse; + b2Vec2 P = -impulse * m_u; + + vA -= m_invMassA * P; + wA -= m_invIA * b2Cross(m_rA, P); + vB += m_invMassB * P; + wB += m_invIB * b2Cross(m_rB, P); + } + } + else + { + // Equal limits + + // Cdot = dot(u, v + cross(w, r)) + b2Vec2 vpA = vA + b2Cross(wA, m_rA); + b2Vec2 vpB = vB + b2Cross(wB, m_rB); + float Cdot = b2Dot(m_u, vpB - vpA); + + float impulse = -m_mass * Cdot; + m_impulse += impulse; + + b2Vec2 P = impulse * m_u; + vA -= m_invMassA * P; + wA -= m_invIA * b2Cross(m_rA, P); + vB += m_invMassB * P; + wB += m_invIB * b2Cross(m_rB, P); + } data.velocities[m_indexA].v = vA; data.velocities[m_indexA].w = wA; @@ -183,12 +267,6 @@ void b2DistanceJoint::SolveVelocityConstraints(const b2SolverData& data) bool b2DistanceJoint::SolvePositionConstraints(const b2SolverData& data) { - if (m_stiffness > 0.0f) - { - // There is no position correction for soft distance constraints. - return true; - } - b2Vec2 cA = data.positions[m_indexA].c; float aA = data.positions[m_indexA].a; b2Vec2 cB = data.positions[m_indexB].c; @@ -201,8 +279,23 @@ bool b2DistanceJoint::SolvePositionConstraints(const b2SolverData& data) b2Vec2 u = cB + rB - cA - rA; float length = u.Normalize(); - float C = length - m_length; - C = b2Clamp(C, -b2_maxLinearCorrection, b2_maxLinearCorrection); + float C; + if (m_minLength == m_maxLength) + { + C = length - m_minLength; + } + else if (length < m_minLength) + { + C = length - m_minLength; + } + else if (m_maxLength < length) + { + C = length - m_maxLength; + } + else + { + return true; + } float impulse = -m_mass * C; b2Vec2 P = impulse * u; @@ -232,7 +325,7 @@ b2Vec2 b2DistanceJoint::GetAnchorB() const b2Vec2 b2DistanceJoint::GetReactionForce(float inv_dt) const { - b2Vec2 F = (inv_dt * m_impulse) * m_u; + b2Vec2 F = inv_dt * (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u; return F; } @@ -242,6 +335,36 @@ float b2DistanceJoint::GetReactionTorque(float inv_dt) const return 0.0f; } +float b2DistanceJoint::SetLength(float length) +{ + m_impulse = 0.0f; + m_length = b2Max(b2_linearSlop, length); + return m_length; +} + +float b2DistanceJoint::SetMinLength(float minLength) +{ + m_lowerImpulse = 0.0f; + m_minLength = b2Clamp(minLength, b2_linearSlop, m_maxLength); + return m_minLength; +} + +float b2DistanceJoint::SetMaxLength(float maxLength) +{ + m_upperImpulse = 0.0f; + m_maxLength = b2Max(maxLength, m_minLength); + return m_maxLength; +} + +float b2DistanceJoint::GetCurrentLength() const +{ + b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA); + b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB); + b2Vec2 d = pB - pA; + float length = d.Length(); + return length; +} + void b2DistanceJoint::Dump() { int32 indexA = m_bodyA->m_islandIndex; @@ -254,7 +377,45 @@ void b2DistanceJoint::Dump() b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); b2Dump(" jd.length = %.9g;\n", m_length); + b2Dump(" jd.minLength = %.9g;\n", m_minLength); + b2Dump(" jd.maxLength = %.9g;\n", m_maxLength); b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); b2Dump(" jd.damping = %.9g;\n", m_damping); b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } + +void b2DistanceJoint::Draw(b2Draw* draw) const +{ + const b2Transform& xfA = m_bodyA->GetTransform(); + const b2Transform& xfB = m_bodyB->GetTransform(); + b2Vec2 pA = b2Mul(xfA, m_localAnchorA); + b2Vec2 pB = b2Mul(xfB, m_localAnchorB); + + b2Vec2 axis = pB - pA; + float length = axis.Normalize(); + + b2Color c1(0.7f, 0.7f, 0.7f); + b2Color c2(0.3f, 0.9f, 0.3f); + b2Color c3(0.9f, 0.3f, 0.3f); + b2Color c4(0.4f, 0.4f, 0.4f); + + draw->DrawSegment(pA, pB, c4); + + b2Vec2 pRest = pA + m_length * axis; + draw->DrawPoint(pRest, 8.0f, c1); + + if (m_minLength != m_maxLength) + { + if (m_minLength > b2_linearSlop) + { + b2Vec2 pMin = pA + m_minLength * axis; + draw->DrawPoint(pMin, 4.0f, c2); + } + + if (m_maxLength < FLT_MAX) + { + b2Vec2 pMax = pA + m_maxLength * axis; + draw->DrawPoint(pMax, 4.0f, c3); + } + } +} diff --git a/src/libraries/box2d/dynamics/b2_fixture.cpp b/src/libraries/box2d/dynamics/b2_fixture.cpp index 420cfdcfa..9fd700aa9 100644 --- a/src/libraries/box2d/dynamics/b2_fixture.cpp +++ b/src/libraries/box2d/dynamics/b2_fixture.cpp @@ -33,7 +33,6 @@ b2Fixture::b2Fixture() { - m_userData = nullptr; m_body = nullptr; m_next = nullptr; m_proxies = nullptr; @@ -47,6 +46,7 @@ void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2Fixtur m_userData = def->userData; m_friction = def->friction; m_restitution = def->restitution; + m_restitutionThreshold = def->restitutionThreshold; m_body = body; m_next = nullptr; @@ -235,6 +235,7 @@ void b2Fixture::Dump(int32 bodyIndex) b2Dump(" b2FixtureDef fd;\n"); b2Dump(" fd.friction = %.9g;\n", m_friction); b2Dump(" fd.restitution = %.9g;\n", m_restitution); + b2Dump(" fd.restitutionThreshold = %.9g;\n", m_restitutionThreshold); b2Dump(" fd.density = %.9g;\n", m_density); b2Dump(" fd.isSensor = bool(%d);\n", m_isSensor); b2Dump(" fd.filter.categoryBits = uint16(%d);\n", m_filter.categoryBits); diff --git a/src/libraries/box2d/dynamics/b2_gear_joint.cpp b/src/libraries/box2d/dynamics/b2_gear_joint.cpp index 414291093..ff36d3e10 100644 --- a/src/libraries/box2d/dynamics/b2_gear_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_gear_joint.cpp @@ -64,6 +64,9 @@ b2GearJoint::b2GearJoint(const b2GearJointDef* def) m_bodyC = m_joint1->GetBodyA(); m_bodyA = m_joint1->GetBodyB(); + // Body B on joint1 must be dynamic + b2Assert(m_bodyA->m_type == b2_dynamicBody); + // Get geometry of joint1 b2Transform xfA = m_bodyA->m_xf; float aA = m_bodyA->m_sweep.a; @@ -96,6 +99,9 @@ b2GearJoint::b2GearJoint(const b2GearJointDef* def) m_bodyD = m_joint2->GetBodyA(); m_bodyB = m_joint2->GetBodyB(); + // Body B on joint2 must be dynamic + b2Assert(m_bodyB->m_type == b2_dynamicBody); + // Get geometry of joint2 b2Transform xfB = m_bodyB->m_xf; float aB = m_bodyB->m_sweep.a; diff --git a/src/libraries/box2d/dynamics/b2_joint.cpp b/src/libraries/box2d/dynamics/b2_joint.cpp index 1f8ac2644..41addbbb2 100644 --- a/src/libraries/box2d/dynamics/b2_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_joint.cpp @@ -31,7 +31,6 @@ #include "box2d/b2_prismatic_joint.h" #include "box2d/b2_pulley_joint.h" #include "box2d/b2_revolute_joint.h" -#include "box2d/b2_rope_joint.h" #include "box2d/b2_weld_joint.h" #include "box2d/b2_wheel_joint.h" #include "box2d/b2_world.h" @@ -157,13 +156,6 @@ b2Joint* b2Joint::Create(const b2JointDef* def, b2BlockAllocator* allocator) } break; - case e_ropeJoint: - { - void* mem = allocator->Allocate(sizeof(b2RopeJoint)); - joint = new (mem) b2RopeJoint(static_cast(def)); - } - break; - case e_motorJoint: { void* mem = allocator->Allocate(sizeof(b2MotorJoint)); @@ -220,10 +212,6 @@ void b2Joint::Destroy(b2Joint* joint, b2BlockAllocator* allocator) allocator->Free(joint, sizeof(b2FrictionJoint)); break; - case e_ropeJoint: - allocator->Free(joint, sizeof(b2RopeJoint)); - break; - case e_motorJoint: allocator->Free(joint, sizeof(b2MotorJoint)); break; diff --git a/src/libraries/box2d/dynamics/b2_prismatic_joint.cpp b/src/libraries/box2d/dynamics/b2_prismatic_joint.cpp index cb550170f..00e77690e 100644 --- a/src/libraries/box2d/dynamics/b2_prismatic_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_prismatic_joint.cpp @@ -462,7 +462,7 @@ b2Vec2 b2PrismaticJoint::GetAnchorB() const b2Vec2 b2PrismaticJoint::GetReactionForce(float inv_dt) const { - return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_lowerImpulse + m_upperImpulse) * m_axis); + return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_lowerImpulse - m_upperImpulse) * m_axis); } float b2PrismaticJoint::GetReactionTorque(float inv_dt) const @@ -607,7 +607,6 @@ void b2PrismaticJoint::Dump() b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); } -/// void b2PrismaticJoint::Draw(b2Draw* draw) const { const b2Transform& xfA = m_bodyA->GetTransform(); diff --git a/src/libraries/box2d/dynamics/b2_revolute_joint.cpp b/src/libraries/box2d/dynamics/b2_revolute_joint.cpp index 35162b084..f7cc4cc29 100644 --- a/src/libraries/box2d/dynamics/b2_revolute_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_revolute_joint.cpp @@ -338,7 +338,7 @@ b2Vec2 b2RevoluteJoint::GetReactionForce(float inv_dt) const float b2RevoluteJoint::GetReactionTorque(float inv_dt) const { - return inv_dt * (m_lowerImpulse + m_upperImpulse); + return inv_dt * (m_motorImpulse + m_lowerImpulse - m_upperImpulse); } float b2RevoluteJoint::GetJointAngle() const diff --git a/src/libraries/box2d/dynamics/b2_wheel_joint.cpp b/src/libraries/box2d/dynamics/b2_wheel_joint.cpp index 3e76678bf..c23b98460 100644 --- a/src/libraries/box2d/dynamics/b2_wheel_joint.cpp +++ b/src/libraries/box2d/dynamics/b2_wheel_joint.cpp @@ -455,7 +455,7 @@ b2Vec2 b2WheelJoint::GetAnchorB() const b2Vec2 b2WheelJoint::GetReactionForce(float inv_dt) const { - return inv_dt * (m_impulse * m_ay + m_springImpulse * m_ax); + return inv_dt * (m_impulse * m_ay + (m_springImpulse + m_lowerImpulse - m_upperImpulse) * m_ax); } float b2WheelJoint::GetReactionTorque(float inv_dt) const diff --git a/src/libraries/box2d/rope/b2_rope.cpp b/src/libraries/box2d/rope/b2_rope.cpp index 511944814..d2425a2af 100644 --- a/src/libraries/box2d/rope/b2_rope.cpp +++ b/src/libraries/box2d/rope/b2_rope.cpp @@ -306,6 +306,10 @@ void b2Rope::Step(float dt, int32 iterations, const b2Vec2& position) { SolveBend_PBD_Height(); } + else if (m_tuning.bendingModel == b2_pbdTriangleBendingModel) + { + SolveBend_PBD_Triangle(); + } if (m_tuning.stretchingModel == b2_pbdStretchingModel) { @@ -750,6 +754,42 @@ void b2Rope::SolveBend_PBD_Height() } } +// M. Kelager: A Triangle Bending Constraint Model for PBD +void b2Rope::SolveBend_PBD_Triangle() +{ + const float stiffness = m_tuning.bendStiffness; + + for (int32 i = 0; i < m_bendCount; ++i) + { + const b2RopeBend& c = m_bendConstraints[i]; + + b2Vec2 b0 = m_ps[c.i1]; + b2Vec2 v = m_ps[c.i2]; + b2Vec2 b1 = m_ps[c.i3]; + + float wb0 = c.invMass1; + float wv = c.invMass2; + float wb1 = c.invMass3; + + float W = wb0 + wb1 + 2.0f * wv; + float invW = stiffness / W; + + b2Vec2 d = v - (1.0f / 3.0f) * (b0 + v + b1); + + b2Vec2 db0 = 2.0f * wb0 * invW * d; + b2Vec2 dv = -4.0f * wv * invW * d; + b2Vec2 db1 = 2.0f * wb1 * invW * d; + + b0 += db0; + v += dv; + b1 += db1; + + m_ps[c.i1] = b0; + m_ps[c.i2] = v; + m_ps[c.i3] = b1; + } +} + void b2Rope::Draw(b2Draw* draw) const { b2Color c(0.4f, 0.5f, 0.7f); diff --git a/src/modules/physics/box2d/Body.cpp b/src/modules/physics/box2d/Body.cpp index c61368636..05070d64f 100644 --- a/src/modules/physics/box2d/Body.cpp +++ b/src/modules/physics/box2d/Body.cpp @@ -45,7 +45,7 @@ Body::Body(World *world, b2Vec2 p, Body::Type type) udata->ref = nullptr; b2BodyDef def; def.position = Physics::scaleDown(p); - def.userData = (void *) udata; + def.userData = udata; body = world->world->CreateBody(&def); // Box2D body holds a reference to the love Body. this->retain(); @@ -529,7 +529,7 @@ int Body::setUserData(lua_State *L) if (udata == nullptr) { udata = new bodyudata(); - body->SetUserData((void *) udata); + body->SetUserData(udata); } if(!udata->ref) diff --git a/src/modules/physics/box2d/Fixture.cpp b/src/modules/physics/box2d/Fixture.cpp index 6278eb45f..6595eec1f 100644 --- a/src/modules/physics/box2d/Fixture.cpp +++ b/src/modules/physics/box2d/Fixture.cpp @@ -45,7 +45,7 @@ Fixture::Fixture(Body *body, Shape *shape, float density) udata->ref = nullptr; b2FixtureDef def; def.shape = shape->shape; - def.userData = (void *)udata; + def.userData = udata; def.density = density; fixture = body->body->CreateFixture(&def); this->retain(); @@ -262,7 +262,7 @@ int Fixture::setUserData(lua_State *L) if (udata == nullptr) { udata = new fixtureudata(); - fixture->SetUserData((void *) udata); + fixture->SetUserData(udata); } if(!udata->ref) diff --git a/src/modules/physics/box2d/Joint.cpp b/src/modules/physics/box2d/Joint.cpp index b1d8cccaa..a2e735fa3 100644 --- a/src/modules/physics/box2d/Joint.cpp +++ b/src/modules/physics/box2d/Joint.cpp @@ -202,7 +202,7 @@ int Joint::setUserData(lua_State *L) if (udata == nullptr) { udata = new jointudata(); - joint->SetUserData((void *) udata); + joint->SetUserData(udata); } if(!udata->ref)