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

This is the googletest based unit testing file for the free function interfaces to playrho::d2::World body 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/WorldBody.hpp>
#include <PlayRho/Dynamics/World.hpp>
#include <PlayRho/Dynamics/BodyConf.hpp>
#include <PlayRho/Dynamics/WorldFixture.hpp>
#include <PlayRho/Dynamics/WorldMisc.hpp>
#include <PlayRho/Dynamics/StepConf.hpp>
#include <PlayRho/Dynamics/Joints/Joint.hpp>
#include <PlayRho/Collision/Shapes/DiskShapeConf.hpp>
#include <PlayRho/Collision/Shapes/PolygonShapeConf.hpp>
#include <chrono>
using namespace playrho;
using namespace playrho::d2;
TEST(WorldBody, WorldCreated)
{
auto world = World{};
const auto body = CreateBody(world);
ASSERT_NE(body, InvalidBodyID);
EXPECT_TRUE(IsEnabled(world, body));
EXPECT_FALSE(IsAwake(world, body));
EXPECT_FALSE(IsSpeedable(world, body));
EXPECT_FALSE(IsAccelerable(world, body));
EXPECT_FALSE(Awaken(world, body));
EXPECT_TRUE(GetFixtures(world, body).empty());
{
auto i = 0;
for (auto&& fixture: GetFixtures(world, body))
{
EXPECT_EQ(GetBody(world, fixture), body);
++i;
}
EXPECT_EQ(i, 0);
}
EXPECT_TRUE(GetJoints(world, body).empty());
{
auto i = 0;
for (auto&& joint: GetJoints(world, body))
{
NOT_USED(joint);
++i;
}
EXPECT_EQ(i, 0);
}
EXPECT_TRUE(GetContacts(world, body).empty());
{
auto i = 0;
for (auto&& ce: GetContacts(world, body))
{
NOT_USED(ce);
++i;
}
EXPECT_EQ(i, 0);
}
}
TEST(WorldBody, SetVelocityDoesNothingToStatic)
{
const auto zeroVelocity = Velocity{
LinearVelocity2{0_mps, 0_mps},
};
auto world = World{};
const auto body = CreateBody(world);
ASSERT_NE(body, InvalidBodyID);
ASSERT_FALSE(IsAwake(world, body));
ASSERT_FALSE(IsSpeedable(world, body));
ASSERT_FALSE(IsAccelerable(world, body));
ASSERT_EQ(GetVelocity(world, body), zeroVelocity);
const auto velocity = Velocity{
LinearVelocity2{1.1_mps, 1.1_mps},
};
SetVelocity(world, body, velocity);
EXPECT_NE(GetVelocity(world, body), velocity);
EXPECT_EQ(GetVelocity(world, body), zeroVelocity);
}
TEST(WorldBody, CreateFixture)
{
auto world = World{};
const auto body = CreateBody(world);
EXPECT_EQ(GetFixtureCount(world, body), std::size_t(0));
const auto valid_shape = Shape{DiskShapeConf(1_m)};
EXPECT_NE(CreateFixture(world, body, valid_shape, FixtureConf{}), InvalidFixtureID);
EXPECT_EQ(GetFixtureCount(world, body), std::size_t(1));
const auto minRadius = GetMinVertexRadius(world);
EXPECT_THROW(CreateFixture(world, body, Shape{DiskShapeConf{minRadius / 2}}), InvalidArgument);
const auto maxRadius = GetMaxVertexRadius(world);
EXPECT_THROW(CreateFixture(world, body, Shape{DiskShapeConf{maxRadius + maxRadius / 10}}),
}
TEST(WorldBody, Destroy)
{
auto world = World{};
EXPECT_THROW(Destroy(world, InvalidBodyID), std::out_of_range);
auto bodyID = InvalidBodyID;
EXPECT_NO_THROW(bodyID = CreateBody(world));
EXPECT_EQ(GetBodyCount(world), BodyCounter(1));
EXPECT_NO_THROW(Destroy(world, bodyID));
EXPECT_EQ(GetBodyCount(world), BodyCounter(0));
const auto bodyA = CreateBody(world);
const auto bodyB = CreateBody(world);
EXPECT_EQ(GetBodyCount(world), BodyCounter(2));
ASSERT_EQ(GetFixtureCount(world, bodyA), std::size_t(0));
ASSERT_EQ(GetFixtureCount(world, bodyB), std::size_t(0));
const auto fixtureA = CreateFixture(world, bodyA, Shape{DiskShapeConf(1_m)}, FixtureConf{});
ASSERT_NE(fixtureA, InvalidFixtureID);
ASSERT_EQ(GetFixtureCount(world, bodyA), std::size_t(1));
EXPECT_TRUE(Destroy(world, fixtureA));
EXPECT_EQ(GetFixtureCount(world, bodyA), std::size_t(0));
}
TEST(WorldBody, SetEnabledCausesIsEnabled)
{
auto world = World{};
const auto body = CreateBody(world);
ASSERT_TRUE(IsEnabled(world, body));
auto value = true;
for (auto i = 0; i < 4; ++i) {
// Set and check twice to ensure same behavior if state already same.
// Inlined to help match state with line number of any reports.
EXPECT_NO_THROW(SetEnabled(world, body, value));
EXPECT_EQ(IsEnabled(world, body), value);
EXPECT_NO_THROW(SetEnabled(world, body, value));
EXPECT_EQ(IsEnabled(world, body), value);
value = !value;
}
}
TEST(WorldBody, SetFixedRotation)
{
auto world = World{};
const auto body = CreateBody(world);
const auto valid_shape = Shape{DiskShapeConf(1_m)};
ASSERT_NE(CreateFixture(world, body, valid_shape, FixtureConf{}), InvalidFixtureID);
ASSERT_FALSE(IsFixedRotation(world, body));
// Test that set fixed rotation to flag already set is not a toggle
SetFixedRotation(world, body, false);
EXPECT_FALSE(IsFixedRotation(world, body));
SetFixedRotation(world, body, true);
EXPECT_TRUE(IsFixedRotation(world, body));
SetFixedRotation(world, body, false);
EXPECT_FALSE(IsFixedRotation(world, body));
}
TEST(WorldBody, CreateAndDestroyFixture)
{
auto world = World{};
auto body = CreateBody(world);
ASSERT_NE(body, InvalidBodyID);
EXPECT_TRUE(GetFixtures(world, body).empty());
EXPECT_FALSE(IsMassDataDirty(world, body));
auto conf = DiskShapeConf{};
conf.vertexRadius = 2.871_m;
conf.location = Vec2{1.912f, -77.31f} * 1_m;
conf.density = 1_kgpm2;
const auto shape = Shape(conf);
{
auto fixture = CreateFixture(world, body, shape, FixtureConf{}, false);
const auto fshape = GetShape(world, fixture);
EXPECT_EQ(GetVertexRadius(fshape, 0), GetVertexRadius(shape, 0));
EXPECT_EQ(TypeCast<DiskShapeConf>(fshape).GetLocation(), conf.GetLocation());
EXPECT_FALSE(GetFixtures(world, body).empty());
{
auto i = 0;
for (const auto& f: GetFixtures(world, body))
{
EXPECT_EQ(f, fixture);
++i;
}
EXPECT_EQ(i, 1);
}
EXPECT_TRUE(IsMassDataDirty(world, body));
ResetMassData(world, body);
EXPECT_FALSE(IsMassDataDirty(world, body));
EXPECT_TRUE(world.Destroy(fixture));
EXPECT_TRUE(GetFixtures(world, body).empty());
EXPECT_TRUE(IsMassDataDirty(world, body));
ResetMassData(world, body);
EXPECT_FALSE(IsMassDataDirty(world, body));
DestroyFixtures(world, body);
EXPECT_TRUE(GetFixtures(world, body).empty());
}
{
auto fixture = CreateFixture(world, body, shape, FixtureConf{}, false);
const auto fshape = GetShape(world, fixture);
EXPECT_EQ(GetVertexRadius(fshape, 0), GetVertexRadius(shape, 0));
EXPECT_EQ(TypeCast<DiskShapeConf>(fshape).GetLocation(), conf.GetLocation());
EXPECT_FALSE(GetFixtures(world, body).empty());
{
auto i = 0;
for (const auto& f: GetFixtures(world, body))
{
EXPECT_EQ(f, fixture);
++i;
}
EXPECT_EQ(i, 1);
}
EXPECT_TRUE(IsMassDataDirty(world, body));
ResetMassData(world, body);
EXPECT_FALSE(IsMassDataDirty(world, body));
EXPECT_FALSE(GetFixtures(world, body).empty());
DestroyFixtures(world, body);
EXPECT_TRUE(GetFixtures(world, body).empty());
EXPECT_FALSE(IsMassDataDirty(world, body));
}
}
TEST(WorldBody, SetType)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
ASSERT_EQ(GetBodiesForProxies(world).size(), 0u);
ASSERT_EQ(GetType(world, body), BodyType::Dynamic);
SetType(world, body, BodyType::Static);
EXPECT_EQ(GetBodiesForProxies(world).size(), 1u);
EXPECT_EQ(GetType(world, body), BodyType::Static);
SetType(world, body, BodyType::Kinematic);
EXPECT_EQ(GetBodiesForProxies(world).size(), 1u);
EXPECT_EQ(GetType(world, body), BodyType::Kinematic);
SetType(world, body, BodyType::Dynamic);
EXPECT_EQ(GetType(world, body), BodyType::Dynamic);
EXPECT_EQ(GetBodiesForProxies(world).size(), 1u);
}
TEST(WorldBody, StaticIsExpected)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Static));
EXPECT_FALSE(IsAccelerable(world, body));
EXPECT_FALSE(IsSpeedable(world, body));
EXPECT_TRUE(IsImpenetrable(world, body));
}
TEST(WorldBody, KinematicIsExpected)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Kinematic));
EXPECT_FALSE(IsAccelerable(world, body));
EXPECT_TRUE( IsSpeedable(world, body));
EXPECT_TRUE( IsImpenetrable(world, body));
}
TEST(WorldBody, DynamicIsExpected)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
EXPECT_TRUE(IsAccelerable(world, body));
EXPECT_TRUE(IsSpeedable(world, body));
EXPECT_FALSE(IsImpenetrable(world, body));
}
TEST(WorldBody, SetMassData)
{
const auto center = Length2{0_m, 0_m};
const auto mass = 32_kg;
const auto rotInertiaUnits = SquareMeter * Kilogram / SquareRadian;
const auto rotInertia = 3 * rotInertiaUnits; // L^2 M QP^-2
const auto massData = MassData{center, mass, rotInertia};
// has effect on dynamic bodies...
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
EXPECT_EQ(GetMass(world, body), 1_kg);
EXPECT_EQ(GetRotInertia(world, body), std::numeric_limits<Real>::infinity() * rotInertiaUnits);
SetMassData(world, body, massData);
EXPECT_EQ(GetMass(world, body), mass);
EXPECT_EQ(GetRotInertia(world, body), rotInertia);
}
// has no rotational effect on fixed rotation dynamic bodies...
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseFixedRotation(true));
EXPECT_EQ(GetMass(world, body), 1_kg);
EXPECT_EQ(GetRotInertia(world, body), std::numeric_limits<Real>::infinity() * rotInertiaUnits);
SetMassData(world, body, massData);
EXPECT_EQ(GetMass(world, body), mass);
EXPECT_EQ(GetRotInertia(world, body), std::numeric_limits<Real>::infinity() * rotInertiaUnits);
}
// has no effect on static bodies...
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Static));
EXPECT_EQ(GetMass(world, body), 0_kg);
EXPECT_EQ(GetRotInertia(world, body), std::numeric_limits<Real>::infinity() * rotInertiaUnits);
SetMassData(world, body, massData);
EXPECT_EQ(GetMass(world, body), 0_kg);
EXPECT_EQ(GetRotInertia(world, body), std::numeric_limits<Real>::infinity() * rotInertiaUnits);
}
}
TEST(WorldBody, SetTransform)
{
auto bd = BodyConf{};
auto world = World{};
ASSERT_EQ(GetBodiesForProxies(world).size(), 0u);
const auto body = CreateBody(world, bd);
const auto xfm1 = Transformation{Length2{}, UnitVec::GetRight()};
ASSERT_EQ(GetTransformation(world, body), xfm1);
ASSERT_EQ(GetBodiesForProxies(world).size(), 0u);
const auto xfm2 = Transformation{Vec2(10, -12) * 1_m, UnitVec::GetLeft()};
SetTransform(world, body, xfm2.p, GetAngle(xfm2.q));
EXPECT_EQ(GetTransformation(world, body).p, xfm2.p);
EXPECT_NEAR(static_cast<double>(GetX(GetTransformation(world, body).q)),
static_cast<double>(GetX(xfm2.q)),
0.001);
EXPECT_NEAR(static_cast<double>(GetY(GetTransformation(world, body).q)),
static_cast<double>(GetY(xfm2.q)),
0.001);
EXPECT_EQ(GetBodiesForProxies(world).size(), 1u);
world.Destroy(body);
EXPECT_EQ(GetBodiesForProxies(world).size(), 0u);
}
TEST(WorldBody, SetAcceleration)
{
const auto someLinearAccel = LinearAcceleration2{2 * MeterPerSquareSecond, 3 * MeterPerSquareSecond};
const auto someAngularAccel = 2 * RadianPerSquareSecond;
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Static));
ASSERT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
ASSERT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
ASSERT_FALSE(IsAwake(world, body));
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, LinearAcceleration2{}, someAngularAccel);
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel, AngularAcceleration{});
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
}
// Kinematic and dynamic bodies awake at creation...
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Kinematic));
ASSERT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
ASSERT_TRUE(IsAwake(world, body));
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, LinearAcceleration2{}, someAngularAccel);
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel, AngularAcceleration{});
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
}
// Dynamic bodies take a non-zero linear or angular acceleration.
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
ASSERT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
ASSERT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
ASSERT_TRUE(IsAwake(world, body));
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, LinearAcceleration2{}, someAngularAccel);
EXPECT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel);
EXPECT_TRUE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel, AngularAcceleration{});
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel);
EXPECT_EQ(GetAngularAcceleration(world, body), 0 * RadianPerSquareSecond);
EXPECT_TRUE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel, someAngularAccel);
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel);
EXPECT_TRUE(IsAwake(world, body));
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel);
// Reseting to same acceleration shouldn't change asleep status...
SetAcceleration(world, body, someLinearAccel, someAngularAccel);
EXPECT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel);
// Seting to lower acceleration shouldn't change asleep status...
SetAcceleration(world, body, someLinearAccel * 0.5f, someAngularAccel * 0.9f);
EXPECT_FALSE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel * 0.5f);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel * 0.9f);
// Seting to higher acceleration or new direction should awaken...
SetAcceleration(world, body, someLinearAccel * 1.5f, someAngularAccel * 1.9f);
EXPECT_TRUE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel * 1.5f);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel * 1.9f);
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel * 1.5f, someAngularAccel * 2.0f);
EXPECT_TRUE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel * 1.5f);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel * 2.0f);
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel * 2.0f, someAngularAccel * 2.0f);
EXPECT_TRUE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel * 2.0f);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel * 2.0f);
UnsetAwake(world, body);
ASSERT_FALSE(IsAwake(world, body));
SetAcceleration(world, body, someLinearAccel * -1.0f, someAngularAccel * 2.0f);
EXPECT_TRUE(IsAwake(world, body));
EXPECT_EQ(GetLinearAcceleration(world, body), someLinearAccel * -1.0f);
EXPECT_EQ(GetAngularAcceleration(world, body), someAngularAccel * 2.0f);
}
}
TEST(WorldBody, SetAngularAcceleration)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
auto acceleration = AngularAcceleration{};
acceleration = Real(2) * RadianPerSquareSecond;
EXPECT_NO_THROW(SetAcceleration(world, body, acceleration));
EXPECT_EQ(GetAngularAcceleration(world, body), acceleration);
acceleration = Real(3) * RadianPerSquareSecond;
EXPECT_NO_THROW(SetAcceleration(world, body, acceleration));
EXPECT_EQ(GetAngularAcceleration(world, body), acceleration);
}
TEST(WorldBody, SetAngularVelocity)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
auto value = AngularVelocity{};
value = Real(4) * RadianPerSecond;
EXPECT_NO_THROW(SetVelocity(world, body, value));
EXPECT_EQ(GetAngularVelocity(world, body), value);
value = Real(5) * RadianPerSecond;
EXPECT_NO_THROW(SetVelocity(world, body, value));
EXPECT_EQ(GetAngularVelocity(world, body), value);
}
TEST(WorldBody, ApplyForce)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, body, Shape{PolygonShapeConf(1_m, 1_m).UseDensity(1_kgpm2)}, FixtureConf{});
ASSERT_EQ(GetMass(world, body), 4_kg);
auto value = Force2{};
value = Force2{4_N, 4_N};
EXPECT_NO_THROW(ApplyForce(world, body, value, GetWorldCenter(world, body)));
EXPECT_EQ(GetX(GetAcceleration(world, body).linear), LinearAcceleration(1_mps2));
EXPECT_EQ(GetY(GetAcceleration(world, body).linear), LinearAcceleration(1_mps2));
EXPECT_EQ(GetAcceleration(world, body).angular, AngularAcceleration());
}
TEST(WorldBody, ApplyTorque)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, body, Shape{PolygonShapeConf(1_m, 1_m).UseDensity(1_kgpm2)}, FixtureConf{});
ASSERT_EQ(GetMass(world, body), 4_kg);
auto value = Torque{};
value = 4_kg * SquareMeter / SquareSecond / Radian;
EXPECT_NO_THROW(ApplyTorque(world, body, value));
EXPECT_EQ(GetX(GetAcceleration(world, body).linear), LinearAcceleration(0_mps2));
EXPECT_EQ(GetY(GetAcceleration(world, body).linear), LinearAcceleration(0_mps2));
EXPECT_EQ(GetAcceleration(world, body).angular,
}
TEST(WorldBody, ApplyLinearImpulse)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, body, Shape{PolygonShapeConf(1_m, 1_m).UseDensity(1_kgpm2)}, FixtureConf{});
ASSERT_EQ(GetMass(world, body), 4_kg);
auto value = Momentum2{40_Ns, 0_Ns};
EXPECT_NO_THROW(ApplyLinearImpulse(world, body, value, GetWorldCenter(world, body)));
EXPECT_EQ(GetX(GetVelocity(world, body).linear), LinearVelocity(10_mps));
EXPECT_EQ(GetY(GetVelocity(world, body).linear), LinearVelocity(0_mps));
EXPECT_EQ(GetVelocity(world, body).angular, AngularVelocity(0_rpm));
}
TEST(WorldBody, ApplyAngularImpulse)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
CreateFixture(world, body, Shape{PolygonShapeConf(1_m, 1_m).UseDensity(1_kgpm2)}, FixtureConf{});
ASSERT_EQ(GetMass(world, body), 4_kg);
EXPECT_NO_THROW(ApplyAngularImpulse(world, body, value));
EXPECT_EQ(GetX(GetVelocity(world, body).linear), LinearVelocity(0_mps));
EXPECT_EQ(GetY(GetVelocity(world, body).linear), LinearVelocity(0_mps));
EXPECT_EQ(GetVelocity(world, body).angular, AngularVelocity(Real(3) * RadianPerSecond));
}
TEST(WorldBody, CreateLotsOfFixtures)
{
auto bd = BodyConf{};
auto conf = DiskShapeConf{};
conf.vertexRadius = 2.871_m;
conf.location = Vec2{1.912f, -77.31f} * 1_m;
conf.density = 1.3_kgpm2;
const auto shape = Shape(conf);
const auto num = 5000;
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
{
auto world = World{};
auto body = CreateBody(world, bd);
ASSERT_NE(body, InvalidBodyID);
EXPECT_TRUE(GetFixtures(world, body).empty());
for (auto i = decltype(num){0}; i < num; ++i)
{
auto fixture = CreateFixture(world, body, shape, FixtureConf{}, false);
ASSERT_NE(fixture, InvalidFixtureID);
}
ResetMassData(world, body);
EXPECT_FALSE(GetFixtures(world, body).empty());
{
int i = decltype(num){0};
for (auto&& f: GetFixtures(world, body))
{
++i;
}
EXPECT_EQ(i, num);
}
}
end = std::chrono::system_clock::now();
const std::chrono::duration<double> elapsed_secs_resetting_at_end = end - start;
start = std::chrono::system_clock::now();
{
auto world = World{};
auto body = CreateBody(world, bd);
ASSERT_NE(body, InvalidBodyID);
EXPECT_TRUE(GetFixtures(world, body).empty());
for (auto i = decltype(num){0}; i < num; ++i)
{
auto fixture = CreateFixture(world, body, shape, FixtureConf{}, true);
ASSERT_NE(fixture, InvalidFixtureID);
}
EXPECT_FALSE(GetFixtures(world, body).empty());
{
auto i = decltype(num){0};
for (auto&& f: GetFixtures(world, body))
{
++i;
}
EXPECT_EQ(i, num);
}
}
end = std::chrono::system_clock::now();
const std::chrono::duration<double> elapsed_secs_resetting_in_create = end - start;
EXPECT_LT(elapsed_secs_resetting_at_end.count(), elapsed_secs_resetting_in_create.count());
}
TEST(WorldBody, GetWorldIndex)
{
auto world = World{};
ASSERT_EQ(GetBodies(world).size(), std::size_t(0));
const auto body0 = CreateBody(world);
ASSERT_EQ(GetBodies(world).size(), std::size_t(1));
EXPECT_EQ(GetWorldIndex(world, body0), BodyCounter(0));
const auto body1 = CreateBody(world);
ASSERT_EQ(GetBodies(world).size(), std::size_t(2));
EXPECT_EQ(GetWorldIndex(world, body1), BodyCounter(1));
const auto body2 = CreateBody(world);
ASSERT_EQ(GetBodies(world).size(), std::size_t(3));
EXPECT_EQ(GetWorldIndex(world, body2), BodyCounter(2));
EXPECT_EQ(GetWorldIndex(world, InvalidBodyID), BodyCounter(-1));
}
TEST(WorldBody, ApplyLinearAccelDoesNothingToStatic)
{
auto world = World{};
const auto body = CreateBody(world);
ASSERT_NE(body, InvalidBodyID);
ASSERT_FALSE(IsAwake(world, body));
ASSERT_FALSE(IsSpeedable(world, body));
ASSERT_FALSE(IsAccelerable(world, body));
const auto zeroAccel = LinearAcceleration2{
};
const auto linAccel = LinearAcceleration2{
};
SetAcceleration(world, body, GetLinearAcceleration(world, body) + linAccel);
EXPECT_NE(GetLinearAcceleration(world, body), linAccel);
EXPECT_EQ(GetLinearAcceleration(world, body), zeroAccel);
}
TEST(WorldBody, GetAccelerationFF)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
ASSERT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
ASSERT_EQ(GetAngularAcceleration(world, body), AngularAcceleration{});
EXPECT_EQ(GetAcceleration(world, body), Acceleration());
}
TEST(WorldBody, SetAccelerationFF)
{
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
ASSERT_EQ(GetLinearAcceleration(world, body), LinearAcceleration2{});
ASSERT_EQ(GetAngularAcceleration(world, body), AngularAcceleration{});
const auto newAccel = Acceleration{
};
SetAcceleration(world, body, newAccel);
EXPECT_EQ(GetAcceleration(world, body), newAccel);
}
{
auto world = World{};
const auto l1 = Length2{-8_m, 0_m};
const auto l2 = Length2{+8_m, 0_m};
const auto l3 = Length2{+16_m, 0_m};
const auto shape = Shape{DiskShapeConf{}.UseRadius(2_m).UseDensity(1e10_kgpm2)};
const auto b1 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(l1));
CreateFixture(world, b1, shape);
EXPECT_EQ(CalcGravitationalAcceleration(world, b1).linear, LinearAcceleration2());
EXPECT_EQ(CalcGravitationalAcceleration(world, b1).angular, AngularAcceleration());
const auto b2 = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(l2));
CreateFixture(world, b2, shape);
const auto accel = CalcGravitationalAcceleration(world, b1);
EXPECT_NEAR(static_cast<double>(Real(GetX(accel.linear)/MeterPerSquareSecond)),
0.032761313021183014, 0.032761313021183014/100);
EXPECT_EQ(GetY(accel.linear), 0 * MeterPerSquareSecond);
EXPECT_EQ(accel.angular, 0 * RadianPerSquareSecond);
const auto b3 = CreateBody(world, BodyConf{}.UseType(BodyType::Static).UseLocation(l3));
EXPECT_EQ(CalcGravitationalAcceleration(world, b3), Acceleration{});
}
TEST(WorldBody, RotateAboutWorldPointFF)
{
auto world = World{};
const auto body = CreateBody(world);
const auto locationA = GetLocation(world, body);
ASSERT_EQ(locationA, Length2(0_m, 0_m));
RotateAboutWorldPoint(world, body, 90_deg, Length2{2_m, 0_m});
const auto locationB = GetLocation(world, body);
EXPECT_NEAR(static_cast<double>(Real(GetX(locationB)/Meter)), +2.0, 0.001);
EXPECT_NEAR(static_cast<double>(Real(GetY(locationB)/Meter)), -2.0, 0.001);
}
TEST(WorldBody, RotateAboutLocalPointFF)
{
auto world = World{};
const auto body = CreateBody(world);
const auto locationA = GetLocation(world, body);
ASSERT_EQ(locationA, Length2(0_m, 0_m));
RotateAboutLocalPoint(world, body, 90_deg, Length2{2_m, 0_m});
const auto locationB = GetLocation(world, body);
EXPECT_NEAR(static_cast<double>(Real(GetX(locationB)/Meter)), +2.0, 0.001);
EXPECT_NEAR(static_cast<double>(Real(GetY(locationB)/Meter)), -2.0, 0.001);
}
TEST(WorldBody, GetCentripetalForce)
{
const auto l1 = Length2{-8_m, 0_m};
auto world = World{};
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic).UseLocation(l1));
const auto shape = Shape{DiskShapeConf{}.UseRadius(2_m).UseDensity(1_kgpm2)};
CreateFixture(world, body, shape);
SetVelocity(world, body, LinearVelocity2{2_mps, 3_mps});
EXPECT_EQ(GetLinearVelocity(world, body), LinearVelocity2(2_mps, 3_mps));
const auto force = GetCentripetalForce(world, body, Length2{1_m, 10_m});
EXPECT_NEAR(static_cast<double>(Real(GetX(force)/Newton)), 8.1230141222476959, 0.01);
EXPECT_NEAR(static_cast<double>(Real(GetY(force)/Newton)), 9.0255714952945709, 0.01);
}
TEST(WorldBody, GetPositionFF)
{
const auto position = Position{Length2{-33_m, +4_m}, 10_deg};
auto world = World{};
auto body = CreateBody(world);
EXPECT_NE(GetPosition(world, body), position);
SetLocation(world, body, position.linear);
SetAngle(world, body, position.angular);
EXPECT_EQ(GetPosition(world, body).linear, position.linear);
EXPECT_NEAR(static_cast<double>(Real(GetPosition(world, body).angular / Degree)),
static_cast<double>(Real(position.angular / Degree)),
0.0001);
}
TEST(WorldBody, GetSetTransformationFF)
{
const auto xfm0 = Transformation{Length2{-33_m, +4_m}, UnitVec::GetTopRight()};
auto world = World{};
auto body = CreateBody(world);
EXPECT_NE(GetTransformation(world, body), xfm0);
SetTransformation(world, body, xfm0);
const auto xfm1 = GetTransformation(world, body);
EXPECT_EQ(xfm1.p, xfm0.p);
EXPECT_NEAR(static_cast<double>(GetX(xfm1.q)), static_cast<double>(GetX(xfm0.q)), 0.0001);
EXPECT_NEAR(static_cast<double>(GetY(xfm1.q)), static_cast<double>(GetY(xfm0.q)), 0.0001);
}
TEST(WorldBody, SetAwake)
{
{
World world;
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Dynamic));
EXPECT_NO_THROW(UnsetAwake(world, body));
EXPECT_FALSE(IsAwake(world, body));
EXPECT_NO_THROW(SetAwake(world, body));
EXPECT_TRUE(IsAwake(world, body));
}
{
World world;
const auto body = CreateBody(world, BodyConf{}.UseType(BodyType::Static));
EXPECT_NO_THROW(UnsetAwake(world, body));
EXPECT_FALSE(IsAwake(world, body));
EXPECT_NO_THROW(SetAwake(world, body));
EXPECT_FALSE(IsAwake(world, body)); // because Static, !IsSpeedable
}
}
TEST(WorldBody, GetBodyRange)
{
auto world = World{};
auto body = InvalidBodyID;
EXPECT_EQ(GetBodyRange(world), BodyCounter(0));
EXPECT_EQ(GetBodyCount(world), BodyCounter(0));
ASSERT_NO_THROW(body = CreateBody(world));
EXPECT_EQ(GetBodyRange(world), BodyCounter(1));
for (auto i = 1; i < 10; ++i) {
ASSERT_NO_THROW(CreateBody(world));
}
EXPECT_EQ(GetBodyRange(world), BodyCounter(10));
ASSERT_NO_THROW(Destroy(world, body));
EXPECT_EQ(GetBodyRange(world), BodyCounter(10));
EXPECT_EQ(GetBodyCount(world), BodyCounter(9));
ASSERT_NO_THROW(body = CreateBody(world));
EXPECT_EQ(GetBodyRange(world), BodyCounter(10));
EXPECT_EQ(GetBodyCount(world), BodyCounter(10));
ASSERT_NO_THROW(Clear(world));
EXPECT_EQ(GetBodyCount(world), BodyCounter(0));
EXPECT_EQ(GetBodyRange(world), BodyCounter(0));
ASSERT_NO_THROW(body = CreateBody(world));
EXPECT_EQ(GetBodyCount(world), BodyCounter(1));
EXPECT_EQ(GetBodyRange(world), BodyCounter(1));
ASSERT_NO_THROW(Destroy(world, body));
EXPECT_EQ(GetBodyCount(world), BodyCounter(0));
EXPECT_EQ(GetBodyRange(world), BodyCounter(1));
}
playrho::d2::GetShape
const Shape & GetShape(const FixtureConf &conf) noexcept
Gets the shape of the given configuration.
Definition: FixtureConf.hpp:126
playrho::d2::SetAcceleration
void SetAcceleration(Body &body, Acceleration value) noexcept
Sets the accelerations on the given body.
Definition: Body.hpp:1032
playrho::d2::GetRotInertia
RotInertia GetRotInertia(const Body &body) noexcept
Gets the rotational inertia of the body.
Definition: Body.hpp:1130
playrho::BodyType::Static
@ Static
Static body type.
playrho::RadianPerSquareSecond
constexpr auto RadianPerSquareSecond
Radian per square second unit of angular acceleration.
Definition: Units.hpp:394
playrho::MeterPerSquareSecond
constexpr auto MeterPerSquareSecond
Meter per square second unit of linear acceleration.
Definition: Units.hpp:345
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::Torque
PLAYRHO_QUANTITY(boost::units::si::torque) Torque
Torque quantity.
Definition: Units.hpp:255
playrho::d2
Name space for 2-dimensionally related PlayRho names.
Definition: AABB.cpp:34
playrho::NOT_USED
void NOT_USED(T &&...)
"Not used" annotator.
Definition: Templates.hpp:98
playrho::d2::RotateAboutWorldPoint
void RotateAboutWorldPoint(World &world, BodyID body, Angle amount, Length2 worldPoint)
Rotates a body a given amount around a point in world coordinates.
Definition: WorldBody.cpp:148
playrho::Kilogram
constexpr auto Kilogram
Kilogram unit of mass.
Definition: Units.hpp:352
playrho::d2::UnitVec::GetRight
static constexpr UnitVec GetRight() noexcept
Gets the right-ward oriented unit vector.
Definition: UnitVec.hpp:74
playrho::d2::IsFixedRotation
bool IsFixedRotation(const Body &body) noexcept
Does this body have fixed rotation?
Definition: Body.hpp:938
playrho::d2::GetCentripetalForce
Force2 GetCentripetalForce(const World &world, BodyID id, Length2 axis)
Gets the centripetal force necessary to put the body into an orbit having the given radius.
Definition: WorldBody.cpp:483
playrho::d2::GetJoints
SizedRange< std::vector< std::pair< BodyID, JointID > >::const_iterator > GetJoints(const World &world, BodyID id)
Gets the range of all joints attached to the identified body.
Definition: WorldBody.cpp:407
playrho::d2::GetMass
Mass GetMass(const Body &body) noexcept
Gets the mass of the body.
Definition: Body.hpp:1082
playrho::d2::GetPosition
constexpr Position GetPosition(const Position pos0, const Position pos1, const Real beta) noexcept
Gets the position between two positions at a given unit interval.
Definition: Position.hpp:137
playrho::d2::Transformation::p
Length2 p
Translational portion of the transformation.
Definition: Transformation.hpp:45
playrho::d2::SetAngle
void SetAngle(World &world, BodyID body, Angle value)
Sets the body's angular orientation.
Definition: WorldBody.cpp:143
playrho::d2::IsAwake
bool IsAwake(const Body &body) noexcept
Gets the awake/asleep state of this body.
Definition: Body.hpp:808
playrho::d2::Clear
void Clear(Island &island) noexcept
Clears the island containers.
Definition: Island.cpp:145
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::Newton
constexpr auto Newton
Newton unit of force.
Definition: Units.hpp:403
playrho::d2::ShapeBuilder::UseDensity
constexpr ConcreteConf & UseDensity(NonNegative< AreaDensity > value) noexcept
Uses the given density.
Definition: ShapeConf.hpp:111
playrho::d2::GetMaxVertexRadius
Length GetMaxVertexRadius(const WorldImpl &world) noexcept
Gets the maximum vertex radius that shapes in this world can be.
Definition: WorldImplMisc.cpp:142
playrho::GetX
constexpr auto & GetX(T &value)
Gets the "X" element of the given value - i.e. the first element.
Definition: Math.hpp:66
playrho
Name space for all PlayRho related names.
Definition: AABB.cpp:33
playrho::d2::GetBodyRange
BodyCounter GetBodyRange(const World &world) noexcept
Gets the extent of the currently valid body range.
Definition: WorldBody.cpp:42
playrho::d2::SetType
void SetType(Body &body, BodyType value) noexcept
Sets the type of this body.
Definition: Body.hpp:699
playrho::d2::BodyConf::type
BodyType type
Type of the body: static, kinematic, or dynamic.
Definition: BodyConf.hpp:108
playrho::Vec2
Vector2< Real > Vec2
Vector with 2 Real elements.
Definition: Vector2.hpp:39
playrho::d2::GetAngularVelocity
AngularVelocity GetAngularVelocity(const Body &body) noexcept
Gets the angular velocity.
Definition: Body.hpp:1178
playrho::BodyCounter
std::remove_const< decltype(MaxBodies)>::type BodyCounter
Count type for bodies.
Definition: Settings.hpp:217
playrho::RadianPerSecond
constexpr auto RadianPerSecond
Radian per second unit of angular velocity.
Definition: Units.hpp:384
playrho::d2::World
Definition of an independent and simulatable "world".
Definition: World.hpp:129
playrho::InvalidFixtureID
constexpr auto InvalidFixtureID
Invalid fixture ID value.
Definition: FixtureID.hpp:33
playrho::LinearVelocity2
Vector2< LinearVelocity > LinearVelocity2
2-element vector of linear velocity (LinearVelocity) quantities.
Definition: Vector2.hpp:47
playrho::NewtonMeterSecond
constexpr auto NewtonMeterSecond
Newton meter second unit of angular momentum.
Definition: Units.hpp:418
playrho::d2::DestroyFixtures
void DestroyFixtures(World &world, BodyID id, bool resetMassData)
Destroys fixtures of the identified body.
Definition: WorldBody.cpp:266
playrho::d2::GetFixtures
SizedRange< std::vector< FixtureID >::const_iterator > GetFixtures(const World &world, BodyID id)
Gets the range of all constant fixtures attached to the given body.
Definition: WorldBody.cpp:79
playrho::d2::FixtureConf
Fixture definition.
Definition: FixtureConf.hpp:46
playrho::d2::IsMassDataDirty
bool IsMassDataDirty(const Body &body) noexcept
Gets whether the mass data for this body is "dirty".
Definition: Body.hpp:954
playrho::detail::MassData
Mass data.
Definition: MassData.hpp:41
playrho::d2::size
std::size_t size(const DynamicTree &tree) noexcept
Gets the "size" of the given tree.
Definition: DynamicTree.hpp:773
playrho::d2::SetMassData
void SetMassData(World &world, BodyID id, const MassData &massData)
Sets the mass properties to override the mass properties of the fixtures.
Definition: WorldBody.cpp:365
playrho::d2::Awaken
bool Awaken(Body &body) noexcept
Awakens the body if it's asleep.
Definition: Body.hpp:1056
playrho::Degree
constexpr auto Degree
Degree unit of angle quantity.
Definition: Units.hpp:374
playrho::d2::SetFixedRotation
void SetFixedRotation(Body &body, bool value)
Sets this body to have fixed rotation.
Definition: Body.hpp:947
playrho::d2::UnsetAwake
void UnsetAwake(Body &body) noexcept
Sets this body to asleep if sleeping is allowed.
Definition: Body.hpp:837
playrho::d2::IsEnabled
bool IsEnabled(const Body &body) noexcept
Gets the enabled/disabled state of the body.
Definition: Body.hpp:771
playrho::AngularAcceleration
PLAYRHO_QUANTITY(boost::units::si::angular_acceleration) AngularAcceleration
Angular acceleration quantity.
Definition: Units.hpp:235
playrho::LinearAcceleration2
Vector2< LinearAcceleration > LinearAcceleration2
2-element vector of linear acceleration (LinearAcceleration) quantities.
Definition: Vector2.hpp:51
playrho::d2::PolygonShapeConf
Polygon shape configuration.
Definition: PolygonShapeConf.hpp:42
playrho::Meter
constexpr auto Meter
Meter unit of Length.
Definition: Units.hpp:337
playrho::SquareMeter
constexpr auto SquareMeter
Square meter unit of area.
Definition: Units.hpp:356
playrho::empty
constexpr bool empty(IndexPair3 pairs) noexcept
Checks whether the given collection of index pairs is empty.
Definition: IndexPair.hpp:69
playrho::d2::UnitVec::GetTopRight
static constexpr UnitVec GetTopRight() noexcept
Gets the 45 degree unit vector.
Definition: UnitVec.hpp:99
playrho::d2::GetBodiesForProxies
SizedRange< std::vector< BodyID >::const_iterator > GetBodiesForProxies(const World &world) noexcept
Gets the bodies-for-proxies range for the given world.
Definition: WorldBody.cpp:53
playrho::d2::RotateAboutLocalPoint
void RotateAboutLocalPoint(World &world, BodyID body, Angle amount, Length2 localPoint)
Rotates a body a given amount around a point in body local coordinates.
Definition: WorldBody.cpp:161
playrho::d2::Destroy
void Destroy(World &world, BodyID id)
Destroys the identified body.
Definition: WorldBody.cpp:73
playrho::d2::GetAngle
Angle GetAngle(const UnitVec value)
Gets the angle of the given unit vector.
Definition: Math.hpp:718
playrho::d2::SetEnabled
void SetEnabled(Body &body) noexcept
Sets the enabled state.
Definition: Body.hpp:779
playrho::d2::SetLocation
void SetLocation(World &world, BodyID body, Length2 value)
Sets the body's location.
Definition: WorldBody.cpp:138
playrho::InvalidBodyID
constexpr auto InvalidBodyID
Invalid body ID value.
Definition: BodyID.hpp:33
playrho::d2::UnitVec::GetLeft
static constexpr UnitVec GetLeft() noexcept
Gets the left-ward oriented unit vector.
Definition: UnitVec.hpp:86
playrho::AngularMomentum
PLAYRHO_QUANTITY(boost::units::si::angular_momentum) AngularMomentum
Angular momentum quantity.
Definition: Units.hpp:304
playrho::d2::SetTransform
void SetTransform(World &world, BodyID id, Length2 location, Angle angle)
Sets the position of the body's origin and rotation.
Definition: WorldBody.hpp:213
playrho::d2::GetBodyCount
BodyCounter GetBodyCount(const World &world) noexcept
Gets the body count in the given world.
Definition: WorldBody.hpp:808
playrho::d2::GetVertexRadius
NonNegative< Length > GetVertexRadius(const DistanceProxy &arg) noexcept
Gets the vertex radius property of a given distance proxy.
Definition: DistanceProxy.hpp:205
playrho::InvalidArgument
Invalid argument logic error.
Definition: InvalidArgument.hpp:33
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::DiskShapeConf::UseRadius
constexpr DiskShapeConf & UseRadius(NonNegative< Length > r) noexcept
Uses the given value as the radius.
Definition: DiskShapeConf.hpp:65
playrho::d2::BodyConf
Configuration for a body.
Definition: BodyConf.hpp:50
playrho::d2::GetLocation
constexpr Length2 GetLocation(const Transformation &value) noexcept
Gets the location information from the given transformation.
Definition: Transformation.hpp:69
playrho::d2::CalcGravitationalAcceleration
Acceleration CalcGravitationalAcceleration(const World &world, BodyID body)
Calculates the gravitationally associated acceleration for the given body within its world.
Definition: WorldBody.cpp:166
playrho::d2::Velocity
2-D velocity related data structure.
Definition: Velocity.hpp:38
playrho::SquareSecond
constexpr auto SquareSecond
Square second unit.
Definition: Units.hpp:324
playrho::d2::SetVelocity
void SetVelocity(Body &body, const Velocity &value) noexcept
Sets the body's velocity (linear and angular velocity).
Definition: Body.hpp:1158
playrho::d2::ApplyLinearImpulse
void ApplyLinearImpulse(Body &body, Momentum2 impulse, Length2 point) noexcept
Applies an impulse at a point.
Definition: Body.cpp:242
playrho::d2::GetMinVertexRadius
Length GetMinVertexRadius(const WorldImpl &world) noexcept
Gets the minimum vertex radius that shapes in this world can be.
Definition: WorldImplMisc.cpp:137
playrho::SquareRadian
constexpr auto SquareRadian
Square radian unit type.
Definition: Units.hpp:379
playrho::d2::GetAcceleration
Acceleration GetAcceleration(const Body &body) noexcept
Gets the given body's acceleration.
Definition: Body.hpp:1020
playrho::d2::Position
2-D positional data structure.
Definition: Position.hpp:37
playrho::d2::ResetMassData
void ResetMassData(World &world, BodyID id)
Resets the mass data properties.
Definition: WorldBody.hpp:611
playrho::Vector
Vector.
Definition: Vector.hpp:49
playrho::d2::Position::linear
Length2 linear
Linear position.
Definition: Position.hpp:38
playrho::d2::GetWorldCenter
Length2 GetWorldCenter(const Body &body) noexcept
Get the world position of the center of mass.
Definition: Body.hpp:908
playrho::d2::GetFixtureCount
FixtureCounter GetFixtureCount(const World &world, BodyID id)
Gets the count of fixtures associated with the identified body.
Definition: WorldBody.hpp:129
playrho::d2::SetAwake
void SetAwake(Body &body) noexcept
Awakens this body.
Definition: Body.hpp:822
playrho::d2::ApplyForce
void ApplyForce(World &world, BodyID id, Force2 force, Length2 point)
Apply a force at a world point.
Definition: WorldBody.cpp:499
playrho::d2::GetType
TypeID GetType(const Shape &shape) noexcept
Gets the type info of the use of the given shape.
Definition: Shape.hpp:329
playrho::d2::GetAngularAcceleration
AngularAcceleration GetAngularAcceleration(const Body &body) noexcept
Gets this body's angular acceleration.
Definition: Body.hpp:1048
playrho::d2::Transformation
Describes a geometric transformation.
Definition: Transformation.hpp:44
playrho::d2::GetBody
BodyID GetBody(const FixtureConf &conf) noexcept
Gets the body of the given configuration.
Definition: FixtureConf.hpp:119
playrho::d2::Acceleration
2-D acceleration related data structure.
Definition: Acceleration.hpp:33
playrho::d2::GetBodies
SizedRange< std::vector< BodyID >::const_iterator > GetBodies(const World &world) noexcept
Gets the bodies of the specified world.
Definition: WorldBody.cpp:47
playrho::d2::GetTransformation
constexpr Transformation GetTransformation(const Length2 ctr, const UnitVec rot, const Length2 localCtr) noexcept
Gets the transformation for the given values.
Definition: Math.hpp:875
playrho::d2::ApplyAngularImpulse
void ApplyAngularImpulse(Body &body, AngularMomentum impulse) noexcept
Applies an angular impulse.
Definition: Body.cpp:252
playrho::d2::DiskShapeConf::vertexRadius
NonNegative< Length > vertexRadius
Vertex radius.
Definition: DiskShapeConf.hpp:102
playrho::d2::Shape
Shape.
Definition: Shape.hpp:183
playrho::d2::GetLinearVelocity
LinearVelocity2 GetLinearVelocity(const Body &body) noexcept
Gets the linear velocity of the center of mass.
Definition: Body.hpp:1168
playrho::GetY
constexpr auto & GetY(T &value)
Gets the "Y" element of the given value - i.e. the second element.
Definition: Math.hpp:73
playrho::LinearAcceleration
PLAYRHO_QUANTITY(boost::units::si::acceleration) LinearAcceleration
Linear acceleration quantity.
Definition: Units.hpp:176
playrho::Length2
Vector2< Length > Length2
2-element vector of Length quantities.
Definition: Vector2.hpp:43
playrho::Radian
constexpr auto Radian
Radian unit of angle.
Definition: Units.hpp:369
playrho::d2::GetWorldIndex
BodyCounter GetWorldIndex(const World &world, BodyID id) noexcept
Gets the world index for the given body.
Definition: WorldBody.cpp:202
playrho::d2::IsSpeedable
bool IsSpeedable(const Body &body) noexcept
Is "speedable".
Definition: Body.hpp:708
playrho::d2::IsAccelerable
bool IsAccelerable(const Body &body) noexcept
Is "accelerable".
Definition: Body.hpp:718
playrho::d2::IsImpenetrable
bool IsImpenetrable(const Body &body) noexcept
Is this body treated like a bullet for continuous collision detection?
Definition: Body.hpp:726
playrho::d2::GetVelocity
Velocity GetVelocity(const Body &body, Time h) noexcept
Gets the velocity of the body after the given time accounting for the body's acceleration and capped ...
Definition: Body.cpp:221
playrho::d2::GetLinearAcceleration
LinearAcceleration2 GetLinearAcceleration(const Body &body) noexcept
Gets this body's linear acceleration.
Definition: Body.hpp:1040
playrho::LinearVelocity
PLAYRHO_QUANTITY(boost::units::si::velocity) LinearVelocity
Linear velocity quantity.
Definition: Units.hpp:167
playrho::d2::ApplyTorque
void ApplyTorque(World &world, BodyID id, Torque torque)
Applies a torque.
Definition: WorldBody.cpp:514
playrho::AngularVelocity
PLAYRHO_QUANTITY(boost::units::si::angular_velocity) AngularVelocity
Angular velocity quantity.
Definition: Units.hpp:225
playrho::d2::DiskShapeConf
Disk shape configuration.
Definition: DiskShapeConf.hpp:42
playrho::d2::SetTransformation
void SetTransformation(Body &body, Transformation value) noexcept
Sets the body's transformation.
Definition: Body.hpp:854