mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #4876 from AndrewMeadows/thermonuclear
adjust margin for hulls with small dimensions
This commit is contained in:
commit
15d2ce6ecc
2 changed files with 40 additions and 42 deletions
|
@ -15,36 +15,48 @@
|
||||||
#include "BulletUtil.h"
|
#include "BulletUtil.h"
|
||||||
|
|
||||||
|
|
||||||
// find the average point on a convex shape
|
|
||||||
glm::vec3 findCenter(const QVector<glm::vec3>& points) {
|
btConvexHullShape* ShapeInfoUtil::createConvexHull(const QVector<glm::vec3>& points) {
|
||||||
glm::vec3 result = glm::vec3(0);
|
assert(points.size() > 0);
|
||||||
for (int i = 0; i < points.size(); i++) {
|
|
||||||
result += points[i];
|
btConvexHullShape* hull = new btConvexHullShape();
|
||||||
|
glm::vec3 center = points[0];
|
||||||
|
glm::vec3 maxCorner = center;
|
||||||
|
glm::vec3 minCorner = center;
|
||||||
|
for (int i = 1; i < points.size(); i++) {
|
||||||
|
center += points[i];
|
||||||
|
maxCorner = glm::max(maxCorner, points[i]);
|
||||||
|
minCorner = glm::min(minCorner, points[i]);
|
||||||
}
|
}
|
||||||
return result * (1.0f / points.size());
|
center /= (float)(points.size());
|
||||||
}
|
|
||||||
|
|
||||||
|
float margin = hull->getMargin();
|
||||||
|
|
||||||
// bullet puts "margins" around all the collision shapes. This can cause shapes will hulls
|
// Bullet puts "margins" around all the collision shapes. This can cause objects that use ConvexHull shapes
|
||||||
// to float a bit above what they are sitting on, etc. One option is to call:
|
// to have visible gaps between them and the surface they touch. One option is to reduce the size of the margin
|
||||||
//
|
// but this can reduce the performance and stability of the simulation (e.g. the GJK algorithm will fail to provide
|
||||||
// compound->setMargin(0.01);
|
// nearest contact points and narrow-phase collisions will fall into more expensive code paths). Alternatively
|
||||||
//
|
// one can shift the geometry of the shape to make the margin surface approximately close to the visible surface.
|
||||||
// to reduce the size of the margin, but this has some consequences for the
|
// This is the strategy we try, but if the object is too small then we start to reduce the margin down to some minimum.
|
||||||
// performance and stability of the simulation. Instead, we clench in all the points of
|
|
||||||
// the hull by the margin. These clenched points + bullets margin will but the actual
|
const float MIN_MARGIN = 0.01f;
|
||||||
// collision hull fairly close to the visual edge of the object.
|
glm::vec3 diagonal = maxCorner - minCorner;
|
||||||
QVector<glm::vec3> shrinkByMargin(const QVector<glm::vec3>& points, const glm::vec3 center, float margin) {
|
float minDimension = glm::min(diagonal[0], diagonal[1]);
|
||||||
QVector<glm::vec3> result(points.size());
|
minDimension = glm::min(minDimension, diagonal[2]);
|
||||||
for (int i = 0; i < points.size(); i++) {
|
margin = glm::min(glm::max(0.5f * minDimension, MIN_MARGIN), margin);
|
||||||
glm::vec3 pVec = points[ i ] - center;
|
hull->setMargin(margin);
|
||||||
glm::vec3 pVecNorm = glm::normalize(pVec);
|
|
||||||
result[ i ] = center + pVec - (pVecNorm * margin);
|
// add the points, correcting for margin
|
||||||
|
glm::vec3 relativeScale = (diagonal - glm::vec3(2.0f * margin)) / diagonal;
|
||||||
|
glm::vec3 correctedPoint;
|
||||||
|
for (int i = 0; i < points.size(); ++i) {
|
||||||
|
correctedPoint = (points[i] - center) * relativeScale + center;
|
||||||
|
hull->addPoint(btVector3(correctedPoint[0], correctedPoint[1], correctedPoint[2]), false);
|
||||||
}
|
}
|
||||||
return result;
|
hull->recalcLocalAabb();
|
||||||
|
return hull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||||
btCollisionShape* shape = NULL;
|
btCollisionShape* shape = NULL;
|
||||||
switch(info.getType()) {
|
switch(info.getType()) {
|
||||||
|
@ -68,30 +80,14 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) {
|
||||||
const QVector<QVector<glm::vec3>>& points = info.getPoints();
|
const QVector<QVector<glm::vec3>>& points = info.getPoints();
|
||||||
uint32_t numSubShapes = info.getNumSubShapes();
|
uint32_t numSubShapes = info.getNumSubShapes();
|
||||||
if (numSubShapes == 1) {
|
if (numSubShapes == 1) {
|
||||||
auto hull = new btConvexHullShape();
|
shape = createConvexHull(info.getPoints()[0]);
|
||||||
const QVector<QVector<glm::vec3>>& points = info.getPoints();
|
|
||||||
glm::vec3 center = findCenter(points[0]);
|
|
||||||
QVector<glm::vec3> shrunken = shrinkByMargin(points[0], center, hull->getMargin());
|
|
||||||
foreach (glm::vec3 point, shrunken) {
|
|
||||||
btVector3 btPoint(point[0], point[1], point[2]);
|
|
||||||
hull->addPoint(btPoint, false);
|
|
||||||
}
|
|
||||||
hull->recalcLocalAabb();
|
|
||||||
shape = hull;
|
|
||||||
} else {
|
} else {
|
||||||
assert(numSubShapes > 1);
|
assert(numSubShapes > 1);
|
||||||
auto compound = new btCompoundShape();
|
auto compound = new btCompoundShape();
|
||||||
btTransform trans;
|
btTransform trans;
|
||||||
trans.setIdentity();
|
trans.setIdentity();
|
||||||
foreach (QVector<glm::vec3> hullPoints, points) {
|
foreach (QVector<glm::vec3> hullPoints, points) {
|
||||||
auto hull = new btConvexHullShape();
|
btConvexHullShape* hull = createConvexHull(hullPoints);
|
||||||
glm::vec3 center = findCenter(points[0]);
|
|
||||||
QVector<glm::vec3> shrunken = shrinkByMargin(hullPoints, center, hull->getMargin());
|
|
||||||
foreach (glm::vec3 point, shrunken) {
|
|
||||||
btVector3 btPoint(point[0], point[1], point[2]);
|
|
||||||
hull->addPoint(btPoint, false);
|
|
||||||
}
|
|
||||||
hull->recalcLocalAabb();
|
|
||||||
compound->addChildShape (trans, hull);
|
compound->addChildShape (trans, hull);
|
||||||
}
|
}
|
||||||
shape = compound;
|
shape = compound;
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
// TODO: rename this to ShapeFactory
|
// TODO: rename this to ShapeFactory
|
||||||
namespace ShapeInfoUtil {
|
namespace ShapeInfoUtil {
|
||||||
|
|
||||||
|
btConvexHullShape* createConvexHull(const QVector<glm::vec3>& points);
|
||||||
|
|
||||||
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
btCollisionShape* createShapeFromInfo(const ShapeInfo& info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue