From d52d50e61b6cf8661add7f815cc205e5edcdf467 Mon Sep 17 00:00:00 2001 From: Louis Langholtz Date: Sat, 30 Mar 2024 19:47:21 -0600 Subject: [PATCH 1/3] Updates Doxygen comments --- Library/include/playrho/BodyID.hpp | 18 +++-- Library/include/playrho/ContactID.hpp | 18 +++-- Library/include/playrho/JointID.hpp | 18 +++-- Library/include/playrho/Settings.hpp | 28 ++++---- Library/include/playrho/Settings.hpp.in | 92 ++++++++++++++++--------- Library/include/playrho/ShapeID.hpp | 18 +++-- Library/include/playrho/d2/Body.hpp | 77 +++++++++++++++------ Library/include/playrho/d2/Sweep.hpp | 18 ++++- Library/source/playrho/d2/Body.cpp | 3 + 9 files changed, 195 insertions(+), 95 deletions(-) diff --git a/Library/include/playrho/BodyID.hpp b/Library/include/playrho/BodyID.hpp index 7ad3606a22..735402e8be 100644 --- a/Library/include/playrho/BodyID.hpp +++ b/Library/include/playrho/BodyID.hpp @@ -34,18 +34,24 @@ namespace playrho { /// @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. +/// @details A strongly typed identifier for uniquely identifying bodes within +/// @c playrho::d2::World instances. +/// This is based on the @c playrho::BodyCounter type as its underlying type. +/// These identifiers can be compared with other body identifiers. +/// Two body identifiers from the same world that compare equal for example, +/// identify the same body within that world. +/// @see InvalidBodyID, BodyCounter, ContactID, JointID, ShapeID, d2::Body, d2::World. using BodyID = detail::IndexingNamedType; /// @brief Invalid body ID value. -/// @details A special, reserved value of a @c BodyID that represents/identifies an _invalid_ body. +/// @details A special, reserved value of a @c playrho::BodyID that +/// represents/identifies an _invalid_ body. /// @see BodyID, IsValid. constexpr auto InvalidBodyID = BodyID{static_cast(-1)}; -/// @brief Determines validity of given value by comparing against InvalidBodyID. -/// @return true if not equal to @c InvalidBodyID , else false. +/// @brief Determines validity of given value by comparing against +/// @c playrho::InvalidBodyID . +/// @return true if not equal to @c playrho::InvalidBodyID , else false. /// @see BodyID, InvalidBodyID. constexpr auto IsValid(const BodyID& value) noexcept -> bool { diff --git a/Library/include/playrho/ContactID.hpp b/Library/include/playrho/ContactID.hpp index e767632cd6..2dbe33fc4f 100644 --- a/Library/include/playrho/ContactID.hpp +++ b/Library/include/playrho/ContactID.hpp @@ -35,18 +35,24 @@ namespace playrho { /// @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. +/// @details A strongly typed identifier for uniquely identifying contacts within +/// @c playrho::d2::World instances. +/// This is based on the @c playrho::ContactCounter type as its underlying type. +/// These identifiers can be compared with other contact identifiers. +/// Two contact identifiers from the same world that compare equal for example, +/// identify the same contact within that world. +/// @see InvalidContactID, Contact, ContactCounter, BodyID, JointID, ShapeID, d2::World. using ContactID = detail::IndexingNamedType; /// @brief Invalid contact ID value. -/// @details A special, reserved value of a @c ContactID that represents/identifies an _invalid_ contact. +/// @details A special, reserved value of a @c playrho::ContactID that +/// represents/identifies an _invalid_ contact. /// @see ContactID, IsValid. constexpr auto InvalidContactID = ContactID{static_cast(-1)}; -/// @brief Determines validity of given value by comparing against InvalidContactID. -/// @return true if not equal to @c InvalidContactID , else false. +/// @brief Determines validity of given value by comparing against +/// @c playrho::InvalidContactID . +/// @return true if not equal to @c playrho::InvalidContactID , else false. /// @see ContactID, InvalidContactID. constexpr auto IsValid(const ContactID& value) noexcept -> bool { diff --git a/Library/include/playrho/JointID.hpp b/Library/include/playrho/JointID.hpp index 59935be6d6..0ce48c02b0 100644 --- a/Library/include/playrho/JointID.hpp +++ b/Library/include/playrho/JointID.hpp @@ -34,18 +34,24 @@ 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. +/// @details A strongly typed identifier for uniquely identifying joints within +/// @c playrho::d2::World instances. +/// This is based on the @c playrho::JointCounter type as its underlying type. +/// These identifiers can be compared with other joint identifiers. +/// Two joint identifiers from the same world that compare equal for example, +/// identify the same joint within that world. +/// @see InvalidJointID, JointCounter, BodyID, ContactID, ShapeID, d2::Joint, d2::World. using JointID = detail::IndexingNamedType; /// @brief Invalid joint ID value. -/// @details A special, reserved value of a @c JointID that represents/identifies an _invalid_ joint. +/// @details A special, reserved value of a @c playrho::JointID that +/// represents/identifies an _invalid_ joint. /// @see JointID, IsValid. constexpr auto InvalidJointID = JointID{static_cast(-1)}; -/// @brief Determines validity of given value by comparing against InvalidJointID. -/// @return true if not equal to @c InvalidJointID , else false. +/// @brief Determines validity of given value by comparing against +/// @c playrho::InvalidJointID . +/// @return true if not equal to @c playrho::InvalidJointID , else false. /// @see JointID, InvalidJointID. constexpr auto IsValid(const JointID& value) noexcept -> bool { diff --git a/Library/include/playrho/Settings.hpp b/Library/include/playrho/Settings.hpp index 1e154920a0..f52fba0c20 100644 --- a/Library/include/playrho/Settings.hpp +++ b/Library/include/playrho/Settings.hpp @@ -175,29 +175,26 @@ constexpr auto DefaultRegMinMomentum = Momentum{0_Ns / 100}; constexpr auto DefaultToiMinMomentum = Momentum{0_Ns / 100}; /// @brief Maximum number of bodies in a world. -/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one value for -/// the _invalid_ body identifier (@c InvalidBodyID). +/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one +/// value for the _invalid_ body identifier (@c playrho::InvalidBodyID ). /// @see BodyCounter, BodyID, InvalidBodyID, MaxContacts, MaxJoints, MaxShapes. constexpr auto MaxBodies = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Count type for bodies. -/// @note This type must always be able to contain the @c MaxBodies value. +/// @note This type must always be able to contain the @c playrho::MaxBodies value. /// @see MaxBodies, ContactCounter, JointCounter, ShapeCounter. using BodyCounter = std::remove_const_t; /// @brief Count type for contacts. -/// @note This type is meant to contain up to the square of the maximum value of a BodyCounter without possibility of overflow. +/// @note This type is meant to contain up to the square of the maximum value of a +/// @c playrho::BodyCounter without possibility of overflow. /// @see MaxContacts, BodyCounter, JointCounter, ShapeCounter. using ContactCounter = WiderType; -/// @brief Invalid contact index. -/// @see ContactCounter. -constexpr auto InvalidContactIndex = static_cast(-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 -/// MaxBodies nodes. +/// @details Uses the formula for the maximum number of edges in an unidirectional graph +/// of @c playrho::MaxBodies 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}; @@ -206,25 +203,26 @@ constexpr auto MaxContacts = ContactCounter{MaxBodies} * ContactCounter{MaxBodie using DynamicTreeSize = ContactCounter; /// @brief Maximum number of joints in a world. -/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one value for -/// the invalid joint identifier (@c InvalidJointID). +/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one +/// value for the invalid joint identifier (@c playrho::InvalidJointID ). /// @see JointCounter, JointID. InvalidJointID, MaxBodies, MaxContacts. MaxShapes. constexpr auto MaxJoints = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Counter type for joints. -/// @note This type must be able to contain the @c MaxJoints value. +/// @note This type must be able to contain the @c playrho::MaxJoints value. /// @see MaxJoints, BodyCounter, ContactCounter, ShapeCounter. using JointCounter = std::remove_const_t; /// @brief Maximum number of shapes in a world. -/// @note This is 65534 based off std::uint16_t and eliminating one value for invalid. +/// @note This is 65534 based off std::uint16_t and eliminating one value for +/// the invalid shape identifier (@c playrho::InvalidShapeID ). /// @see ShapeCounter, ShapeID, InvalidShapeID, MaxBodies, MaxContacts, MaxJoints. constexpr auto MaxShapes = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Count type for shapes. -/// @note This type must always be able to contain the MaxShapes value. +/// @note This type must always be able to contain the @c playrho::MaxShapes value. /// @see MaxShapes, BodyCounter, ContactCounter, JointCounter. using ShapeCounter = std::remove_const_t; diff --git a/Library/include/playrho/Settings.hpp.in b/Library/include/playrho/Settings.hpp.in index 7d90cf6ed5..f13415e4b6 100644 --- a/Library/include/playrho/Settings.hpp.in +++ b/Library/include/playrho/Settings.hpp.in @@ -30,19 +30,19 @@ #ifndef PLAYRHO_SETTINGS_HPP #define PLAYRHO_SETTINGS_HPP -#include -#include -#include -#include -#include -#include +#include // for std::uint8_t #include // for std::numeric_limits +#include // for std::remove_const_t +// IWYU pragma: begin_exports + +#include #include -#include #include #include +// IWYU pragma: end_exports + namespace playrho { /// @brief Maximum number of supportable edges in a simplex. @@ -57,7 +57,7 @@ constexpr auto MaxChildCount = std::numeric_limits::max() >> 6; /// @note This type must always be able to contain the MaxChildCount value. using ChildCounter = std::remove_const_t; -/// Time step iterations type. +/// @brief Time step iterations type. /// @details A type for counting iterations per time-step. using TimestepIters = std::uint8_t; @@ -66,23 +66,27 @@ constexpr auto MaxFloat = std::numeric_limits::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 ContactFeature::Index type. +/// @see MaxShapeVertices, InvalidVertex. using VertexCounter = std::remove_const_t; /// @brief Invalid vertex index. +/// @details This is a special, reserved value for indicating/identifying an invalid vertex. +/// @see VertexCounter. constexpr auto InvalidVertex = static_cast(-1); /// @brief Default linear slop. @@ -92,15 +96,18 @@ constexpr auto InvalidVertex = static_cast(-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 = @PLAYRHO_REAL_LINEARSLOP@; /// @brief Default minimum vertex radius. /// @note Recommend using 0.01_m or DefaultLinearSlop * Real(2). +/// @see DefaultMaxVertexRadius, DefaultLinearSlop. constexpr auto DefaultMinVertexRadius = @PLAYRHO_REAL_MINVERTEXRADIUS@; /// @brief Default maximum vertex radius. /// @note Recommend using 255_m or DefaultLinearSlop * 2 * 25500. +/// @see DefaultMinVertexRadius, DefaultLinearSlop. constexpr auto DefaultMaxVertexRadius = @PLAYRHO_REAL_MAXVERTEXRADIUS@; /// @brief Default AABB extension amount. @@ -113,37 +120,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 @@ -157,75 +168,90 @@ 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 std::uint16_t and eliminating one value for invalid. +/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one +/// value for the _invalid_ body identifier (@c playrho::InvalidBodyID ). +/// @see BodyCounter, BodyID, InvalidBodyID, MaxContacts, MaxJoints, MaxShapes. constexpr auto MaxBodies = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Count type for bodies. -/// @note This type must always be able to contain the MaxBodies value. +/// @note This type must always be able to contain the @c playrho::MaxBodies value. +/// @see MaxBodies, ContactCounter, JointCounter, ShapeCounter. using BodyCounter = std::remove_const_t; /// @brief Count type for contacts. -/// @note This type must be able to contain the squared value of BodyCounter. +/// @note This type is meant to contain up to the square of the maximum value of a +/// @c playrho::BodyCounter without possibility of overflow. +/// @see MaxContacts, BodyCounter, JointCounter, ShapeCounter. using ContactCounter = WiderType; -/// @brief Invalid contact index. -constexpr auto InvalidContactIndex = static_cast(-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 -/// MaxBodies nodes. +/// @details Uses the formula for the maximum number of edges in an unidirectional graph +/// of @c playrho::MaxBodies 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 std::uint16_t and eliminating one value for invalid. +/// @note This is 2^16 - 2, i.e. 65534, based off std::uint16_t and eliminating one +/// value for the invalid joint identifier (@c playrho::InvalidJointID ). +/// @see JointCounter, JointID. InvalidJointID, MaxBodies, MaxContacts. MaxShapes. constexpr auto MaxJoints = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Counter type for joints. -/// @note This type must be able to contain the MaxJoints value. +/// @note This type must be able to contain the @c playrho::MaxJoints value. +/// @see MaxJoints, BodyCounter, ContactCounter, ShapeCounter. using JointCounter = std::remove_const_t; /// @brief Maximum number of shapes in a world. -/// @note This is 65534 based off std::uint16_t and eliminating one value for invalid. +/// @note This is 65534 based off std::uint16_t and eliminating one value for +/// the invalid shape identifier (@c playrho::InvalidShapeID ). +/// @see ShapeCounter, ShapeID, InvalidShapeID, MaxBodies, MaxContacts, MaxJoints. constexpr auto MaxShapes = static_cast(std::numeric_limits::max() - std::uint16_t{1}); /// @brief Count type for shapes. -/// @note This type must always be able to contain the MaxShapes value. +/// @note This type must always be able to contain the @c playrho::MaxShapes value. +/// @see MaxShapes, BodyCounter, ContactCounter, JointCounter. using ShapeCounter = std::remove_const_t; /// @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); diff --git a/Library/include/playrho/ShapeID.hpp b/Library/include/playrho/ShapeID.hpp index e55d4679e8..dc8adc4fcf 100644 --- a/Library/include/playrho/ShapeID.hpp +++ b/Library/include/playrho/ShapeID.hpp @@ -34,18 +34,24 @@ 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. +/// @details A strongly typed identifier for uniquely identifying shapes within +/// @c playrho::d2::World instances. +/// This is based on the @c playrho::ShapeCounter type as its underlying type. +/// These identifiers can be compared with other shape identifiers. +/// Two shape identifiers from the same world that compare equal for example, +/// identify the same shape within that world. +/// @see InvalidShapeID, ShapeCounter, BodyID, ContactID, JointID, d2::Shape, d2::World. using ShapeID = detail::IndexingNamedType; /// @brief Invalid shape ID value. -/// @details A special, reserved value of a @c ShapeID that represents/identifies an _invalid_ shape. +/// @details A special, reserved value of a @c playrho::ShapeID that +/// represents/identifies an _invalid_ shape. /// @see ShapeID, IsValid. constexpr auto InvalidShapeID = ShapeID{static_cast(-1)}; -/// @brief Determines validity of given value by comparing against InvalidShapeID. -/// @return true if not equal to @c InvalidShapeID , else false. +/// @brief Determines validity of given value by comparing against +/// @c playrho::InvalidShapeID . +/// @return true if not equal to @c playrho::InvalidShapeID , else false. /// @see ShapeID, InvalidShapeID. constexpr auto IsValid(const ShapeID& value) noexcept -> bool { diff --git a/Library/include/playrho/d2/Body.hpp b/Library/include/playrho/d2/Body.hpp index 76a86992e4..ebce53897a 100644 --- a/Library/include/playrho/d2/Body.hpp +++ b/Library/include/playrho/d2/Body.hpp @@ -89,14 +89,12 @@ class Body /// @brief Initializing constructor. /// @note To create a body within a world, use World::CreateBody. /// @param bd Configuration data for the body to construct. - /// @post GetFlags() will return the value of - /// GetFlags(const BodyConf&) given by @a bd. /// @post GetLinearDamping() returns value of @a bd.linearDamping. /// @post GetAngularDamping() returns value of @a bd.angularDamping. /// @post GetInvMass() returns Real(0)/Kilogram if /// bd.type != BodyType::Dynamic, otherwise it returns value of /// @a bd.invMass. - /// @post GetInvRotI() returns InvRotInertia{} if + /// @post GetInvRotInertia() returns InvRotInertia{} if /// bd.type != BodyType::Dynamic, otherwise it returns value of /// @a bd.invRotI. /// @post GetVelocity() will return the value as if @@ -105,8 +103,7 @@ class Body /// @post GetAcceleration() will return the value as if /// SetAcceleration(LinearAcceleration2, AngularAcceleration) had been /// called with values of @a bd.linearAcceleration and @a bd.angularAcceleration. - /// @see GetFlags(const BodyConf&). - /// @see GetFlags, GetLinearDamping, GetAngularDamping, GetInvMass, GetTransformation, + /// @see GetLinearDamping, GetAngularDamping, GetInvMass, GetTransformation, /// GetVelocity, GetAcceleration. /// @see World::CreateBody. explicit Body(const BodyConf& bd = GetDefaultBodyConf()); @@ -121,11 +118,13 @@ class Body /// 4. Damping of the body. /// 5. Restitutioen and friction values of body's shape parts when experiencing /// collisions. + /// /// @return the world transform of the body's origin. /// @see SetSweep. const Transformation& GetTransformation() const noexcept; /// @brief Gets the body's sweep. + /// @return The sweep used by this body. /// @see SetSweep. const Sweep& GetSweep() const noexcept; @@ -151,14 +150,6 @@ class Body /// @see GetVelocity, IsSpeedable(const Body&). void JustSetVelocity(const Velocity& value) noexcept; - /// @brief Sets the linear and rotational accelerations on this body. - /// @note This has no effect on non-accelerable bodies. - /// @note A non-zero acceleration will also awaken the body. - /// @param linear Linear acceleration. - /// @param angular Angular acceleration. - /// @see GetLinearAcceleration, GetAngularAcceleration. - void SetAcceleration(const LinearAcceleration2& linear, AngularAcceleration angular) noexcept; - /// @brief Gets this body's linear acceleration. /// @see SetAcceleration. LinearAcceleration2 GetLinearAcceleration() const noexcept; @@ -167,6 +158,20 @@ class Body /// @see SetAcceleration. AngularAcceleration GetAngularAcceleration() const noexcept; + /// @brief Sets the linear and rotational accelerations on this body. + /// @note This has no effect on non-accelerable bodies. + /// @note A non-zero acceleration will also awaken the body. + /// @param linear Linear acceleration. + /// @param angular Angular acceleration. + /// @pre @p linear and @p angular are both valid. I.e. + /// IsValid(linear) && IsValid(angular). + /// @post GetLinearAcceleration() returns @p linear . + /// @post GetAngularAcceleration() returns @p angular . + /// @post IsAwake() is true and GetUnderActiveTime() returns + /// zero if either of the new accelerations are higher, or the new linear acceleration + /// is in a new direction, or the sign of the new angular acceleration is different. + void SetAcceleration(const LinearAcceleration2& linear, AngularAcceleration angular) noexcept; + /// @brief Gets the inverse total mass of the body. /// @details This is the cached result of dividing 1 by the body's mass or zero for non /// linearly-accelerable bodies. @@ -188,6 +193,8 @@ class Body NonNegativeFF GetInvRotInertia() const noexcept; /// @brief Sets the inverse mass data and clears the mass-data-dirty flag. + /// @post GetInvMass() returns the set inverse mass. + /// @post GetInvRotInertia() returns the set inverse rotational inertia. /// @post IsMassDataDirty() returns false. /// @see GetInvMass, GetInvRotInertia, IsMassDataDirty. void SetInvMassData(NonNegative invMass, NonNegative invRotI) noexcept; @@ -197,7 +204,8 @@ class Body NonNegative GetLinearDamping() const noexcept; /// @brief Sets the linear damping of the body. - /// @see GetLinearDamping. + /// @post GetLinearDamping() returns the value set. + /// @see GetLinearDamping(). void SetLinearDamping(NonNegative linearDamping) noexcept; /// @brief Gets the angular damping of the body. @@ -205,6 +213,7 @@ class Body NonNegative GetAngularDamping() const noexcept; /// @brief Sets the angular damping of the body. + /// @post GetAngularDamping() returns the value set. /// @see GetAngularDamping. void SetAngularDamping(NonNegative angularDamping) noexcept; @@ -218,19 +227,27 @@ class Body /// @post GetUnderActiveTime() returns 0. /// @post IsAwake(const Body&) returns true for BodyType::Dynamic or /// BodyType::Kinematic, and returns false for BodyType::Static. - /// @see GetType. + /// @see GetType, GetFlags. void SetType(BodyType value) noexcept; /// @brief Whether or not this was destroyed. + /// @details If you have gotten this body's value from a world, this function says + /// whether the world considers the body destroyed or not. /// @see SetDestroyed, UnsetDestroyed. constexpr bool IsDestroyed() const noexcept; /// @brief Sets the destroyed property. - /// @note This is only meaningfully used by the world implementation. + /// @note This is only meaningfully used by the world implementation. While calling this + /// in your code will have the stated post condition, it won't effect any bodies within + /// a world. + /// @post IsDestroyed() returns true. constexpr void SetDestroyed() noexcept; /// @brief Unsets the destroyed property. - /// @note This is only meaningfully used by the world implementation. + /// @note This is only meaningfully used by the world implementation. While calling this + /// in your code will have the stated post condition, it won't effect any bodies within + /// a world. + /// @post IsDestroyed() returns false. constexpr void UnsetDestroyed() noexcept; /// @brief Is "speedable". @@ -319,6 +336,7 @@ class Body /// @brief Sets this body to have fixed rotation. /// @note This causes the mass to be reset. + /// @post IsFixedRotation() returns the value set. /// @see IsFixedRotation. void SetFixedRotation(bool flag); @@ -342,31 +360,46 @@ class Body bool IsEnabled() const noexcept; /// @brief Sets the enabled state. + /// @post IsEnabled() returns true. /// @see IsEnabled(const Body&). void SetEnabled() noexcept; /// @brief Unsets the enabled flag. + /// @post IsEnabled() returns false. /// @see IsEnabled. void UnsetEnabled() noexcept; - /// @brief Sets the sweep value of the given body. - /// @see GetSweep. + /// @brief Sets the body's sweep value. + /// @note This may also change the body's transformation. + /// @pre The body is speedable or the new sweep's position 0 and 1 are equal to each other. + /// @post GetSweep() returns the value set. + /// @post GetTransformation() returns GetTransform1(value). + /// @see GetSweep, GetTransformation, IsSpeedable. void SetSweep(const Sweep& value) noexcept; /// @brief Sets the "position 0" value of the body to the given position. + /// @pre The body is speedable or the new position is equal to the existing position 0. + /// @post GetSweep().pos0 is the value set. /// @see GetSweep, SetSweep. void SetPosition0(const Position& value) noexcept; /// @brief Sets the body sweep's "position 1" value. - /// @see GetSweep, SetSweep. + /// @pre The body is speedable or the new position is equal to the existing position 1. + /// @post GetSweep().pos1 is the value set. + /// @post GetTransformation() returns GetTransform1(GetSweep()) + /// of the new sweep. + /// @see GetSweep, SetSweep, GetTransformation. void SetPosition1(const Position& value) noexcept; /// @brief Resets the given body's "alpha-0" value. + /// @post GetSweep().alpha0 is zero. /// @see GetSweep. void ResetAlpha0() noexcept; - /// @brief Calls the body sweep's Advance0 function to advance to - /// the given value. + /// @brief Advances the body sweep's position 0 and alpha 0 values. + /// @pre The body is speedable or body's sweep positions 0 and 1 are the same. + /// @post GetSweep() returns what calling + /// Advance0(GetSweep(), value) would return before this call. /// @see GetSweep. void Advance0(ZeroToUnderOneFF value) noexcept; diff --git a/Library/include/playrho/d2/Sweep.hpp b/Library/include/playrho/d2/Sweep.hpp index 7dc54be990..7a0c6a9222 100644 --- a/Library/include/playrho/d2/Sweep.hpp +++ b/Library/include/playrho/d2/Sweep.hpp @@ -43,9 +43,21 @@ namespace playrho::d2 { struct Sweep { /// @brief Default constructor. + /// @post pos0 is the value of Position{}. + /// @post pos1 is the value of Position{}. + /// @post localCenter is the value of Length2{}. + /// @post alpha0 is zero. constexpr Sweep() = default; /// @brief Initializing constructor. + /// @param p0 Value for position 0. + /// @param p1 Value for position 1. + /// @param lc Local center. + /// @param a0 Alpha 0 for the sweep. + /// @post pos0 is the value of @p p0 . + /// @post pos1 is the value of @p p1 . + /// @post localCenter is the value of @p lc . + /// @post alpha0 is the value of @p a0 . constexpr Sweep(const Position& p0, const Position& p1, const Length2& lc = Length2{0_m, 0_m}, ZeroToUnderOneFF a0 = {}) noexcept : pos0{p0}, pos1{p1}, localCenter{lc}, alpha0{a0} @@ -53,6 +65,10 @@ struct Sweep } /// @brief Initializing constructor. + /// @post pos0 is the value of @p p . + /// @post pos1 is the value of @p p . + /// @post localCenter is the value of @p lc . + /// @post alpha0 is zero. constexpr explicit Sweep(const Position& p, const Length2& lc = Length2{0_m, 0_m}) : Sweep{p, p, lc, ZeroToUnderOneFF{}} { @@ -81,7 +97,7 @@ struct Sweep /// and the sweep's alpha 0. /// @details This advances position 0 (pos0) of the sweep towards position /// 1 (pos1) by a factor of the difference between the given alpha and -/// the alpha 0. +/// the alpha 0. This **does not** change the sweep's position 1. /// @param sweep The sweep to return an advancement of. /// @param alpha Valid new time factor in [0,1) to update the sweep to. Sweep Advance0(const Sweep& sweep, ZeroToUnderOneFF alpha) noexcept; diff --git a/Library/source/playrho/d2/Body.cpp b/Library/source/playrho/d2/Body.cpp index 0e70e6839c..e31b2c1092 100644 --- a/Library/source/playrho/d2/Body.cpp +++ b/Library/source/playrho/d2/Body.cpp @@ -217,6 +217,9 @@ void Body::SetAcceleration(const LinearAcceleration2& linear, AngularAcceleratio } } else { + // If the new linear or angular accelerations are higher, or the linear acceleration + // changes direction, or the sign of the new angular acceleration is different, then + // also set the awake flag and reset the under active time. if ((m_angularAcceleration < angular) || (GetMagnitudeSquared(m_linearAcceleration) < GetMagnitudeSquared(linear)) || (playrho::GetAngle(m_linearAcceleration) != playrho::GetAngle(linear)) || From 700289a86bb89fd729af861cb82fa8984bbe1bfb Mon Sep 17 00:00:00 2001 From: Louis Langholtz Date: Sun, 14 Apr 2024 10:33:24 -0600 Subject: [PATCH 2/3] Moves ClipList code into Manifold.cpp --- .../xcode5/PlayRho.xcodeproj/project.pbxproj | 8 --- Library/CMakeLists.txt | 2 - Library/include/playrho/d2/ClipList.hpp | 65 ----------------- Library/source/playrho/d2/ClipList.cpp | 71 ------------------- Library/source/playrho/d2/Manifold.cpp | 64 ++++++++++++++++- 5 files changed, 63 insertions(+), 147 deletions(-) delete mode 100644 Library/include/playrho/d2/ClipList.hpp delete mode 100644 Library/source/playrho/d2/ClipList.cpp diff --git a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj index 3027762a43..ebeeed786f 100644 --- a/Build/xcode5/PlayRho.xcodeproj/project.pbxproj +++ b/Build/xcode5/PlayRho.xcodeproj/project.pbxproj @@ -412,8 +412,6 @@ 996B7B8D2A6DF25200A8207F /* PoolMemoryResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 996B7B8A2A6DF25200A8207F /* PoolMemoryResource.cpp */; }; 996B7B8F2A6EED6200A8207F /* polymorphic_allocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 996B7B8E2A6EED6200A8207F /* polymorphic_allocator.cpp */; }; 9980D10A29C8ACB700007B35 /* WorldConf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9980D10929C8ACB700007B35 /* WorldConf.cpp */; }; - 998A7C012A801C1C00F29B01 /* ClipList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 998A7BFF2A801C1C00F29B01 /* ClipList.cpp */; }; - 998A7C022A801C1C00F29B01 /* ClipList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 998A7C002A801C1C00F29B01 /* ClipList.hpp */; }; 998A7C052A80404600F29B01 /* StatsResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 998A7C032A80404600F29B01 /* StatsResource.cpp */; }; 998A7C062A80404600F29B01 /* StatsResource.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 998A7C042A80404600F29B01 /* StatsResource.hpp */; }; 998A7C082A814F9300F29B01 /* StatsResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 998A7C072A814F9300F29B01 /* StatsResource.cpp */; }; @@ -920,8 +918,6 @@ 996B7B8A2A6DF25200A8207F /* PoolMemoryResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PoolMemoryResource.cpp; sourceTree = ""; }; 996B7B8E2A6EED6200A8207F /* polymorphic_allocator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = polymorphic_allocator.cpp; sourceTree = ""; }; 9980D10929C8ACB700007B35 /* WorldConf.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WorldConf.cpp; sourceTree = ""; }; - 998A7BFF2A801C1C00F29B01 /* ClipList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClipList.cpp; sourceTree = ""; }; - 998A7C002A801C1C00F29B01 /* ClipList.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ClipList.hpp; sourceTree = ""; }; 998A7C032A80404600F29B01 /* StatsResource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StatsResource.cpp; sourceTree = ""; }; 998A7C042A80404600F29B01 /* StatsResource.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = StatsResource.hpp; sourceTree = ""; }; 998A7C072A814F9300F29B01 /* StatsResource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StatsResource.cpp; sourceTree = ""; }; @@ -1298,7 +1294,6 @@ 470F94A51EC4C79B00AA3C82 /* BodyConf.hpp */, 474BAB2C1E5D00960058E08A /* BodyConstraint.hpp */, 80BB8936141C3E5900F1753A /* ChainShapeConf.hpp */, - 998A7C002A801C1C00F29B01 /* ClipList.hpp */, 476162C71E245C9D002C7FB0 /* CodeDumper.hpp */, 99D1BE242AEF1FFD001BA497 /* ContactImpulsesFunction.hpp */, 47363E8520027FE2005912B1 /* ContactImpulsesList.hpp */, @@ -1384,7 +1379,6 @@ 80BB894D141C3E5900F1753A /* Body.cpp */, 470F9B4B1EEF20B6007EF7B6 /* BodyConf.cpp */, 80BB8935141C3E5900F1753A /* ChainShapeConf.cpp */, - 998A7BFF2A801C1C00F29B01 /* ClipList.cpp */, 476162C61E245C9D002C7FB0 /* CodeDumper.cpp */, 47363E8420027FE2005912B1 /* ContactImpulsesList.cpp */, 80BB8963141C3E5900F1753A /* ContactSolver.cpp */, @@ -1647,7 +1641,6 @@ 4734B2271DC29F7C00F15E29 /* SimplexEdge.hpp in Headers */, 4787D6BB1F2E946E008C115E /* PrismaticJointConf.hpp in Headers */, 47C85D1B1F0D9D8D00F70C56 /* Units.hpp in Headers */, - 998A7C022A801C1C00F29B01 /* ClipList.hpp in Headers */, 99D1BE212AEF18F8001BA497 /* ShapeFunction.hpp in Headers */, 998A7C0C2A82D55100F29B01 /* Contactable.hpp in Headers */, 470F9B181EDF2959007EF7B6 /* Transformation.hpp in Headers */, @@ -2171,7 +2164,6 @@ 47363E8920029DFD005912B1 /* Velocity.cpp in Sources */, 4787D6BA1F2E946E008C115E /* PrismaticJointConf.cpp in Sources */, 4787D6CE1F2EC902008C115E /* MotorJointConf.cpp in Sources */, - 998A7C012A801C1C00F29B01 /* ClipList.cpp in Sources */, 4787D6CA1F2EA3A1008C115E /* GearJointConf.cpp in Sources */, 80BB89BE141C3E5900F1753A /* Contact.cpp in Sources */, 80BB89C0141C3E5900F1753A /* ContactSolver.cpp in Sources */, diff --git a/Library/CMakeLists.txt b/Library/CMakeLists.txt index d0dd71de43..15510c39f4 100644 --- a/Library/CMakeLists.txt +++ b/Library/CMakeLists.txt @@ -207,7 +207,6 @@ set(PLAYRHO_D2_HDRS include/playrho/d2/BodyConf.hpp include/playrho/d2/BodyConstraint.hpp include/playrho/d2/ChainShapeConf.hpp - include/playrho/d2/ClipList.hpp include/playrho/d2/CodeDumper.hpp include/playrho/d2/ContactImpulsesFunction.hpp include/playrho/d2/ContactImpulsesList.hpp @@ -277,7 +276,6 @@ set(PLAYRHO_D2_SRCS source/playrho/d2/Body.cpp source/playrho/d2/BodyConf.cpp source/playrho/d2/ChainShapeConf.cpp - source/playrho/d2/ClipList.cpp source/playrho/d2/CodeDumper.cpp source/playrho/d2/ContactImpulsesList.cpp source/playrho/d2/ContactSolver.cpp diff --git a/Library/include/playrho/d2/ClipList.hpp b/Library/include/playrho/d2/ClipList.hpp deleted file mode 100644 index 762ce6eef2..0000000000 --- a/Library/include/playrho/d2/ClipList.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2023 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef PLAYRHO_D2_CLIPLIST_HPP -#define PLAYRHO_D2_CLIPLIST_HPP - -/// @file -/// @brief Structures and functions used for computing clip lists. - -// IWYU pragma: begin_exports - -#include -#include -#include - -#include - -// IWYU pragma: end_exports - -namespace playrho::d2 { - -/// @brief Clip vertex. -/// @details Used for computing contact manifolds. -struct ClipVertex -{ - Length2 v; ///< Vertex of edge or polygon. - ContactFeature cf; ///< Contact feature information. -}; - -/// @brief Clip list for ClipSegmentToLine. -/// @see ClipSegmentToLine. -using ClipList = ArrayList; - -/// Clipping for contact manifolds. -/// @details This returns an array of points from the given line that are inside of the plane as -/// defined by a given normal and offset. -/// @param vIn Clip list of two points defining the line. -/// @param normal Normal of the plane with which to determine intersection. -/// @param offset Offset of the plane with which to determine intersection. -/// @param indexA Index of vertex A. -/// @return List of zero one or two clip points. -ClipList ClipSegmentToLine(const ClipList& vIn, const UnitVec& normal, Length offset, - ContactFeature::Index indexA); - -} - -#endif /* PLAYRHO_D2_CLIPLIST_HPP */ diff --git a/Library/source/playrho/d2/ClipList.cpp b/Library/source/playrho/d2/ClipList.cpp deleted file mode 100644 index 2ea834ac41..0000000000 --- a/Library/source/playrho/d2/ClipList.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Original work Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * Modified work Copyright (c) 2023 Louis Langholtz https://github.com/louis-langholtz/PlayRho - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include - -#include - -namespace playrho::d2 { - -ClipList ClipSegmentToLine(const ClipList& vIn, const UnitVec& normal, Length offset, - ContactFeature::Index indexA) -{ - ClipList vOut; - - if (size(vIn) == 2) // must have two points (for a segment) - { - // Use Sutherland-Hodgman clipping: - // (https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm ). - - // Calculate the distance of end points to the line - const auto distance0 = Dot(normal, vIn[0].v) - offset; - const auto distance1 = Dot(normal, vIn[1].v) - offset; - - // If the points are behind the plane... - // Ideally they are. Then we get face-vertex contact features which are simpler to - // calculate. Note that it also helps to avoid changing the contact feature from the - // given clip vertices. So the code here also accepts distances that are just slightly - // over zero. - if (distance0 <= 0_m || AlmostZero(StripUnit(distance0))) - { - vOut.push_back(vIn[0]); - } - if (distance1 <= 0_m || AlmostZero(StripUnit(distance1))) - { - vOut.push_back(vIn[1]); - } - - // If we didn't already find two points & the points are on different sides of the plane... - if (size(vOut) < 2 && signbit(StripUnit(distance0)) != signbit(StripUnit(distance1))) - { - // Neither distance0 nor distance1 is 0 and either one or the other is negative (but not both). - // Find intersection point of edge and plane - // Vertex A is hitting edge B. - const auto interp = distance0 / (distance0 - distance1); - const auto vertex = vIn[0].v + (vIn[1].v - vIn[0].v) * interp; - vOut.push_back(ClipVertex{vertex, GetVertexFaceContactFeature(indexA, vIn[0].cf.indexB)}); - } - } - - return vOut; -} - -} diff --git a/Library/source/playrho/d2/Manifold.cpp b/Library/source/playrho/d2/Manifold.cpp index d1012535e0..0287d80704 100644 --- a/Library/source/playrho/d2/Manifold.cpp +++ b/Library/source/playrho/d2/Manifold.cpp @@ -26,7 +26,6 @@ #include #include // for size -#include #include #include #include @@ -39,6 +38,69 @@ namespace playrho::d2 { namespace { +/// @brief Clip vertex. +/// @details Used for computing contact manifolds. +struct ClipVertex +{ + Length2 v; ///< Vertex of edge or polygon. + ContactFeature cf; ///< Contact feature information. +}; + +/// @brief Clip list for ClipSegmentToLine. +/// @see ClipSegmentToLine. +using ClipList = ArrayList; + +/// Clipping for contact manifolds. +/// @details This returns an array of points from the given line that are inside of the plane as +/// defined by a given normal and offset. +/// @param vIn Clip list of two points defining the line. +/// @param normal Normal of the plane with which to determine intersection. +/// @param offset Offset of the plane with which to determine intersection. +/// @param indexA Index of vertex A. +/// @return List of zero one or two clip points. +ClipList ClipSegmentToLine(const ClipList& vIn, const UnitVec& normal, Length offset, + ContactFeature::Index indexA) +{ + ClipList vOut; + + if (size(vIn) == 2) // must have two points (for a segment) + { + // Use Sutherland-Hodgman clipping: + // (https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm ). + + // Calculate the distance of end points to the line + const auto distance0 = Dot(normal, vIn[0].v) - offset; + const auto distance1 = Dot(normal, vIn[1].v) - offset; + + // If the points are behind the plane... + // Ideally they are. Then we get face-vertex contact features which are simpler to + // calculate. Note that it also helps to avoid changing the contact feature from the + // given clip vertices. So the code here also accepts distances that are just slightly + // over zero. + if (distance0 <= 0_m || AlmostZero(StripUnit(distance0))) + { + vOut.push_back(vIn[0]); + } + if (distance1 <= 0_m || AlmostZero(StripUnit(distance1))) + { + vOut.push_back(vIn[1]); + } + + // If we didn't already find two points & the points are on different sides of the plane... + if (size(vOut) < 2 && signbit(StripUnit(distance0)) != signbit(StripUnit(distance1))) + { + // Neither distance0 nor distance1 is 0 and either one or the other is negative (but not both). + // Find intersection point of edge and plane + // Vertex A is hitting edge B. + const auto interp = distance0 / (distance0 - distance1); + const auto vertex = vIn[0].v + (vIn[1].v - vIn[0].v) * interp; + vOut.push_back(ClipVertex{vertex, GetVertexFaceContactFeature(indexA, vIn[0].cf.indexB)}); + } + } + + return vOut; +} + constexpr auto face = ContactFeature::e_face; constexpr auto vertex = ContactFeature::e_vertex; From 85b8f022162971c803e55d7fc7db512eb1b32e8f Mon Sep 17 00:00:00 2001 From: Louis Langholtz Date: Sun, 14 Apr 2024 10:49:11 -0600 Subject: [PATCH 3/3] Narrows scope of PointStates --- Testbed/Framework/Test.cpp | 1 + Testbed/Framework/Test.hpp | 4 ++-- UnitTests/World.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Testbed/Framework/Test.cpp b/Testbed/Framework/Test.cpp index 6bd647487a..d46f08789d 100644 --- a/Testbed/Framework/Test.cpp +++ b/Testbed/Framework/Test.cpp @@ -35,6 +35,7 @@ #include "Test.hpp" #include +#include // for GetPointStates using namespace playrho; using namespace playrho::d2; diff --git a/Testbed/Framework/Test.hpp b/Testbed/Framework/Test.hpp index 33204cdb99..bbaa50fde6 100644 --- a/Testbed/Framework/Test.hpp +++ b/Testbed/Framework/Test.hpp @@ -22,8 +22,8 @@ #ifndef PLAYRHO_TEST_HPP #define PLAYRHO_TEST_HPP -#include #include +#include #include #include #include @@ -31,8 +31,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/UnitTests/World.cpp b/UnitTests/World.cpp index a3ae325ca6..179ca9db71 100644 --- a/UnitTests/World.cpp +++ b/UnitTests/World.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include // for GetPointStates #include #include #include