From 5ebf1254740e793668efb81a9a4f5b7c1c3fca51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Wed, 1 Mar 2017 17:40:12 +0100 Subject: [PATCH] Physics2D: Add NearestBodyQuery --- include/Nazara/Physics2D/Collider2D.hpp | 11 ++++++- include/Nazara/Physics2D/Collider2D.inl | 39 ++++++++++++++++++++++-- include/Nazara/Physics2D/PhysWorld2D.hpp | 15 +++++++++ src/Nazara/Physics2D/Collider2D.cpp | 3 ++ src/Nazara/Physics2D/PhysWorld2D.cpp | 34 +++++++++++++++++++++ src/Nazara/Physics2D/RigidBody2D.cpp | 3 ++ 6 files changed, 101 insertions(+), 4 deletions(-) diff --git a/include/Nazara/Physics2D/Collider2D.hpp b/include/Nazara/Physics2D/Collider2D.hpp index e5b988756..b09e8781f 100644 --- a/include/Nazara/Physics2D/Collider2D.hpp +++ b/include/Nazara/Physics2D/Collider2D.hpp @@ -42,13 +42,19 @@ namespace Nz virtual float ComputeInertialMatrix(float mass) const = 0; + inline Nz::UInt32 GetCategoryMask() const; + inline Nz::UInt32 GetCollisionGroup() const; inline unsigned int GetCollisionId() const; + inline Nz::UInt32 GetCollisionMask() const; virtual ColliderType2D GetType() const = 0; inline bool IsTrigger() const; - inline void SetCollisionId(unsigned long typeId); + inline void SetCategoryMask(Nz::UInt32 categoryMask); + inline void SetCollisionGroup(Nz::UInt32 groupId); + inline void SetCollisionId(unsigned int typeId); + inline void SetCollisionMask(Nz::UInt32 mask); inline void SetTrigger(bool trigger); Collider2D& operator=(const Collider2D&) = delete; @@ -61,7 +67,10 @@ namespace Nz virtual std::vector CreateShapes(RigidBody2D* body) const = 0; bool m_trigger; + Nz::UInt32 m_categoryMask; + Nz::UInt32 m_collisionGroup; unsigned int m_collisionId; + Nz::UInt32 m_collisionMask; private: virtual std::vector GenerateShapes(RigidBody2D* body) const; diff --git a/include/Nazara/Physics2D/Collider2D.inl b/include/Nazara/Physics2D/Collider2D.inl index 71b909a2c..60cf8559f 100644 --- a/include/Nazara/Physics2D/Collider2D.inl +++ b/include/Nazara/Physics2D/Collider2D.inl @@ -2,32 +2,66 @@ // 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 Collider2D::Collider2D() : + m_trigger(false), + m_categoryMask(0xFFFFFFFF), + m_collisionGroup(0), m_collisionId(0), - m_trigger(false) + m_collisionMask(0xFFFFFFFF) { } + inline Nz::UInt32 Collider2D::GetCategoryMask() const + { + return m_categoryMask; + } + + inline Nz::UInt32 Collider2D::GetCollisionGroup() const + { + return m_collisionGroup; + } + inline unsigned int Collider2D::GetCollisionId() const { return m_collisionId; } + inline Nz::UInt32 Collider2D::GetCollisionMask() const + { + return m_collisionMask; + } + inline bool Collider2D::IsTrigger() const { return m_trigger; } - inline void Collider2D::SetCollisionId(unsigned long typeId) + inline void Collider2D::SetCategoryMask(Nz::UInt32 categoryMask) + { + m_categoryMask = categoryMask; + } + + inline void Collider2D::SetCollisionGroup(Nz::UInt32 groupId) + { + m_collisionGroup = groupId; + } + + inline void Collider2D::SetCollisionId(unsigned int typeId) { m_collisionId = typeId; } + inline void Collider2D::SetCollisionMask(Nz::UInt32 mask) + { + m_collisionMask = mask; + } + inline void Collider2D::SetTrigger(bool trigger) { m_trigger = trigger; @@ -108,4 +142,3 @@ namespace Nz } #include -#include "Collider2D.hpp" diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index 760773c7d..09e39959b 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -8,6 +8,7 @@ #define NAZARA_PHYSWORLD2D_HPP #include +#include #include #include #include @@ -29,6 +30,7 @@ namespace Nz public: struct Callback; + struct NearestQueryResult; PhysWorld2D(); PhysWorld2D(const PhysWorld2D&) = delete; @@ -39,6 +41,8 @@ namespace Nz cpSpace* GetHandle() const; float GetStepSize() const; + bool NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result); + void RegisterCallbacks(unsigned int collisionId, const Callback& callbacks); void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, const Callback& callbacks); @@ -59,6 +63,17 @@ namespace Nz void* userdata; }; + struct NearestQueryResult + { + Nz::RigidBody2D* nearestBody; + Nz::Vector2f closestPoint; + Nz::Vector2f fraction; + float distance; + }; + + NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/); + NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/); + private: void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); diff --git a/src/Nazara/Physics2D/Collider2D.cpp b/src/Nazara/Physics2D/Collider2D.cpp index cce3301aa..3a679fad9 100644 --- a/src/Nazara/Physics2D/Collider2D.cpp +++ b/src/Nazara/Physics2D/Collider2D.cpp @@ -13,9 +13,12 @@ namespace Nz std::vector Collider2D::GenerateShapes(RigidBody2D* body) const { + cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask); + std::vector shapes = CreateShapes(body); for (cpShape* shape : shapes) { + cpShapeSetFilter(shape, filter); cpShapeSetCollisionType(shape, m_collisionId); cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse); } diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 7c15beee3..52881b827 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -37,6 +37,35 @@ namespace Nz return m_stepSize; } + bool PhysWorld2D::NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result) + { + cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask); + + if (result) + { + cpPointQueryInfo queryInfo; + + if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo)) + { + result->closestPoint.Set(queryInfo.point.x, queryInfo.point.y); + result->distance = queryInfo.distance; + result->fraction.Set(queryInfo.gradient.x, queryInfo.gradient.y); + result->nearestBody = static_cast(cpShapeGetUserData(shape)); + + return true; + } + else + return false; + } + else + { + if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr)) + return true; + else + return false; + } + } + void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks) { InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks); @@ -63,7 +92,12 @@ namespace Nz while (m_timestepAccumulator >= m_stepSize) { + OnPhysWorld2DPreStep(this); + cpSpaceStep(m_handle, m_stepSize); + + OnPhysWorld2DPostStep(this); + m_timestepAccumulator -= m_stepSize; } } diff --git a/src/Nazara/Physics2D/RigidBody2D.cpp b/src/Nazara/Physics2D/RigidBody2D.cpp index d01a426a2..d4d5aafd0 100644 --- a/src/Nazara/Physics2D/RigidBody2D.cpp +++ b/src/Nazara/Physics2D/RigidBody2D.cpp @@ -229,7 +229,10 @@ namespace Nz cpSpace* space = m_world->GetHandle(); for (cpShape* shape : m_shapes) + { + cpShapeSetUserData(shape, this); cpSpaceAddShape(space, shape); + } cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass)); }