From 8d49b694cc146e2e8fb4e5e300825486dc1a2b20 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Dec 2014 10:08:26 -0800 Subject: [PATCH] ShapeManager doesn't support tiny and giant shapes --- libraries/physics/src/ShapeInfoUtil.cpp | 88 ++++++++++--------------- libraries/physics/src/ShapeManager.cpp | 28 +++++--- libraries/shared/src/ShapeInfo.cpp | 27 ++++++-- libraries/shared/src/ShapeInfo.h | 12 +++- 4 files changed, 86 insertions(+), 69 deletions(-) diff --git a/libraries/physics/src/ShapeInfoUtil.cpp b/libraries/physics/src/ShapeInfoUtil.cpp index e4ea118a0b..3d8e0b77a8 100644 --- a/libraries/physics/src/ShapeInfoUtil.cpp +++ b/libraries/physics/src/ShapeInfoUtil.cpp @@ -57,87 +57,70 @@ int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) { } void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info) { - info._data.clear(); if (shape) { - info._type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType()); - switch(info._type) { - case BOX_SHAPE: - { + int type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType()); + switch(type) { + case BOX_SHAPE: { const btBoxShape* boxShape = static_cast(shape); glm::vec3 halfExtents; bulletToGLM(boxShape->getHalfExtentsWithMargin(), halfExtents); - info._data.push_back(halfExtents); + info.setBox(halfExtents); } break; - case SPHERE_SHAPE: - { + case SPHERE_SHAPE: { const btSphereShape* sphereShape = static_cast(shape); - glm::vec3 data; - bulletToGLM(btVector3(0.0f, 0.0f, sphereShape->getRadius()), data); - info._data.push_back(data); + info.setSphere(sphereShape->getRadius()); } break; - case CYLINDER_SHAPE: - { + case CYLINDER_SHAPE: { + // NOTE: we only support cylinders along yAxis const btCylinderShape* cylinderShape = static_cast(shape); - glm::vec3 halfExtents; - bulletToGLM(cylinderShape->getHalfExtentsWithMargin(), halfExtents); - info._data.push_back(halfExtents); + btVector3 halfExtents = cylinderShape->getHalfExtentsWithMargin(); + info.setCylinder(halfExtents.getX(), halfExtents.getY()); } break; - case CAPSULE_SHAPE: - { + case CAPSULE_SHAPE: { + // NOTE: we only support capsules along yAxis const btCapsuleShape* capsuleShape = static_cast(shape); - glm::vec3 data; - bulletToGLM(btVector3(capsuleShape->getRadius(), capsuleShape->getHalfHeight(), 0.0f), data); - info._data.push_back(data); - // NOTE: we only support capsules with axis along yAxis + info.setCapsule(capsuleShape->getRadius(), capsuleShape->getHalfHeight()); } break; default: - info._type = INVALID_SHAPE; + info.clear(); break; } } else { - info._type = INVALID_SHAPE; + info.clear(); } } btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { btCollisionShape* shape = NULL; - int numData = info._data.size(); - switch(info._type) { + const QVector& data = info.getData(); + switch(info.getType()) { case BOX_SHAPE: { - if (numData > 0) { - btVector3 halfExtents; - glmToBullet(info._data[0], halfExtents); - shape = new btBoxShape(halfExtents); - } + btVector3 halfExtents; + glmToBullet(data[0], halfExtents); + shape = new btBoxShape(halfExtents); } break; case SPHERE_SHAPE: { - if (numData > 0) { - float radius = info._data[0].z; - shape = new btSphereShape(radius); - } + float radius = data[0].z; + shape = new btSphereShape(radius); } break; case CYLINDER_SHAPE: { - if (numData > 0) { - btVector3 halfExtents; - glmToBullet(info._data[0], halfExtents); - // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - // halfExtents = btVector3(radius, halfHeight, unused) - shape = new btCylinderShape(halfExtents); - } + btVector3 halfExtents; + glmToBullet(data[0], halfExtents); + // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X + // halfExtents = btVector3(radius, halfHeight, unused) + shape = new btCylinderShape(halfExtents); } break; case CAPSULE_SHAPE: { - if (numData > 0) { - float radius = info._data[0].x; - float height = 2.0f * info._data[0].y; - shape = new btCapsuleShape(radius, height); - } + float radius = data[0].x; + float height = 2.0f * data[0].y; + shape = new btCapsuleShape(radius, height); } break; } @@ -150,12 +133,13 @@ DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) { // 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._type, primeIndex++); + unsigned int hash = DoubleHashKey::hashFunction((unsigned int)info.getType(), primeIndex++); + const QVector& data = info.getData(); glm::vec3 tmpData; - int numData = info._data.size(); + int numData = data.size(); for (int i = 0; i < numData; ++i) { - tmpData = info._data[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() @@ -169,10 +153,10 @@ DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) { // 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._type); + hash = DoubleHashKey::hashFunction2((unsigned int)info.getType()); for (int i = 0; i < numData; ++i) { - tmpData = info._data[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() diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 670fcf54ae..1da705a5ff 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -10,6 +10,9 @@ // #ifdef USE_BULLET_PHYSICS + +#include + #include "ShapeInfoUtil.h" #include "ShapeManager.h" @@ -25,23 +28,28 @@ ShapeManager::~ShapeManager() { _shapeMap.clear(); } - btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { + // Very small or large objects are not supported. + float diagonal = glm::length2(info.getBoundingBoxDiagonal()); + 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); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { shapeRef->_refCount++; return shapeRef->_shape; - } else { - btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); - if (shape) { - ShapeReference newRef; - newRef._refCount = 1; - newRef._shape = shape; - _shapeMap.insert(key, newRef); - } - return shape; } + btCollisionShape* shape = ShapeInfoUtil::createShapeFromInfo(info); + if (shape) { + ShapeReference newRef; + newRef._refCount = 1; + newRef._shape = shape; + _shapeMap.insert(key, newRef); + } + return shape; } bool ShapeManager::releaseShape(const ShapeInfo& info) { diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 9e733e7b6e..d402a048a0 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -16,6 +16,11 @@ //#include "DoubleHashKey.h" #include "ShapeInfo.h" +void ShapeInfo::clear() { + _type = INVALID_SHAPE; + _data.clear(); +} + void ShapeInfo::setBox(const glm::vec3& halfExtents) { _type = BOX_SHAPE; _data.clear(); @@ -25,19 +30,31 @@ void ShapeInfo::setBox(const glm::vec3& halfExtents) { void ShapeInfo::setSphere(float radius) { _type = SPHERE_SHAPE; _data.clear(); - _data.push_back(glm::vec3(0.0f, 0.0f, radius)); + _data.push_back(glm::vec3(radius)); } -void ShapeInfo::setCylinder(float radius, float height) { +void ShapeInfo::setCylinder(float radius, float halfHeight) { _type = CYLINDER_SHAPE; _data.clear(); // NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X - _data.push_back(glm::vec3(radius, 0.5f * height, radius)); + _data.push_back(glm::vec3(radius, halfHeight, radius)); } -void ShapeInfo::setCapsule(float radius, float height) { +void ShapeInfo::setCapsule(float radius, float halfHeight) { _type = CAPSULE_SHAPE; _data.clear(); - _data.push_back(glm::vec3(radius, 0.5f * height, 0.0f)); + _data.push_back(glm::vec3(radius, halfHeight, radius)); } +glm::vec3 ShapeInfo::getBoundingBoxDiagonal() const { + switch(_type) { + case BOX_SHAPE: + case SPHERE_SHAPE: + case CYLINDER_SHAPE: + case CAPSULE_SHAPE: + return 2.0f * _data[0]; + default: + break; + } + return glm::vec3(0.0f); +} diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index ec5352e3da..7ba290122c 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -21,11 +21,19 @@ class ShapeInfo { public: ShapeInfo() : _type(INVALID_SHAPE) {} + void clear(); + void setBox(const glm::vec3& halfExtents); void setSphere(float radius); - void setCylinder(float radius, float height); - void setCapsule(float radius, float height); + void setCylinder(float radius, float halfHeight); + void setCapsule(float radius, float halfHeight); + const int getType() const { return _type; } + const QVector& getData() const { return _data; } + + glm::vec3 getBoundingBoxDiagonal() const; + +protected: int _type; QVector _data; };