Line data Source code
1 : #ifndef F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP 2 : #define F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP 3 : 4 : #include "Disc.hpp" 5 : #include "Membrane.hpp" 6 : #include "Types.hpp" 7 : #include "Vector2d.hpp" 8 : 9 : #include <optional> 10 : #include <set> 11 : #include <vector> 12 : 13 : namespace cell 14 : { 15 : 16 : class CollisionDetector 17 : { 18 : public: 19 : struct Params 20 : { 21 : std::vector<Disc>* discs = nullptr; 22 : std::vector<Membrane>* membranes = nullptr; 23 : std::vector<Disc*>* intrudingDiscs = nullptr; 24 : Membrane* containingMembrane = nullptr; 25 : }; 26 : 27 : enum class EntryType 28 : { 29 : Disc, 30 : Membrane, 31 : IntrudingDisc 32 : }; 33 : 34 : enum class CollisionType 35 : { 36 : DiscDisc, 37 : DiscIntrudingDisc, 38 : DiscContainingMembrane, 39 : DiscChildMembrane, 40 : None 41 : }; 42 : 43 : struct Entry 44 : { 45 : std::size_t index = 0; 46 : double radius = 0; 47 : sf::Vector2d position; 48 : double minX = 0, maxX = 0; 49 : EntryType type = EntryType::Disc; 50 : }; 51 : 52 : struct Collision 53 : { 54 : Disc* disc = nullptr; 55 : Disc* otherDisc = nullptr; 56 : Membrane* membrane = nullptr; 57 : CollisionType type = CollisionType::None; 58 : 59 22 : bool isInvalidatedByDestroyedDisc() const 60 : { 61 22 : return disc->isMarkedDestroyed() || (otherDisc && otherDisc->isMarkedDestroyed()); 62 : } 63 : }; 64 : 65 : struct DetectedCollisions 66 : { 67 : std::vector<Collision> collisions; 68 : std::unordered_map<CollisionType, std::vector<std::size_t>> indexes; 69 : }; 70 : 71 : public: 72 : CollisionDetector(const DiscTypeRegistry& discTypeRegistry, const MembraneTypeRegistry& membraneTypeRegistry); 73 : 74 : void buildEntries(const std::vector<Disc>& discs, const std::vector<Membrane>& membranes, 75 : const std::vector<Disc*>& intrudingDiscs); 76 : DetectedCollisions detectCollisions(const Params& params); 77 : 78 : DiscTypeMap<int> getAndResetCollisionCounts(); 79 : 80 : private: 81 : template <typename ElementType, typename RegistryType> 82 : Entry createEntry(const ElementType& element, const RegistryType& registry, std::size_t index, 83 : EntryType entryType) const; 84 : 85 : bool discIsContainedByMembrane(const Entry& entry); 86 : 87 : private: 88 : DiscTypeMap<int> collisionCounts_; 89 : 90 : const DiscTypeRegistry& discTypeRegistry_; 91 : const MembraneTypeRegistry& membraneTypeRegistry_; 92 : 93 : std::vector<Entry> entries_; 94 : Params params_; 95 : }; 96 : 97 : template <typename ElementType, typename RegistryType> 98 22 : inline CollisionDetector::Entry CollisionDetector::createEntry(const ElementType& element, const RegistryType& registry, 99 : std::size_t index, EntryType entryType) const 100 : { 101 22 : const double r = registry.getByID(element.getTypeID()).getRadius(); 102 22 : const auto& p = element.getPosition(); 103 : 104 22 : return Entry{.index = index, .radius = r, .position = p, .minX = p.x - r, .maxX = p.x + r, .type = entryType}; 105 : } 106 : 107 : } // namespace cell 108 : 109 : #endif /* F674C74F_4648_4098_89DD_4A99F7F0CB5C_HPP */