Backported from Godot4: Clean up Hash Functions

Clean up and do fixes to hash functions and newly introduced murmur3 hashes in #61934
* Clean up usage of murmur3
* Fixed usages of binary murmur3 on floats (this is invalid)
* Changed DJB2 to use xor (which seems to be better)
- reduz
141c375581
This commit is contained in:
Relintai 2022-08-17 10:42:50 +02:00
parent d9669b0ed0
commit 73709fa1ae
9 changed files with 197 additions and 141 deletions

View File

@ -117,12 +117,12 @@ bool Array::operator==(const Array &p_array) const {
}
uint32_t Array::hash() const {
uint32_t h = hash_djb2_one_32(0);
uint32_t h = hash_murmur3_one_32(0);
for (int i = 0; i < _p->array.size(); i++) {
h = hash_djb2_one_32(_p->array[i].hash(), h);
h = hash_murmur3_one_32(_p->array[i].hash(), h);
}
return h;
return hash_fmix32(h);
}
void Array::operator=(const Array &p_array) {
_ref(p_array);

View File

@ -343,7 +343,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
OBJTYPE_RLOCK;
#ifdef DEBUG_METHODS_ENABLED
uint64_t hash = hash_djb2_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
uint64_t hash = hash_murmur3_one_64(HashMapHasherDefault::hash(VERSION_FULL_CONFIG));
List<StringName> names;
@ -361,8 +361,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
if (t->api != p_api || !t->exposed) {
continue;
}
hash = hash_djb2_one_64(t->name.hash(), hash);
hash = hash_djb2_one_64(t->inherits.hash(), hash);
hash = hash_murmur3_one_64(t->name.hash(), hash);
hash = hash_murmur3_one_64(t->inherits.hash(), hash);
{ //methods
@ -386,27 +386,27 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
MethodBind *mb = t->method_map[F->get()];
hash = hash_djb2_one_64(mb->get_name().hash(), hash);
hash = hash_djb2_one_64(mb->get_argument_count(), hash);
hash = hash_djb2_one_64(mb->get_argument_type(-1), hash); //return
hash = hash_murmur3_one_64(mb->get_name().hash(), hash);
hash = hash_murmur3_one_64(mb->get_argument_count(), hash);
hash = hash_murmur3_one_64(mb->get_argument_type(-1), hash); //return
for (int i = 0; i < mb->get_argument_count(); i++) {
const PropertyInfo info = mb->get_argument_info(i);
hash = hash_djb2_one_64(info.type, hash);
hash = hash_djb2_one_64(info.name.hash(), hash);
hash = hash_djb2_one_64(info.hint, hash);
hash = hash_djb2_one_64(info.hint_string.hash(), hash);
hash = hash_murmur3_one_64(info.type, hash);
hash = hash_murmur3_one_64(info.name.hash(), hash);
hash = hash_murmur3_one_64(info.hint, hash);
hash = hash_murmur3_one_64(info.hint_string.hash(), hash);
}
hash = hash_djb2_one_64(mb->get_default_argument_count(), hash);
hash = hash_murmur3_one_64(mb->get_default_argument_count(), hash);
for (int i = 0; i < mb->get_default_argument_count(); i++) {
//hash should not change, i hope for tis
Variant da = mb->get_default_argument(i);
hash = hash_djb2_one_64(da.hash(), hash);
hash = hash_murmur3_one_64(da.hash(), hash);
}
hash = hash_djb2_one_64(mb->get_hint_flags(), hash);
hash = hash_murmur3_one_64(mb->get_hint_flags(), hash);
}
}
@ -423,8 +423,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
snames.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
hash = hash_djb2_one_64(F->get().hash(), hash);
hash = hash_djb2_one_64(t->constant_map[F->get()], hash);
hash = hash_murmur3_one_64(F->get().hash(), hash);
hash = hash_murmur3_one_64(t->constant_map[F->get()], hash);
}
}
@ -442,9 +442,9 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
MethodInfo &mi = t->signal_map[F->get()];
hash = hash_djb2_one_64(F->get().hash(), hash);
hash = hash_murmur3_one_64(F->get().hash(), hash);
for (int i = 0; i < mi.arguments.size(); i++) {
hash = hash_djb2_one_64(mi.arguments[i].type, hash);
hash = hash_murmur3_one_64(mi.arguments[i].type, hash);
}
}
}
@ -465,23 +465,23 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
PropertySetGet *psg = t->property_setget.getptr(F->get());
ERR_FAIL_COND_V(!psg, 0);
hash = hash_djb2_one_64(F->get().hash(), hash);
hash = hash_djb2_one_64(psg->setter.hash(), hash);
hash = hash_djb2_one_64(psg->getter.hash(), hash);
hash = hash_murmur3_one_64(F->get().hash(), hash);
hash = hash_murmur3_one_64(psg->setter.hash(), hash);
hash = hash_murmur3_one_64(psg->getter.hash(), hash);
}
}
//property list
for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
hash = hash_djb2_one_64(F->get().name.hash(), hash);
hash = hash_djb2_one_64(F->get().type, hash);
hash = hash_djb2_one_64(F->get().hint, hash);
hash = hash_djb2_one_64(F->get().hint_string.hash(), hash);
hash = hash_djb2_one_64(F->get().usage, hash);
hash = hash_murmur3_one_64(F->get().name.hash(), hash);
hash = hash_murmur3_one_64(F->get().type, hash);
hash = hash_murmur3_one_64(F->get().hint, hash);
hash = hash_murmur3_one_64(F->get().hint_string.hash(), hash);
hash = hash_murmur3_one_64(F->get().usage, hash);
}
}
return hash;
return hash_fmix32(hash);
#else
return 0;
#endif

