Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp')
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp251
1 files changed, 163 insertions, 88 deletions
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index a291d6b7ce7..7d4875d8037 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -18,71 +18,107 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
-: m_heightStickWidth(heightStickWidth),
-m_heightStickLength(heightStickLength),
-m_maxHeight(maxHeight),
-m_width((btScalar)heightStickWidth-1),
-m_length((btScalar)heightStickLength-1),
-m_heightfieldDataUnknown(heightfieldData),
-m_useFloatData(useFloatData),
-m_flipQuadEdges(flipQuadEdges),
-m_useDiamondSubdivision(false),
-m_upAxis(upAxis),
-m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
{
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
+}
+
- btScalar quantizationMargin = 1.f;
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+{
+ // legacy constructor: support only float or unsigned char,
+ // and min height is zero
+ PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+ btScalar minHeight = 0.0;
+
+ // previously, height = uchar * maxHeight / 65535.
+ // So to preserve legacy behavior, heightScale = maxHeight / 65535
+ btScalar heightScale = maxHeight / 65535;
+
+ initialize(heightStickWidth, heightStickLength, heightfieldData,
+ heightScale, minHeight, maxHeight, upAxis, hdt,
+ flipQuadEdges);
+}
- //enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
- btVector3 halfExtents(0,0,0);
+void btHeightfieldTerrainShape::initialize
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+ // validation
+ btAssert(heightStickWidth > 1 && "bad width");
+ btAssert(heightStickLength > 1 && "bad length");
+ btAssert(heightfieldData && "null heightfield data");
+ // 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");
+
+ // initialize member variables
+ m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
+ m_heightStickWidth = heightStickWidth;
+ m_heightStickLength = heightStickLength;
+ m_minHeight = minHeight;
+ m_maxHeight = maxHeight;
+ m_width = (btScalar) (heightStickWidth - 1);
+ m_length = (btScalar) (heightStickLength - 1);
+ m_heightScale = heightScale;
+ m_heightfieldDataUnknown = heightfieldData;
+ m_heightDataType = hdt;
+ m_flipQuadEdges = flipQuadEdges;
+ m_useDiamondSubdivision = false;
+ m_upAxis = upAxis;
+ m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+
+ // determine min/max axis-aligned bounding box (aabb) values
switch (m_upAxis)
{
case 0:
{
- halfExtents.setValue(
- btScalar(m_maxHeight),
- btScalar(m_width), //?? don't know if this should change
- btScalar(m_length));
+ m_localAabbMin.setValue(m_minHeight, 0, 0);
+ m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
break;
}
case 1:
{
- halfExtents.setValue(
- btScalar(m_width),
- btScalar(m_maxHeight),
- btScalar(m_length));
+ m_localAabbMin.setValue(0, m_minHeight, 0);
+ m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
break;
};
case 2:
{
- halfExtents.setValue(
- btScalar(m_width),
- btScalar(m_length),
- btScalar(m_maxHeight)
- );
+ m_localAabbMin.setValue(0, 0, m_minHeight);
+ m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
break;
}
default:
{
//need to get valid m_upAxis
- btAssert(0);
+ btAssert(0 && "Bad m_upAxis");
}
}
- halfExtents*= btScalar(0.5);
-
- m_localAabbMin = -halfExtents - clampValue;
- m_localAabbMax = halfExtents + clampValue;
- btVector3 aabbSize = m_localAabbMax - m_localAabbMin;
-
+ // remember origin (defined as exact middle of aabb)
+ m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
}
+
btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
{
}
@@ -92,57 +128,80 @@ btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
- halfExtents += btVector3(getMargin(),getMargin(),getMargin());
+
+ btVector3 localOrigin(0, 0, 0);
+ localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
+ localOrigin *= m_localScaling;
btMatrix3x3 abs_b = t.getBasis().absolute();
- btPoint3 center = t.getOrigin();
+ btVector3 center = t.getOrigin();
btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
abs_b[1].dot(halfExtents),
abs_b[2].dot(halfExtents));
-
+ extent += btVector3(getMargin(),getMargin(),getMargin());
aabbMin = center - extent;
aabbMax = center + extent;
-
-
}
-btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
+
+/// This returns the "raw" (user's initial) height, not the actual height.
+/// The actual height needs to be adjusted to be relative to the center
+/// of the heightfield's AABB.
+btScalar
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
{
btScalar val = 0.f;
- if (m_useFloatData)
+ switch (m_heightDataType)
{
- val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
- } else
- {
- //assume unsigned short int
- unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
- val = heightFieldValue* (m_maxHeight/btScalar(65535));
+ case PHY_FLOAT:
+ {
+ val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
+ break;
+ }
+
+ case PHY_UCHAR:
+ {
+ unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
+ val = heightFieldValue * m_heightScale;
+ break;
+ }
+
+ case PHY_SHORT:
+ {
+ short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
+ val = hfValue * m_heightScale;
+ break;
+ }
+
+ default:
+ {
+ btAssert(!"Bad m_heightDataType");
+ }
}
+
return val;
}
-
+/// this returns the vertex in bullet-local coordinates
void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
-
btAssert(x>=0);
btAssert(y>=0);
btAssert(x<m_heightStickWidth);
btAssert(y<m_heightStickLength);
-
- btScalar height = getHeightFieldValue(x,y);
+ btScalar height = getRawHeightFieldValue(x,y);
switch (m_upAxis)
{
case 0:
{
vertex.setValue(
- height,
+ height - m_localOrigin.getX(),
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0) ) + y
);
@@ -152,7 +211,7 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
- height,
+ height - m_localOrigin.getY(),
(-m_length/btScalar(2.0)) + y
);
break;
@@ -162,7 +221,7 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
vertex.setValue(
(-m_width/btScalar(2.0)) + x,
(-m_length/btScalar(2.0)) + y,
- height
+ height - m_localOrigin.getZ()
);
break;
}
@@ -174,45 +233,76 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
}
vertex*=m_localScaling;
-
}
+
+static inline int
+getQuantized
+(
+btScalar x
+)
+{
+ if (x < 0.0) {
+ return (int) (x - 0.5);
+ }
+ return (int) (x + 0.5);
+}
+
+
+
+/// given input vector, return quantized version
+/**
+ This routine is basically determining the gridpoint indices for a given
+ input vector, answering the question: "which gridpoint is closest to the
+ provided point?".
+
+ "with clamp" means that we restrict the point to be in the heightfield's
+ axis-aligned bounding box.
+ */
void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
{
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax);
- btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
-
- //TODO: optimization: check out how to removed this btFabs
+ out[0] = getQuantized(clampedPoint.getX());
+ out[1] = getQuantized(clampedPoint.getY());
+ out[2] = getQuantized(clampedPoint.getZ());
- out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
- out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
- out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
-
}
+
+/// process all triangles within the provided axis-aligned bounding box
+/**
+ basic algorithm:
+ - convert input aabb to local coordinates (scale down and shift for local origin)
+ - convert input aabb to a range of heightfield grid points (quantize)
+ - iterate over all triangles in that subset of the grid
+ */
void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
- (void)callback;
- (void)aabbMax;
- (void)aabbMin;
+ // scale down the input aabb's so they are in local (non-scaled) coordinates
+ btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+ btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
- //quantize the aabbMin and aabbMax, and adjust the start/end ranges
+ // account for local origin
+ localAabbMin += m_localOrigin;
+ localAabbMax += m_localOrigin;
+ //quantize the aabbMin and aabbMax, and adjust the start/end ranges
int quantizedAabbMin[3];
int quantizedAabbMax[3];
-
- btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
- btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
-
quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
-
+ // expand the min/max quantized values
+ // this is to catch the case where the input aabb falls between grid points!
+ for (int i = 0; i < 3; ++i) {
+ quantizedAabbMin[i]--;
+ quantizedAabbMax[i]++;
+ }
int startX=0;
int endX=m_heightStickWidth-1;
@@ -223,11 +313,6 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
{
case 0:
{
- quantizedAabbMin[1]+=m_heightStickWidth/2-1;
- quantizedAabbMax[1]+=m_heightStickWidth/2+1;
- quantizedAabbMin[2]+=m_heightStickLength/2-1;
- quantizedAabbMax[2]+=m_heightStickLength/2+1;
-
if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1];
if (quantizedAabbMax[1]<endX)
@@ -240,11 +325,6 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
case 1:
{
- quantizedAabbMin[0]+=m_heightStickWidth/2-1;
- quantizedAabbMax[0]+=m_heightStickWidth/2+1;
- quantizedAabbMin[2]+=m_heightStickLength/2-1;
- quantizedAabbMax[2]+=m_heightStickLength/2+1;
-
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)
@@ -257,11 +337,6 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
};
case 2:
{
- quantizedAabbMin[0]+=m_heightStickWidth/2-1;
- quantizedAabbMax[0]+=m_heightStickWidth/2+1;
- quantizedAabbMin[1]+=m_heightStickLength/2-1;
- quantizedAabbMax[1]+=m_heightStickLength/2+1;
-
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
if (quantizedAabbMax[0]<endX)