Physics2D tests (#129)
* Quaternion: Fix singularity on Z axis when converting to euler angles * CollisionComponent2D: Add method to retrieve AABB * Collider2D: Fix constructor for Box with Vector2 * Physics2D: Fix rotation (Chipmunk works with radian and Nazara degrees) and copy constructor of RigidBody2D * Colider2D: Add New for convex and tests for the new classes
This commit is contained in:
committed by
Jérôme Leclercq
parent
9806231b5c
commit
41a1b5d493
@@ -173,15 +173,52 @@ SCENARIO("Quaternion", "[MATH][QUATERNION]")
|
||||
|
||||
WHEN("We get the rotation between two vectors")
|
||||
{
|
||||
/*TODO
|
||||
* Nz::Quaternionf rotationBetweenXY = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitY());
|
||||
Nz::Quaternionf rotationBetweenXY = Nz::Quaternionf::RotationBetween(Nz::Vector3f::UnitX(), Nz::Vector3f::UnitY());
|
||||
|
||||
THEN("The rotation in left-handed is 270 degree on z")
|
||||
THEN("The rotation in right-handed is 90 degree on z")
|
||||
{
|
||||
Nz::Quaternionf rotation270Z(Nz::FromDegrees(270.f), Nz::Vector3f::UnitZ());
|
||||
Nz::Quaternionf rotation90Z(Nz::FromDegrees(90.f), Nz::Vector3f::UnitZ());
|
||||
REQUIRE(rotation90Z == rotationBetweenXY);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("Different angles")
|
||||
{
|
||||
Nz::Quaternionf rotation90X(0.707f, 0.707f, 0.f, 0.f);
|
||||
Nz::Quaternionf rotation90Y(0.707f, 0.f, 0.707f, 0.f);
|
||||
Nz::Quaternionf rotation90Z(0.707f, 0.f, 0.f, 0.707f);
|
||||
|
||||
Nz::Quaternionf rotation180X(0.f, 1.f, 0.f, 0.f);
|
||||
Nz::Quaternionf rotation180Y(0.f, 0.f, 1.f, 0.f);
|
||||
Nz::Quaternionf rotation180Z(0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
Nz::Quaternionf rotation270X(-0.707f, 0.707f, 0.f, 0.f);
|
||||
Nz::Quaternionf rotation270Y(-0.707f, 0.f, 0.707f, 0.f);
|
||||
Nz::Quaternionf rotation270Z(-0.707f, 0.f, 0.f, 0.707f);
|
||||
|
||||
Nz::Quaternionf special(0.707f, 0.006f, 0.006f, 0.707f);
|
||||
|
||||
WHEN("We convert them to euler angles")
|
||||
{
|
||||
THEN("Those are equal to")
|
||||
{
|
||||
CHECK(Nz::NumberEquals(rotation90X.ToEulerAngles().pitch, Nz::FromDegrees(90.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(rotation90Y.ToEulerAngles().yaw, Nz::FromDegrees(90.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(rotation90Z.ToEulerAngles().roll, Nz::FromDegrees(90.f), 0.1f));
|
||||
|
||||
CHECK(rotation180X == Nz::EulerAnglesf(180.f, 0.f, 0.f));
|
||||
CHECK(rotation180Y == Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
||||
CHECK(rotation180Z == Nz::EulerAnglesf(0.f, 0.f, 180.f));
|
||||
|
||||
CHECK(Nz::NumberEquals(rotation270X.ToEulerAngles().pitch, Nz::FromDegrees(-90.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(rotation270Y.ToEulerAngles().yaw, Nz::FromDegrees(-90.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(rotation270Z.ToEulerAngles().roll, Nz::FromDegrees(-90.f), 0.1f));
|
||||
|
||||
CHECK(Nz::NumberEquals(special.ToEulerAngles().pitch, Nz::FromDegrees(0.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(special.ToEulerAngles().yaw, Nz::FromDegrees(1.f), 0.1f));
|
||||
CHECK(Nz::NumberEquals(special.ToEulerAngles().roll, Nz::FromDegrees(90.f), 0.1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
133
tests/Engine/Physics2D/Collider2D.cpp
Normal file
133
tests/Engine/Physics2D/Collider2D.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <Nazara/Physics2D/Collider2D.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
SCENARIO("Collider2D", "[PHYSICS2D][COLLIDER2D]")
|
||||
{
|
||||
GIVEN("No particular elements")
|
||||
{
|
||||
WHEN("We construct a box with Rect")
|
||||
{
|
||||
Nz::Rectf aabb(5.f, 3.f, 10.f, 6.f);
|
||||
Nz::BoxCollider2D box(aabb);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(box.GetRect() == aabb);
|
||||
CHECK(box.GetSize() == aabb.GetLengths());
|
||||
CHECK(box.GetType() == Nz::ColliderType2D_Box);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a box with Vector2D")
|
||||
{
|
||||
Nz::Vector2f vec(5.f, 3.f);
|
||||
Nz::Rectf aabb(-2.5f, -1.5f, 5.f, 3.f);
|
||||
Nz::BoxCollider2D box(vec);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(box.GetRect() == aabb);
|
||||
CHECK(box.GetSize() == vec);
|
||||
CHECK(box.GetType() == Nz::ColliderType2D_Box);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a circle")
|
||||
{
|
||||
Nz::Vector2f position(5.f, 3.f);
|
||||
float radius = 7.f;
|
||||
Nz::CircleCollider2D circle(radius, position);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(circle.GetRadius() == Approx(radius));
|
||||
CHECK(circle.GetType() == Nz::ColliderType2D_Circle);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a compound")
|
||||
{
|
||||
Nz::Rectf aabb(0.f, 0.f, 1.f, 1.f);
|
||||
Nz::BoxCollider2DRef box1 = Nz::BoxCollider2D::New(aabb);
|
||||
aabb.Translate(Nz::Vector2f::Unit());
|
||||
Nz::BoxCollider2DRef box2 = Nz::BoxCollider2D::New(aabb);
|
||||
|
||||
std::vector<Nz::Collider2DRef> colliders;
|
||||
colliders.push_back(box1);
|
||||
colliders.push_back(box2);
|
||||
Nz::CompoundCollider2D compound(colliders);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(compound.GetType() == Nz::ColliderType2D_Compound);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a convex")
|
||||
{
|
||||
std::vector<Nz::Vector2f> vertices;
|
||||
vertices.push_back(Nz::Vector2f(0.f, 0.f));
|
||||
vertices.push_back(Nz::Vector2f(0.f, 1.f));
|
||||
vertices.push_back(Nz::Vector2f(1.f, 1.f));
|
||||
vertices.push_back(Nz::Vector2f(1.f, 0.f));
|
||||
|
||||
Nz::ConvexCollider2D convex(Nz::SparsePtr<const Nz::Vector2f>(vertices.data()), vertices.size());
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(convex.GetType() == Nz::ColliderType2D_Convex);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a null")
|
||||
{
|
||||
Nz::NullCollider2D null;
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(null.GetType() == Nz::ColliderType2D_Null);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We construct a segment")
|
||||
{
|
||||
Nz::Vector2f firstPoint(2.f, 1.f);
|
||||
Nz::Vector2f secondPoint(-4.f, -3.f);
|
||||
Nz::SegmentCollider2D segment(firstPoint, secondPoint);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(segment.GetFirstPoint() == firstPoint);
|
||||
CHECK(segment.GetLength() == firstPoint.Distance(secondPoint));
|
||||
CHECK(segment.GetSecondPoint() == secondPoint);
|
||||
CHECK(segment.GetType() == Nz::ColliderType2D_Segment);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We verify general purpose methods")
|
||||
{
|
||||
Nz::Rectf aabb(5.f, 3.f, 10.f, 6.f);
|
||||
Nz::BoxCollider2D box(aabb);
|
||||
|
||||
Nz::UInt32 categoryMask = 1;
|
||||
Nz::UInt32 groupId = 2;
|
||||
Nz::UInt32 typeId = 3;
|
||||
Nz::UInt32 mask = 4;
|
||||
bool trigger = true;
|
||||
box.SetCategoryMask(categoryMask);
|
||||
box.SetCollisionGroup(groupId);
|
||||
box.SetCollisionId(typeId);
|
||||
box.SetCollisionMask(mask);
|
||||
box.SetTrigger(trigger);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(box.GetCategoryMask() == categoryMask);
|
||||
CHECK(box.GetCollisionGroup() == groupId);
|
||||
CHECK(box.GetCollisionId() == typeId);
|
||||
CHECK(box.GetCollisionMask() == mask);
|
||||
CHECK(box.IsTrigger() == trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
tests/Engine/Physics2D/PhysWorld2D.cpp
Normal file
114
tests/Engine/Physics2D/PhysWorld2D.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include <Nazara/Physics2D/PhysWorld2D.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world, const Nz::Vector2f& position, bool isMoving = true, const Nz::Vector2f& lengths = Nz::Vector2f::Unit());
|
||||
|
||||
Nz::UInt32 collisionGroup = 1;
|
||||
Nz::UInt32 categoryMask = 2;
|
||||
Nz::UInt32 collisionMask = 3;
|
||||
|
||||
SCENARIO("PhysWorld2D", "[PHYSICS2D][PHYSWORLD2D]")
|
||||
{
|
||||
GIVEN("A physic world and a bunch of entities on a grid")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
std::vector<Nz::RigidBody2D> bodies;
|
||||
const int numberOfBodiesPerLign = 3;
|
||||
for (int i = 0; i != numberOfBodiesPerLign; ++i)
|
||||
{
|
||||
for (int j = 0; j != numberOfBodiesPerLign; ++j)
|
||||
{
|
||||
bodies.push_back(CreateBody(world, Nz::Vector2f(10.f * i, 10.f * j)));
|
||||
}
|
||||
}
|
||||
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We ask for the nearest body")
|
||||
{
|
||||
Nz::PhysWorld2D::NearestQueryResult result;
|
||||
REQUIRE(world.NearestBodyQuery(-Nz::Vector2f::UnitY() * 1.f, 2.f, collisionGroup, categoryMask, collisionMask, &result));
|
||||
|
||||
THEN("It should be the one on the origin")
|
||||
{
|
||||
CHECK(result.nearestBody == &bodies[0]);
|
||||
CHECK(result.closestPoint == Nz::Vector2f::Zero());
|
||||
CHECK(result.fraction == -Nz::Vector2f::UnitY());
|
||||
CHECK(result.distance == Approx(1.f));
|
||||
}
|
||||
|
||||
REQUIRE(world.NearestBodyQuery(Nz::Vector2f::UnitY() * 2.f, 2.f, collisionGroup, categoryMask, collisionMask, &result));
|
||||
|
||||
THEN("It should be the one on the origin")
|
||||
{
|
||||
CHECK(result.nearestBody == &bodies[0]);
|
||||
CHECK(result.closestPoint == Nz::Vector2f::UnitY());
|
||||
CHECK(result.fraction == Nz::Vector2f::UnitY());
|
||||
CHECK(result.distance == Approx(1.f));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We ask for the first ray collision")
|
||||
{
|
||||
Nz::Vector2f origin = -Nz::Vector2f::UnitY() * 2.f;
|
||||
Nz::Vector2f end = (numberOfBodiesPerLign + 1) * 10.f * Nz::Vector2f::UnitY();
|
||||
Nz::PhysWorld2D::RaycastHit result;
|
||||
REQUIRE(world.RaycastQueryFirst(origin, end, 1.f, collisionGroup, categoryMask, collisionMask, &result));
|
||||
|
||||
THEN("It should be the one on the origin")
|
||||
{
|
||||
CHECK(result.nearestBody == &bodies[0]);
|
||||
CHECK(result.fraction == Approx(1.f / 42.f));
|
||||
CHECK(result.hitPos == Nz::Vector2f::Zero());
|
||||
CHECK(result.hitNormal == -Nz::Vector2f::UnitY());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We ask for the ray collisions")
|
||||
{
|
||||
Nz::Vector2f origin = -Nz::Vector2f::UnitY() * 2.f;
|
||||
Nz::Vector2f end = (numberOfBodiesPerLign + 1) * 10.f * Nz::Vector2f::UnitY();
|
||||
std::vector<Nz::PhysWorld2D::RaycastHit> results;
|
||||
REQUIRE(world.RaycastQuery(origin, end, 1.f, collisionGroup, categoryMask, collisionMask, &results));
|
||||
|
||||
THEN("It should be the first lign")
|
||||
{
|
||||
REQUIRE(results.size() == numberOfBodiesPerLign);
|
||||
|
||||
for (int i = 0; i != numberOfBodiesPerLign; ++i)
|
||||
{
|
||||
const Nz::PhysWorld2D::RaycastHit& result = results[i];
|
||||
CHECK(result.nearestBody == &bodies[i]);
|
||||
CHECK(result.fraction == Approx(i / 4.f).epsilon(0.1f));
|
||||
CHECK(result.hitPos == Nz::Vector2f(0.f, i * 10.f));
|
||||
CHECK(result.hitNormal == -Nz::Vector2f::UnitY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We ask for a region")
|
||||
{
|
||||
std::vector<Nz::RigidBody2D*> results;
|
||||
world.RegionQuery(Nz::Rectf(-5.f, -5.f, 5.f, 5.f), collisionGroup, categoryMask, collisionMask, &results);
|
||||
|
||||
THEN("It should be the one on the origin")
|
||||
{
|
||||
REQUIRE(results.size() == 1);
|
||||
CHECK(results[0] == &bodies[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world, const Nz::Vector2f& position, bool isMoving, const Nz::Vector2f& lengths)
|
||||
{
|
||||
Nz::Rectf aabb(0.f, 0.f, lengths.x, lengths.y);
|
||||
Nz::Collider2DRef box = Nz::BoxCollider2D::New(aabb);
|
||||
box->SetCategoryMask(categoryMask);
|
||||
box->SetCollisionMask(collisionMask);
|
||||
float mass = isMoving ? 1.f : 0.f;
|
||||
Nz::RigidBody2D rigidBody(&world, mass, box);
|
||||
rigidBody.SetPosition(position);
|
||||
return rigidBody;
|
||||
}
|
||||
318
tests/Engine/Physics2D/RigidBody2D.cpp
Normal file
318
tests/Engine/Physics2D/RigidBody2D.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
||||
#include <Nazara/Physics2D/PhysWorld2D.hpp>
|
||||
#include <Catch/catch.hpp>
|
||||
|
||||
Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world);
|
||||
void EQUALITY(const Nz::RigidBody2D& left, const Nz::RigidBody2D& right);
|
||||
|
||||
SCENARIO("RigidBody2D", "[PHYSICS2D][RIGIDBODY2D]")
|
||||
{
|
||||
GIVEN("A physic world and a rigid body")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
Nz::Vector2f positionAABB(3.f, 4.f);
|
||||
Nz::Rectf aabb(positionAABB.x, positionAABB.y, 1.f, 2.f);
|
||||
Nz::Collider2DRef box = Nz::BoxCollider2D::New(aabb);
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, box);
|
||||
float angularVelocity = 0.2f;
|
||||
body.SetAngularVelocity(angularVelocity);
|
||||
Nz::Vector2f massCenter(5.f, 7.f);
|
||||
body.SetMassCenter(massCenter);
|
||||
Nz::Vector2f position(9.f, 1.f);
|
||||
body.SetPosition(position);
|
||||
float rotation = 0.1f;
|
||||
body.SetRotation(rotation);
|
||||
Nz::Vector2f velocity(-4.f, -2.f);
|
||||
body.SetVelocity(velocity);
|
||||
bool userdata = false;
|
||||
body.SetUserdata(&userdata);
|
||||
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We copy construct the body")
|
||||
{
|
||||
body.AddForce(Nz::Vector2f(3.f, 5.f));
|
||||
Nz::RigidBody2D copiedBody(body);
|
||||
EQUALITY(copiedBody, body);
|
||||
world.Step(1.f);
|
||||
EQUALITY(copiedBody, body);
|
||||
}
|
||||
|
||||
WHEN("We move construct the body")
|
||||
{
|
||||
Nz::RigidBody2D copiedBody(body);
|
||||
Nz::RigidBody2D movedBody(std::move(body));
|
||||
EQUALITY(movedBody, copiedBody);
|
||||
}
|
||||
|
||||
WHEN("We copy assign the body")
|
||||
{
|
||||
Nz::RigidBody2D copiedBody(&world, 0.f);
|
||||
copiedBody = body;
|
||||
EQUALITY(copiedBody, body);
|
||||
}
|
||||
|
||||
WHEN("We move assign the body")
|
||||
{
|
||||
Nz::RigidBody2D copiedBody(body);
|
||||
Nz::RigidBody2D movedBody(&world, 0.f);
|
||||
movedBody = std::move(body);
|
||||
EQUALITY(movedBody, copiedBody);
|
||||
}
|
||||
|
||||
WHEN("We set a new geometry")
|
||||
{
|
||||
float radius = 5.f;
|
||||
Nz::Vector2f positionCircle(0.f, 0.f);
|
||||
Nz::Collider2DRef circle = Nz::CircleCollider2D::New(radius, position);
|
||||
body.SetGeom(circle);
|
||||
|
||||
world.Step(1.f);
|
||||
|
||||
THEN("The aabb should be updated")
|
||||
{
|
||||
Nz::Rectf circleAABB(position.x - radius, position.y - radius, 2.f * radius, 2.f* radius);
|
||||
REQUIRE(body.GetAABB() == circleAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
Nz::Rectf aabb(3.f, 4.f, 1.f, 2.f);
|
||||
|
||||
WHEN("We get a rigid body from a function")
|
||||
{
|
||||
std::vector<Nz::RigidBody2D> tmp;
|
||||
tmp.push_back(CreateBody(world));
|
||||
tmp.push_back(CreateBody(world));
|
||||
world.Step(1.f);
|
||||
|
||||
THEN("They should be valid")
|
||||
{
|
||||
CHECK(tmp[0].GetAABB() == aabb);
|
||||
CHECK(tmp[1].GetAABB() == aabb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world and a rigid body")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
Nz::Vector2f positionAABB(3.f, 4.f);
|
||||
Nz::Rectf aabb(positionAABB.x, positionAABB.y, 1.f, 2.f);
|
||||
Nz::Collider2DRef box = Nz::BoxCollider2D::New(aabb);
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, box);
|
||||
bool userData = false;
|
||||
body.SetUserdata(&userData);
|
||||
|
||||
Nz::Vector2f position = Nz::Vector2f::Zero();
|
||||
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We retrieve standard information")
|
||||
{
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(body.GetAABB() == aabb);
|
||||
CHECK(body.GetAngularVelocity() == Approx(0.f));
|
||||
CHECK(body.GetCenterOfGravity() == Nz::Vector2f::Zero());
|
||||
CHECK(body.GetGeom() == box);
|
||||
CHECK(body.GetMass() == Approx(mass));
|
||||
CHECK(body.GetPosition() == position);
|
||||
CHECK(body.GetRotation() == Approx(0.f));
|
||||
CHECK(body.GetUserdata() == &userData);
|
||||
CHECK(body.GetVelocity() == Nz::Vector2f::Zero());
|
||||
|
||||
CHECK(body.IsMoveable() == true);
|
||||
CHECK(body.IsSleeping() == false);
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We set a velocity")
|
||||
{
|
||||
Nz::Vector2f velocity(Nz::Vector2f::Unit());
|
||||
body.SetVelocity(velocity);
|
||||
position += velocity;
|
||||
world.Step(1.f);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
aabb.Translate(velocity);
|
||||
CHECK(body.GetAABB() == aabb);
|
||||
CHECK(body.GetCenterOfGravity() == Nz::Vector2f::Zero());
|
||||
CHECK(body.GetPosition() == position);
|
||||
CHECK(body.GetVelocity() == velocity);
|
||||
}
|
||||
|
||||
AND_THEN("We apply an impulse in the opposite direction")
|
||||
{
|
||||
body.AddImpulse(-velocity);
|
||||
world.Step(1.f);
|
||||
|
||||
REQUIRE(body.GetVelocity() == Nz::Vector2f::Zero());
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We set an angular velocity")
|
||||
{
|
||||
float angularSpeed = Nz::FromDegrees(90.f);
|
||||
body.SetAngularVelocity(angularSpeed);
|
||||
world.Step(1.f);
|
||||
|
||||
THEN("We expect those to be true")
|
||||
{
|
||||
CHECK(body.GetAngularVelocity() == Approx(angularSpeed));
|
||||
CHECK(body.GetRotation() == Approx(angularSpeed));
|
||||
CHECK(body.GetAABB() == Nz::Rectf(-6.f, 3.f, 2.f, 1.f));
|
||||
|
||||
world.Step(1.f);
|
||||
CHECK(body.GetRotation() == Approx(2.f * angularSpeed));
|
||||
CHECK(body.GetAABB() == Nz::Rectf(-4.f, -6.f, 1.f, 2.f));
|
||||
|
||||
world.Step(1.f);
|
||||
CHECK(body.GetRotation() == Approx(3.f * angularSpeed));
|
||||
CHECK(body.GetAABB() == Nz::Rectf(4.f, -4.f, 2.f, 1.f));
|
||||
|
||||
world.Step(1.f);
|
||||
CHECK(body.GetRotation() == Approx(4.f * angularSpeed));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We apply a torque")
|
||||
{
|
||||
float angularSpeed = Nz::DegreeToRadian(90.f);
|
||||
body.AddTorque(angularSpeed);
|
||||
world.Step(1.f);
|
||||
|
||||
THEN("It is also counter-clockwise")
|
||||
{
|
||||
CHECK(body.GetAngularVelocity() >= 0.f);
|
||||
CHECK(body.GetRotation() >= 0.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world and a rigid body of circle")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
Nz::Vector2f position(3.f, 4.f);
|
||||
float radius = 5.f;
|
||||
Nz::Collider2DRef circle = Nz::CircleCollider2D::New(radius, position);
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, circle);
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We ask for the aabb of the circle")
|
||||
{
|
||||
THEN("We expect this to be true")
|
||||
{
|
||||
Nz::Rectf circleAABB(position.x - radius, position.y - radius, 2.f * radius, 2.f* radius);
|
||||
REQUIRE(body.GetAABB() == circleAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world and a rigid body of compound")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
Nz::Rectf aabb(0.f, 0.f, 1.f, 1.f);
|
||||
Nz::BoxCollider2DRef box1 = Nz::BoxCollider2D::New(aabb);
|
||||
aabb.Translate(Nz::Vector2f::Unit());
|
||||
Nz::BoxCollider2DRef box2 = Nz::BoxCollider2D::New(aabb);
|
||||
|
||||
std::vector<Nz::Collider2DRef> colliders;
|
||||
colliders.push_back(box1);
|
||||
colliders.push_back(box2);
|
||||
Nz::CompoundCollider2DRef compound = Nz::CompoundCollider2D::New(colliders);
|
||||
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, compound);
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We ask for the aabb of the compound")
|
||||
{
|
||||
THEN("We expect this to be true")
|
||||
{
|
||||
Nz::Rectf compoundAABB(0.f, 0.f, 2.f, 2.f);
|
||||
REQUIRE(body.GetAABB() == compoundAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world and a rigid body of circle")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
std::vector<Nz::Vector2f> vertices;
|
||||
vertices.push_back(Nz::Vector2f(0.f, 0.f));
|
||||
vertices.push_back(Nz::Vector2f(0.f, 1.f));
|
||||
vertices.push_back(Nz::Vector2f(1.f, 1.f));
|
||||
vertices.push_back(Nz::Vector2f(1.f, 0.f));
|
||||
|
||||
Nz::SparsePtr<const Nz::Vector2f> sparsePtr(vertices.data());
|
||||
Nz::ConvexCollider2DRef convex = Nz::ConvexCollider2D::New(sparsePtr, vertices.size());
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, convex);
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We ask for the aabb of the convex")
|
||||
{
|
||||
THEN("We expect this to be true")
|
||||
{
|
||||
Nz::Rectf convexAABB(0.f, 0.f, 1.f, 1.f);
|
||||
REQUIRE(body.GetAABB() == convexAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("A physic world and a rigid body of segment")
|
||||
{
|
||||
Nz::PhysWorld2D world;
|
||||
|
||||
Nz::Vector2f positionA(3.f, 4.f);
|
||||
Nz::Vector2f positionB(1.f, -4.f);
|
||||
Nz::Collider2DRef segment = Nz::SegmentCollider2D::New(positionA, positionB, 0.f);
|
||||
float mass = 1.f;
|
||||
Nz::RigidBody2D body(&world, mass, segment);
|
||||
world.Step(1.f);
|
||||
|
||||
WHEN("We ask for the aabb of the segment")
|
||||
{
|
||||
THEN("We expect this to be true")
|
||||
{
|
||||
Nz::Rectf segmentAABB(positionA, positionB);
|
||||
REQUIRE(body.GetAABB() == segmentAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nz::RigidBody2D CreateBody(Nz::PhysWorld2D& world)
|
||||
{
|
||||
Nz::Vector2f positionAABB(3.f, 4.f);
|
||||
Nz::Rectf aabb(positionAABB.x, positionAABB.y, 1.f, 2.f);
|
||||
Nz::Collider2DRef box = Nz::BoxCollider2D::New(aabb);
|
||||
float mass = 1.f;
|
||||
return Nz::RigidBody2D(&world, mass, box);
|
||||
}
|
||||
|
||||
void EQUALITY(const Nz::RigidBody2D& left, const Nz::RigidBody2D& right)
|
||||
{
|
||||
CHECK(left.GetAABB() == right.GetAABB());
|
||||
CHECK(left.GetAngularVelocity() == right.GetAngularVelocity());
|
||||
CHECK(left.GetCenterOfGravity() == right.GetCenterOfGravity());
|
||||
CHECK(left.GetGeom() == right.GetGeom());
|
||||
CHECK(left.GetHandle() != right.GetHandle());
|
||||
CHECK(left.GetMass() == right.GetMass());
|
||||
CHECK(left.GetPosition() == right.GetPosition());
|
||||
CHECK(left.GetRotation() == right.GetRotation());
|
||||
CHECK(left.GetUserdata() == right.GetUserdata());
|
||||
CHECK(left.GetVelocity() == right.GetVelocity());
|
||||
}
|
||||
Reference in New Issue
Block a user