Gaia-ECS v0.9.3
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
7namespace gaia {
8 namespace ecs {
9 struct Entity;
10
11#if GAIA_USE_PARTITIONED_BLOOM_FILTER
12 static constexpr uint64_t s_ct_queryMask_primes[4] = {
13 11400714819323198485ull, // golden ratio
14 14029467366897019727ull, //
15 1609587929392839161ull, //
16 9650029242287828579ull //
17 };
18
19 struct QueryMask {
20 uint64_t value[4];
21
22 bool operator==(const QueryMask& other) const {
23 return ((value[0] ^ other.value[0]) | //
24 (value[1] ^ other.value[1]) | //
25 (value[2] ^ other.value[2]) | //
26 (value[3] ^ other.value[3])) == 0;
27 }
28 bool operator!=(const QueryMask& other) const {
29 return !(*this == other);
30 }
31 };
32
34 GAIA_NODISCARD inline QueryMask hash_entity_id(Entity entity) {
35 QueryMask mask{};
36 const uint64_t id = entity.id();
37
38 // Pick 1 bit in each 16-bit block.
39 // We are shifting right by 60 bits, leaving only the top 4 bits of the 64-bit product. This effectively
40 // gives us a random-ish value in the range 0–15, which fits one bit per 16-bit block (since 2^4 = 16).
41 const auto bit0 = (id * s_ct_queryMask_primes[0]) >> (64 - 4);
42 const auto bit1 = (id * s_ct_queryMask_primes[1]) >> (64 - 4);
43 const auto bit2 = (id * s_ct_queryMask_primes[2]) >> (64 - 4);
44 const auto bit3 = (id * s_ct_queryMask_primes[3]) >> (64 - 4);
45
46 mask.value[0] = 1ull << bit0;
47 mask.value[1] = 1ull << bit1;
48 mask.value[2] = 1ull << bit2;
49 mask.value[3] = 1ull << bit3;
50
51 return mask;
52 }
53
55 GAIA_NODISCARD inline QueryMask build_entity_mask(EntitySpan entities) {
56 QueryMask result{};
57 for (auto entity: entities) {
58 QueryMask hash = hash_entity_id(entity);
59 result.value[0] |= hash.value[0];
60 result.value[1] |= hash.value[1];
61 result.value[2] |= hash.value[2];
62 result.value[3] |= hash.value[3];
63 }
64 return result;
65 }
66
68 GAIA_NODISCARD inline bool match_entity_mask(const QueryMask& m1, const QueryMask& m2) {
69 const uint64_t r0 = m1.value[0] & m2.value[0];
70 const uint64_t r1 = m1.value[1] & m2.value[1];
71 const uint64_t r2 = m1.value[2] & m2.value[2];
72 const uint64_t r3 = m1.value[3] & m2.value[3];
73 return bool(int(r0 != 0) & int(r1 != 0) & int(r2 != 0) & int(r3 != 0));
74 }
75#else
76 using QueryMask = uint64_t;
77
79 GAIA_NODISCARD inline QueryMask hash_entity_id(Entity entity) {
80 return (entity.id() * 11400714819323198485ull) >> (64 - 6);
81 }
82
84 GAIA_NODISCARD inline QueryMask build_entity_mask(EntitySpan entities) {
85 QueryMask mask = 0;
86 for (auto entity: entities)
87 mask |= (1ull << hash_entity_id(entity));
88
89 return mask;
90 }
91
93 GAIA_NODISCARD inline bool match_entity_mask(const QueryMask& m1, const QueryMask& m2) {
94 return (m1 & m2) != 0;
95 }
96#endif
97 } // namespace ecs
98} // namespace gaia
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9