Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates 20240121 #573

Merged
merged 7 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ jobs:

- name: Prerequisites
run: |
sudo apt update
sudo apt install doxygen graphviz
sudo apt-get -y update
sudo apt-get -y install doxygen graphviz

- name: Configure
run: >
Expand Down
22 changes: 13 additions & 9 deletions Library/include/playrho/BodyID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,27 @@
// IWYU pragma: begin_exports

#include <playrho/detail/IndexingNamedType.hpp>
#include <playrho/Settings.hpp>
#include <playrho/Settings.hpp> // for BodyCounter

// IWYU pragma: end_exports

namespace playrho {

/// @brief Strongly typed identifier for bodies within @c World instances.
/// @brief Body identifier.
/// @details A strongly typed identifier for uniquely identifying bodes within @c d2::World
/// instances. This is based on the @c BodyCounter type as its underlying type.
/// @see BodyCounter, ContactID, JointID, ShapeID, d2::Body, d2::World.
using BodyID = detail::IndexingNamedType<BodyCounter, struct BodyIdentifier>;

/// @brief Invalid body ID value.
/// @see BodyID.
constexpr auto InvalidBodyID = static_cast<BodyID>(static_cast<BodyID::underlying_type>(-1));

/// @brief Determines if the given value is valid.
/// @see BodyID.
template <>
constexpr bool IsValid(const BodyID& value) noexcept
/// @details A special, reserved value of a @c BodyID that represents/identifies an _invalid_ body.
/// @see BodyID, IsValid.
constexpr auto InvalidBodyID = BodyID{static_cast<BodyID::underlying_type>(-1)};

/// @brief Determines validity of given value by comparing against <code>InvalidBodyID</code>.
/// @return true if not equal to @c InvalidBodyID , else false.
/// @see BodyID, InvalidBodyID.
constexpr auto IsValid(const BodyID& value) noexcept -> bool
{
return value != InvalidBodyID;
}
Expand Down
19 changes: 12 additions & 7 deletions Library/include/playrho/ContactID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,21 @@

namespace playrho {

/// @brief Strongly typed identifier of contacts within @c World instances.
/// @brief Contact identifier.
/// @details A strongly typed identifier for uniquely identifying contacts within @c d2::World
/// instances. This is based on the @c ContactCounter type as its underlying type.
/// @see Contact, ContactCounter, BodyID, JointID, ShapeID, d2::World.
using ContactID = detail::IndexingNamedType<ContactCounter, struct ContactIdentifier>;

/// @brief Invalid contact ID value.
constexpr auto InvalidContactID =
static_cast<ContactID>(static_cast<ContactID::underlying_type>(-1));

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const ContactID& value) noexcept
/// @details A special, reserved value of a @c ContactID that represents/identifies an _invalid_ contact.
/// @see ContactID, IsValid.
constexpr auto InvalidContactID = ContactID{static_cast<ContactID::underlying_type>(-1)};

/// @brief Determines validity of given value by comparing against <code>InvalidContactID</code>.
/// @return true if not equal to @c InvalidContactID , else false.
/// @see ContactID, InvalidContactID.
constexpr auto IsValid(const ContactID& value) noexcept -> bool
{
return value != InvalidContactID;
}
Expand Down
16 changes: 11 additions & 5 deletions Library/include/playrho/JointID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@
namespace playrho {

/// @brief Joint identifier.
/// @details A strongly typed identifier for uniquely identifying joints within @c d2::World
/// instances. This is based on the @c JointCounter type as its underlying type.
/// @see JointCounter, BodyID, ContactID, ShapeID, d2::Joint, d2::World.
using JointID = detail::IndexingNamedType<JointCounter, struct JointIdentifier>;

/// @brief Invalid joint ID value.
constexpr auto InvalidJointID = static_cast<JointID>(static_cast<JointID::underlying_type>(-1));

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const JointID& value) noexcept
/// @details A special, reserved value of a @c JointID that represents/identifies an _invalid_ joint.
/// @see JointID, IsValid.
constexpr auto InvalidJointID = JointID{static_cast<JointID::underlying_type>(-1)};

/// @brief Determines validity of given value by comparing against <code>InvalidJointID</code>.
/// @return true if not equal to @c InvalidJointID , else false.
/// @see JointID, InvalidJointID.
constexpr auto IsValid(const JointID& value) noexcept -> bool
{
return value != InvalidJointID;
}
Expand Down
3 changes: 1 addition & 2 deletions Library/include/playrho/Matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@ using InvMass22 = Matrix22<InvMass>;
using Mat33 = Matrix33<Real>;

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const Mat22& value) noexcept
constexpr auto IsValid(const Mat22& value) noexcept -> bool
{
return IsValid(get<0>(value)) && IsValid(get<1>(value));
}
Expand Down
66 changes: 47 additions & 19 deletions Library/include/playrho/Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ constexpr auto MaxChildCount = std::numeric_limits<std::uint32_t>::max() >> 6;
/// @note This type must always be able to contain the <code>MaxChildCount</code> value.
using ChildCounter = std::remove_const_t<decltype(MaxChildCount)>;

