mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 20:48:56 +02:00
ShapeManager doesn't support tiny and giant shapes
This commit is contained in:
parent
64cdef42fe
commit
8d49b694cc
4 changed files with 86 additions and 69 deletions
|
@ -57,87 +57,70 @@ int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info) {
|
void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info) {
|
||||||
info._data.clear();
|
|
||||||
if (shape) {
|
if (shape) {
|
||||||
info._type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType());
|
int type = ShapeInfoUtil::fromBulletShapeType(shape->getShapeType());
|
||||||
switch(info._type) {
|
switch(type) {
|
||||||
case BOX_SHAPE:
|
case BOX_SHAPE: {
|
||||||
{
|
|
||||||
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
|
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
|
||||||
glm::vec3 halfExtents;
|
glm::vec3 halfExtents;
|
||||||
bulletToGLM(boxShape->getHalfExtentsWithMargin(), halfExtents);
|
bulletToGLM(boxShape->getHalfExtentsWithMargin(), halfExtents);
|
||||||
info._data.push_back(halfExtents);
|
info.setBox(halfExtents);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPHERE_SHAPE:
|
case SPHERE_SHAPE: {
|
||||||
{
|
|
||||||
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
|
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
|
||||||
glm::vec3 data;
|
info.setSphere(sphereShape->getRadius());
|
||||||
bulletToGLM(btVector3(0.0f, 0.0f, sphereShape->getRadius()), data);
|
|
||||||
info._data.push_back(data);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CYLINDER_SHAPE:
|
case CYLINDER_SHAPE: {
|
||||||
{
|
// NOTE: we only support cylinders along yAxis
|
||||||
const btCylinderShape* cylinderShape = static_cast<const btCylinderShape*>(shape);
|
const btCylinderShape* cylinderShape = static_cast<const btCylinderShape*>(shape);
|
||||||
glm::vec3 halfExtents;
|
btVector3 halfExtents = cylinderShape->getHalfExtentsWithMargin();
|
||||||
bulletToGLM(cylinderShape->getHalfExtentsWithMargin(), halfExtents);
|
info.setCylinder(halfExtents.getX(), halfExtents.getY());
|
||||||
info._data.push_back(halfExtents);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPSULE_SHAPE:
|
case CAPSULE_SHAPE: {
|
||||||
{
|
// NOTE: we only support capsules along yAxis
|
||||||
const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
|
const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
|
||||||
glm::vec3 data;
|
info.setCapsule(capsuleShape->getRadius(), capsuleShape->getHalfHeight());
|
||||||
bulletToGLM(btVector3(capsuleShape->getRadius(), capsuleShape->getHalfHeight(), 0.0f), data);
|
|
||||||
info._data.push_back(data);
|
|
||||||
// NOTE: we only support capsules with axis along yAxis
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
info._type = INVALID_SHAPE;
|
info.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info._type = INVALID_SHAPE;
|
info.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||||
btCollisionShape* shape = NULL;
|
btCollisionShape* shape = NULL;
|
||||||
int numData = info._data.size();
|
const QVector<glm::vec3>& data = info.getData();
|
||||||
switch(info._type) {
|
switch(info.getType()) {
|
||||||
case BOX_SHAPE: {
|
case BOX_SHAPE: {
|
||||||
if (numData > 0) {
|
btVector3 halfExtents;
|
||||||
btVector3 halfExtents;
|
glmToBullet(data[0], halfExtents);
|
||||||
glmToBullet(info._data[0], halfExtents);
|
shape = new btBoxShape(halfExtents);
|
||||||
shape = new btBoxShape(halfExtents);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPHERE_SHAPE: {
|
case SPHERE_SHAPE: {
|
||||||
if (numData > 0) {
|
float radius = data[0].z;
|
||||||
float radius = info._data[0].z;
|
shape = new btSphereShape(radius);
|
||||||
shape = new btSphereShape(radius);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CYLINDER_SHAPE: {
|
case CYLINDER_SHAPE: {
|
||||||
if (numData > 0) {
|
btVector3 halfExtents;
|
||||||
btVector3 halfExtents;
|
glmToBullet(data[0], halfExtents);
|
||||||
glmToBullet(info._data[0], halfExtents);
|
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
|
||||||
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
|
// halfExtents = btVector3(radius, halfHeight, unused)
|
||||||
// halfExtents = btVector3(radius, halfHeight, unused)
|
shape = new btCylinderShape(halfExtents);
|
||||||
shape = new btCylinderShape(halfExtents);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAPSULE_SHAPE: {
|
case CAPSULE_SHAPE: {
|
||||||
if (numData > 0) {
|
float radius = data[0].x;
|
||||||
float radius = info._data[0].x;
|
float height = 2.0f * data[0].y;
|
||||||
float height = 2.0f * info._data[0].y;
|
shape = new btCapsuleShape(radius, height);
|
||||||
shape = new btCapsuleShape(radius, height);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -150,12 +133,13 @@ DoubleHashKey ShapeInfoUtil::computeHash(const ShapeInfo& info) {
|
||||||
// scramble the bits of the type
|
// scramble the bits of the type
|
||||||
// TODO?: provide lookup table for hash of info._type rather than recompute?
|
// TODO?: provide lookup table for hash of info._type rather than recompute?
|
||||||
int primeIndex = 0;
|
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<glm::vec3>& data = info.getData();
|
||||||
|
|
||||||
glm::vec3 tmpData;
|
glm::vec3 tmpData;
|
||||||
int numData = info._data.size();
|
int numData = data.size();
|
||||||
for (int i = 0; i < numData; ++i) {
|
for (int i = 0; i < numData; ++i) {
|
||||||
tmpData = info._data[i];
|
tmpData = data[i];
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
// 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()
|
// 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
|
// compute hash2
|
||||||
// scramble the bits of the type
|
// scramble the bits of the type
|
||||||
// TODO?: provide lookup table for hash2 of info._type rather than recompute?
|
// 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) {
|
for (int i = 0; i < numData; ++i) {
|
||||||
tmpData = info._data[i];
|
tmpData = data[i];
|
||||||
for (int j = 0; j < 3; ++j) {
|
for (int j = 0; j < 3; ++j) {
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
// 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()
|
// so the cast to int produces a round() effect rather than a floor()
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
#ifdef USE_BULLET_PHYSICS
|
||||||
|
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
|
|
||||||
#include "ShapeInfoUtil.h"
|
#include "ShapeInfoUtil.h"
|
||||||
#include "ShapeManager.h"
|
#include "ShapeManager.h"
|
||||||
|
|
||||||
|
@ -25,23 +28,28 @@ ShapeManager::~ShapeManager() {
|
||||||
_shapeMap.clear();
|
_shapeMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
|
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);
|
DoubleHashKey key = ShapeInfoUtil::computeHash(info);
|
||||||
ShapeReference* shapeRef = _shapeMap.find(key);
|
ShapeReference* shapeRef = _shapeMap.find(key);
|
||||||
if (shapeRef) {
|
if (shapeRef) {
|
||||||
shapeRef->_refCount++;
|
shapeRef->_refCount++;
|
||||||
return shapeRef->_shape;
|
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) {
|
bool ShapeManager::releaseShape(const ShapeInfo& info) {
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
//#include "DoubleHashKey.h"
|
//#include "DoubleHashKey.h"
|
||||||
#include "ShapeInfo.h"
|
#include "ShapeInfo.h"
|
||||||
|
|
||||||
|
void ShapeInfo::clear() {
|
||||||
|
_type = INVALID_SHAPE;
|
||||||
|
_data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||||
_type = BOX_SHAPE;
|
_type = BOX_SHAPE;
|
||||||
_data.clear();
|
_data.clear();
|
||||||
|
@ -25,19 +30,31 @@ void ShapeInfo::setBox(const glm::vec3& halfExtents) {
|
||||||
void ShapeInfo::setSphere(float radius) {
|
void ShapeInfo::setSphere(float radius) {
|
||||||
_type = SPHERE_SHAPE;
|
_type = SPHERE_SHAPE;
|
||||||
_data.clear();
|
_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;
|
_type = CYLINDER_SHAPE;
|
||||||
_data.clear();
|
_data.clear();
|
||||||
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
|
// 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;
|
_type = CAPSULE_SHAPE;
|
||||||
_data.clear();
|
_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);
|
||||||
|
}
|
||||||
|
|
|
@ -21,11 +21,19 @@ class ShapeInfo {
|
||||||
public:
|
public:
|
||||||
ShapeInfo() : _type(INVALID_SHAPE) {}
|
ShapeInfo() : _type(INVALID_SHAPE) {}
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
void setBox(const glm::vec3& halfExtents);
|
void setBox(const glm::vec3& halfExtents);
|
||||||
void setSphere(float radius);
|
void setSphere(float radius);
|
||||||
void setCylinder(float radius, float height);
|
void setCylinder(float radius, float halfHeight);
|
||||||
void setCapsule(float radius, float height);
|
void setCapsule(float radius, float halfHeight);
|
||||||
|
|
||||||
|
const int getType() const { return _type; }
|
||||||
|
const QVector<glm::vec3>& getData() const { return _data; }
|
||||||
|
|
||||||
|
glm::vec3 getBoundingBoxDiagonal() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
int _type;
|
int _type;
|
||||||
QVector<glm::vec3> _data;
|
QVector<glm::vec3> _data;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue