From 45e571dd02cfed91b8a4c7e954b7693fd1b11617 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 26 Oct 2017 08:16:41 -0700 Subject: [PATCH] cleanup ShapeInfo::getHash() --- libraries/physics/src/ShapeManager.cpp | 8 +- libraries/physics/src/ShapeManager.h | 10 +- libraries/shared/src/HashKey.cpp | 67 +++++++++++++ libraries/shared/src/HashKey.h | 52 ++++++++++ libraries/shared/src/ShapeInfo.cpp | 119 +++++------------------ libraries/shared/src/ShapeInfo.h | 6 +- tests/physics/src/ShapeInfoTests.cpp | 129 +++++++++---------------- tests/physics/src/ShapeInfoTests.h | 4 - 8 files changed, 202 insertions(+), 193 deletions(-) create mode 100644 libraries/shared/src/HashKey.cpp create mode 100644 libraries/shared/src/HashKey.h diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 77716f671b..97b9e5dab1 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -32,7 +32,7 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { if (info.getType() == SHAPE_TYPE_NONE) { return nullptr; } - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { shapeRef->refCount++; @@ -50,7 +50,7 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { } // private helper method -bool ShapeManager::releaseShapeByKey(const DoubleHashKey& key) { +bool ShapeManager::releaseShapeByKey(const HashKey& key) { ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { if (shapeRef->refCount > 0) { @@ -88,7 +88,7 @@ bool ShapeManager::releaseShape(const btCollisionShape* shape) { void ShapeManager::collectGarbage() { int numShapes = _pendingGarbage.size(); for (int i = 0; i < numShapes; ++i) { - DoubleHashKey& key = _pendingGarbage[i]; + HashKey& key = _pendingGarbage[i]; ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { ShapeFactory::deleteShape(shapeRef->shape); @@ -99,7 +99,7 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { return shapeRef->refCount; diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index ed81b5e8f8..6ec3573b53 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -17,7 +17,7 @@ #include -#include "DoubleHashKey.h" +#include "HashKey.h" class ShapeManager { public: @@ -41,18 +41,18 @@ public: bool hasShape(const btCollisionShape* shape) const; private: - bool releaseShapeByKey(const DoubleHashKey& key); + bool releaseShapeByKey(const HashKey& key); class ShapeReference { public: int refCount; const btCollisionShape* shape; - DoubleHashKey key; + HashKey key; ShapeReference() : refCount(0), shape(nullptr) {} }; - btHashMap _shapeMap; - btAlignedObjectArray _pendingGarbage; + btHashMap _shapeMap; + btAlignedObjectArray _pendingGarbage; }; #endif // hifi_ShapeManager_h diff --git a/libraries/shared/src/HashKey.cpp b/libraries/shared/src/HashKey.cpp new file mode 100644 index 0000000000..488eccb1bf --- /dev/null +++ b/libraries/shared/src/HashKey.cpp @@ -0,0 +1,67 @@ +// +// HashKey.cpp +// libraries/shared/src +// +// Created by Andrew Meadows 2017.10.25 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "HashKey.h" + +#include "NumericalConstants.h" + + +const uint8_t NUM_PRIMES = 64; +const uint64_t PRIMES[] = { + 4194301UL, 4194287UL, 4194277UL, 4194271UL, 4194247UL, 4194217UL, 4194199UL, 4194191UL, + 4194187UL, 4194181UL, 4194173UL, 4194167UL, 4194143UL, 4194137UL, 4194131UL, 4194107UL, + 4194103UL, 4194023UL, 4194011UL, 4194007UL, 4193977UL, 4193971UL, 4193963UL, 4193957UL, + 4193939UL, 4193929UL, 4193909UL, 4193869UL, 4193807UL, 4193803UL, 4193801UL, 4193789UL, + 4193759UL, 4193753UL, 4193743UL, 4193701UL, 4193663UL, 4193633UL, 4193573UL, 4193569UL, + 4193551UL, 4193549UL, 4193531UL, 4193513UL, 4193507UL, 4193459UL, 4193447UL, 4193443UL, + 4193417UL, 4193411UL, 4193393UL, 4193389UL, 4193381UL, 4193377UL, 4193369UL, 4193359UL, + 4193353UL, 4193327UL, 4193309UL, 4193303UL, 4193297UL, 4193279UL, 4193269UL, 4193263UL +}; + + +// this hash function inspired by Squirrel Eiserloh's GDC2017 talk: "Noise-Based RNG" +uint64_t squirrel3_64(uint64_t data, uint8_t primeIndex) { + constexpr uint64_t BIT_NOISE1 = 2760725261486592643UL; + constexpr uint64_t BIT_NOISE2 = 6774464464027632833UL; + constexpr uint64_t BIT_NOISE3 = 5545331650366059883UL; + + // blend prime numbers into the hash to prevent dupes + // when hashing the same set of numbers in a different order + uint64_t hash = PRIMES[primeIndex % NUM_PRIMES] * data; + hash *= BIT_NOISE1; + hash ^= (hash >> 16); + hash += BIT_NOISE2; + hash ^= (hash << 16); + hash *= BIT_NOISE3; + return hash ^ (hash >> 16); +} + +constexpr float QUANTIZED_VALUES_PER_METER = 250.0f; + +// static +float HashKey::getNumQuantizedValuesPerMeter() { + return QUANTIZED_VALUES_PER_METER; +} + +void HashKey::hashUint64(uint64_t data) { + _hash += squirrel3_64(data, ++_hashCount); +} + +void HashKey::hashFloat(float data) { + _hash += squirrel3_64((uint64_t)((int64_t)(data * QUANTIZED_VALUES_PER_METER)), ++_hashCount); +} + +void HashKey::hashVec3(const glm::vec3& data) { + _hash += squirrel3_64((uint64_t)((int64_t)(data[0] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); + _hash *= squirrel3_64((uint64_t)((int64_t)(data[1] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); + _hash ^= squirrel3_64((uint64_t)((int64_t)(data[2] * QUANTIZED_VALUES_PER_METER)), ++_hashCount); +} + diff --git a/libraries/shared/src/HashKey.h b/libraries/shared/src/HashKey.h new file mode 100644 index 0000000000..5fce182084 --- /dev/null +++ b/libraries/shared/src/HashKey.h @@ -0,0 +1,52 @@ +// +// HashKey.h +// libraries/shared/src +// +// Created by Andrew Meadows 2017.10.25 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_HashKey_h +#define hifi_HashKey_h + +#include +#include + +#include + + +// HashKey for use with btHashMap which requires a particular API for its keys. In particular it +// requires its Key to implement these methods: +// +// bool Key::equals() +// int32_t Key::getHash() +// +// The important thing about the HashKey implementation is that while getHash() returns 32-bits, +// internally HashKey stores a 64-bit hash which is used for the equals() comparison. This allows +// btHashMap to insert "dupe" 32-bit keys to different "values". + +class HashKey { +public: + static float getNumQuantizedValuesPerMeter(); + + // These two methods are required by btHashMap. + bool equals(const HashKey& other) const { return _hash == other._hash; } + int32_t getHash() const { return (int32_t)((uint32_t)_hash); } + + void clear() { _hash = _hashCount = 0; } + bool isNull() const { return _hash == 0 && _hashCount == 0; } + void hashUint64(uint64_t data); + void hashFloat(float data); + void hashVec3(const glm::vec3& data); + + uint64_t getHash64() const { return _hash; } // for debug/test purposes + +private: + uint64_t _hash { 0 }; + uint8_t _hashCount { 0 }; +}; + +#endif // hifi_HashKey_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 36ce38335a..8cdc4bcf14 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -53,7 +53,7 @@ void ShapeInfo::clear() { _triangleIndices.clear(); _halfExtents = glm::vec3(0.0f); _offset = glm::vec3(0.0f); - _doubleHashKey.clear(); + _hashKey.clear(); _type = SHAPE_TYPE_NONE; } @@ -87,14 +87,14 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString default: break; } - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setBox(const glm::vec3& halfExtents) { _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setSphere(float radius) { @@ -102,12 +102,12 @@ void ShapeInfo::setSphere(float radius) { _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); _halfExtents = glm::vec3(radius); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { _pointCollection = pointCollection; - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setCapsuleY(float radius, float halfHeight) { @@ -116,12 +116,12 @@ void ShapeInfo::setCapsuleY(float radius, float halfHeight) { radius = glm::max(radius, MIN_HALF_EXTENT); halfHeight = glm::max(halfHeight, 0.0f); _halfExtents = glm::vec3(radius, halfHeight, radius); - _doubleHashKey.clear(); + _hashKey.clear(); } void ShapeInfo::setOffset(const glm::vec3& offset) { _offset = offset; - _doubleHashKey.clear(); + _hashKey.clear(); } uint32_t ShapeInfo::getNumSubShapes() const { @@ -256,119 +256,46 @@ bool ShapeInfo::contains(const glm::vec3& point) const { } } -const DoubleHashKey& ShapeInfo::getHash() const { +const HashKey& ShapeInfo::getHash() const { // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. - if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { - bool useOffset = glm::length2(_offset) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET; + if (_hashKey.isNull() && _type != SHAPE_TYPE_NONE) { // The key is not yet cached therefore we must compute it. - // compute hash1 - // TODO?: provide lookup table for hash/hash2 of _type rather than recompute? - uint32_t primeIndex = 0; - _doubleHashKey.computeHash((uint32_t)_type, primeIndex++); - + _hashKey.hashUint64((uint64_t)_type); if (_type != SHAPE_TYPE_SIMPLE_HULL) { - // compute hash1 - uint32_t hash = _doubleHashKey.getHash(); - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - hash ^= DoubleHashKey::hashFunction( - (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), - primeIndex++); - if (useOffset) { - hash ^= DoubleHashKey::hashFunction( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f), - primeIndex++); - } - } - _doubleHashKey.setHash(hash); - - // compute hash2 - hash = _doubleHashKey.getHash2(); - for (int j = 0; j < 3; ++j) { - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - uint32_t floatHash = DoubleHashKey::hashFunction2( - (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f)); - if (useOffset) { - floatHash ^= DoubleHashKey::hashFunction2( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f)); - } - hash += ~(floatHash << 17); - hash ^= (floatHash >> 11); - hash += (floatHash << 4); - hash ^= (floatHash >> 7); - hash += ~(floatHash << 10); - hash = (hash << 16) | (hash >> 16); - } - _doubleHashKey.setHash2(hash); + _hashKey.hashVec3(_halfExtents); + _hashKey.hashVec3(_offset); } else { - + // TODO: we could avoid hashing all of these points if we were to supply the ShapeInfo with a unique + // descriptive string. Shapes that are uniquely described by their type and URL could just put their + // url in the description. assert(_pointCollection.size() == (size_t)1); const PointList & points = _pointCollection.back(); const int numPoints = (int)points.size(); - uint32_t hash = _doubleHashKey.getHash(); - uint32_t hash2 = _doubleHashKey.getHash2(); - for (int pointIndex = 0; pointIndex < numPoints; ++pointIndex) { - // compute hash1 & 2 - const glm::vec3 &curPoint = points[pointIndex]; - for (int vecCompIndex = 0; vecCompIndex < 3; ++vecCompIndex) { - - // NOTE: 0.49f is used to bump the float up almost half a millimeter - // so the cast to int produces a round() effect rather than a floor() - uint32_t valueToHash = (uint32_t)(curPoint[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, curPoint[vecCompIndex]) * 0.49f); - - hash ^= DoubleHashKey::hashFunction(valueToHash, primeIndex++); - uint32_t floatHash = DoubleHashKey::hashFunction2(valueToHash); - - if (useOffset) { - - const uint32_t offsetValToHash = (uint32_t)(_offset[vecCompIndex] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[vecCompIndex])* 0.49f); - - hash ^= DoubleHashKey::hashFunction(offsetValToHash, primeIndex++); - floatHash ^= DoubleHashKey::hashFunction2(offsetValToHash); - } - - hash2 += ~(floatHash << 17); - hash2 ^= (floatHash >> 11); - hash2 += (floatHash << 4); - hash2 ^= (floatHash >> 7); - hash2 += ~(floatHash << 10); - hash2 = (hash2 << 16) | (hash2 >> 16); - } + for (int i = 0; i < numPoints; ++i) { + _hashKey.hashVec3(points[i]); } - - _doubleHashKey.setHash(hash); - _doubleHashKey.setHash2(hash2); } QString url = _url.toString(); if (!url.isEmpty()) { - // fold the urlHash into both parts QByteArray baUrl = url.toLocal8Bit(); uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size()); - _doubleHashKey.setHash(_doubleHashKey.getHash() ^ urlHash); - _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ urlHash); + _hashKey.hashUint64((uint64_t)urlHash); } - uint32_t numHulls = 0; if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) { - numHulls = (uint32_t)_pointCollection.size(); + uint64_t numHulls = (uint64_t)_pointCollection.size(); + _hashKey.hashUint64(numHulls); } else if (_type == SHAPE_TYPE_SIMPLE_HULL) { - numHulls = 1; - } - if (numHulls > 0) { - uint32_t hash = DoubleHashKey::hashFunction(numHulls, primeIndex++); - _doubleHashKey.setHash(_doubleHashKey.getHash() ^ hash); - hash = DoubleHashKey::hashFunction2(numHulls); - _doubleHashKey.setHash2(_doubleHashKey.getHash2() ^ hash); + _hashKey.hashUint64(1); } } - return _doubleHashKey; + return _hashKey; } void ShapeInfo::setHalfExtents(const glm::vec3& halfExtents) { _halfExtents = glm::max(halfExtents, glm::vec3(MIN_HALF_EXTENT)); + _hashKey.clear(); } diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index d658b936a3..069241e29d 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -18,7 +18,7 @@ #include #include -#include "DoubleHashKey.h" +#include "HashKey.h" const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored @@ -89,7 +89,7 @@ public: /// For compound shapes it will only return whether it is inside the bounding box bool contains(const glm::vec3& point) const; - const DoubleHashKey& getHash() const; + const HashKey& getHash() const; protected: void setHalfExtents(const glm::vec3& halfExtents); @@ -99,7 +99,7 @@ protected: TriangleIndices _triangleIndices; glm::vec3 _halfExtents = glm::vec3(0.0f); glm::vec3 _offset = glm::vec3(0.0f); - mutable DoubleHashKey _doubleHashKey; + mutable HashKey _hashKey; ShapeType _type = SHAPE_TYPE_NONE; }; diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index c6a19084a2..79d0092dc3 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -23,108 +23,78 @@ QTEST_MAIN(ShapeInfoTests) +// Enable this to manually run testHashCollisions +// (NOT a regular unit test; takes ~40 secs to run on an i7) +//#define MANUAL_TEST true + void ShapeInfoTests::testHashFunctions() { #if MANUAL_TEST int maxTests = 10000000; ShapeInfo info; - btHashMap hashes; + btHashMap hashes; - uint32_t bits[32]; - uint32_t masks[32]; - for (int i = 0; i < 32; ++i) { + const int32_t NUM_HASH_BITS = 32; + uint32_t bits[NUM_HASH_BITS]; + uint32_t masks[NUM_HASH_BITS]; + for (int i = 0; i < NUM_HASH_BITS; ++i) { bits[i] = 0; - masks[i] = 1U << i; + masks[i] = 1UL << i; } - float deltaLength = 0.002f; - float endLength = 100.0f; + float deltaLength = 1.0f / (HashKey::getNumQuantizedValuesPerMeter() - 3.0f); + float endLength = 2000.0f * deltaLength; int numSteps = (int)(endLength / deltaLength); int testCount = 0; int numCollisions = 0; btClock timer; - for (int x = 1; x < numSteps && testCount < maxTests; ++x) { - float radiusX = (float)x * deltaLength; + for (int i = 1; i < numSteps && testCount < maxTests; ++i) { + float radiusX = (float)i * deltaLength; + int32_t* hashPtr; // test sphere info.setSphere(radiusX); ++testCount; - DoubleHashKey key = info.getHash(); - uint32_t* hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; + HashKey key = info.getHash(); + hashPtr = hashes.find(key); + if (hashPtr) { + std::cout << testCount << " hash collision sphere radius = " << radiusX + << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr + << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key.getHash(), key.getHash2()); + hashes.insert(key, key.getHash()); } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { - ++bits[k]; + // track bit distribution counts to evaluate hash function randomness + for (int j = 0; j < NUM_HASH_BITS; ++j) { + if (masks[j] & key.getHash()) { + ++bits[j]; } } for (int y = 1; y < numSteps && testCount < maxTests; ++y) { float radiusY = (float)y * deltaLength; - /* TODO: reimplement Cylinder and Capsule shapes - // test cylinder and capsule - int types[] = { CYLINDER_SHAPE_PROXYTYPE, CAPSULE_SHAPE_PROXYTYPE }; - for (int i = 0; i < 2; ++i) { - switch(types[i]) { - case CYLINDER_SHAPE_PROXYTYPE: { - info.setCylinder(radiusX, radiusY); - break; - } - case CAPSULE_SHAPE_PROXYTYPE: { - info.setCapsuleY(radiusX, radiusY); - break; - } - } - - ++testCount; - key = info.getHash(); - hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX << " radiusY = " << radiusY - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; - ++numCollisions; - assert(false); - } else { - hashes.insert(key.getHash(), key.getHash2()); - } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { - ++bits[k]; - } - } - } - */ - for (int z = 1; z < numSteps && testCount < maxTests; ++z) { float radiusZ = (float)z * deltaLength; // test box info.setBox(glm::vec3(radiusX, radiusY, radiusZ)); ++testCount; - DoubleHashKey key = info.getHash(); - hashPtr = hashes.find(key.getHash()); - if (hashPtr && *hashPtr == key.getHash2()) { - std::cout << testCount << " hash collision radiusX = " << radiusX - << " radiusY = " << radiusY << " radiusZ = " << radiusZ - << " h1 = 0x" << std::hex << key.getHash() - << " h2 = 0x" << std::hex << key.getHash2() - << std::endl; + HashKey key = info.getHash(); + hashPtr = hashes.find(key); + if (hashPtr) { + std::cout << testCount << " hash collision box dimensions = < " << radiusX + << ", " << radiusY << ", " << radiusZ << " >" + << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr << " : 0x" << key.getHash64() + << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key.getHash(), key.getHash2()); + hashes.insert(key, key.getHash()); } - for (int k = 0; k < 32; ++k) { - if (masks[k] & key.getHash2()) { + // track bit distribution counts to evaluate hash function randomness + for (int k = 0; k < NUM_HASH_BITS; ++k) { + if (masks[k] & key.getHash()) { ++bits[k]; } } @@ -135,7 +105,8 @@ void ShapeInfoTests::testHashFunctions() { std::cout << msec << " msec with " << numCollisions << " collisions out of " << testCount << " hashes" << std::endl; // print out distribution of bits - for (int i = 0; i < 32; ++i) { + // ideally the numbers in each bin will be about the same + for (int i = 0; i < NUM_HASH_BITS; ++i) { std::cout << "bit 0x" << std::hex << masks[i] << std::dec << " = " << bits[i] << std::endl; } QCOMPARE(numCollisions, 0); @@ -146,15 +117,14 @@ void ShapeInfoTests::testBoxShape() { ShapeInfo info; glm::vec3 halfExtents(1.23f, 4.56f, 7.89f); info.setBox(halfExtents); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; } @@ -163,15 +133,14 @@ void ShapeInfoTests::testSphereShape() { ShapeInfo info; float radius = 1.23f; info.setSphere(radius); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; } @@ -182,15 +151,14 @@ void ShapeInfoTests::testCylinderShape() { float radius = 1.23f; float height = 4.56f; info.setCylinder(radius, height); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; */ @@ -202,15 +170,14 @@ void ShapeInfoTests::testCapsuleShape() { float radius = 1.23f; float height = 4.56f; info.setCapsule(radius, height); - DoubleHashKey key = info.getHash(); + HashKey key = info.getHash(); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; - DoubleHashKey otherKey = otherInfo.getHash(); + HashKey otherKey = otherInfo.getHash(); QCOMPARE(key.getHash(), otherKey.getHash()); - QCOMPARE(key.getHash2(), otherKey.getHash2()); delete shape; */ diff --git a/tests/physics/src/ShapeInfoTests.h b/tests/physics/src/ShapeInfoTests.h index fbd89a13a8..1f6054dd1a 100644 --- a/tests/physics/src/ShapeInfoTests.h +++ b/tests/physics/src/ShapeInfoTests.h @@ -18,10 +18,6 @@ //#include "BulletTestUtils.h" //#include "../QTestExtensions.h" -// Enable this to manually run testHashCollisions -// (NOT a regular unit test; takes ~17 secs to run on an i7) -#define MANUAL_TEST false - class ShapeInfoTests : public QObject { Q_OBJECT private slots: