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

This is the googletest based unit testing file for the free function interfaces to playrho::d2::World contact member functions and additional functionality.

/*
* 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/WorldContact.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <PlayRho/Dynamics/WorldFixture.hpp>
#include <PlayRho/Dynamics/WorldBody.hpp>
#include <PlayRho/Dynamics/WorldMisc.hpp>
#include <PlayRho/Dynamics/StepConf.hpp>
#include <PlayRho/Dynamics/BodyConf.hpp>
#include <PlayRho/Dynamics/FixtureConf.hpp>
#include <PlayRho/Collision/Shapes/DiskShapeConf.hpp>
using namespace playrho;
using namespace playrho::d2;
TEST(WorldContact, SetAwake)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto fA = CreateFixture(world, bA, Shape{shape});
const auto fB = CreateFixture(world, bB, Shape{shape});
ASSERT_TRUE(GetContacts(world).empty());
Step(world, StepConf{});
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
const auto c = contacts.begin()->second;
ASSERT_EQ(GetFixtureA(world, c), fA);
ASSERT_EQ(GetFixtureB(world, c), fB);
ASSERT_TRUE(IsAwake(world, c));
ASSERT_NO_THROW(UnsetAwake(world, bA));
ASSERT_FALSE(IsAwake(world, bA));
ASSERT_NO_THROW(UnsetAwake(world, bB));
ASSERT_FALSE(IsAwake(world, bB));
EXPECT_NO_THROW(SetAwake(world, c));
EXPECT_TRUE(IsAwake(world, c));
EXPECT_TRUE(IsAwake(world, bA));
EXPECT_TRUE(IsAwake(world, bB));
}
TEST(WorldContact, ResetFriction)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto fA = CreateFixture(world, bA, Shape{shape});
const auto fB = CreateFixture(world, bB, Shape{shape});
ASSERT_TRUE(GetContacts(world).empty());
Step(world, StepConf{});
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
const auto c = contacts.begin()->second;
ASSERT_EQ(GetFixtureA(world, c), fA);
ASSERT_EQ(GetFixtureB(world, c), fB);
ASSERT_GT(GetFriction(shape), Real(0));
ASSERT_NEAR(static_cast<double>(GetFriction(world, c)),
static_cast<double>(Real{GetFriction(shape)}),
0.01);
SetFriction(world, c, GetFriction(shape) * Real(2));
ASSERT_NE(GetFriction(world, c), GetFriction(shape));
ResetFriction(world, c);
EXPECT_NEAR(static_cast<double>(GetFriction(world, c)),
static_cast<double>(Real{GetFriction(shape)}),
0.01);
}
TEST(WorldContact, ResetRestitution)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto fA = CreateFixture(world, bA, Shape{shape});
const auto fB = CreateFixture(world, bB, Shape{shape});
ASSERT_TRUE(GetContacts(world).empty());
Step(world, StepConf{});
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
const auto c = contacts.begin()->second;
ASSERT_EQ(GetFixtureA(world, c), fA);
ASSERT_EQ(GetFixtureB(world, c), fB);
ASSERT_EQ(GetRestitution(shape), Real(0));
ASSERT_EQ(GetRestitution(world, c), GetRestitution(shape));
SetRestitution(world, c, Real(2));
ASSERT_NE(GetRestitution(world, c), GetRestitution(shape));
ResetRestitution(world, c);
EXPECT_EQ(GetRestitution(world, c), GetRestitution(shape));
}
TEST(WorldContact, SetUnsetEnabled)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, bA, Shape{shape});
CreateFixture(world, bB, Shape{shape});
ASSERT_NO_THROW(Step(world, StepConf{}));
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
const auto c = contacts.begin()->second;
EXPECT_NO_THROW(SetEnabled(world, c));
EXPECT_TRUE(IsEnabled(world, c));
EXPECT_NO_THROW(UnsetEnabled(world, c));
EXPECT_FALSE(IsEnabled(world, c));
EXPECT_NO_THROW(SetEnabled(world, c));
EXPECT_TRUE(IsEnabled(world, c));
}
TEST(WorldContact, SetTangentSpeed)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, bA, Shape{shape});
CreateFixture(world, bB, Shape{shape});
ASSERT_NO_THROW(Step(world, StepConf{}));
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
const auto c = contacts.begin()->second;
{
const auto linearVelocity = LinearVelocity{5.6_mps};
EXPECT_NO_THROW(SetTangentSpeed(world, c, linearVelocity));
EXPECT_EQ(GetTangentSpeed(world, c), linearVelocity);
}
{
const auto linearVelocity = LinearVelocity{0.2_mps};
EXPECT_NO_THROW(SetTangentSpeed(world, c, linearVelocity));
EXPECT_EQ(GetTangentSpeed(world, c), linearVelocity);
}
}
TEST(WorldContact, WorldManifoldAndMore)
{
const auto shape = DiskShapeConf{};
auto world = World{};
const auto bA = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
const auto bB = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, bA, Shape{shape});
CreateFixture(world, bB, Shape{shape});
ASSERT_NO_THROW(Step(world, StepConf{}));
const auto contacts = GetContacts(world);
ASSERT_EQ(contacts.size(), ContactCounter(1));
EXPECT_EQ(GetContactRange(world), 1u);
const auto c = contacts.begin()->second;
{
auto manifold = WorldManifold{};
EXPECT_NO_THROW(manifold = GetWorldManifold(world, c));
EXPECT_EQ(manifold.GetPointCount(), 1u);
EXPECT_EQ(manifold.GetNormal(), UnitVec::GetRight());
}
EXPECT_EQ(GetToiCount(world, c), 0u);
EXPECT_FALSE(HasValidToi(world, c));
EXPECT_EQ(GetChildIndexA(world, c), ChildCounter(0));
EXPECT_EQ(GetChildIndexB(world, c), ChildCounter(0));
}
playrho::d2::UnsetEnabled
void UnsetEnabled(Body &body) noexcept
Unsets the enabled state.
Definition: Body.hpp:787
playrho::BodyType::Static
@ Static
Static body type.
playrho::d2::CreateBody
BodyID CreateBody(World &world, const BodyConf &def)
Creates a rigid body with the given configuration.
Definition: WorldBody.cpp:58
playrho::d2::BodyConf::UseType
constexpr BodyConf & UseType(BodyType t) noexcept
Use the given type.
Definition: BodyConf.hpp:166
playrho::d2
Name space for 2-dimensionally related PlayRho names.
Definition: AABB.cpp:34
playrho::d2::UnitVec::GetRight
static constexpr UnitVec GetRight() noexcept
Gets the right-ward oriented unit vector.
Definition: UnitVec.hpp:74
playrho::d2::HasValidToi
auto HasValidToi(const Contact &contact) noexcept
Gets whether a TOI is set.
Definition: Contact.hpp:694
playrho::d2::IsAwake
bool IsAwake(const Body &body) noexcept
Gets the awake/asleep state of this body.
Definition: Body.hpp:808
playrho::d2::WorldManifold
Essentially a Manifold expressed in world coordinate terms.
Definition: WorldManifold.hpp:41
playrho::d2::GetContacts
SizedRange< std::vector< KeyedContactPtr >::const_iterator > GetContacts(const World &world, BodyID id)
Gets the container of all contacts attached to the identified body.
Definition: WorldBody.cpp:478
playrho
Name space for all PlayRho related names.
Definition: AABB.cpp:33
playrho::d2::GetWorldManifold
WorldManifold GetWorldManifold(const Manifold &manifold, Transformation xfA, Length radiusA, Transformation xfB, Length radiusB)
Gets the world manifold for the given data.
Definition: WorldManifold.cpp:105
playrho::d2::GetChildIndexB
ChildCounter GetChildIndexB(const Contact &contact) noexcept
Gets the child index B of the given contact.
Definition: Contact.hpp:616
playrho::d2::GetChildIndexA
ChildCounter GetChildIndexA(const Contact &contact) noexcept
Gets the child index A of the given contact.
Definition: Contact.hpp:609
playrho::d2::World
Definition of an independent and simulatable "world".
Definition: World.hpp:129
playrho::d2::SetTangentSpeed
void SetTangentSpeed(Contact &contact, LinearVelocity value) noexcept
Sets the desired tangent speed for a conveyor belt behavior.
Definition: Contact.hpp:766
playrho::ContactCounter
Wider< BodyCounter >::type ContactCounter
Count type for contacts.
Definition: Settings.hpp:221
playrho::d2::GetFriction
Real GetFriction(const Shape &shape) noexcept
Gets the coefficient of friction.
Definition: Shape.hpp:294
playrho::d2::GetTangentSpeed
auto GetTangentSpeed(const Contact &contact) noexcept
Gets the desired tangent speed.
Definition: Contact.hpp:757
playrho::d2::UnsetAwake
void UnsetAwake(Body &body) noexcept
Sets this body to asleep if sleeping is allowed.
Definition: Body.hpp:837
playrho::d2::SetFriction
void SetFriction(Contact &contact, Real value) noexcept
Sets the friction value for the identified contact.
Definition: Contact.hpp:728
playrho::d2::ResetRestitution
void ResetRestitution(World &world, ContactID id)
Resets the restitution to the default value.
Definition: WorldContact.hpp:233
playrho::d2::IsEnabled
bool IsEnabled(const Body &body) noexcept
Gets the enabled/disabled state of the body.
Definition: Body.hpp:771
playrho::empty
constexpr bool empty(IndexPair3 pairs) noexcept
Checks whether the given collection of index pairs is empty.
Definition: IndexPair.hpp:69
playrho::d2::SetEnabled
void SetEnabled(Body &body) noexcept
Sets the enabled state.
Definition: Body.hpp:779
playrho::ChildCounter
std::remove_const< decltype(MaxChildCount)>::type ChildCounter
Child counter type.
Definition: Settings.hpp:97
playrho::StepConf
Step configuration.
Definition: StepConf.hpp:42
playrho::d2::GetToiCount
auto GetToiCount(const Contact &contact) noexcept
Gets the time of impact count.
Definition: Contact.hpp:672
playrho::d2::CreateFixture
FixtureID CreateFixture(World &world, FixtureConf def, bool resetMassData)
Creates a fixture within the specified world.
Definition: WorldFixture.cpp:48
playrho::Real
float Real
Real-number type.
Definition: Real.hpp:69
playrho::d2::SetRestitution
void SetRestitution(Contact &contact, Real value)
Sets the restitution value for the identified contact.
Definition: Contact.hpp:748
playrho::d2::BodyConf
Configuration for a body.
Definition: BodyConf.hpp:50
playrho::d2::GetRestitution
Real GetRestitution(const Shape &shape) noexcept
Gets the coefficient of restitution value of the given shape.
Definition: Shape.hpp:299
playrho::d2::ResetFriction
void ResetFriction(World &world, ContactID id)
Resets the friction mixture to the default value.
Definition: WorldContact.hpp:225
playrho::d2::SetAwake
void SetAwake(Body &body) noexcept
Awakens this body.
Definition: Body.hpp:822
playrho::d2::GetFixtureB
FixtureID GetFixtureB(const Contact &contact) noexcept
Gets the fixture B associated with the given contact.
Definition: Contact.hpp:602
playrho::d2::GetContactRange
ContactCounter GetContactRange(const World &world) noexcept
Gets the extent of the currently valid contact range.
Definition: WorldContact.cpp:34
playrho::d2::Shape
Shape.
Definition: Shape.hpp:183
playrho::d2::Step
StepStats Step(WorldImpl &world, const StepConf &conf)
Steps the given world the specified amount.
Definition: WorldImplMisc.cpp:85
playrho::d2::GetFixtureA
FixtureID GetFixtureA(const Contact &contact) noexcept
Gets the fixture A associated with the given contact.
Definition: Contact.hpp:595
playrho::LinearVelocity
PLAYRHO_QUANTITY(boost::units::si::velocity) LinearVelocity
Linear velocity quantity.
Definition: Units.hpp:167
playrho::d2::DiskShapeConf
Disk shape configuration.
Definition: DiskShapeConf.hpp:42