From b92e23fcd67a831e873920d17a49f7e07b345308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Thu, 2 Aug 2018 15:42:14 +0200 Subject: [PATCH] Physics2D: Add Arbiter2D --- ChangeLog.md | 1 + include/Nazara/Physics2D/Arbiter2D.hpp | 57 +++++++++++++++ include/Nazara/Physics2D/Arbiter2D.inl | 17 +++++ include/Nazara/Physics2D/PhysWorld2D.hpp | 10 +-- src/Nazara/Physics2D/Arbiter2D.cpp | 89 ++++++++++++++++++++++++ src/Nazara/Physics2D/PhysWorld2D.cpp | 17 +++-- 6 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 include/Nazara/Physics2D/Arbiter2D.hpp create mode 100644 include/Nazara/Physics2D/Arbiter2D.inl create mode 100644 src/Nazara/Physics2D/Arbiter2D.cpp diff --git a/ChangeLog.md b/ChangeLog.md index 149c75d44..4cd68d12a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -128,6 +128,7 @@ Nazara Engine: - Added LuaImplQueryArg & LuaImplReplyVal functions for Vector[2|3] - Fixed bug in ENet implementation causing legit reliable packets to be dropped on sequence number overflow - Fixed bug where index wouldn't be used in String::FindLast and String::FindWord +- Physics 2D contact callbacks now include an arbiter allowing to query/set parameters about the collision Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Physics2D/Arbiter2D.hpp b/include/Nazara/Physics2D/Arbiter2D.hpp new file mode 100644 index 000000000..64c38dd8d --- /dev/null +++ b/include/Nazara/Physics2D/Arbiter2D.hpp @@ -0,0 +1,57 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 2D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ARBITER2D_HPP +#define NAZARA_ARBITER2D_HPP + +#include +#include +#include +#include + +struct cpArbiter; + +namespace Nz +{ + class NAZARA_PHYSICS2D_API Arbiter2D + { + public: + inline Arbiter2D(cpArbiter* arbiter); + Arbiter2D(const Arbiter2D&) = delete; + Arbiter2D(Arbiter2D&&) = default; + ~Arbiter2D() = default; + + float ComputeTotalKinematicEnergy() const; + Nz::Vector2f ComputeTotalImpulse() const; + + std::size_t GetContactCount() const; + float GetContactDepth(std::size_t i) const; + Nz::Vector2f GetContactPointA(std::size_t i) const; + Nz::Vector2f GetContactPointB(std::size_t i) const; + + float GetElasticity() const; + float GetFriction() const; + Nz::Vector2f GetNormal() const; + Nz::Vector2f GetSurfaceVelocity() const; + + bool IsFirstContact() const; + bool IsRemoval() const; + + void SetElasticity(float elasticity); + void SetFriction(float friction); + void SetSurfaceVelocity(const Nz::Vector2f& surfaceVelocity); + + Arbiter2D& operator=(const Arbiter2D&) = delete; + Arbiter2D& operator=(Arbiter2D&&) = default; + + private: + MovablePtr m_arbiter; + }; +} + +#include + +#endif // NAZARA_ARBITER2D_HPP diff --git a/include/Nazara/Physics2D/Arbiter2D.inl b/include/Nazara/Physics2D/Arbiter2D.inl new file mode 100644 index 000000000..5e6b3edf6 --- /dev/null +++ b/include/Nazara/Physics2D/Arbiter2D.inl @@ -0,0 +1,17 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 2D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline Arbiter2D::Arbiter2D(cpArbiter* arbiter) : + m_arbiter(arbiter) + { + } +} + +#include diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 301e73563..3e726de00 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -22,14 +22,16 @@ struct cpSpace; namespace Nz { + class Arbiter2D; + class NAZARA_PHYSICS2D_API PhysWorld2D { friend RigidBody2D; - using ContactEndCallback = std::function; - using ContactPreSolveCallback = std::function; - using ContactPostSolveCallback = std::function; - using ContactStartCallback = std::function; + using ContactEndCallback = std::function; + using ContactPreSolveCallback = std::function; + using ContactPostSolveCallback = std::function; + using ContactStartCallback = std::function; using DebugDrawCircleCallback = std::function; using DebugDrawDotCallback = std::function; diff --git a/src/Nazara/Physics2D/Arbiter2D.cpp b/src/Nazara/Physics2D/Arbiter2D.cpp new file mode 100644 index 000000000..8a1243d26 --- /dev/null +++ b/src/Nazara/Physics2D/Arbiter2D.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 2D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + float Nz::Arbiter2D::ComputeTotalKinematicEnergy() const + { + return float(cpArbiterTotalKE(m_arbiter)); + } + + Nz::Vector2f Arbiter2D::ComputeTotalImpulse() const + { + cpVect impulse = cpArbiterTotalImpulse(m_arbiter); + return Nz::Vector2f(Nz::Vector2(impulse.x, impulse.y)); + } + + std::size_t Arbiter2D::GetContactCount() const + { + return cpArbiterGetCount(m_arbiter); + } + + float Arbiter2D::GetContactDepth(std::size_t i) const + { + return cpArbiterGetDepth(m_arbiter, int(i)); + } + + Nz::Vector2f Arbiter2D::GetContactPointA(std::size_t i) const + { + cpVect point = cpArbiterGetPointA(m_arbiter, int(i)); + return Nz::Vector2f(Nz::Vector2(point.x, point.y)); + } + + Nz::Vector2f Arbiter2D::GetContactPointB(std::size_t i) const + { + cpVect point = cpArbiterGetPointB(m_arbiter, int(i)); + return Nz::Vector2f(Nz::Vector2(point.x, point.y)); + } + + float Arbiter2D::GetElasticity() const + { + return float(cpArbiterGetRestitution(m_arbiter)); + } + float Arbiter2D::GetFriction() const + { + return float(cpArbiterGetFriction(m_arbiter)); + } + + Nz::Vector2f Arbiter2D::GetNormal() const + { + cpVect normal = cpArbiterGetNormal(m_arbiter); + return Nz::Vector2f(Nz::Vector2(normal.x, normal.y)); + } + + Nz::Vector2f Arbiter2D::GetSurfaceVelocity() const + { + cpVect velocity = cpArbiterGetNormal(m_arbiter); + return Nz::Vector2f(Nz::Vector2(velocity.x, velocity.y)); + } + + bool Arbiter2D::IsFirstContact() const + { + return cpArbiterIsFirstContact(m_arbiter) == cpTrue; + } + + bool Arbiter2D::IsRemoval() const + { + return cpArbiterIsRemoval(m_arbiter) == cpTrue; + } + + void Arbiter2D::SetElasticity(float elasticity) + { + cpArbiterSetRestitution(m_arbiter, elasticity); + } + + void Arbiter2D::SetFriction(float friction) + { + cpArbiterSetFriction(m_arbiter, friction); + } + + void Arbiter2D::SetSurfaceVelocity(const Nz::Vector2f& surfaceVelocity) + { + cpArbiterSetSurfaceVelocity(m_arbiter, cpv(surfaceVelocity.x, surfaceVelocity.y)); + } +} diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index b967e63e5..764ca1cf8 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -358,8 +359,10 @@ namespace Nz RigidBody2D* firstRigidBody = static_cast(cpBodyGetUserData(firstBody)); RigidBody2D* secondRigidBody = static_cast(cpBodyGetUserData(secondBody)); + Arbiter2D arbiter(arb); + const Callback* customCallbacks = static_cast(data); - if (customCallbacks->startCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata)) + if (customCallbacks->startCallback(*world, arbiter, *firstRigidBody, *secondRigidBody, customCallbacks->userdata)) { cpBool retA = cpArbiterCallWildcardBeginA(arb, space); cpBool retB = cpArbiterCallWildcardBeginB(arb, space); @@ -382,8 +385,10 @@ namespace Nz RigidBody2D* firstRigidBody = static_cast(cpBodyGetUserData(firstBody)); RigidBody2D* secondRigidBody = static_cast(cpBodyGetUserData(secondBody)); + Arbiter2D arbiter(arb); + const Callback* customCallbacks = static_cast(data); - customCallbacks->endCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata); + customCallbacks->endCallback(*world, arbiter, *firstRigidBody, *secondRigidBody, customCallbacks->userdata); cpArbiterCallWildcardSeparateA(arb, space); cpArbiterCallWildcardSeparateB(arb, space); @@ -402,8 +407,10 @@ namespace Nz RigidBody2D* firstRigidBody = static_cast(cpBodyGetUserData(firstBody)); RigidBody2D* secondRigidBody = static_cast(cpBodyGetUserData(secondBody)); + Arbiter2D arbiter(arb); + const Callback* customCallbacks = static_cast(data); - if (customCallbacks->preSolveCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata)) + if (customCallbacks->preSolveCallback(*world, arbiter, *firstRigidBody, *secondRigidBody, customCallbacks->userdata)) { cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space); cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space); @@ -426,8 +433,10 @@ namespace Nz RigidBody2D* firstRigidBody = static_cast(cpBodyGetUserData(firstBody)); RigidBody2D* secondRigidBody = static_cast(cpBodyGetUserData(secondBody)); + Arbiter2D arbiter(arb); + const Callback* customCallbacks = static_cast(data); - customCallbacks->postSolveCallback(*world, *firstRigidBody, *secondRigidBody, customCallbacks->userdata); + customCallbacks->postSolveCallback(*world, arbiter, *firstRigidBody, *secondRigidBody, customCallbacks->userdata); cpArbiterCallWildcardPostSolveA(arb, space); cpArbiterCallWildcardPostSolveB(arb, space);