Merge pull request #4474 from AndrewMeadows/thermonuclear

proper shape management for ConvexHull shapes
This commit is contained in:
Seth Alves 2015-03-18 17:01:58 -07:00
commit f800b29682
4 changed files with 43 additions and 89 deletions

View file

@ -303,7 +303,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
_points << mesh.vertices;
}
info.setParams(getShapeType(), 0.5f * getDimensions(), NULL, _collisionModelURL);
info.setParams(getShapeType(), 0.5f * getDimensions(), _collisionModelURL);
info.setConvexHull(_points);
}
}

View file

@ -505,10 +505,8 @@ void PhysicsEngine::removeObjectFromBullet(ObjectMotionState* motionState) {
btRigidBody* body = motionState->getRigidBody();
if (body) {
const btCollisionShape* shape = body->getCollisionShape();
ShapeInfo shapeInfo;
ShapeInfoUtil::collectInfoFromShape(shape, shapeInfo);
_dynamicsWorld->removeRigidBody(body);
_shapeManager.releaseShape(shapeInfo);
_shapeManager.releaseShape(shape);
// NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it.
motionState->setRigidBody(NULL);
delete body;

View file

@ -19,10 +19,9 @@ void ShapeInfo::clear() {
_type = SHAPE_TYPE_NONE;
_halfExtents = glm::vec3(0.0f);
_doubleHashKey.clear();
_externalData = NULL;
}
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector<glm::vec3>* data, QString url) {
void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) {
_type = type;
switch(type) {
case SHAPE_TYPE_NONE:
@ -45,7 +44,6 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QVector<
_halfExtents = halfExtents;
break;
}
_externalData = data;
}
void ShapeInfo::setBox(const glm::vec3& halfExtents) {
@ -109,91 +107,53 @@ float ShapeInfo::computeVolume() const {
}
const DoubleHashKey& ShapeInfo::getHash() const {
// NOTE: we cache the hash so we only ever need to compute it once for any valid ShapeInfo instance.
// 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) {
// cast this to non-const pointer so we can do our dirty work
// 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<ShapeInfo*>(this);
DoubleHashKey& key = thisPtr->_doubleHashKey;
// 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++);
key.computeHash((uint32_t)_type, primeIndex++);
const QVector<glm::vec3>* data = getData();
if (data) {
// if externalData exists we use it to continue the hash
// compute hash
uint32_t hash = _doubleHashKey.getHash();
// compute hash1
uint32_t hash = key.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;
}
key.setHash(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()
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
// compute hash2
hash = key.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);
}
key.setHash2(hash);
QString url = _url.toString();
if (url == "") {
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);
}
}
} else {
QByteArray baUrl = url.toLocal8Bit();
const char *cUrl = baUrl.data();
hash = qChecksum(cUrl, baUrl.count());
}
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);
QString url = _url.toString();
if (!url.isEmpty()) {
// fold the urlHash into both parts
QByteArray baUrl = url.toLocal8Bit();
const char *cUrl = baUrl.data();
uint32_t urlHash = qChecksum(cUrl, baUrl.count());
key.setHash(key.getHash() ^ urlHash);
key.setHash2(key.getHash2() ^ urlHash);
}
}
return _doubleHashKey;

View file

@ -40,7 +40,7 @@ class ShapeInfo {
public:
void clear();
void setParams(ShapeType type, const glm::vec3& halfExtents, QVector<glm::vec3>* data = NULL, QString url="");
void setParams(ShapeType type, const glm::vec3& halfExtents, QString url="");
void setBox(const glm::vec3& halfExtents);
void setSphere(float radius);
void setEllipsoid(const glm::vec3& halfExtents);
@ -51,9 +51,6 @@ public:
const glm::vec3& getHalfExtents() const { return _halfExtents; }
void setData(const QVector<glm::vec3>* data) { _externalData = data; }
const QVector<glm::vec3>* getData() const { return _externalData; }
const QVector<glm::vec3>& getPoints() const { return _points; }
void clearPoints () { _points.clear(); }
@ -67,7 +64,6 @@ protected:
ShapeType _type = SHAPE_TYPE_NONE;
glm::vec3 _halfExtents = glm::vec3(0.0f);
DoubleHashKey _doubleHashKey;
const QVector<glm::vec3>* _externalData = NULL;
QVector<glm::vec3> _points; // points for convex collision hull
QUrl _url; // url for model of convex collision hull
};