Merge pull request #7934 from AndrewMeadows/trim-convex-hulls

reduce number of points in unreasonable convex hulls
This commit is contained in:
Brad Hefta-Gaub 2016-05-20 15:30:36 -07:00
commit 9dded91af3
5 changed files with 54 additions and 31 deletions

View file

@ -217,6 +217,12 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re
} else if (entity->isReadyToComputeShape()) {
ShapeInfo shapeInfo;
entity->computeShapeInfo(shapeInfo);
int numPoints = shapeInfo.getMaxNumPoints();
if (numPoints > MAX_HULL_POINTS) {
qWarning() << "convex hull with" << numPoints
<< "points for entity" << entity->getName()
<< "at" << entity->getPosition() << " will be reduced";
}
btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo);
if (shape) {
EntityMotionState* motionState = new EntityMotionState(shape, entity);

View file

@ -10,6 +10,7 @@
//
#include <glm/gtx/norm.hpp>
#include <BulletCollision/CollisionShapes/btShapeHull.h>
#include <SharedUtil.h> // for MILLIMETERS_PER_METER
@ -64,6 +65,22 @@ btConvexHullShape* ShapeFactory::createConvexHull(const QVector<glm::vec3>& poin
correctedPoint = (points[i] - center) * relativeScale + center;
hull->addPoint(btVector3(correctedPoint[0], correctedPoint[1], correctedPoint[2]), false);
}
if (points.size() > MAX_HULL_POINTS) {
// create hull approximation
btShapeHull shapeHull(hull);
shapeHull.buildHull(margin);
// we cannot copy Bullet shapes so we must create a new one...
btConvexHullShape* newHull = new btConvexHullShape();
const btVector3* newPoints = shapeHull.getVertexPointer();
for (int i = 0; i < shapeHull.numVertices(); ++i) {
newHull->addPoint(newPoints[i], false);
}
// ...and delete the old one
delete hull;
hull = newHull;
}
hull->recalcLocalAabb();
return hull;
}

View file

@ -99,6 +99,18 @@ uint32_t ShapeInfo::getNumSubShapes() const {
}
return 1;
}
int ShapeInfo::getMaxNumPoints() const {
int numPoints = 0;
for (int i = 0; i < _points.size(); ++i) {
int n = _points[i].size();
if (n > numPoints) {
numPoints = n;
}
}
return numPoints;
}
float ShapeInfo::computeVolume() const {
const float DEFAULT_VOLUME = 1.0f;
float volume = DEFAULT_VOLUME;

View file

@ -22,6 +22,10 @@
const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored
// Bullet has a mesh generation util for convex shapes that we used to
// trim convex hulls with many points down to only 42 points.
const int MAX_HULL_POINTS = 42;
enum ShapeType {
SHAPE_TYPE_NONE,
SHAPE_TYPE_BOX,
@ -61,6 +65,7 @@ public:
void clearPoints () { _points.clear(); }
void appendToPoints (const QVector<glm::vec3>& newPoints) { _points << newPoints; }
int getMaxNumPoints() const;
float computeVolume() const;

View file

@ -23,7 +23,7 @@ void StreamUtil::dump(std::ostream& s, const QByteArray& buffer) {
while (i < buffer.size()) {
for(int j = 0; i < buffer.size() && j < row_size; ++j) {
char byte = buffer[i];
s << hex_digits[(byte >> 4) & 0x0f] << hex_digits[byte & 0x0f] << " ";
s << hex_digits[(byte >> 4) & 0x0f] << hex_digits[byte & 0x0f] << ' ';
++i;
}
s << "\n";
@ -31,21 +31,21 @@ void StreamUtil::dump(std::ostream& s, const QByteArray& buffer) {
}
std::ostream& operator<<(std::ostream& s, const glm::vec3& v) {
s << "<" << v.x << " " << v.y << " " << v.z << ">";
s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
return s;
}
std::ostream& operator<<(std::ostream& s, const glm::quat& q) {
s << "<" << q.x << " " << q.y << " " << q.z << " " << q.w << ">";
s << '(' << q.x << ' ' << q.y << ' ' << q.z << ' ' << q.w << ')';
return s;
}
std::ostream& operator<<(std::ostream& s, const glm::mat4& m) {
s << "[";
s << '[';
for (int j = 0; j < 4; ++j) {
s << " " << m[0][j] << " " << m[1][j] << " " << m[2][j] << " " << m[3][j] << ";";
s << ' ' << m[0][j] << ' ' << m[1][j] << ' ' << m[2][j] << ' ' << m[3][j] << ';';
}
s << " ]";
s << " ]";
return s;
}
@ -69,54 +69,37 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion) {
#include <QDebug>
QDebug& operator<<(QDebug& dbg, const glm::vec2& v) {
dbg.nospace() << "{type='glm::vec2'"
", x=" << v.x <<
", y=" << v.y <<
"}";
dbg.nospace() << '(' << v.x << ", " << v.y << ')';
return dbg;
}
QDebug& operator<<(QDebug& dbg, const glm::vec3& v) {
dbg.nospace() << "{type='glm::vec3'"
", x=" << v.x <<
", y=" << v.y <<
", z=" << v.z <<
"}";
dbg.nospace() << '(' << v.x << ", " << v.y << ", " << v.z << ')';
return dbg;
}
QDebug& operator<<(QDebug& dbg, const glm::vec4& v) {
dbg.nospace() << "{type='glm::vec4'"
", x=" << v.x <<
", y=" << v.y <<
", z=" << v.z <<
", w=" << v.w <<
"}";
dbg.nospace() << '(' << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ')';
return dbg;
}
QDebug& operator<<(QDebug& dbg, const glm::quat& q) {
dbg.nospace() << "{type='glm::quat'"
", x=" << q.x <<
", y=" << q.y <<
", z=" << q.z <<
", w=" << q.w <<
"}";
dbg.nospace() << '(' << q.x << ", " << q.y << ", " << q.z << ", " << q.w << ')';
return dbg;
}
QDebug& operator<<(QDebug& dbg, const glm::mat4& m) {
dbg.nospace() << "{type='glm::mat4', [";
dbg.nospace() << '[';
for (int j = 0; j < 4; ++j) {
dbg << ' ' << m[0][j] << ' ' << m[1][j] << ' ' << m[2][j] << ' ' << m[3][j] << ';';
}
return dbg << " ]}";
return dbg << " ]";
}
QDebug& operator<<(QDebug& dbg, const QVariantHash& v) {
dbg.nospace() << "[";
dbg.nospace() << "[ ";
for (QVariantHash::const_iterator it = v.constBegin(); it != v.constEnd(); it++) {
dbg << it.key() << ":" << it.value();
dbg << it.key() << ':' << it.value();
}
return dbg << " ]";
}