PlayRho  2.0.0
An interactive physics engine & library.
Body.cpp

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

/*
* 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 "gtest/gtest.h"
using namespace playrho;
using namespace playrho::d2;
TEST(Body, DefaultConstruction)
{
EXPECT_EQ(Body().GetType(), BodyType::Static);
EXPECT_TRUE(Body().IsEnabled());
EXPECT_FALSE(Body().IsAwake());
EXPECT_FALSE(Body().IsSpeedable());
EXPECT_FALSE(Body().IsDestroyed());
EXPECT_TRUE(IsEnabled(Body()));
EXPECT_FALSE(IsAwake(Body()));
EXPECT_FALSE(IsSpeedable(Body()));
}
TEST(Body, StaticTypeConstruction)
{
const auto body = Body(BodyConf().Use(BodyType::Static));
EXPECT_FALSE(body.IsDestroyed());
EXPECT_TRUE(body.IsImpenetrable());
EXPECT_FALSE(body.IsSpeedable());
EXPECT_FALSE(body.IsAccelerable());
EXPECT_TRUE(body.IsSleepingAllowed());
EXPECT_FALSE(body.IsAwake());
EXPECT_FALSE(body.IsFixedRotation());
EXPECT_FALSE(body.IsMassDataDirty());
EXPECT_TRUE(body.IsEnabled());
}
TEST(Body, KinematicTypeConstruction)
{
const auto body = Body(BodyConf().Use(BodyType::Kinematic));
EXPECT_FALSE(body.IsDestroyed());
EXPECT_TRUE(body.IsImpenetrable());
EXPECT_TRUE(body.IsSpeedable());
EXPECT_FALSE(body.IsAccelerable());
EXPECT_TRUE(body.IsSleepingAllowed());
EXPECT_TRUE(body.IsAwake());
EXPECT_FALSE(body.IsFixedRotation());
EXPECT_FALSE(body.IsMassDataDirty());
EXPECT_TRUE(body.IsEnabled());
}
TEST(Body, DynamicTypeConstruction)
{
const auto body = Body(BodyConf().Use(BodyType::Dynamic));
EXPECT_FALSE(body.IsDestroyed());
EXPECT_FALSE(body.IsImpenetrable());
EXPECT_TRUE(body.IsSpeedable());
EXPECT_TRUE(body.IsAccelerable());
EXPECT_TRUE(body.IsSleepingAllowed());
EXPECT_TRUE(body.IsAwake());
EXPECT_FALSE(body.IsFixedRotation());
EXPECT_FALSE(body.IsMassDataDirty());
EXPECT_TRUE(body.IsEnabled());
}
TEST(Body, UseFixedRotationConstruction)
{
EXPECT_TRUE(Body(BodyConf().UseFixedRotation(true)).IsFixedRotation());
EXPECT_FALSE(Body(BodyConf().UseFixedRotation(false)).IsFixedRotation());
}
TEST(Body, UseAwakeConstruction)
{
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Static).UseAwake(true)).IsAwake());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Static).UseAwake(false)).IsAwake());
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Kinematic).UseAwake(true)).IsAwake());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Kinematic).UseAwake(false)).IsAwake());
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Dynamic).UseAwake(true)).IsAwake());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Dynamic).UseAwake(false)).IsAwake());
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Dynamic).UseAllowSleep(false).UseAwake(false)).IsAwake());
}
TEST(Body, UseAllowSleepConstruction)
{
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Static).UseAllowSleep(true)).IsSleepingAllowed());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Static).UseAllowSleep(false)).IsSleepingAllowed());
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Kinematic).UseAllowSleep(true)).IsSleepingAllowed());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Kinematic).UseAllowSleep(false)).IsSleepingAllowed());
EXPECT_TRUE(Body(BodyConf().Use(BodyType::Dynamic).UseAllowSleep(true)).IsSleepingAllowed());
EXPECT_FALSE(Body(BodyConf().Use(BodyType::Dynamic).UseAllowSleep(false)).IsSleepingAllowed());
}
TEST(Body, ShapeOnConstruction)
{
const auto shapeId = ShapeID(1u);
ASSERT_TRUE(!empty(Body(BodyConf{}.Use(shapeId)).GetShapes()));
ASSERT_EQ(size(Body(BodyConf{}.Use(shapeId)).GetShapes()), 1u);
EXPECT_EQ(Body(BodyConf{}.Use(shapeId)).GetShapes()[0], shapeId);
}
TEST(Body, LinearDampingOnConstruction)
{
EXPECT_EQ(Body(BodyConf{}.UseLinearDamping(0_Hz)).GetLinearDamping(), 0_Hz);
EXPECT_EQ(Body(BodyConf{}.UseLinearDamping(20_Hz)).GetLinearDamping(), 20_Hz);
EXPECT_EQ(Body(BodyConf{}.UseLinearDamping(30_Hz)).GetLinearDamping(), 30_Hz);
}
TEST(Body, AngularDampingOnConstruction)
{
EXPECT_EQ(Body(BodyConf{}.UseAngularDamping(0_Hz)).GetAngularDamping(), 0_Hz);
EXPECT_EQ(Body(BodyConf{}.UseAngularDamping(20_Hz)).GetAngularDamping(), 20_Hz);
EXPECT_EQ(Body(BodyConf{}.UseAngularDamping(30_Hz)).GetAngularDamping(), 30_Hz);
}
TEST(Body, InvMassOnConstruction)
{
EXPECT_EQ(Body(BodyConf{}.Use(BodyType::Dynamic)).GetInvMass(), Real(1) / 1_kg);
EXPECT_EQ(Body(BodyConf{}.Use(BodyType::Kinematic)).GetInvMass(), Real(0) / 1_kg);
EXPECT_EQ(Body(BodyConf{}.Use(BodyType::Static)).GetInvMass(), Real(0) / 1_kg);
}
TEST(Body, TransformationOnConstruction)
{
{
const auto conf = BodyConf{}.UseLocation(Length2{10_m, 12_m}).UseAngle(90_deg);
EXPECT_EQ(Body(conf).GetTransformation(), GetTransform1(conf.sweep));
}
{
const auto conf = BodyConf{}.UseLocation(Length2{4_m, -3_m}).UseAngle(-32_deg);
EXPECT_EQ(Body(conf).GetTransformation(), GetTransform1(conf.sweep));
}
}
TEST(Body, VelocityOnConstruction)
{
auto body = Body{};
body.SetVelocity(Velocity{LinearVelocity2{1_mps, 2_mps}, 3_rpm});
EXPECT_EQ(
Body(BodyConf{}.Use(Velocity{LinearVelocity2{1_mps, 2_mps}, 3_rpm})).GetVelocity().linear,
body.GetVelocity().linear);
EXPECT_EQ(
Body(BodyConf{}.Use(Velocity{LinearVelocity2{1_mps, 2_mps}, 3_rpm})).GetVelocity().angular,
body.GetVelocity().angular);
}
TEST(Body, AccelerationOnConstruction)
{
auto body = Body{};
body.SetAcceleration(LinearAcceleration2{2_mps2, 3_mps2}, Real(4) * RadianPerSquareSecond);
EXPECT_EQ(Body(BodyConf{}
.UseLinearAcceleration(LinearAcceleration2{2_mps2, 3_mps2})
.UseAngularAcceleration(Real(4) * RadianPerSquareSecond))
body.GetLinearAcceleration());
EXPECT_EQ(Body(BodyConf{}
.UseLinearAcceleration(LinearAcceleration2{2_mps2, 3_mps2})
.UseAngularAcceleration(Real(4) * RadianPerSquareSecond))
body.GetAngularAcceleration());
}
TEST(Body, SetUnsetDestroyed)
{
auto body = Body();
ASSERT_FALSE(body.IsDestroyed());
body.SetDestroyed();
EXPECT_TRUE(body.IsDestroyed());
body.UnsetDestroyed();
EXPECT_FALSE(body.IsDestroyed());
}
TEST(Body, SetUnsetDestroyedFreeFuncs)
{
auto body = Body();
ASSERT_FALSE(IsDestroyed(body));
SetDestroyed(body);
EXPECT_TRUE(IsDestroyed(body));
EXPECT_FALSE(IsDestroyed(body));
}
TEST(Body, EqualsOperator)
{
EXPECT_TRUE(Body() == Body());
{
auto body = Body{};
EXPECT_TRUE(body == Body());
}
{
auto bodyA = Body();
auto bodyB = Body();
bodyB.SetDestroyed();
EXPECT_FALSE(bodyA == bodyB);
bodyA.SetDestroyed();
EXPECT_TRUE(bodyA == bodyB);
bodyB.UnsetDestroyed();
EXPECT_FALSE(bodyA == bodyB);
bodyA.UnsetDestroyed();
EXPECT_TRUE(bodyA == bodyB);
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_TRUE(body1 == body2);
}
{
auto body = Body{};
SetTransformation(body, Transformation{Length2{2_m, 0_m}, UnitVec{}});
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
body.SetSweep(Sweep{Position{Length2{}, 2_deg}});
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
body.SetType(BodyType::Kinematic);
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
body.SetType(BodyType::Kinematic);
body.JustSetVelocity(Velocity{LinearVelocity2{}, 2_rpm});
EXPECT_FALSE(body == Body());
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
body1.SetAcceleration(LinearAcceleration2{}, Real(2) * RadianPerSquareSecond);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_FALSE(body1 == body2);
}
{
auto body = Body{};
SetMass(body, 3.2_kg);
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
body.SetInvMassData(body.GetInvMass(), (Real(2) * SquareRadian) / (2_m2 * 1.2_kg));
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
SetLinearDamping(body, 2_Hz);
EXPECT_FALSE(body == Body());
}
{
auto body = Body{};
SetAngularDamping(body, 2_Hz);
EXPECT_FALSE(body == Body());
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
body1.SetUnderActiveTime(2_s);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_FALSE(body1 == body2);
}
{
auto bodyA = Body{};
auto bodyB = Body{};
bodyA.Attach(ShapeID(1));
EXPECT_FALSE(bodyA == bodyB);
bodyB.Attach(ShapeID(1));
EXPECT_TRUE(bodyA == bodyB);
}
{
auto bodyA = Body{};
bodyA.SetType(BodyType::Dynamic);
ASSERT_TRUE(IsSleepingAllowed(bodyA));
auto bodyB = Body{};
bodyB.SetType(BodyType::Dynamic);
ASSERT_TRUE(IsSleepingAllowed(bodyA));
bodyA.SetSleepingAllowed(false);
ASSERT_FALSE(IsSleepingAllowed(bodyA));
EXPECT_FALSE(bodyA == bodyB);
}
}
TEST(Body, NotEqualsOperator)
{
EXPECT_FALSE(Body() != Body());
{
auto body = Body{};
EXPECT_FALSE(body != Body());
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_FALSE(body1 != body2);
}
{
auto body = Body{};
SetTransformation(body, Transformation{Length2{2_m, 0_m}, UnitVec{}});
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
body.SetSweep(Sweep{Position{Length2{}, 2_deg}});
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
body.SetType(BodyType::Kinematic);
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
body.SetType(BodyType::Kinematic);
body.JustSetVelocity(Velocity{LinearVelocity2{}, 2_rpm});
EXPECT_TRUE(body != Body());
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
body1.SetAcceleration(LinearAcceleration2{}, Real(2) * RadianPerSquareSecond);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_TRUE(body1 != body2);
}
{
auto body = Body{};
SetMass(body, 3.2_kg);
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
body.SetInvMassData(body.GetInvMass(), (Real(2) * SquareRadian) / (2_m2 * 1.2_kg));
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
SetLinearDamping(body, 2_Hz);
EXPECT_TRUE(body != Body());
}
{
auto body = Body{};
SetAngularDamping(body, 2_Hz);
EXPECT_TRUE(body != Body());
}
{
auto body1 = Body{};
body1.SetType(BodyType::Dynamic);
body1.SetUnderActiveTime(2_s);
auto body2 = Body{};
body2.SetType(BodyType::Dynamic);
EXPECT_TRUE(body1 != body2);
}
}
Declarations of the Body class, and functions associated with it.
static constexpr auto DefaultLinearDamping
Default linear damping.
Definition: Body.hpp:84
static constexpr auto DefaultAngularDamping
Default angular damping.
Definition: Body.hpp:87
constexpr auto RadianPerSquareSecond
Radian per square second unit of angular acceleration.
Definition: Units.hpp:478
constexpr auto SquareRadian
Square radian unit type.
Definition: Units.hpp:463
Definition: AABB.hpp:48
constexpr void SetDestroyed(Body &body) noexcept
Sets the destroyed property of the given body.
Definition: Body.hpp:770
std::size_t size(const DynamicTree &tree) noexcept
Gets the "size" of the given tree.
Definition: DynamicTree.hpp:715
bool IsAwake(const Body &body) noexcept
Gets the awake/asleep state of this body.
Definition: Body.hpp:884
Velocity GetVelocity(const Body &body) noexcept
Gets the velocity.
Definition: Body.hpp:1292
NonNegative< Frequency > GetLinearDamping(const Body &body) noexcept
Gets the linear damping of the body.
Definition: Body.hpp:1122
bool IsSleepingAllowed(const Body &body) noexcept
Gets whether or not this body allowed to sleep.
Definition: Body.hpp:833
Transformation GetTransform1(const Sweep &sweep) noexcept
Gets the transform at "time" one.
Definition: Math.hpp:271
void SetAngularDamping(Body &body, NonNegative< Frequency > value) noexcept
Sets the angular damping of the body.
Definition: Body.hpp:1146
BodyType GetType(const Body &body) noexcept
Gets the type of this body.
Definition: Body.hpp:748
NonNegative< Frequency > GetAngularDamping(const Body &body) noexcept
Gets the angular damping of the body.
Definition: Body.hpp:1138
const Transformation & GetTransformation(const Body &body) noexcept
Gets the body's transformation.
Definition: Body.hpp:1014
NonNegativeFF< InvMass > GetInvMass(const Body &body) noexcept
Gets the inverse total mass of the body.
Definition: Body.hpp:1102
bool IsSpeedable(const Body &body) noexcept
Is "speedable".
Definition: Body.hpp:786
bool IsFixedRotation(const Body &body) noexcept
Does this body have fixed rotation?
Definition: Body.hpp:1073
AngularAcceleration GetAngularAcceleration(const Body &body) noexcept
Gets this body's angular acceleration.
Definition: Body.hpp:1183
void SetLinearDamping(Body &body, NonNegative< Frequency > value) noexcept
Sets the linear damping of the body.
Definition: Body.hpp:1130
bool IsEnabled(const Body &body) noexcept
Gets the enabled/disabled state of the body.
Definition: Body.hpp:850
auto IsDestroyed(const AabbTreeWorld &world, BodyID id) -> bool
Gets whether the given identifier is to a body that's been destroyed.
Definition: AabbTreeWorld.hpp:341
constexpr void UnsetDestroyed(Body &body) noexcept
Unsets the destroyed property of the given body.
Definition: Body.hpp:777
LinearAcceleration2 GetLinearAcceleration(const Body &body) noexcept
Gets this body's linear acceleration.
Definition: Body.hpp:1175
void SetMass(Body &body, Mass mass)
Sets the mass of the given body.
Definition: Body.hpp:1225
void SetTransformation(Body &body, const Transformation &value) noexcept
Sets the body's transformation.
Definition: Body.cpp:270
const std::vector< ShapeID > & GetShapes(const AabbTreeWorld &world, BodyID id)
Disassociates all of the associated shape from the validly identified body.
Definition: AabbTreeWorld.cpp:2913
Definition: ArrayList.hpp:43
float Real
Real-number type.
Definition: Real.hpp:69
Vector2< LinearVelocity > LinearVelocity2
2-element vector of linear velocity (LinearVelocity) quantities.
Definition: Vector2.hpp:58
Vector2< LinearAcceleration > LinearAcceleration2
2-element vector of linear acceleration (LinearAcceleration) quantities.
Definition: Vector2.hpp:62
detail::IndexingNamedType< ShapeCounter, struct ShapeIdentifier > ShapeID
Shape identifier.
Definition: ShapeID.hpp:44
Vector2< Length > Length2
2-element vector of Length quantities.
Definition: Vector2.hpp:51
constexpr bool empty(IndexPair3 pairs) noexcept
Checks whether the given collection of index pairs is empty.
Definition: IndexPair.hpp:75
AngularVelocity angular
Angular velocity.
Definition: Velocity.hpp:47
LinearVelocity2 linear
Linear velocity.
Definition: Velocity.hpp:46