/// Time step iterations type.
/// @brief Time step iterations type.
/// @details A type for counting iterations per time-step.
using TimestepIters = std::uint8_t;

Expand All @@ -65,23 +65,27 @@ constexpr auto MaxFloat = std::numeric_limits<Real>::max(); // FLT_MAX

// Collision

/// Maximum manifold points.
/// This is the maximum number of contact points between two convex shapes.
/// @brief Maximum manifold points.
/// @details This is the maximum number of contact points between two convex shapes.
/// Do not change this value.
/// @note For memory efficiency, uses the smallest integral type that can hold the value.
/// @note For memory efficiency, this uses the smallest integral type that can hold the value.
constexpr auto MaxManifoldPoints = std::uint8_t{2};

/// @brief Maximum number of vertices for any shape type.
/// @note For memory efficiency, uses the smallest integral type that can hold the value minus
/// one that's left out as a sentinel value.
/// one that's left out as a special, reserved value.
/// @see VertexCounter, InvalidVertex.
constexpr auto MaxShapeVertices = std::uint8_t{254};

/// @brief Vertex count type.
/// @note This type must not support more than 255 vertices as that would conflict
/// with the <code>ContactFeature::Index</code> type.
/// @see MaxShapeVertices, InvalidVertex.
using VertexCounter = std::remove_const_t<decltype(MaxShapeVertices)>;

/// @brief Invalid vertex index.
/// @details This is a special, reserved value for indicating/identifying an invalid vertex.
/// @see VertexCounter.
constexpr auto InvalidVertex = static_cast<VertexCounter>(-1);

/// @brief Default linear slop.
Expand All @@ -91,15 +95,18 @@ constexpr auto InvalidVertex = static_cast<VertexCounter>(-1);
/// between bodies at rest.
/// @note Smaller values relative to sizes of bodies increases the time it takes
/// for bodies to come to rest.
/// @note The value used by Box2D 2.3.2 b2_linearSlop define is 0.005_m.
/// @note The value used by Box2D 2.3.2's @c b2_linearSlop define is 0.005 (meters).
/// @see DefaultAngularSlop.
constexpr auto DefaultLinearSlop = 0.005_m;

/// @brief Default minimum vertex radius.
/// @note Recommend using <code>0.01_m</code> or <code>DefaultLinearSlop * Real(2)</code>.
/// @see DefaultMaxVertexRadius, DefaultLinearSlop.
constexpr auto DefaultMinVertexRadius = 0.01_m;

/// @brief Default maximum vertex radius.
/// @note Recommend using <code>255_m</code> or <code>DefaultLinearSlop * 2 * 25500</code>.
/// @see DefaultMinVertexRadius, DefaultLinearSlop.
constexpr auto DefaultMaxVertexRadius = 255_m;

/// @brief Default AABB extension amount.
Expand All @@ -112,37 +119,41 @@ constexpr auto DefaultDistanceMultiplier = Real(2);
/// @details
/// A small angle used as a collision and constraint tolerance. Usually it is
/// chosen to be numerically significant, but visually insignificant.
/// @see DefaultLinearSlop.
constexpr auto DefaultAngularSlop = (Pi * 2_rad) / Real(180);

/// @brief Default maximum linear correction.
/// @details The maximum linear position correction used when solving constraints.
/// This helps to prevent overshoot.
/// @note This value should be greater than the linear slop value.
/// @see DefaultMaxAngularCorrection.
constexpr auto DefaultMaxLinearCorrection = 0.2_m;

/// @brief Default maximum angular correction.
/// @note This value should be greater than the angular slop value.
/// @see DefaultMaxLinearCorrection.
constexpr auto DefaultMaxAngularCorrection = Real(8.0f / 180.0f) * Pi * 1_rad;

/// @brief Default maximum translation amount.
/// @see DefaultMaxRotation.
constexpr auto DefaultMaxTranslation = 2_m;

/// @brief Default maximum rotation per world step.
/// @warning This value should always be less than 180 degrees - i.e. less than .5 * Pi * Radian.
/// @note This limit is meant to prevent numerical problems. Adjusting this value isn't advised.
/// @see StepConf::maxRotation.
/// @see DefaultMaxTranslation, StepConf::maxRotation.
constexpr auto DefaultMaxRotation = Angle{179_deg};

/// @brief Default maximum time of impact iterations.
constexpr auto DefaultMaxToiIters = std::uint8_t{20};

