diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index 75362b72e6..74b0304ace 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include // for MILLIMETERS_PER_METER #include "ShapeFactory.h" @@ -59,7 +61,8 @@ btConvexHullShape* ShapeFactory::createConvexHull(const QVector& poin btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; - switch(info.getType()) { + int type = info.getType(); + switch(type) { case SHAPE_TYPE_BOX: { shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } @@ -95,5 +98,17 @@ btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) { } break; } + if (shape && type != SHAPE_TYPE_COMPOUND) { + if (glm::length2(info.getOffset()) > MIN_SHAPE_OFFSET * MIN_SHAPE_OFFSET) { + // this shape has an offset, which we support by wrapping the true shape + // in a btCompoundShape with a local transform + auto compound = new btCompoundShape(); + btTransform trans; + trans.setIdentity(); + trans.setOrigin(glmToBullet(info.getOffset())); + compound->addChildShape(trans, shape); + shape = compound; + } + } return shape; } diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 676cd8c253..1d0cd56b86 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -181,6 +181,7 @@ bool ShapeInfo::contains(const glm::vec3& point) const { const DoubleHashKey& 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; // The key is not yet cached therefore we must compute it! To this end we bypass the const-ness // of this method by grabbing a non-const pointer to "this" and a non-const reference to _doubleHashKey. ShapeInfo* thisPtr = const_cast(this); @@ -199,9 +200,11 @@ const DoubleHashKey& ShapeInfo::getHash() const { hash ^= DoubleHashKey::hashFunction( (uint32_t)(_halfExtents[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _halfExtents[j]) * 0.49f), primeIndex++); - hash ^= DoubleHashKey::hashFunction( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f), - primeIndex++); + if (useOffset) { + hash ^= DoubleHashKey::hashFunction( + (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[j]) * 0.49f), + primeIndex++); + } } key.setHash(hash); @@ -212,8 +215,10 @@ const DoubleHashKey& ShapeInfo::getHash() const { // 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)); - floatHash ^= DoubleHashKey::hashFunction2( - (uint32_t)(_offset[j] * MILLIMETERS_PER_METER + copysignf(1.0f, _offset[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); diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 62047745bf..a3fbe55f36 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -16,9 +16,12 @@ #include #include #include +#include #include "DoubleHashKey.h" +const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored + enum ShapeType { SHAPE_TYPE_NONE, SHAPE_TYPE_BOX,