clean HashKey API, reduce dependency tree

This commit is contained in:
Andrew Meadows 2019-02-08 14:18:33 -08:00
parent 17ab0cb92e
commit a3567dea3a
5 changed files with 43 additions and 42 deletions

View file

@ -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;
}

View file

@ -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) {}
};

View file

@ -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 };

View file

@ -13,6 +13,7 @@
#include <math.h>
#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<glm::vec3>& centers, const std::vector<float>& radiuses) {
@ -158,12 +159,12 @@ void ShapeInfo::setMultiSphere(const std::vector<glm::vec3>& 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;
}

View file

@ -18,8 +18,6 @@
#include <glm/glm.hpp>
#include <glm/gtx/norm.hpp>
#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;
};