summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2021-09-29 15:47:08 +0200
committerRémi Verschelde <rverschelde@gmail.com>2021-09-30 10:45:40 +0200
commit71f8b809b2e650755dee9b7d5005c889a6bd3ae1 (patch)
treeee7479cea32b5c9dbb82ff3fe90f8d7940c7ace1 /thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
parent4a9a2315666ecdde98b2e0f61802b005b862203d (diff)
bullet: Sync with upstream 3.17
Stop include Bullet headers using `-isystem` for GCC/Clang as it misleads SCons into not properly rebuilding all files when headers change. This means we also need to make sure Bullet builds without warning, and current version fares fairly well, there were just a couple to fix (patch included). Increase minimum version for distro packages to 2.90 (this was never released as the "next" version after 2.89 was 3.05... but that covers it too). Fixes #43868. (cherry picked from commit b7901c773c2eaff26b5c3a5342773a70571b2648)
Diffstat (limited to 'thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp')
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp135
1 files changed, 118 insertions, 17 deletions
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index cab6980b65..01bf7f67f5 100644
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -18,12 +18,57 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+ int heightStickWidth, int heightStickLength,
+ const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
+ int upAxis, bool flipQuadEdges)
+ : m_userValue3(0), m_triangleInfoMap(0)
+{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_FLOAT,
+ flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+ int heightStickWidth, int heightStickLength, const double* heightfieldData,
+ btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+ : m_userValue3(0), m_triangleInfoMap(0)
+{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_DOUBLE,
+ flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+ int heightStickWidth, int heightStickLength, const short* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+ : m_userValue3(0), m_triangleInfoMap(0)
+{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, PHY_SHORT,
+ flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
+ int heightStickWidth, int heightStickLength, const unsigned char* heightfieldData, btScalar heightScale,
+ btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
+ : m_userValue3(0), m_triangleInfoMap(0)
+{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, PHY_UCHAR,
+ flipQuadEdges);
+}
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(
int heightStickWidth, int heightStickLength, const void* heightfieldData,
btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
PHY_ScalarType hdt, bool flipQuadEdges)
:m_userValue3(0),
m_triangleInfoMap(0)
{
+ // legacy constructor: Assumes PHY_FLOAT means btScalar.
+#ifdef BT_USE_DOUBLE_PRECISION
+ if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
+#endif
initialize(heightStickWidth, heightStickLength, heightfieldData,
heightScale, minHeight, maxHeight, upAxis, hdt,
flipQuadEdges);
@@ -33,9 +78,12 @@ btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int h
: m_userValue3(0),
m_triangleInfoMap(0)
{
- // legacy constructor: support only float or unsigned char,
- // and min height is zero
+ // legacy constructor: support only btScalar or unsigned char data,
+ // and min height is zero.
PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+#ifdef BT_USE_DOUBLE_PRECISION
+ if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
+#endif
btScalar minHeight = 0.0f;
// previously, height = uchar * maxHeight / 65535.
@@ -59,7 +107,7 @@ void btHeightfieldTerrainShape::initialize(
// btAssert(heightScale) -- do we care? Trust caller here
btAssert(minHeight <= maxHeight); // && "bad min/max height");
btAssert(upAxis >= 0 && upAxis < 3); // && "bad upAxis--should be in range [0,2]");
- btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT); // && "Bad height data type enum");
+ btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_DOUBLE || hdt != PHY_SHORT); // && "Bad height data type enum");
// initialize member variables
m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
@@ -152,6 +200,12 @@ btHeightfieldTerrainShape::getRawHeightFieldValue(int x, int y) const
break;
}
+ case PHY_DOUBLE:
+ {
+ val = m_heightfieldDataDouble[(y * m_heightStickWidth) + x];
+ break;
+ }
+
case PHY_UCHAR:
{
unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
@@ -232,6 +286,30 @@ getQuantized(
return (int)(x + 0.5);
}
+// Equivalent to std::minmax({a, b, c}).
+// Performs at most 3 comparisons.
+static btHeightfieldTerrainShape::Range minmaxRange(btScalar a, btScalar b, btScalar c)
+{
+ if (a > b)
+ {
+ if (b > c)
+ return btHeightfieldTerrainShape::Range(c, a);
+ else if (a > c)
+ return btHeightfieldTerrainShape::Range(b, a);
+ else
+ return btHeightfieldTerrainShape::Range(b, c);
+ }
+ else
+ {
+ if (a > c)
+ return btHeightfieldTerrainShape::Range(c, b);
+ else if (b > c)
+ return btHeightfieldTerrainShape::Range(a, b);
+ else
+ return btHeightfieldTerrainShape::Range(a, c);
+ }
+}
+
/// given input vector, return quantized version
/**
This routine is basically determining the gridpoint indices for a given
@@ -334,7 +412,8 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
// TODO If m_vboundsGrid is available, use it to determine if we really need to process this area
-
+
+ const Range aabbUpRange(aabbMin[m_upAxis], aabbMax[m_upAxis]);
for (int j = startJ; j < endJ; j++)
{
for (int x = startX; x < endX; x++)
@@ -349,29 +428,51 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
{
- //first triangle
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, 2 * x, j);
- //second triangle
- // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
- getVertex(x + 1, j + 1, vertices[indices[1]]);
+
+ // Skip triangle processing if the triangle is out-of-AABB.
+ Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
+
+ if (upRange.overlaps(aabbUpRange))
+ callback->processTriangle(vertices, 2 * x, j);
+
+ // already set: getVertex(x, j, vertices[indices[0]])
+
+ // equivalent to: getVertex(x + 1, j + 1, vertices[indices[1]]);
+ vertices[indices[1]] = vertices[indices[2]];
+
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, 2 * x+1, j);
+ upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
+ upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
+
+ if (upRange.overlaps(aabbUpRange))
+ callback->processTriangle(vertices, 2 * x + 1, j);
}
else
{
- //first triangle
getVertex(x, j, vertices[indices[0]]);
getVertex(x, j + 1, vertices[indices[1]]);
getVertex(x + 1, j, vertices[indices[2]]);
- callback->processTriangle(vertices, 2 * x, j);
- //second triangle
- getVertex(x + 1, j, vertices[indices[0]]);
- //getVertex(x,j+1,vertices[1]);
+
+ // Skip triangle processing if the triangle is out-of-AABB.
+ Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
+
+ if (upRange.overlaps(aabbUpRange))
+ callback->processTriangle(vertices, 2 * x, j);
+
+ // already set: getVertex(x, j + 1, vertices[indices[1]]);
+
+ // equivalent to: getVertex(x + 1, j, vertices[indices[0]]);
+ vertices[indices[0]] = vertices[indices[2]];
+
getVertex(x + 1, j + 1, vertices[indices[2]]);
- callback->processTriangle(vertices, 2 * x+1, j);
+ upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
+ upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
+
+ if (upRange.overlaps(aabbUpRange))
+ callback->processTriangle(vertices, 2 * x + 1, j);
}
}
}
@@ -846,4 +947,4 @@ void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
void btHeightfieldTerrainShape::clearAccelerator()
{
m_vboundsGrid.clear();
-} \ No newline at end of file
+}