From 12a7021bb5c89e005e690f5f22812759ebd720de Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sun, 8 Feb 2015 15:12:44 -0800 Subject: [PATCH] ShapeInfo computs own DoubleHashKey, gets new API --- libraries/physics/src/ShapeInfoUtil.cpp | 163 +++++++++--------- libraries/physics/src/ShapeInfoUtil.h | 5 +- libraries/physics/src/ShapeManager.cpp | 8 +- .../{physics => shared}/src/DoubleHashKey.cpp | 23 ++- libraries/shared/src/DoubleHashKey.h | 49 ++++++ libraries/shared/src/ShapeInfo.cpp | 150 +++++++++++----- libraries/shared/src/ShapeInfo.h | 37 ++-- 7 files changed, 288 insertions(+), 147 deletions(-) rename libraries/{physics => shared}/src/DoubleHashKey.cpp (66%) create mode 100644 libraries/shared/src/DoubleHashKey.h diff --git a/libraries/physics/src/ShapeInfoUtil.cpp b/libraries/physics/src/ShapeInfoUtil.cpp index 2893f4aebe..42492a235a 100644 --- a/libraries/physics/src/ShapeInfoUtil.cpp +++ b/libraries/physics/src/ShapeInfoUtil.cpp @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include #include // for MILLIMETERS_PER_METER #include "ShapeInfoUtil.h" @@ -24,12 +23,9 @@ int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) { case SHAPE_TYPE_SPHERE: bulletShapeType = SPHERE_SHAPE_PROXYTYPE; break; - case SHAPE_TYPE_CAPSULE: + case SHAPE_TYPE_CAPSULE_Y: bulletShapeType = CAPSULE_SHAPE_PROXYTYPE; break; - case SHAPE_TYPE_CYLINDER: - bulletShapeType = CYLINDER_SHAPE_PROXYTYPE; - break; } return bulletShapeType; } @@ -44,10 +40,7 @@ int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) { shapeInfoType = SHAPE_TYPE_SPHERE; break; case CAPSULE_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_CAPSULE; - break; - case CYLINDER_SHAPE_PROXYTYPE: - shapeInfoType = SHAPE_TYPE_CYLINDER; + shapeInfoType = SHAPE_TYPE_CAPSULE_Y; break; } return shapeInfoType; @@ -67,19 +60,6 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf info.setSphere(sphereShape->getRadius()); } break; - case SHAPE_TYPE_CYLINDER: { - // NOTE: we only support cylinders along yAxis - const btCylinderShape* cylinderShape = static_cast(shape); - btVector3 halfExtents = cylinderShape->getHalfExtentsWithMargin(); - info.setCylinder(halfExtents.getX(), halfExtents.getY()); - } - break; - case SHAPE_TYPE_CAPSULE: { - // NOTE: we only support capsules along yAxis - const btCapsuleShape* capsuleShape = static_cast(shape); - info.setCapsule(capsuleShape->getRadius(), capsuleShape->getHalfHeight()); - } - break; default: info.clear(); break; @@ -91,27 +71,20 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; - const QVector& data = info.getData(); switch(info.getType()) { case SHAPE_TYPE_BOX: { - // data[0] is halfExtents - shape = new btBoxShape(glmToBullet(data[0])); + shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; case SHAPE_TYPE_SPHERE: { - float radius = data[0].z; + float radius = info.getHalfExtents().x; shape = new btSphereShape(radius); } break; - case SHAPE_TYPE_CYLINDER: { - // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - // data[0] = btVector3(radius, halfHeight, unused) - shape = new btCylinderShape(glmToBullet(data[0])); - } - break; - case SHAPE_TYPE_CAPSULE: { - float radius = data[0].x; - float height = 2.0f * data[0].y; + case SHAPE_TYPE_CAPSULE_Y: { + glm::vec3 halfExtents = info.getHalfExtents(); + float radius = halfExtents.x; + float height = 2.0f * halfExtents.y; shape = new btCapsuleShape(radius, height); } break; @@ -119,49 +92,85 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { return shape; } -DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) { - DoubleHashKey key; - // compute hash - // scramble the bits of the type - // TODO?: provide lookup table for hash of info._type rather than recompute? - int primeIndex = 0; - unsigned int hash = DoubleHashKey::hashFunction((unsigned int)info.getType(), primeIndex++); - const QVector& data = info.getData(); +/* +const DoubleHashKey& ShapeInfo::computeHash() { + if (_hash.isNull()) { + // compute hash1 + // TODO?: provide lookup table for hash/hash2 of _type rather than recompute? + int primeIndex = 0; + _doubleHashKey._hash = DoubleHashKey::hashFunction((uint32_t)_type, primeIndex++); + _doubleHashKey._hash2 = DoubleHashKey::hashFunction2((uint32_t)_type()); + + if (getData()) { + // if externalData exists we use that to continue the hash - glm::vec3 tmpData; - int numData = data.size(); - for (int i = 0; i < numData; ++i) { - tmpData = data[i]; - 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() - unsigned int floatHash = - DoubleHashKey::hashFunction((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++); - hash ^= floatHash; + // compute hash + uint32_t hash = _doubleHashKey._hash; + const QVector& data = getData(); + + glm::vec3 tmpData; + int numData = data.size(); + for (int i = 0; i < numData; ++i) { + tmpData = data[i]; + 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::hashFunction((uint32_t)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + } + _doubleHashKey._hash = (int32_t)hash; + + // compute hash2 + hash = _doubleHashKey._hash2; + for (int i = 0; i < numData; ++i) { + tmpData = data[i]; + 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)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + } + _doubleHashKey._hash2 = (uint32_t)hash; + } else { + // this shape info has no external data so we just use extents to continue hash + // compute hash1 + uint32_t hash = _doubleHashKey._hash; + 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::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + _doubleHashKey._hash = (uint32_t)hash; + + // compute hash2 + hash = _doubleHashKey._hash2; + 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)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + _doubleHashKey._hash2 = (uint32_t)hash; } } - key._hash = (int)hash; - - // compute hash2 - // scramble the bits of the type - // TODO?: provide lookup table for hash2 of info._type rather than recompute? - hash = DoubleHashKey::hashFunction2((unsigned int)info.getType()); - - for (int i = 0; i < numData; ++i) { - tmpData = data[i]; - 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() - unsigned int floatHash = - DoubleHashKey::hashFunction2((int)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f)); - hash += ~(floatHash << 17); - hash ^= (floatHash >> 11); - hash += (floatHash << 4); - hash ^= (floatHash >> 7); - hash += ~(floatHash << 10); - hash = (hash << 16) | (hash >> 16); - } - } - key._hash2 = (int)hash; - return key; + + return _doubleHashKey; } +*/ diff --git a/libraries/physics/src/ShapeInfoUtil.h b/libraries/physics/src/ShapeInfoUtil.h index 438e3df715..d55ad2cdfb 100644 --- a/libraries/physics/src/ShapeInfoUtil.h +++ b/libraries/physics/src/ShapeInfoUtil.h @@ -15,10 +15,9 @@ #include #include +#include #include -#include "DoubleHashKey.h" - // translates between ShapeInfo and btShape namespace ShapeInfoUtil { @@ -26,7 +25,7 @@ namespace ShapeInfoUtil { btCollisionShape* createShapeFromInfo(const ShapeInfo& info); - DoubleHashKey computeHash(const ShapeInfo& info); + //DoubleHashKey computeHash(const ShapeInfo& info); // TODO? just use bullet shape types everywhere? int toBulletShapeType(int shapeInfoType); diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index b153150ce6..4de7976549 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -28,13 +28,13 @@ ShapeManager::~ShapeManager() { btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { // Very small or large objects are not supported. - float diagonal = glm::length2(info.getBoundingBoxDiagonal()); + float diagonal = 4.0f * glm::length2(info.getHalfExtents()); const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e4f; // 100 m cube if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) { return NULL; } - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { shapeRef->_refCount++; @@ -51,7 +51,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { } bool ShapeManager::releaseShape(const ShapeInfo& info) { - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { if (shapeRef->_refCount > 0) { @@ -95,7 +95,7 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - DoubleHashKey key = ShapeInfoUtil::computeHash(info); + DoubleHashKey key = info.getHash(); const ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { return shapeRef->_refCount; diff --git a/libraries/physics/src/DoubleHashKey.cpp b/libraries/shared/src/DoubleHashKey.cpp similarity index 66% rename from libraries/physics/src/DoubleHashKey.cpp rename to libraries/shared/src/DoubleHashKey.cpp index fae1d715fb..794604d21b 100644 --- a/libraries/physics/src/DoubleHashKey.cpp +++ b/libraries/shared/src/DoubleHashKey.cpp @@ -1,6 +1,6 @@ // // DoubleHashKey.cpp -// libraries/physcis/src +// libraries/shared/src // // Created by Andrew Meadows 2014.11.02 // Copyright 2014 High Fidelity, Inc. @@ -11,8 +11,8 @@ #include "DoubleHashKey.h" -const int NUM_PRIMES = 64; -const unsigned int PRIMES[] = { +const uint32_t NUM_PRIMES = 64; +const uint32_t PRIMES[] = { 4194301U, 4194287U, 4194277U, 4194271U, 4194247U, 4194217U, 4194199U, 4194191U, 4194187U, 4194181U, 4194173U, 4194167U, 4194143U, 4194137U, 4194131U, 4194107U, 4194103U, 4194023U, 4194011U, 4194007U, 4193977U, 4193971U, 4193963U, 4193957U, @@ -23,8 +23,8 @@ const unsigned int PRIMES[] = { 4193353U, 4193327U, 4193309U, 4193303U, 4193297U, 4193279U, 4193269U, 4193263U }; -unsigned int DoubleHashKey::hashFunction(unsigned int value, int primeIndex) { - unsigned int hash = PRIMES[primeIndex % NUM_PRIMES] * (value + 1U); +uint32_t DoubleHashKey::hashFunction(uint32_t value, uint32_t primeIndex) { + uint32_t hash = PRIMES[primeIndex % NUM_PRIMES] * (value + 1U); hash += ~(hash << 15); hash ^= (hash >> 10); hash += (hash << 3); @@ -33,11 +33,16 @@ unsigned int DoubleHashKey::hashFunction(unsigned int value, int primeIndex) { return hash ^ (hash >> 16); } -unsigned int DoubleHashKey::hashFunction2(unsigned int value) { - unsigned hash = 0x811c9dc5U; - for (int i = 0; i < 4; i++ ) { - unsigned int byte = (value << (i * 8)) >> (24 - i * 8); +uint32_t DoubleHashKey::hashFunction2(uint32_t value) { + uint32_t hash = 0x811c9dc5U; + for (uint32_t i = 0; i < 4; i++ ) { + uint32_t byte = (value << (i * 8)) >> (24 - i * 8); hash = ( hash ^ byte ) * 0x01000193U; } return hash; } + +void DoubleHashKey::computeHash(uint32_t value, uint32_t primeIndex) { + _hash = DoubleHashKey::hashFunction(value, primeIndex); + _hash2 = DoubleHashKey::hashFunction2(value); +} diff --git a/libraries/shared/src/DoubleHashKey.h b/libraries/shared/src/DoubleHashKey.h new file mode 100644 index 0000000000..3b08bf7c1a --- /dev/null +++ b/libraries/shared/src/DoubleHashKey.h @@ -0,0 +1,49 @@ +// +// DoubleHashKey.h +// libraries/shared/src +// +// Created by Andrew Meadows 2014.11.02 +// Copyright 2014 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_DoubleHashKey_h +#define hifi_DoubleHashKey_h + +#include + +// DoubleHashKey for use with btHashMap +class DoubleHashKey { +public: + static uint32_t hashFunction(uint32_t value, uint32_t primeIndex); + static uint32_t hashFunction2(uint32_t value); + + DoubleHashKey() : _hash(0), _hash2(0) { } + + DoubleHashKey(uint32_t value, uint32_t primeIndex = 0) : + _hash(hashFunction(value, primeIndex)), + _hash2(hashFunction2(value)) { + } + + void clear() { _hash = 0; _hash2 = 0; } + bool isNull() const { return _hash == 0 && _hash2 == 0; } + + bool equals(const DoubleHashKey& other) const { + return _hash == other._hash && _hash2 == other._hash2; + } + + void computeHash(uint32_t value, uint32_t primeIndex = 0); + uint32_t getHash() const { return _hash; } + uint32_t getHash2() const { return _hash2; } + + void setHash(uint32_t hash) { _hash = hash; } + void setHash2(uint32_t hash2) { _hash2 = hash2; } + +private: + uint32_t _hash; + uint32_t _hash2; +}; + +#endif // hifi_DoubleHashKey_h diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 0003e59ed8..2d6724b9a5 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -13,54 +13,40 @@ #include "SharedUtil.h" // for MILLIMETERS_PER_METER -//#include "DoubleHashKey.h" #include "ShapeInfo.h" void ShapeInfo::clear() { _type = SHAPE_TYPE_NONE; - _data.clear(); + _halfExtents = glm::vec3(0.0f); + _doubleHashKey.clear(); + _externalData = NULL; +} + +void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector* data) { } void ShapeInfo::setBox(const glm::vec3& halfExtents) { _type = SHAPE_TYPE_BOX; - _data.clear(); - // _data[0] = < halfX, halfY, halfZ > - _data.push_back(halfExtents); + _halfExtents = halfExtents; + _doubleHashKey.clear(); } void ShapeInfo::setSphere(float radius) { _type = SHAPE_TYPE_SPHERE; - _data.clear(); - // _data[0] = < radius, radius, radius > - _data.push_back(glm::vec3(radius)); + _halfExtents = glm::vec3(radius, radius, radius); + _doubleHashKey.clear(); } -void ShapeInfo::setCylinder(float radius, float halfHeight) { - _type = SHAPE_TYPE_CYLINDER; - _data.clear(); - // _data[0] = < radius, halfHeight, radius > - // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - _data.push_back(glm::vec3(radius, halfHeight, radius)); +void ShapeInfo::setEllipsoid(const glm::vec3& halfExtents) { + _type = SHAPE_TYPE_ELLIPSOID; + _halfExtents = halfExtents; + _doubleHashKey.clear(); } -void ShapeInfo::setCapsule(float radius, float halfHeight) { - _type = SHAPE_TYPE_CAPSULE; - _data.clear(); - // _data[0] = < radius, halfHeight, radius > - _data.push_back(glm::vec3(radius, halfHeight, radius)); -} - -glm::vec3 ShapeInfo::getBoundingBoxDiagonal() const { - switch(_type) { - case SHAPE_TYPE_BOX: - case SHAPE_TYPE_SPHERE: - case SHAPE_TYPE_CYLINDER: - case SHAPE_TYPE_CAPSULE: - return 2.0f * _data[0]; - default: - break; - } - return glm::vec3(0.0f); +void ShapeInfo::setCapsuleY(float radius, float halfHeight) { + _type = SHAPE_TYPE_CAPSULE_Y; + _halfExtents = glm::vec3(radius, halfHeight, radius); + _doubleHashKey.clear(); } float ShapeInfo::computeVolume() const { @@ -68,23 +54,23 @@ float ShapeInfo::computeVolume() const { float volume = DEFAULT_VOLUME; switch(_type) { case SHAPE_TYPE_BOX: { - // factor of 8.0 because the components of _data[0] are all halfExtents - volume = 8.0f * _data[0].x * _data[0].y * _data[0].z; + // factor of 8.0 because the components of _halfExtents are all halfExtents + volume = 8.0f * _halfExtents.x * _halfExtents.y * _halfExtents.z; break; } case SHAPE_TYPE_SPHERE: { - float radius = _data[0].x; + float radius = _halfExtents.x; volume = 4.0f * PI * radius * radius * radius / 3.0f; break; } - case SHAPE_TYPE_CYLINDER: { - float radius = _data[0].x; - volume = PI * radius * radius * 2.0f * _data[0].y; + case SHAPE_TYPE_CYLINDER_Y: { + float radius = _halfExtents.x; + volume = PI * radius * radius * 2.0f * _halfExtents.y; break; } - case SHAPE_TYPE_CAPSULE: { - float radius = _data[0].x; - volume = PI * radius * radius * (2.0f * _data[0].y + 4.0f * radius / 3.0f); + case SHAPE_TYPE_CAPSULE_Y: { + float radius = _halfExtents.x; + volume = PI * radius * radius * (2.0f * _halfExtents.y + 4.0f * radius / 3.0f); break; } default: @@ -93,3 +79,85 @@ float ShapeInfo::computeVolume() const { assert(volume > 0.0f); return volume; } + +const DoubleHashKey& ShapeInfo::getHash() const { + // NOTE: we cache the hash so we only ever need to compute it once for any valid ShapeInfo instance. + if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) { + // cast this to non-const pointer so we can do our dirty work + ShapeInfo* thisPtr = const_cast(this); + // compute hash1 + // TODO?: provide lookup table for hash/hash2 of _type rather than recompute? + uint32_t primeIndex = 0; + thisPtr->_doubleHashKey.computeHash((uint32_t)_type, primeIndex++); + + const QVector* data = getData(); + if (data) { + // if externalData exists we use it to continue the hash + + // compute hash + uint32_t hash = _doubleHashKey.getHash(); + + glm::vec3 tmpData; + int numData = data->size(); + for (int i = 0; i < numData; ++i) { + tmpData = (*data)[i]; + 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::hashFunction((uint32_t)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + } + thisPtr->_doubleHashKey.setHash(hash); + + // compute hash2 + hash = _doubleHashKey.getHash2(); + for (int i = 0; i < numData; ++i) { + tmpData = (*data)[i]; + 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)(tmpData[j] * MILLIMETERS_PER_METER + copysignf(1.0f, tmpData[j]) * 0.49f)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + } + thisPtr->_doubleHashKey.setHash2(hash); + } else { + // this shape info has no external data so type+extents should be enough to generate a unique hash + // 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() + uint32_t floatHash = + DoubleHashKey::hashFunction((uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++); + hash ^= floatHash; + } + thisPtr->_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)); + hash += ~(floatHash << 17); + hash ^= (floatHash >> 11); + hash += (floatHash << 4); + hash ^= (floatHash >> 7); + hash += ~(floatHash << 10); + hash = (hash << 16) | (hash >> 16); + } + thisPtr->_doubleHashKey.setHash2(hash); + } + } + return _doubleHashKey; +} diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index b57f6311b2..b6dc88e4b7 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -15,40 +15,51 @@ #include #include -#include "Shape.h" +#include "DoubleHashKey.h" enum ShapeType { SHAPE_TYPE_NONE, SHAPE_TYPE_BOX, SHAPE_TYPE_SPHERE, SHAPE_TYPE_ELLIPSOID, - SHAPE_TYPE_CYLINDER, - SHAPE_TYPE_CAPSULE, - SHAPE_TYPE_CONVEX_HULL, + SHAPE_TYPE_HULL, SHAPE_TYPE_PLANE, - SHAPE_TYPE_COMPOUND + SHAPE_TYPE_COMPOUND, + SHAPE_TYPE_CAPSULE_X, + SHAPE_TYPE_CAPSULE_Y, + SHAPE_TYPE_CAPSULE_Z, + SHAPE_TYPE_CYLINDER_X, + SHAPE_TYPE_CYLINDER_Y, + SHAPE_TYPE_CYLINDER_Z }; class ShapeInfo { public: - ShapeInfo() : _type(SHAPE_TYPE_NONE) {} - void clear(); + void setParams(ShapeType type, const glm::vec3& halfExtents, QVector* data = NULL); void setBox(const glm::vec3& halfExtents); void setSphere(float radius); - void setCylinder(float radius, float halfHeight); - void setCapsule(float radius, float halfHeight); + void setEllipsoid(const glm::vec3& halfExtents); + //void setHull(); // TODO: implement this + void setCapsuleY(float radius, float halfHeight); const int getType() const { return _type; } - const QVector& getData() const { return _data; } - glm::vec3 getBoundingBoxDiagonal() const; + const glm::vec3& getHalfExtents() const { return _halfExtents; } + + void setData(const QVector* data) { _externalData = data; } + const QVector* getData() const { return _externalData; } + float computeVolume() const; + const DoubleHashKey& getHash() const; + protected: - int _type; - QVector _data; + ShapeType _type = SHAPE_TYPE_NONE; + glm::vec3 _halfExtents = glm::vec3(0.0f); + DoubleHashKey _doubleHashKey; + const QVector* _externalData = NULL; }; #endif // hifi_ShapeInfo_h