RavEngine
Loading...
Searching...
No Matches
SparseSet.hpp
1#pragma once
2#include "unordered_vector.hpp"
3#include "Common3D.hpp"
4
5namespace RavEngine {
6 template<typename index_t,typename container_t>
8 public:
9 constexpr static index_t default_index = std::numeric_limits<index_t>::max();
10 constexpr static index_t INVALID_INDEX = default_index;
11 using index_type = index_t;
12 using value_type = typename container_t::value_type;
13 private:
14 container_t dense_set;
15 std::vector<index_t> sparse_set{ default_index };
16
17 public:
18 std::vector<index_t> reverse_map;
19 using const_iterator = typename decltype(dense_set)::const_iterator_type;
20
21 template<typename ... A>
22 inline void Emplace(index_t sparse_index, A&& ... args) {
23 //if a record for this does not exist, create it
24 if (!HasForSparseIndex(sparse_index)) {
25 dense_set.emplace(args...);
26 reverse_map.emplace_back(sparse_index);
27 if (sparse_index >= sparse_set.size()) {
28 sparse_set.resize(closest_multiple_of<int>(sparse_index + 1, 2), default_index); //ensure there is enough space for this id
29 }
30 sparse_set[sparse_index] = static_cast<typename decltype(sparse_set)::value_type>(dense_set.size() - 1);
31 }
32 }
33
34 inline void EraseAtSparseIndex(index_t sparse_index) {
35 // get the record, then call erase on it
36 assert(HasForSparseIndex(sparse_index));
37
38 auto denseidx = SparseToDense(sparse_index);
39 dense_set.erase(dense_set.begin() + denseidx);
40
41 if (denseidx < dense_set.size()) { // did a move happen during this deletion?
42 auto ownerOfMoved = reverse_map.back();
43 sparse_set[ownerOfMoved] = denseidx;
44 reverse_map[denseidx] = reverse_map.back();
45 }
46 reverse_map.pop_back();
47 sparse_set[sparse_index] = INVALID_INDEX;
48 }
49
50 inline auto& GetForSparseIndex(index_t sparse_index) {
51 assert(HasForSparseIndex(sparse_index));
52 return dense_set[SparseToDense(sparse_index)];
53 }
54
55 inline auto SparseToDense(index_t sparse_index) {
56 return sparse_set[sparse_index];
57 }
58
59 inline bool HasForSparseIndex(index_t sparse_index) const {
60 return sparse_index < sparse_set.size() && sparse_set[sparse_index] != default_index;
61 }
62
63 auto begin() {
64 return dense_set.begin();
65 }
66
67 auto end() {
68 return dense_set.end();
69 }
70
71 auto begin() const {
72 return dense_set.begin();
73 }
74
75 auto end() const {
76 return dense_set.end();
77 }
78
79 // get by dense index, not by entity ID
80 value_type& Get(index_t idx) {
81 return dense_set[idx];
82 }
83
84 // given a dense index, return its sparse index
85 index_t& GetSparseIndexForDense(index_t idx) {
86 return reverse_map[idx];
87 }
88
89 const value_type& Get(index_t idx) const {
90 return Get(idx);
91 }
92
93 auto DenseSize() const {
94 return dense_set.size();
95 }
96
97 auto GetDenseData() const {
98 return dense_set.data();
99 }
100
101 inline auto& GetDense() {
102 return dense_set;
103 }
104 };
105
106 template<typename index_t, typename container_t>
107 class UnorderedSparseSet : public UnorderedSparseSetGenericContainer<index_t, unordered_vector<container_t>> {};
108}
Definition SparseSet.hpp:107
Definition concurrentqueue.h:747
Definition Animation.hpp:6