View File

@ -213,14 +213,14 @@ void Dictionary::_unref() const {
_p = nullptr;
}
uint32_t Dictionary::hash() const {
uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);
uint32_t h = hash_murmur3_one_32(Variant::DICTIONARY);
for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
h = hash_djb2_one_32(E.key().hash(), h);
h = hash_djb2_one_32(E.value().hash(), h);
h = hash_murmur3_one_32(E.key().hash(), h);
h = hash_murmur3_one_32(E.value().hash(), h);
}
return h;
return hash_fmix32(h);
}
Array Dictionary::keys() const {

View File

@ -36,6 +36,7 @@
#include "core/os/file_access.h"
#include "core/print_string.h"
#include "core/set.h"
#include "core/hashfuncs.h"
// Pandemonium's packed file magic header ("GDPC" in ASCII).
#define PACK_HEADER_MAGIC 0x43504447
@ -81,6 +82,11 @@ private:
return a == p_md5.a && b == p_md5.b;
};
static uint32_t hash(const PathMD5 &p_val) {
uint32_t h = hash_murmur3_one_32(p_val.a);
return hash_fmix32(hash_murmur3_one_32(p_val.b, h));
}
PathMD5() {
a = b = 0;
};

View File

@ -30,6 +30,30 @@
#include "networked_multiplayer_peer.h"
#include "core/os/os.h"
uint32_t NetworkedMultiplayerPeer::generate_unique_id() const {
uint32_t hash = 0;
while (hash == 0 || hash == 1) {
hash = hash_murmur3_one_32(
(uint32_t)OS::get_singleton()->get_ticks_usec());
hash = hash_murmur3_one_32(
(uint32_t)OS::get_singleton()->get_unix_time(), hash);
hash = hash_murmur3_one_32(
(uint32_t)OS::get_singleton()->get_user_data_dir().hash64(), hash);
hash = hash_murmur3_one_32(
(uint32_t)((uint64_t)this), hash); // Rely on ASLR heap
hash = hash_murmur3_one_32(
(uint32_t)((uint64_t)&hash), hash); // Rely on ASLR stack
hash = hash_fmix32(hash);
hash = hash & 0x7FFFFFFF; // Make it compatible with unsigned, since negative ID is used for exclusion
}
return hash;
}
void NetworkedMultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transfer_mode", "mode"), &NetworkedMultiplayerPeer::set_transfer_mode);
ClassDB::bind_method(D_METHOD("get_transfer_mode"), &NetworkedMultiplayerPeer::get_transfer_mode);
@ -45,6 +69,8 @@ void NetworkedMultiplayerPeer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_refuse_new_connections", "enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections);
ClassDB::bind_method(D_METHOD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections);
ClassDB::bind_method(D_METHOD("generate_unique_id"), &NetworkedMultiplayerPeer::generate_unique_id);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_connections"), "set_refuse_new_connections", "is_refusing_new_connections");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_mode", PROPERTY_HINT_ENUM, "Unreliable,Unreliable Ordered,Reliable"), "set_transfer_mode", "get_transfer_mode");

View File

@ -72,6 +72,8 @@ public:
virtual ConnectionStatus get_connection_status() const = 0;
uint32_t generate_unique_id() const;
NetworkedMultiplayerPeer();
};

View File

