diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 3fbf8ffaf5..6806b3a398 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -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); diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index de3e9cc794..71b919b7ee 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -10,6 +10,7 @@ // #include +#include #include // for MILLIMETERS_PER_METER @@ -64,6 +65,22 @@ btConvexHullShape* ShapeFactory::createConvexHull(const QVector& 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; } diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 1d0cd56b86..0974c88e73 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -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; diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 79390b6680..1632d22450 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -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& newPoints) { _points << newPoints; } + int getMaxNumPoints() const; float computeVolume() const; diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index d4378d82b3..876de2e698 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -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& 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 << " ]"; }