/// Default maximum time of impact root iterator count.
/// @brief Default maximum time of impact root iterator count.
constexpr auto DefaultMaxToiRootIters = std::uint8_t{30};

/// Default max number of distance iterations.
/// @brief Default max number of distance iterations.
constexpr auto DefaultMaxDistanceIters = std::uint8_t{20};

/// Default maximum number of sub steps.
/// @brief Default maximum number of sub steps.
/// @details
/// This is the default maximum number of sub-steps per contact in continuous physics simulation.
/// In other words, this is the default maximum number of times in a world step that a contact will
Expand All @@ -156,75 +167,92 @@ constexpr auto DefaultMaxSubSteps = std::uint8_t{8};
constexpr auto DefaultVelocityThreshold = 1_mps;

/// @brief Default regular-phase minimum momentum.
/// @see DefaultToiMinMomentum.
constexpr auto DefaultRegMinMomentum = Momentum{0_Ns / 100};

/// @brief Default TOI-phase minimum momentum.
/// @see DefaultRegMinMomentum.
constexpr auto DefaultToiMinMomentum = Momentum{0_Ns / 100};

/// @brief Maximum number of bodies in a world.
/// @note This is 65534 based off <code>std::uint16_t</code> and eliminating one value for invalid.
/// @note This is 2^16 - 2, i.e. 65534, based off <code>std::uint16_t</code> and eliminating one value for
/// the _invalid_ body identifier (@c InvalidBodyID).
/// @see BodyCounter, BodyID, InvalidBodyID, MaxContacts, MaxJoints, MaxShapes.
constexpr auto MaxBodies = static_cast<std::uint16_t>(std::numeric_limits<std::uint16_t>::max() -
std::uint16_t{1});

/// @brief Count type for bodies.
/// @note This type must always be able to contain the <code>MaxBodies</code> value.
/// @note This type must always be able to contain the @c MaxBodies value.
/// @see MaxBodies, ContactCounter, JointCounter, ShapeCounter.
using BodyCounter = std::remove_const_t<decltype(MaxBodies)>;

/// @brief Count type for contacts.
/// @note This type must be able to contain the squared value of <code>BodyCounter</code>.
/// @note This type is meant to contain up to the square of the maximum value of a <code>BodyCounter</code> without possibility of overflow.
/// @see MaxContacts, BodyCounter, JointCounter, ShapeCounter.
using ContactCounter = WiderType<BodyCounter>;

/// @brief Invalid contact index.
/// @see ContactCounter.
constexpr auto InvalidContactIndex = static_cast<ContactCounter>(-1);

/// @brief Maximum number of contacts in a world (2147319811).
/// @details Uses the formula for the maximum number of edges in an unidirectional graph of
/// <code>MaxBodies</code> nodes.
/// This occurs when every possible body is connected to every other body.
/// @see ContactCounter. ContactID, InvalidContactID, MaxBodies, MaxJoints, MaxShapes.
constexpr auto MaxContacts = ContactCounter{MaxBodies} * ContactCounter{MaxBodies - 1} / ContactCounter{2};

/// @brief Dynamic tree size type.
using DynamicTreeSize = ContactCounter;

/// @brief Maximum number of joints in a world.
/// @note This is 65534 based off <code>std::uint16_t</code> and eliminating one value for invalid.
/// @note This is 2^16 - 2, i.e. 65534, based off <code>std::uint16_t</code> and eliminating one value for
/// the invalid joint identifier (@c InvalidJointID).
/// @see JointCounter, JointID. InvalidJointID, MaxBodies, MaxContacts. MaxShapes.
constexpr auto MaxJoints = static_cast<std::uint16_t>(std::numeric_limits<std::uint16_t>::max() -
std::uint16_t{1});

/// @brief Counter type for joints.
/// @note This type must be able to contain the <code>MaxJoints</code> value.
/// @note This type must be able to contain the @c MaxJoints value.
/// @see MaxJoints, BodyCounter, ContactCounter, ShapeCounter.
using JointCounter = std::remove_const_t<decltype(MaxJoints)>;

/// @brief Maximum number of shapes in a world.
/// @note This is 65534 based off <code>std::uint16_t</code> and eliminating one value for invalid.
/// @see ShapeCounter, ShapeID, InvalidShapeID, MaxBodies, MaxContacts, MaxJoints.
constexpr auto MaxShapes = static_cast<std::uint16_t>(std::numeric_limits<std::uint16_t>::max() -
std::uint16_t{1});

/// @brief Count type for shapes.
/// @note This type must always be able to contain the <code>MaxShapes</code> value.
/// @see MaxShapes, BodyCounter, ContactCounter, JointCounter.
using ShapeCounter = std::remove_const_t<decltype(MaxShapes)>;

/// @brief Default step time.
/// @see DefaultStepFrequency.
constexpr auto DefaultStepTime = Time{1_s / 60};