@ -262,7 +262,7 @@ void Resource::notify_change_to_owners() {
#ifdef TOOLS_ENABLED
uint32_t Resource::hash_edited_version() const {
uint32_t hash = hash_djb2_one_32(get_edited_version());
uint32_t hash = hash_murmur3_one_32(get_edited_version());
List<PropertyInfo> plist;
get_property_list(&plist);
@ -271,7 +271,7 @@ uint32_t Resource::hash_edited_version() const {
if (E->get().usage & PROPERTY_USAGE_STORAGE && E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) {
RES res = get(E->get().name);
if (res.is_valid()) {
hash = hash_djb2_one_32(res->hash_edited_version(), hash);
hash = hash_murmur3_one_32(res->hash_edited_version(), hash);
}
}
}

View File

@ -3228,10 +3228,10 @@ uint32_t Variant::hash() const {
return _data._bool ? 1 : 0;
} break;
case INT: {
return _data._int;
return hash_one_uint64((uint64_t)_data._int);
} break;
case REAL: {
return hash_djb2_one_float(_data._real);
return hash_murmur3_one_float(_data._real);
} break;
case STRING: {
return reinterpret_cast<const String *>(_data._mem)->hash();
@ -3239,34 +3239,22 @@ uint32_t Variant::hash() const {
// math types
case RECT2: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x);
hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.y, hash);
hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash);
return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Rect2 *>(_data._mem));
} break;
case RECT2I: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2i *>(_data._mem)->position.x);
hash = hash_djb2_one_float(reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash);
hash = hash_djb2_one_float(reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash);
return hash_djb2_one_float(reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Rect2i *>(_data._mem));
} break;
case VECTOR2: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x);
return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector2 *>(_data._mem));
} break;
case VECTOR2I: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2i *>(_data._mem)->x);
return hash_djb2_one_float(reinterpret_cast<const Vector2i *>(_data._mem)->y, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector2i *>(_data._mem));
} break;
case VECTOR3: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->x);
hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash);
return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector3 *>(_data._mem));
} break;
case VECTOR3I: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3i *>(_data._mem)->x);
hash = hash_djb2_one_float(reinterpret_cast<const Vector3i *>(_data._mem)->y, hash);
return hash_djb2_one_float(reinterpret_cast<const Vector3i *>(_data._mem)->z, hash);
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector3i *>(_data._mem));
} break;
case VECTOR4: {
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4 *>(_data._mem));
@ -3274,60 +3262,69 @@ uint32_t Variant::hash() const {
case VECTOR4I: {
return HashMapHasherDefault::hash(*reinterpret_cast<const Vector4i *>(_data._mem));
} break;
case PLANE: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x);
hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.y, hash);
hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.z, hash);
return hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->d, hash);
uint32_t h = HASH_MURMUR3_SEED;
const Plane &p = *reinterpret_cast<const Plane *>(_data._mem);
h = hash_murmur3_one_real(p.normal.x, h);
h = hash_murmur3_one_real(p.normal.y, h);
h = hash_murmur3_one_real(p.normal.z, h);
h = hash_murmur3_one_real(p.d, h);
return hash_fmix32(h);
} break;
case QUATERNION: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->x);
hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->y, hash);
hash = hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->z, hash);
return hash_djb2_one_float(reinterpret_cast<const Quaternion *>(_data._mem)->w, hash);
uint32_t h = HASH_MURMUR3_SEED;
const Quaternion &q = *reinterpret_cast<const Quaternion *>(_data._mem);
h = hash_murmur3_one_real(q.x, h);
h = hash_murmur3_one_real(q.y, h);
h = hash_murmur3_one_real(q.z, h);
h = hash_murmur3_one_real(q.w, h);
return hash_fmix32(h);
} break;
case AABB: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
hash = hash_djb2_one_float(_data._aabb->position[i], hash);
hash = hash_djb2_one_float(_data._aabb->size[i], hash);
}
return hash;
return HashMapHasherDefault::hash(*_data._aabb);
} break;
case BASIS: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
hash = hash_djb2_one_float(_data._basis->rows[i][j], hash);
}
}
return hash;
uint32_t h = HASH_MURMUR3_SEED;
const Basis &b = *_data._basis;
h = hash_murmur3_one_real(b[0].x, h);
h = hash_murmur3_one_real(b[0].y, h);
h = hash_murmur3_one_real(b[0].z, h);
h = hash_murmur3_one_real(b[1].x, h);
h = hash_murmur3_one_real(b[1].y, h);
h = hash_murmur3_one_real(b[1].z, h);
h = hash_murmur3_one_real(b[2].x, h);
h = hash_murmur3_one_real(b[2].y, h);
h = hash_murmur3_one_real(b[2].z, h);
return hash_fmix32(h);
} break;
case TRANSFORM: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
hash = hash_djb2_one_float(_data._transform->basis.rows[i][j], hash);
}
hash = hash_djb2_one_float(_data._transform->origin[i], hash);
}
return hash;
uint32_t h = HASH_MURMUR3_SEED;
const Transform &t = *_data._transform;
h = hash_murmur3_one_real(t.basis[0].x, h);
h = hash_murmur3_one_real(t.basis[0].y, h);
h = hash_murmur3_one_real(t.basis[0].z, h);
h = hash_murmur3_one_real(t.basis[1].x, h);
h = hash_murmur3_one_real(t.basis[1].y, h);
h = hash_murmur3_one_real(t.basis[1].z, h);
h = hash_murmur3_one_real(t.basis[2].x, h);
h = hash_murmur3_one_real(t.basis[2].y, h);
h = hash_murmur3_one_real(t.basis[2].z, h);
h = hash_murmur3_one_real(t.origin.x, h);
h = hash_murmur3_one_real(t.origin.y, h);
h = hash_murmur3_one_real(t.origin.z, h);
return hash_fmix32(h);
} break;
case TRANSFORM2D: {
uint32_t hash = 5831;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
hash = hash_djb2_one_float(_data._transform2d->columns[i][j], hash);
}
}
uint32_t h = HASH_MURMUR3_SEED;
const Transform2D &t = *_data._transform2d;
h = hash_murmur3_one_real(t[0].x, h);
h = hash_murmur3_one_real(t[0].y, h);
h = hash_murmur3_one_real(t[1].x, h);
h = hash_murmur3_one_real(t[1].y, h);
h = hash_murmur3_one_real(t[2].x, h);
h = hash_murmur3_one_real(t[2].y, h);
return hash;
return hash_fmix32(h);
} break;
case PROJECTION: {
uint32_t h = HASH_MURMUR3_SEED;
@ -3353,19 +3350,22 @@ uint32_t Variant::hash() const {
// misc types
case COLOR: {
uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->r);
hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->g, hash);
hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->b, hash);
return hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->a, hash);
uint32_t h = HASH_MURMUR3_SEED;
const Color &c = *reinterpret_cast<const Color *>(_data._mem);
h = hash_murmur3_one_float(c.r, h);
h = hash_murmur3_one_float(c.g, h);
h = hash_murmur3_one_float(c.b, h);
h = hash_murmur3_one_float(c.a, h);
return hash_fmix32(h);
} break;
case NODE_PATH: {
return reinterpret_cast<const NodePath *>(_data._mem)->hash();
} break;
case RID: {
return hash_djb2_one_64(reinterpret_cast<const ::RID *>(_data._mem)->get_id());
return hash_one_uint64(reinterpret_cast<const ::RID *>(_data._mem)->get_id());
} break;
case OBJECT: {
return hash_djb2_one_64(make_uint64_t(_UNSAFE_OBJ_PROXY_PTR(*this)));
return hash_one_uint64(hash_make_uint64_t(_UNSAFE_OBJ_PROXY_PTR(*this)));
} break;
case STRING_NAME: {
return reinterpret_cast<const StringName *>(_data._mem)->hash();
@ -3383,9 +3383,9 @@ uint32_t Variant::hash() const {
int len = arr.size();
if (likely(len)) {
PoolVector<uint8_t>::Read r = arr.read();
return hash_djb2_buffer((uint8_t *)&r[0], len);
return hash_murmur3_buffer((uint8_t *)&r[0], len);
} else {
return hash_djb2_one_64(0);
return hash_murmur3_one_64(0);
}
} break;
@ -3394,9 +3394,9 @@ uint32_t Variant::hash() const {
int len = arr.size();
if (likely(len)) {
PoolVector<int>::Read r = arr.read();
return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(int));
return hash_murmur3_buffer((uint8_t *)&r[0], len * sizeof(int));
} else {
return hash_djb2_one_64(0);
return hash_murmur3_one_64(0);
}
} break;
@ -3406,14 +3406,20 @@ uint32_t Variant::hash() const {
if (likely(len)) {
PoolVector<real_t>::Read r = arr.read();
return hash_djb2_buffer((uint8_t *)&r[0], len * sizeof(real_t));
uint32_t h = HASH_MURMUR3_SEED;
for (int i = 0; i < len; i++) {
h = hash_murmur3_one_real(r[i], h);
}
return hash_fmix32(h);
} else {
return hash_djb2_one_float(0.0);
return hash_murmur3_one_real(0.0);
}
} break;
case POOL_STRING_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<String> &arr = *reinterpret_cast<const PoolVector<String> *>(_data._mem);
int len = arr.size();
@ -3421,14 +3427,16 @@ uint32_t Variant::hash() const {
PoolVector<String>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_32(r[i].hash(), hash);
hash = hash_murmur3_one_32(r[i].hash(), hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR2_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector2> &arr = *reinterpret_cast<const PoolVector<Vector2> *>(_data._mem);
int len = arr.size();
@ -3436,15 +3444,17 @@ uint32_t Variant::hash() const {
PoolVector<Vector2>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_murmur3_one_real(r[i].x, hash);
hash = hash_murmur3_one_real(r[i].y, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR2I_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector2i> &arr = *reinterpret_cast<const PoolVector<Vector2i> *>(_data._mem);
int len = arr.size();
@ -3452,15 +3462,17 @@ uint32_t Variant::hash() const {
PoolVector<Vector2i>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_murmur3_one_32(r[i].x, hash);
hash = hash_murmur3_one_32(r[i].y, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR3_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector3> &arr = *reinterpret_cast<const PoolVector<Vector3> *>(_data._mem);
int len = arr.size();
@ -3468,16 +3480,18 @@ uint32_t Variant::hash() const {
PoolVector<Vector3>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_djb2_one_float(r[i].z, hash);
hash = hash_murmur3_one_real(r[i].x, hash);
hash = hash_murmur3_one_real(r[i].y, hash);
hash = hash_murmur3_one_real(r[i].z, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR3I_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector3i> &arr = *reinterpret_cast<const PoolVector<Vector3i> *>(_data._mem);
int len = arr.size();
@ -3485,16 +3499,18 @@ uint32_t Variant::hash() const {
PoolVector<Vector3i>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_djb2_one_float(r[i].z, hash);
hash = hash_murmur3_one_32(r[i].x, hash);
hash = hash_murmur3_one_32(r[i].y, hash);
hash = hash_murmur3_one_32(r[i].z, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR4_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector4> &arr = *reinterpret_cast<const PoolVector<Vector4> *>(_data._mem);
int len = arr.size();
@ -3502,17 +3518,19 @@ uint32_t Variant::hash() const {
PoolVector<Vector4>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_djb2_one_float(r[i].z, hash);
hash = hash_djb2_one_float(r[i].w, hash);
hash = hash_murmur3_one_real(r[i].x, hash);
hash = hash_murmur3_one_real(r[i].y, hash);
hash = hash_murmur3_one_real(r[i].z, hash);
hash = hash_murmur3_one_real(r[i].w, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_VECTOR4I_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Vector4i> &arr = *reinterpret_cast<const PoolVector<Vector4i> *>(_data._mem);
int len = arr.size();
@ -3520,17 +3538,19 @@ uint32_t Variant::hash() const {
PoolVector<Vector4i>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].x, hash);
hash = hash_djb2_one_float(r[i].y, hash);
hash = hash_djb2_one_float(r[i].z, hash);
hash = hash_djb2_one_float(r[i].w, hash);
hash = hash_murmur3_one_32(r[i].x, hash);
hash = hash_murmur3_one_32(r[i].y, hash);
hash = hash_murmur3_one_32(r[i].z, hash);
hash = hash_murmur3_one_32(r[i].w, hash);
}
hash = hash_fmix32(hash);
}
return hash;
} break;
case POOL_COLOR_ARRAY: {
uint32_t hash = 5831;
uint32_t hash = HASH_MURMUR3_SEED;
const PoolVector<Color> &arr = *reinterpret_cast<const PoolVector<Color> *>(_data._mem);
int len = arr.size();
@ -3538,11 +3558,13 @@ uint32_t Variant::hash() const {
PoolVector<Color>::Read r = arr.read();
for (int i = 0; i < len; i++) {
hash = hash_djb2_one_float(r[i].r, hash);
hash = hash_djb2_one_float(r[i].g, hash);
hash = hash_djb2_one_float(r[i].b, hash);
hash = hash_djb2_one_float(r[i].a, hash);
hash = hash_murmur3_one_real(r[i].r, hash);
hash = hash_murmur3_one_real(r[i].g, hash);
hash = hash_murmur3_one_real(r[i].b, hash);
hash = hash_murmur3_one_real(r[i].a, hash);
}
hash = hash_fmix32(hash);
}
return hash;

View File

@ -132,7 +132,7 @@ class Delaunay3D {
_FORCE_INLINE_ static uint32_t hash(const Triangle &p_triangle) {
uint32_t h = hash_djb2_one_32(p_triangle.triangle[0]);
h = hash_djb2_one_32(p_triangle.triangle[1], h);
return hash_djb2_one_32(p_triangle.triangle[2], h);
return hash_fmix32(hash_djb2_one_32(p_triangle.triangle[2], h));
}
};