Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
query_mask.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include "gaia/ecs/component.h"
5#include "gaia/ecs/id.h"
6
8namespace gaia {
9 namespace ecs {
10 struct Entity;
11
12#if GAIA_USE_PARTITIONED_BLOOM_FILTER
13 static constexpr uint64_t s_ct_queryMask_primes[4] = {
14 11400714819323198485ull, // golden ratio
15 14029467366897019727ull, //
16 1609587929392839161ull, //
17 9650029242287828579ull //
18 };
19
20 struct QueryMask {
21 uint64_t value[4];
22
23 bool operator==(const QueryMask& other) const {
24 return ((value[0] ^ other.value[0]) | //
25 (value[1] ^ other.value[1]) | //
26 (value[2] ^ other.value[2]) | //
27 (value[3] ^ other.value[3])) == 0;
28 }
29 bool operator!=(const QueryMask& other) const {
30 return !(*this == other);
31 }
32 };
33
35 GAIA_NODISCARD inline QueryMask hash_entity_id(Entity entity) {
36 QueryMask mask{};
37 const uint64_t id = entity.id();
38
39 // Pick one bit in each 64-bit partition.
40 const auto bit0 = (id * s_ct_queryMask_primes[0]) >> (64 - 6);
41 const auto bit1 = (id * s_ct_queryMask_primes[1]) >> (64 - 6);
42 const auto bit2 = (id * s_ct_queryMask_primes[2]) >> (64 - 6);
43 const auto bit3 = (id * s_ct_queryMask_primes[3]) >> (64 - 6);
44
45 mask.value[0] = 1ull << bit0;
46 mask.value[1] = 1ull << bit1;
47 mask.value[2] = 1ull << bit2;
48 mask.value[3] = 1ull << bit3;
49
50 return mask;
51 }
52
54 GAIA_NODISCARD inline QueryMask build_entity_mask(EntitySpan entities) {
55 QueryMask result{};
56 for (auto entity: entities) {
57 QueryMask hash = hash_entity_id(entity);
58 result.value[0] |= hash.value[0];
59 result.value[1] |= hash.value[1];
60 result.value[2] |= hash.value[2];
61 result.value[3] |= hash.value[3];
62 }
63 return result;
64 }
65
67 GAIA_NODISCARD inline bool match_entity_mask(const QueryMask& m1, const QueryMask& m2) {
68 const uint64_t r0 = m1.value[0] & m2.value[0];
69 const uint64_t r1 = m1.value[1] & m2.value[1];
70 const uint64_t r2 = m1.value[2] & m2.value[2];
71 const uint64_t r3 = m1.value[3] & m2.value[3];
72 return bool(int(r0 != 0) & int(r1 != 0) & int(r2 != 0) & int(r3 != 0));
73 }
74#else
75 using QueryMask = uint64_t;
76
78 GAIA_NODISCARD inline QueryMask hash_entity_id(Entity entity) {
79 return (entity.id() * 11400714819323198485ull) >> (64 - 6);
80 }
81
83 GAIA_NODISCARD inline QueryMask build_entity_mask(EntitySpan entities) {
84 QueryMask mask = 0;
85 for (auto entity: entities)
86 mask |= (1ull << hash_entity_id(entity));
87
88 return mask;
89 }
90
92 GAIA_NODISCARD inline bool match_entity_mask(const QueryMask& m1, const QueryMask& m2) {
93 return (m1 & m2) != 0;
94 }
95#endif
96 } // namespace ecs
97} // namespace gaia