PlayRho  1.1.0
An Interactive Real-Time-Oriented C++ Physics Engine & Library
Joint.cpp

This is the googletest based unit testing file for the interfaces to playrho::d2::Joint.

/*
* Copyright (c) 2020 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 "UnitTests.hpp"
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Common/Templates.hpp>
#include <PlayRho/Dynamics/Joints/JointConf.hpp>
#include <PlayRho/Dynamics/Joints/WheelJointConf.hpp>
#include <any>
#include <stdexcept> // for std::invalid_argument
#include <type_traits>
using namespace playrho;
using namespace playrho::d2;
// Macros for testing eligibility of types for construction with or assignment to Joint instances.
#define DEFINE_GETBODYA \
[[maybe_unused]] BodyID GetBodyA(const JointTester&) noexcept \
{ \
return InvalidBodyID; \
}
#define DEFINE_GETBODYB \
[[maybe_unused]] BodyID GetBodyB(const JointTester&) noexcept \
{ \
return InvalidBodyID; \
}
#define DEFINE_GETCOLLIDECONNECTED \
[[maybe_unused]] bool GetCollideConnected(const JointTester&) noexcept \
{ \
return false; \
}
#define DEFINE_SHIFTORIGIN \
[[maybe_unused]] bool ShiftOrigin(JointTester&, Length2) noexcept \
{ \
return false; \
}
#define DEFINE_INITVELOCITY \
[[maybe_unused]] void InitVelocity(JointTester&, std::vector<BodyConstraint>&, \
const StepConf&, const ConstraintSolverConf&) \
{ \
}
#define DEFINE_SOLVEVELOCITY \
[[maybe_unused]] bool SolveVelocity(JointTester&, std::vector<BodyConstraint>&, \
const StepConf&) \
{ \
return true; \
}
#define DEFINE_SOLVEPOSITION \
[[maybe_unused]] bool SolvePosition(const JointTester&, std::vector<BodyConstraint>&, \
const ConstraintSolverConf&) \
{ \
return true; \
}
#define DEFINE_EQUALS \
[[maybe_unused]] bool operator==(const JointTester& lhs, const JointTester& rhs) noexcept \
{ \
return lhs.number == rhs.number; \
}
namespace test {
// Namespace of type eligible for use with Joint.
namespace sans_none {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_none
// Namespace of type ineligible for use with Joint because missing GetBodyA.
namespace sans_getbodya {
namespace {
struct JointTester {
int number = 0;
};
// DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_getbodya
// Namespace of type ineligible for use with Joint because missing GetBodyB.
namespace sans_getbodyb {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
// DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_getbodyb
// Namespace of type ineligible for use with Joint because missing GetCollideConnected.
namespace sans_getcollideconnected {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
// DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_getcollideconnected
// Namespace of type ineligible for use with Joint because missing ShiftOrigin.
namespace sans_shiftorigin {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
// DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_shiftorigin
// Namespace of type ineligible for use with Joint because missing InitVelocity.
namespace sans_initvelocity {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
// DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_initvelocity
// Namespace of type ineligible for use with Joint because missing SolveVelocity.
namespace sans_solvevelocity {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
// DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_solvevelocity
// Namespace of type ineligible for use with Joint because missing SolvePosition.
namespace sans_solveposition {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
// DEFINE_SOLVEPOSITION;
DEFINE_EQUALS;
} // namespace
} // namespace sans_solveposition
// Namespace of type ineligible for use with Joint because missing equals operator.
namespace sans_equals {
namespace {
struct JointTester {
int number = 0;
};
DEFINE_GETBODYA;
DEFINE_GETBODYB;
DEFINE_GETCOLLIDECONNECTED;
DEFINE_SHIFTORIGIN;
DEFINE_INITVELOCITY;
DEFINE_SOLVEVELOCITY;
DEFINE_SOLVEPOSITION;
// DEFINE_EQUALS;
} // namespace
} // namespace sans_equals
// Namespace of type ineligible for use with Joint because missing all required functions.
namespace sans_all {
namespace {
struct JointTester {
int number = 0;
};
} // namespace
} // namespace sans_all
// Compile-time test the different combos defined above...
} // namespace test
TEST(JointBuilder, Construction)
{
}
TEST(JointBuilder, UseBodyA)
{
const auto b = static_cast<BodyID>(2);
EXPECT_NE(JointBuilder<JointConf>{}.bodyA, b);
EXPECT_EQ(JointBuilder<JointConf>{}.UseBodyA(b).bodyA, b);
}
TEST(JointBuilder, UseBodyB)
{
const auto b = static_cast<BodyID>(77);
EXPECT_NE(JointBuilder<JointConf>{}.bodyB, b);
EXPECT_EQ(JointBuilder<JointConf>{}.UseBodyB(b).bodyB, b);
}
TEST(JointBuilder, UseCollideConnected)
{
const auto value = true;
EXPECT_EQ(JointBuilder<JointConf>{}.UseCollideConnected(value).collideConnected, value);
}
TEST(Joint, ByteSize)
{
// Check size at test runtime instead of compile-time via static_assert to avoid stopping
// builds and to report actual size rather than just reporting that expected size is wrong.
switch (sizeof(void*)) {
case 4:
break;
case 8:
EXPECT_EQ(sizeof(Joint), std::size_t(8));
break;
default:
break;
}
}
TEST(Joint, Traits)
{
EXPECT_FALSE(IsIterable<Joint>::value);
EXPECT_FALSE((IsAddable<Joint>::value));
EXPECT_TRUE(std::is_default_constructible<Joint>::value);
EXPECT_TRUE(std::is_nothrow_default_constructible<Joint>::value);
EXPECT_FALSE(std::is_trivially_default_constructible<Joint>::value);
EXPECT_TRUE(std::is_copy_constructible<Joint>::value);
EXPECT_FALSE(std::is_nothrow_copy_constructible<Joint>::value);
EXPECT_FALSE(std::is_trivially_copy_constructible<Joint>::value);
EXPECT_TRUE(std::is_copy_assignable<Joint>::value);
EXPECT_FALSE(std::is_nothrow_copy_assignable<Joint>::value);
EXPECT_FALSE(std::is_trivially_copy_assignable<Joint>::value);
EXPECT_TRUE(std::is_destructible<Joint>::value);
EXPECT_TRUE(std::is_nothrow_destructible<Joint>::value);
EXPECT_FALSE(std::is_trivially_destructible<Joint>::value);
// Double parenthesis needed for proper macro expansion.
EXPECT_TRUE((std::is_constructible<Joint, int>::value));
EXPECT_TRUE((std::is_constructible<Joint, char*>::value));
EXPECT_TRUE((std::is_constructible<Joint, test::sans_none::JointTester>::value));
}
TEST(Joint, DefaultConstructor)
{
const Joint joint;
EXPECT_TRUE(joint == joint);
EXPECT_FALSE(joint != joint);
EXPECT_EQ(GetBodyA(joint), InvalidBodyID);
EXPECT_EQ(GetBodyB(joint), InvalidBodyID);
EXPECT_FALSE(GetCollideConnected(joint));
EXPECT_FALSE(joint.has_value());
}
TEST(Joint, LimitStateToStringFF)
{
const auto equalLimitsString = std::string(ToString(LimitState::e_equalLimits));
const auto inactiveLimitString = std::string(ToString(LimitState::e_inactiveLimit));
const auto upperLimitsString = std::string(ToString(LimitState::e_atUpperLimit));
const auto lowerLimitsString = std::string(ToString(LimitState::e_atLowerLimit));
EXPECT_FALSE(equalLimitsString.empty());
EXPECT_FALSE(inactiveLimitString.empty());
EXPECT_FALSE(upperLimitsString.empty());
EXPECT_FALSE(lowerLimitsString.empty());
std::set<std::string> names;
names.insert(equalLimitsString);
names.insert(inactiveLimitString);
names.insert(upperLimitsString);
names.insert(lowerLimitsString);
EXPECT_EQ(names.size(), decltype(names.size()){4});
}
{
int foo = 5;
std::any test{foo};
std::string roo = "wow";
test = roo;
test = std::any{foo};
{
const auto joint = Joint{};
auto value = static_cast<const int*>(nullptr);
EXPECT_NO_THROW(value = TypeCast<const int>(&joint));
EXPECT_TRUE(value == nullptr);
}
{
auto joint = Joint{};
auto value = static_cast<int*>(nullptr);
EXPECT_NO_THROW(value = TypeCast<int>(&joint));
EXPECT_TRUE(value == nullptr);
}
{
const auto joint = Joint{};
EXPECT_THROW(TypeCast<int>(joint), std::bad_cast);
EXPECT_THROW(TypeCast<const int>(joint), std::bad_cast);
}
{
auto joint = Joint{};
EXPECT_THROW(TypeCast<int>(joint), std::bad_cast);
EXPECT_THROW(TypeCast<const int>(joint), std::bad_cast);
}
{
auto number = 10;
const auto original = test::sans_none::JointTester{number};
EXPECT_EQ(original.number, number);
auto joint = Joint{original};
EXPECT_TRUE(joint.has_value());
EXPECT_THROW(TypeCast<int>(joint), std::bad_cast);
auto value = test::sans_none::JointTester{};
EXPECT_NO_THROW(value = TypeCast<test::sans_none::JointTester>(joint));
EXPECT_EQ(value.number, number);
EXPECT_NO_THROW(TypeCast<test::sans_none::JointTester&>(joint).number = 3);
EXPECT_EQ(TypeCast<const test::sans_none::JointTester&>(joint).number, 3);
EXPECT_NO_THROW(value = TypeCast<test::sans_none::JointTester>(joint));
EXPECT_EQ(value.number, 3);
EXPECT_NO_THROW(TypeCast<test::sans_none::JointTester>(&joint)->number = 4);
EXPECT_EQ(TypeCast<const test::sans_none::JointTester>(joint).number, 4);
EXPECT_TRUE(joint == joint);
EXPECT_FALSE(joint != joint);
EXPECT_EQ(GetBodyA(joint), InvalidBodyID);
EXPECT_EQ(GetBodyB(joint), InvalidBodyID);
EXPECT_FALSE(GetCollideConnected(joint));
}
}
TEST(Joint, ForConstantDataTypeCastIsLikeAnyCast)
{
const auto foo = Joint{test::sans_none::JointTester{1}};
const auto bar = std::any{test::sans_none::JointTester{1}};
EXPECT_TRUE(TypeCast<const test::sans_none::JointTester*>(&foo) == nullptr);
EXPECT_TRUE(std::any_cast<const test::sans_none::JointTester*>(&bar) == nullptr);
EXPECT_TRUE(TypeCast<test::sans_none::JointTester*>(&foo) == nullptr);
EXPECT_TRUE(std::any_cast<test::sans_none::JointTester*>(&bar) == nullptr);
EXPECT_TRUE(TypeCast<const test::sans_none::JointTester>(&foo) != nullptr);
EXPECT_TRUE(std::any_cast<const test::sans_none::JointTester>(&bar) != nullptr);
EXPECT_TRUE(TypeCast<test::sans_none::JointTester>(&foo) != nullptr);
EXPECT_TRUE(std::any_cast<test::sans_none::JointTester>(&bar) != nullptr);
}
TEST(Joint, ForMutableDataTypeCastIsLikeAnyCast)
{
auto foo = Joint{test::sans_none::JointTester{1}};
auto bar = std::any{test::sans_none::JointTester{1}};
EXPECT_TRUE(TypeCast<const test::sans_none::JointTester*>(&foo) == nullptr);
EXPECT_TRUE(std::any_cast<const test::sans_none::JointTester*>(&bar) == nullptr);
EXPECT_TRUE(TypeCast<test::sans_none::JointTester*>(&foo) == nullptr);
EXPECT_TRUE(std::any_cast<test::sans_none::JointTester*>(&bar) == nullptr);
EXPECT_TRUE(TypeCast<const test::sans_none::JointTester>(&foo) != nullptr);
EXPECT_TRUE(std::any_cast<const test::sans_none::JointTester>(&bar) != nullptr);
EXPECT_TRUE(TypeCast<test::sans_none::JointTester>(&foo) != nullptr);
EXPECT_TRUE(std::any_cast<test::sans_none::JointTester>(&bar) != nullptr);
}
{
auto result = Momentum2{};
EXPECT_NO_THROW(result = GetLinearReaction(Joint{}));
EXPECT_EQ(result, Momentum2());
}
{
auto result = AngularMomentum{};
EXPECT_NO_THROW(result = GetAngularReaction(Joint{}));
EXPECT_EQ(result, AngularMomentum());
}
TEST(Joint, SetMotorSpeedThrows)
{
auto joint = Joint{};
EXPECT_THROW(SetMotorSpeed(joint, 1_rpm), std::invalid_argument);
}
TEST(Joint, SetMaxMotorForceThrows)
{
auto joint = Joint{};
EXPECT_THROW(SetMaxMotorForce(joint, 2_N), std::invalid_argument);
}
TEST(Joint, SetMaxMotorTorqueThrows)
{
auto joint = Joint{};
EXPECT_THROW(SetMaxMotorTorque(joint, 2_Nm), std::invalid_argument);
}
TEST(Joint, SetLinearLimitsThrows)
{
auto joint = Joint{};
EXPECT_THROW(SetLinearLimits(joint, 2_m, 4_m), std::invalid_argument);
}
TEST(Joint, SetAngularLimitsThrows)
{
auto joint = Joint{};
EXPECT_THROW(SetAngularLimits(joint, 2_deg, 4_deg), std::invalid_argument);
}
TEST(Joint, IsLimitEnabledThrows)
{
EXPECT_THROW(IsLimitEnabled(Joint{}), std::invalid_argument);
}
TEST(Joint, EnableLimitThrows)
{
auto joint = Joint{};
EXPECT_THROW(EnableLimit(joint, true), std::invalid_argument);
EXPECT_THROW(EnableLimit(joint, false), std::invalid_argument);
}
TEST(Joint, IsMotorEnabledThrows)
{
auto joint = Joint{};
EXPECT_THROW(IsMotorEnabled(joint), std::invalid_argument);
}
TEST(Joint, EnableMotorThrows)
{
auto joint = Joint{};
EXPECT_THROW(EnableMotor(joint, true), std::invalid_argument);
EXPECT_THROW(EnableMotor(joint, false), std::invalid_argument);
}
TEST(Joint, GetLimitStateThrows)
{
auto joint = Joint{};
EXPECT_THROW(GetLimitState(joint), std::invalid_argument);
}
TEST(Joint, EqualsOperator)
{
const auto j0 = Joint(WheelJointConf());
EXPECT_TRUE(j0 == j0);
{
auto conf = WheelJointConf{};
conf.localAnchorA = Length2{1.2_m, -3_m};
const auto j1 = Joint(conf);
EXPECT_TRUE(j1 == j1);
EXPECT_FALSE(j0 == j1);
}
{
auto conf = WheelJointConf{};
conf.localAnchorB = Length2{1.2_m, -3_m};
const auto j1 = Joint(conf);
EXPECT_TRUE(j1 == j1);
EXPECT_FALSE(j0 == j1);
}
{
auto conf = WheelJointConf{};
conf.motorSpeed = 0.12_rpm;
const auto j1 = Joint(conf);
EXPECT_TRUE(j1 == j1);
EXPECT_FALSE(j0 == j1);
}
// TODO: test remaining fields.
}
TEST(Joint, NotEqualsOperator)
{
const auto j0 = Joint(WheelJointConf());
EXPECT_FALSE(j0 != j0);
{
auto conf = WheelJointConf{};
conf.frequency = 13_Hz;
const auto j1 = Joint(conf);
EXPECT_FALSE(j1 != j1);
EXPECT_TRUE(j0 != j1);
}
// TODO: test remaining fields.
}
playrho::d2::JointBuilder::UseBodyA
constexpr reference UseBodyA(BodyID b) noexcept
Use value for body A setting.
Definition: JointConf.hpp:80
playrho::d2
Name space for 2-dimensionally related PlayRho names.
Definition: AABB.cpp:34
playrho::d2::JointConf::bodyA
BodyID bodyA
1st attached body.
Definition: JointConf.hpp:36
playrho::d2::JointBuilder::UseCollideConnected
constexpr reference UseCollideConnected(bool v) noexcept
Use value for collide connected setting.
Definition: JointConf.hpp:94
playrho::d2::IsLimitEnabled
bool IsLimitEnabled(const Joint &object)
Gets the specified joint's limit property if it supports one.
Definition: Joint.cpp:534
playrho
Name space for all PlayRho related names.
Definition: AABB.cpp:33
playrho::d2::SetMaxMotorTorque
void SetMaxMotorTorque(Joint &object, Torque value)
Sets the given joint's max motor torque if its type supports that.
Definition: Joint.cpp:363
playrho::d2::EnableMotor
void EnableMotor(Joint &object, bool value)
Enables the specified joint's motor property if it supports one.
Definition: Joint.cpp:575
playrho::Momentum2
Vector2< Momentum > Momentum2
2-element vector of Momentum quantities.
Definition: Vector2.hpp:65
playrho::d2::GetBodyB
BodyID GetBodyB(const Contact &contact) noexcept
Gets the body B ID of the given contact.
Definition: Contact.hpp:588
playrho::d2::SetMaxMotorForce
void SetMaxMotorForce(Joint &object, Force value)
Sets the given joint's max motor force if its type supports that.
Definition: Joint.cpp:341
playrho::d2::GetCollideConnected
bool GetCollideConnected(const Joint &object) noexcept
Gets collide connected.
Definition: Joint.hpp:293
playrho::d2::GetBodyA
BodyID GetBodyA(const Contact &contact) noexcept
Gets the body A ID of the given contact.
Definition: Contact.hpp:581
playrho::d2::GetLimitState
LimitState GetLimitState(const Joint &object)
Definition: Joint.cpp:631
playrho::d2::IsMotorEnabled
bool IsMotorEnabled(const Joint &object)
Gets the specified joint's motor property value if it supports one.
Definition: Joint.cpp:560
playrho::d2::Joint::has_value
bool has_value() const noexcept
Checks whether this instance contains a value.
Definition: Joint.hpp:256
playrho::d2::WheelJointConf::localAnchorB
Length2 localAnchorB
The local anchor point relative to body B's origin.
Definition: WheelJointConf.hpp:106
playrho::d2::SetLinearLimits
void SetLinearLimits(Joint &object, Length lower, Length upper)
Sets the joint limits.
Definition: Joint.cpp:496
playrho::d2::IsValidJointType
An "is valid joint type" trait.
Definition: Joint.hpp:481
playrho::d2::TypeCast
std::add_pointer_t< std::add_const_t< T > > TypeCast(const Shape *value) noexcept
Converts the given shape into its current configuration value.
Definition: Shape.hpp:610
playrho::IsAddable
Template for determining if the given types are addable.
Definition: Templates.hpp:189
playrho::d2::WheelJointConf
Wheel joint definition.
Definition: WheelJointConf.hpp:55
playrho::InvalidBodyID
constexpr auto InvalidBodyID
Invalid body ID value.
Definition: BodyID.hpp:33
playrho::AngularMomentum
PLAYRHO_QUANTITY(boost::units::si::angular_momentum) AngularMomentum
Angular momentum quantity.
Definition: Units.hpp:304
playrho::d2::SetAngularLimits
void SetAngularLimits(Joint &object, Angle lower, Angle upper)
Sets the joint limits.
Definition: Joint.cpp:524
playrho::d2::GetAngularReaction
constexpr AngularMomentum GetAngularReaction(const DistanceJointConf &) noexcept
Gets the current angular reaction for the given configuration.
Definition: DistanceJointConf.hpp:170
playrho::d2::ToString
const char * ToString(LimitState val) noexcept
Provides a human readable C-style string uniquely identifying the given limit state.
Definition: LimitState.cpp:29
playrho::d2::WheelJointConf::localAnchorA
Length2 localAnchorA
The local anchor point relative to body A's origin.
Definition: WheelJointConf.hpp:103
playrho::d2::SetMotorSpeed
void SetMotorSpeed(Joint &object, AngularVelocity value)
Sets the given joint's motor speed if its type supports that.
Definition: Joint.cpp:269
playrho::Vector
Vector.
Definition: Vector.hpp:49
playrho::IsIterable
typename detail::IsIterableImpl< T > IsIterable
Determines whether the given type is an iterable type.
Definition: Templates.hpp:225
playrho::d2::JointBuilder
Joint builder definition structure.
Definition: JointConf.hpp:72
playrho::d2::GetLinearReaction
constexpr Momentum2 GetLinearReaction(const DistanceJointConf &object) noexcept
Gets the current linear reaction for the given configuration.
Definition: DistanceJointConf.hpp:163
playrho::d2::WheelJointConf::motorSpeed
AngularVelocity motorSpeed
The desired angular motor speed.
Definition: WheelJointConf.hpp:121
playrho::detail::IndexingNamedType< BodyCounter, struct BodyIdentifier >
playrho::d2::JointBuilder::UseBodyB
constexpr reference UseBodyB(BodyID b) noexcept
Use value for body B setting.
Definition: JointConf.hpp:87
playrho::d2::Joint
A joint-like constraint on one or more bodies.
Definition: Joint.hpp:144
playrho::d2::JointConf::bodyB
BodyID bodyB
2nd attached body.
Definition: JointConf.hpp:39
playrho::d2::WheelJointConf::frequency
NonNegative< Frequency > frequency
Suspension frequency, zero indicates no suspension.
Definition: WheelJointConf.hpp:124
playrho::d2::JointConf::collideConnected
bool collideConnected
Collide connected.
Definition: JointConf.hpp:43
playrho::d2::EnableLimit
void EnableLimit(Joint &object, bool value)
Enables the specified joint's limit property if it supports one.
Definition: Joint.cpp:546
playrho::d2::LimitState::e_inactiveLimit
@ e_inactiveLimit
Inactive limit.