From a3567dea3a2db620262f503a770fe750812dbf47 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 8 Feb 2019 14:18:33 -0800 Subject: [PATCH] clean HashKey API, reduce dependency tree --- libraries/physics/src/ShapeManager.cpp | 21 +++++------ libraries/physics/src/ShapeManager.h | 4 +-- libraries/shared/src/HashKey.h | 5 ++- libraries/shared/src/ShapeInfo.cpp | 49 ++++++++++++++------------ libraries/shared/src/ShapeInfo.h | 6 ++-- 5 files changed, 43 insertions(+), 42 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index cb37b0f96d..991cd0efc9 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -33,8 +33,8 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { if (info.getType() == SHAPE_TYPE_NONE) { return nullptr; } - HashKey key = info.getHash(); - ShapeReference* shapeRef = _shapeMap.find(key); + HashKey hashKey(info.getHash()); + ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { shapeRef->refCount++; return shapeRef->shape; @@ -44,27 +44,28 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { ShapeReference newRef; newRef.refCount = 1; newRef.shape = shape; - newRef.key = key; - _shapeMap.insert(key, newRef); + newRef.key = info.getHash(); + _shapeMap.insert(hashKey, newRef); } return shape; } // private helper method -bool ShapeManager::releaseShapeByKey(const HashKey& key) { - ShapeReference* shapeRef = _shapeMap.find(key); +bool ShapeManager::releaseShapeByKey(uint64_t key) { + HashKey hashKey(key); + ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { if (shapeRef->refCount > 0) { shapeRef->refCount--; if (shapeRef->refCount == 0) { // look for existing entry in _pendingGarbage, starting from the back for (int32_t i = _pendingGarbage.size() - 1; i > -1; --i) { - if (_pendingGarbage[i] == key.getHash64()) { + if (_pendingGarbage[i] == key) { // already on the list, don't add it again return true; } } - _pendingGarbage.push_back(key.getHash64()); + _pendingGarbage.push_back(key); const int MAX_SHAPE_GARBAGE_CAPACITY = 255; if (_pendingGarbage.size() > MAX_SHAPE_GARBAGE_CAPACITY) { collectGarbage(); @@ -107,8 +108,8 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - HashKey key = info.getHash(); - const ShapeReference* shapeRef = _shapeMap.find(key); + HashKey hashKey(info.getHash()); + const ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { return shapeRef->refCount; } diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index 58f1b53c18..47b6c5340a 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -63,13 +63,13 @@ public: bool hasShape(const btCollisionShape* shape) const; private: - bool releaseShapeByKey(const HashKey& key); + bool releaseShapeByKey(uint64_t key); class ShapeReference { public: int refCount; const btCollisionShape* shape; - HashKey key; + uint64_t key { 0 }; ShapeReference() : refCount(0), shape(nullptr) {} }; diff --git a/libraries/shared/src/HashKey.h b/libraries/shared/src/HashKey.h index a32a8664a7..446eb4c25f 100644 --- a/libraries/shared/src/HashKey.h +++ b/libraries/shared/src/HashKey.h @@ -39,13 +39,12 @@ public: 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; } + // These methods for accumulating a hash. 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 + uint64_t getHash64() const { return _hash; } private: uint64_t _hash { 0 }; diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index c256cf2b76..bf51e455c5 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -13,6 +13,7 @@ #include +#include "HashKey.h" #include "NumericalConstants.h" // for MILLIMETERS_PER_METER /**jsdoc @@ -96,7 +97,7 @@ void ShapeInfo::clear() { _sphereCollection.clear(); _halfExtents = glm::vec3(0.0f); _offset = glm::vec3(0.0f); - _hashKey.clear(); + _hash64 = 0; _type = SHAPE_TYPE_NONE; } @@ -131,14 +132,14 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString default: break; } - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setBox(const glm::vec3& halfExtents) { _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setSphere(float radius) { @@ -146,7 +147,7 @@ void ShapeInfo::setSphere(float radius) { _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); _halfExtents = glm::vec3(radius); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setMultiSphere(const std::vector& centers, const std::vector& radiuses) { @@ -158,12 +159,12 @@ void ShapeInfo::setMultiSphere(const std::vector& centers, const std: SphereData sphere = SphereData(centers[i], radiuses[i]); _sphereCollection.push_back(sphere); } - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { _pointCollection = pointCollection; - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setCapsuleY(float radius, float cylinderHalfHeight) { @@ -172,12 +173,12 @@ void ShapeInfo::setCapsuleY(float radius, float cylinderHalfHeight) { radius = glm::max(radius, MIN_HALF_EXTENT); cylinderHalfHeight = glm::max(cylinderHalfHeight, 0.0f); _halfExtents = glm::vec3(radius, cylinderHalfHeight + radius, radius); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setOffset(const glm::vec3& offset) { _offset = offset; - _hashKey.clear(); + _hash64 = 0; } uint32_t ShapeInfo::getNumSubShapes() const { @@ -269,20 +270,21 @@ float ShapeInfo::computeVolume() const { return volume; } -const HashKey& ShapeInfo::getHash() const { +uint64_t ShapeInfo::getHash() const { // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. - if (_hashKey.isNull() && _type != SHAPE_TYPE_NONE) { + if (_hash64 == 0 && _type != SHAPE_TYPE_NONE) { + HashKey hashKey; // The key is not yet cached therefore we must compute it. - _hashKey.hashUint64((uint64_t)_type); + hashKey.hashUint64((uint64_t)_type); if (_type == SHAPE_TYPE_MULTISPHERE) { for (auto &sphereData : _sphereCollection) { - _hashKey.hashVec3(glm::vec3(sphereData)); - _hashKey.hashFloat(sphereData.w); + hashKey.hashVec3(glm::vec3(sphereData)); + hashKey.hashFloat(sphereData.w); } } else if (_type != SHAPE_TYPE_SIMPLE_HULL) { - _hashKey.hashVec3(_halfExtents); - _hashKey.hashVec3(_offset); + 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 @@ -292,7 +294,7 @@ const HashKey& ShapeInfo::getHash() const { const int numPoints = (int)points.size(); for (int i = 0; i < numPoints; ++i) { - _hashKey.hashVec3(points[i]); + hashKey.hashVec3(points[i]); } } @@ -300,23 +302,24 @@ const HashKey& ShapeInfo::getHash() const { if (!url.isEmpty()) { QByteArray baUrl = url.toLocal8Bit(); uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size()); - _hashKey.hashUint64((uint64_t)urlHash); + hashKey.hashUint64((uint64_t)urlHash); } if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) { uint64_t numHulls = (uint64_t)_pointCollection.size(); - _hashKey.hashUint64(numHulls); + hashKey.hashUint64(numHulls); } else if (_type == SHAPE_TYPE_MULTISPHERE) { uint64_t numSpheres = (uint64_t)_sphereCollection.size(); - _hashKey.hashUint64(numSpheres); + hashKey.hashUint64(numSpheres); } else if (_type == SHAPE_TYPE_SIMPLE_HULL) { - _hashKey.hashUint64(1); - } + hashKey.hashUint64(1); + } + _hash64 = hashKey.getHash64(); } - return _hashKey; + return _hash64; } void ShapeInfo::setHalfExtents(const glm::vec3& halfExtents) { _halfExtents = glm::max(halfExtents, glm::vec3(MIN_HALF_EXTENT)); - _hashKey.clear(); + _hash64 = 0; } diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index d838d7b214..6b0f981b24 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -18,8 +18,6 @@ #include #include -#include "HashKey.h" - const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored // Bullet has a mesh generation util for convex shapes that we used to @@ -91,7 +89,7 @@ public: float computeVolume() const; - const HashKey& getHash() const; + uint64_t getHash() const; protected: void setHalfExtents(const glm::vec3& halfExtents); @@ -102,7 +100,7 @@ protected: TriangleIndices _triangleIndices; glm::vec3 _halfExtents = glm::vec3(0.0f); glm::vec3 _offset = glm::vec3(0.0f); - mutable HashKey _hashKey; + mutable uint64_t _hash64; ShapeType _type = SHAPE_TYPE_NONE; };