Push the current work on the Physics2D module

This commit is contained in:
Lynix
2016-10-14 17:07:13 +02:00
parent 080db76ac1
commit 9a7767867b
16 changed files with 883 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Collider2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <chipmunk/chipmunk.h>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
Collider2D::~Collider2D() = default;
/******************************** CircleCollider2D *********************************/
CircleCollider2D::CircleCollider2D(float radius, const Vector2f& offset) :
m_offset(offset),
m_radius(radius)
{
}
float CircleCollider2D::ComputeInertialMatrix(float mass) const
{
return cpMomentForCircle(mass, 0.f, m_radius, cpv(m_offset.x, m_offset.y));
}
ColliderType2D CircleCollider2D::GetType() const
{
return ColliderType2D_Circle;
}
std::vector<cpShape*> CircleCollider2D::CreateShapes(RigidBody2D* body) const
{
std::vector<cpShape*> shapes;
shapes.push_back(cpCircleShapeNew(body->GetHandle(), m_radius, cpv(m_offset.x, m_offset.y)));
return shapes;
}
/********************************* NullCollider2D **********************************/
ColliderType2D NullCollider2D::GetType() const
{
return ColliderType2D_Null;
}
float NullCollider2D::ComputeInertialMatrix(float mass) const
{
return 0.f;
}
std::vector<cpShape*> NullCollider2D::CreateShapes(RigidBody2D* body) const
{
return std::vector<cpShape*>();
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics3D/Config.hpp>
#if NAZARA_PHYSICS_MANAGE_MEMORY
#include <Nazara/Core/MemoryManager.hpp>
#include <new> // Nécessaire ?
void* operator new(std::size_t size)
{
return Nz::MemoryManager::Allocate(size, false);
}
void* operator new[](std::size_t size)
{
return Nz::MemoryManager::Allocate(size, true);
}
void operator delete(void* pointer) noexcept
{
Nz::MemoryManager::Free(pointer, false);
}
void operator delete[](void* pointer) noexcept
{
Nz::MemoryManager::Free(pointer, true);
}
#endif // NAZARA_PHYSICS_MANAGE_MEMORY

View File

@@ -0,0 +1,60 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <chipmunk/chipmunk.h>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
PhysWorld2D::PhysWorld2D() :
m_stepSize(0.005f),
m_timestepAccumulator(0.f)
{
m_handle = cpSpaceNew();
cpSpaceSetUserData(m_handle, this);
}
PhysWorld2D::~PhysWorld2D()
{
cpSpaceFree(m_handle);
}
Vector2f PhysWorld2D::GetGravity() const
{
cpVect gravity = cpSpaceGetGravity(m_handle);
return Vector2f(gravity.x, gravity.y);
}
cpSpace* PhysWorld2D::GetHandle() const
{
return m_handle;
}
float PhysWorld2D::GetStepSize() const
{
return m_stepSize;
}
void PhysWorld2D::SetGravity(const Vector2f& gravity)
{
cpSpaceSetGravity(m_handle, cpv(gravity.x, gravity.y));
}
void PhysWorld2D::SetStepSize(float stepSize)
{
m_stepSize = stepSize;
}
void PhysWorld2D::Step(float timestep)
{
m_timestepAccumulator += timestep;
while (m_timestepAccumulator >= m_stepSize)
{
cpSpaceStep(m_handle, m_stepSize);
m_timestepAccumulator -= m_stepSize;
}
}
}

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Physics2D.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
bool Physics2D::Initialize()
{
if (s_moduleReferenceCounter > 0)
{
s_moduleReferenceCounter++;
return true; // Déjà initialisé
}
// Initialisation des dépendances
if (!Core::Initialize())
{
NazaraError("Failed to initialize core module");
return false;
}
s_moduleReferenceCounter++;
NazaraNotice("Initialized: Physics2D module");
return true;
}
bool Physics2D::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
void Physics2D::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
// Le module est soit encore utilisé, soit pas initialisé
if (s_moduleReferenceCounter > 1)
s_moduleReferenceCounter--;
return;
}
// Libération du module
s_moduleReferenceCounter = 0;
NazaraNotice("Uninitialized: Physics2D module");
// Libération des dépendances
Core::Uninitialize();
}
unsigned int Physics2D::s_moduleReferenceCounter = 0;
}

View File

@@ -0,0 +1,266 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Physics 3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <chipmunk/chipmunk.h>
#include <chipmunk/chipmunk_private.h>
#include <algorithm>
#include <Nazara/Physics3D/Debug.hpp>
namespace Nz
{
RigidBody2D::RigidBody2D(PhysWorld2D* world, float mass) :
RigidBody2D(world, mass, nullptr)
{
}
RigidBody2D::RigidBody2D(PhysWorld2D* world, float mass, Collider2DRef geom) :
m_geom(),
m_forceAccumulator(Vector3f::Zero()),
m_torqueAccumulator(Vector3f::Zero()),
m_world(world),
m_gravityFactor(1.f),
m_mass(0.f)
{
NazaraAssert(m_world, "Invalid world");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
SetGeom(geom);
SetMass(mass);
}
RigidBody2D::RigidBody2D(const RigidBody2D& object) :
m_geom(object.m_geom),
m_forceAccumulator(Vector3f::Zero()),
m_torqueAccumulator(Vector3f::Zero()),
m_world(object.m_world),
m_gravityFactor(object.m_gravityFactor),
m_mass(0.f)
{
NazaraAssert(m_world, "Invalid world");
NazaraAssert(m_geom, "Invalid geometry");
m_handle = cpBodyNew(0.f, 0.f);
cpBodySetUserData(m_handle, this);
cpSpaceAddBody(m_world->GetHandle(), m_handle);
SetGeom(object.GetGeom());
SetMass(object.GetMass());
}
RigidBody2D::RigidBody2D(RigidBody2D&& object) :
m_geom(std::move(object.m_geom)),
m_forceAccumulator(std::move(object.m_forceAccumulator)),
m_torqueAccumulator(std::move(object.m_torqueAccumulator)),
m_handle(object.m_handle),
m_world(object.m_world),
m_gravityFactor(object.m_gravityFactor),
m_mass(object.m_mass)
{
object.m_handle = nullptr;
}
RigidBody2D::~RigidBody2D()
{
if (m_handle)
cpBodyFree(m_handle);
}
void RigidBody2D::AddForce(const Vector2f& force, CoordSys coordSys)
{
return AddForce(force, GetCenterOfGravity(coordSys), coordSys);
}
void RigidBody2D::AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys)
{
switch (coordSys)
{
case CoordSys_Global:
cpBodyApplyForceAtWorldPoint(m_handle, cpv(force.x, force.y), cpv(force.x, force.y));
break;
case CoordSys_Local:
cpBodyApplyForceAtLocalPoint(m_handle, cpv(force.x, force.y), cpv(point.x, point.y));
break;
}
}
void RigidBody2D::AddTorque(float torque)
{
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque);
}
Rectf RigidBody2D::GetAABB() const
{
cpBB bb = cpBBNew(0.f, 0.f, 0.f, 0.f);
for (cpShape* shape : m_shapes)
bb = cpBBMerge(bb, cpShapeGetBB(shape));
return Rectf(bb.l, bb.t, bb.r - bb.l, bb.b - bb.t);
}
float RigidBody2D::GetAngularVelocity() const
{
return cpBodyGetAngularVelocity(m_handle);
}
const Collider2DRef& RigidBody2D::GetGeom() const
{
return m_geom;
}
float RigidBody2D::GetGravityFactor() const
{
return m_gravityFactor;
}
cpBody* RigidBody2D::GetHandle() const
{
return m_handle;
}
float RigidBody2D::GetMass() const
{
return m_mass;
}
Vector2f RigidBody2D::GetCenterOfGravity(CoordSys coordSys) const
{
cpVect cog = cpBodyGetCenterOfGravity(m_handle);
switch (coordSys)
{
case CoordSys_Global:
cog = cpBodyLocalToWorld(m_handle, cog);
break;
case CoordSys_Local:
break; // Nothing to do
}
return Vector2f(cog.x, cog.y);
}
Vector2f RigidBody2D::GetPosition() const
{
cpVect pos = cpBodyGetPosition(m_handle);
return Vector2f(pos.x, pos.y);
}
float RigidBody2D::GetRotation() const
{
return cpBodyGetAngle(m_handle);
}
Vector2f RigidBody2D::GetVelocity() const
{
cpVect vel = cpBodyGetVelocity(m_handle);
return Vector2f(vel.x, vel.y);
}
bool RigidBody2D::IsMoveable() const
{
return m_mass > 0.f;
}
bool RigidBody2D::IsSleeping() const
{
return cpBodyIsSleeping(m_handle) != 0;
}
void RigidBody2D::SetAngularVelocity(float angularVelocity)
{
cpBodySetAngularVelocity(m_handle, angularVelocity);
}
void RigidBody2D::SetGeom(Collider2DRef geom)
{
if (m_geom.Get() != geom)
{
for (cpShape* shape : m_shapes)
cpBodyRemoveShape(m_handle, shape);
if (geom)
m_geom = geom;
else
m_geom = NullCollider2D::New();
m_shapes = m_geom->CreateShapes(this);
}
}
void RigidBody2D::SetGravityFactor(float gravityFactor)
{
m_gravityFactor = gravityFactor;
}
void RigidBody2D::SetMass(float mass)
{
if (m_mass > 0.f)
{
if (mass > 0.f)
cpBodySetMass(m_handle, mass);
else
cpBodySetType(m_handle, CP_BODY_TYPE_STATIC);
}
else if (mass > 0.f)
{
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC);
}
m_mass = mass;
}
void RigidBody2D::SetMassCenter(const Vector2f& center)
{
if (m_mass > 0.f)
cpBodySetCenterOfGravity(m_handle, cpv(center.x, center.y));
}
void RigidBody2D::SetPosition(const Vector2f& position)
{
cpBodySetPosition(m_handle, cpv(position.x, position.y));
}
void RigidBody2D::SetRotation(float rotation)
{
cpBodySetAngle(m_handle, rotation);
}
void RigidBody2D::SetVelocity(const Vector2f& velocity)
{
cpBodySetVelocity(m_handle, cpv(velocity.x, velocity.y));
}
RigidBody2D& RigidBody2D::operator=(const RigidBody2D& object)
{
RigidBody2D physObj(object);
return operator=(std::move(physObj));
}
RigidBody2D& RigidBody2D::operator=(RigidBody2D&& object)
{
if (m_handle)
cpBodyFree(m_handle);
m_handle = object.m_handle;
m_forceAccumulator = std::move(object.m_forceAccumulator);
m_geom = std::move(object.m_geom);
m_gravityFactor = object.m_gravityFactor;
m_mass = object.m_mass;
m_torqueAccumulator = std::move(object.m_torqueAccumulator);
m_world = object.m_world;
object.m_handle = nullptr;
return *this;
}
}