/// @brief Default step frequency.
/// @see DefaultStepTime.
constexpr auto DefaultStepFrequency = 60_Hz;

// Sleep

/// Default minimum still time to sleep.
/// @brief Default minimum still time to sleep.
/// @details The default minimum time bodies must be still for bodies to be put to sleep.
constexpr auto DefaultMinStillTimeToSleep = Time{1_s / 2}; // aka 0.5 secs

/// Default linear sleep tolerance.
/// @brief Default linear sleep tolerance.
/// @details A body cannot sleep if the magnitude of its linear velocity is above this amount.
/// @see DefaultAngularSleepTolerance.
constexpr auto DefaultLinearSleepTolerance = 0.01_mps; // aka 0.01

/// Default angular sleep tolerance.
/// @brief Default angular sleep tolerance.
/// @details A body cannot sleep if its angular velocity is above this amount.
/// @see DefaultLinearSleepTolerance.
constexpr auto DefaultAngularSleepTolerance = Real((Pi * 2) / 180) * RadianPerSecond;

/// Default circles ratio.
/// @brief Default circles ratio.
/// @details Ratio used for switching between rounded-corner collisions and closest-face
/// biased normal collisions.
constexpr auto DefaultCirclesRatio = Real(10);
Expand Down
16 changes: 11 additions & 5 deletions Library/include/playrho/ShapeID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@
namespace playrho {

/// @brief Shape identifier.
/// @details A strongly typed identifier for uniquely identifying shapes within @c d2::World
/// instances. This is based on the @c ShapeCounter type as its underlying type.
/// @see ShapeCounter, BodyID, ContactID, JointID, d2::Shape, d2::World.
using ShapeID = detail::IndexingNamedType<ShapeCounter, struct ShapeIdentifier>;

/// @brief Invalid fixture ID value.
constexpr auto InvalidShapeID = static_cast<ShapeID>(static_cast<ShapeID::underlying_type>(-1));
/// @brief Invalid shape ID value.
/// @details A special, reserved value of a @c ShapeID that represents/identifies an _invalid_ shape.
/// @see ShapeID, IsValid.
constexpr auto InvalidShapeID = ShapeID{static_cast<ShapeID::underlying_type>(-1)};

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const ShapeID& value) noexcept
/// @brief Determines validity of given value by comparing against <code>InvalidShapeID</code>.
/// @return true if not equal to @c InvalidShapeID , else false.
/// @see ShapeID, InvalidShapeID.
constexpr auto IsValid(const ShapeID& value) noexcept -> bool
{
return value != InvalidShapeID;
}
Expand Down
14 changes: 8 additions & 6 deletions Library/include/playrho/Templates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@

namespace playrho {

/// @brief Determines if the given value is valid.
/// @brief Determines if the given value is valid, using the equality operator.
/// @details Any value for which the comparison of that value with itself is @c true
/// is considered valid by this function, and any value for which this comparison is
/// @c false is said to be not valid. If this seems like an odd algorithm, be aware
/// that this is essentially how floating point @c NaN (not-a-number) works.
/// @see https://en.wikipedia.org/wiki/NaN
template <typename T>
constexpr bool IsValid(const T& value) noexcept
constexpr auto IsValid(const T& value) noexcept -> bool
{
// Note: This is not necessarily a no-op!! But it is a "constexpr".
//
Expand All @@ -52,11 +57,8 @@ constexpr bool IsValid(const T& value) noexcept
return value == value; // NOLINT(misc-redundant-expression)
}

// IsValid template specializations.

/// @brief Determines if the given value is valid.
template <>
constexpr bool IsValid(const std::size_t& value) noexcept
constexpr auto IsValid(std::size_t value) noexcept -> bool
{
return value != static_cast<std::size_t>(-1);
}
Expand Down
2 changes: 1 addition & 1 deletion Library/include/playrho/Vector2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ constexpr auto GetFwdPerpendicular(const Vector2<T>& vector) noexcept -> Vector2

/// @brief Determines whether the given vector contains finite coordinates.
template <typename TYPE>
constexpr bool IsValid(const Vector2<TYPE>& value) noexcept
constexpr auto IsValid(const Vector2<TYPE>& value) noexcept -> bool
{
return IsValid(get<0>(value)) && IsValid(get<1>(value));
}
Expand Down
3 changes: 1 addition & 2 deletions Library/include/playrho/Vector3.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ using Mass3 = Vector3<Mass>;
using InvMass3 = Vector3<InvMass>;

/// @brief Determines whether the given vector contains finite coordinates.
template <>
constexpr bool IsValid(const Vec3& value) noexcept
constexpr auto IsValid(const Vec3& value) noexcept -> bool
{
return IsValid(get<0>(value)) && IsValid(get<1>(value)) && IsValid(get<2>(value));
}
Expand Down
Loading
Loading