2020-11-16 14:47:43 +08:00
|
|
|
/*
|
|
|
|
Bullet Continuous Collision Detection and Physics Library
|
|
|
|
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied warranty.
|
|
|
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it freely,
|
|
|
|
subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H
|
|
|
|
#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
|
|
|
|
|
|
|
|
#include "btConcaveShape.h"
|
|
|
|
#include "LinearMath/btAlignedObjectArray.h"
|
|
|
|
|
|
|
|
///btHeightfieldTerrainShape simulates a 2D heightfield terrain
|
|
|
|
/**
|
|
|
|
The caller is responsible for maintaining the heightfield array; this
|
|
|
|
class does not make a copy.
|
|
|
|
|
|
|
|
The heightfield can be dynamic so long as the min/max height values
|
|
|
|
capture the extremes (heights must always be in that range).
|
|
|
|
|
|
|
|
The local origin of the heightfield is assumed to be the exact
|
|
|
|
center (as determined by width and length and height, with each
|
|
|
|
axis multiplied by the localScaling).
|
|
|
|
|
|
|
|
\b NOTE: be careful with coordinates. If you have a heightfield with a local
|
|
|
|
min height of -100m, and a max height of +500m, you may be tempted to place it
|
|
|
|
at the origin (0,0) and expect the heights in world coordinates to be
|
|
|
|
-100 to +500 meters.
|
|
|
|
Actually, the heights will be -300 to +300m, because bullet will re-center
|
|
|
|
the heightfield based on its AABB (which is determined by the min/max
|
|
|
|
heights). So keep in mind that once you create a btHeightfieldTerrainShape
|
|
|
|
object, the heights will be adjusted relative to the center of the AABB. This
|
|
|
|
is different to the behavior of many rendering engines, but is useful for
|
|
|
|
physics engines.
|
|
|
|
|
|
|
|
Most (but not all) rendering and heightfield libraries assume upAxis = 1
|
|
|
|
(that is, the y-axis is "up"). This class allows any of the 3 coordinates
|
|
|
|
to be "up". Make sure your choice of axis is consistent with your rendering
|
|
|
|
system.
|
|
|
|
|
|
|
|
The heightfield heights are determined from the data type used for the
|
|
|
|
heightfieldData array.
|
|
|
|
|
2021-08-19 22:53:54 +08:00
|
|
|
- unsigned char: height at a point is the uchar value at the
|
2020-11-16 14:47:43 +08:00
|
|
|
grid point, multipled by heightScale. uchar isn't recommended
|
|
|
|
because of its inability to deal with negative values, and
|
|
|
|
low resolution (8-bit).
|
|
|
|
|
2021-08-19 22:53:54 +08:00
|
|
|
- short: height at a point is the short int value at that grid
|
2020-11-16 14:47:43 +08:00
|
|
|
point, multipled by heightScale.
|
|
|
|
|
2021-08-19 22:53:54 +08:00
|
|
|
- float or dobule: height at a point is the value at that grid point.
|
2020-11-16 14:47:43 +08:00
|
|
|
|
|
|
|
Whatever the caller specifies as minHeight and maxHeight will be honored.
|
|
|
|
The class will not inspect the heightfield to discover the actual minimum
|
|
|
|
or maximum heights. These values are used to determine the heightfield's
|
|
|
|
axis-aligned bounding box, multiplied by localScaling.
|
|
|
|
|
|
|
|
For usage and testing see the TerrainDemo.
|
|
|
|
*/
|
|
|
|
ATTRIBUTE_ALIGNED16(class)
|
|
|
|
btHeightfieldTerrainShape : public btConcaveShape
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
struct Range
|
|
|
|
{
|
2021-08-19 22:53:54 +08:00
|
|
|
Range() {}
|
|
|
|
Range(btScalar min, btScalar max) : min(min), max(max) {}
|
|
|
|
|
|
|
|
bool overlaps(const Range& other) const
|
|
|
|
{
|
|
|
|
return !(min > other.max || max < other.min);
|
|
|
|
}
|
|
|
|
|
2020-11-16 14:47:43 +08:00
|
|
|
btScalar min;
|
|
|
|
btScalar max;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
btVector3 m_localAabbMin;
|
|
|
|
btVector3 m_localAabbMax;
|
|
|
|
btVector3 m_localOrigin;
|
|
|
|
|
|
|
|
///terrain data
|
|
|
|
int m_heightStickWidth;
|
|
|
|
int m_heightStickLength;
|
|
|
|
btScalar m_minHeight;
|
|
|
|
btScalar m_maxHeight;
|
|
|
|
btScalar m_width;
|
|
|
|
btScalar m_length;
|
|
|
|
btScalar m_heightScale;
|
|
|
|
union {
|
|
|
|
const unsigned char* m_heightfieldDataUnsignedChar;
|
|
|
|
const short* m_heightfieldDataShort;
|
2021-08-19 22:53:54 +08:00
|
|
|
const float* m_heightfieldDataFloat;
|
|
|
|
const double* m_heightfieldDataDouble;
|
2020-11-16 14:47:43 +08:00
|
|
|
const void* m_heightfieldDataUnknown;
|
|
|
|
};
|
|
|
|
|
|
|
|
PHY_ScalarType m_heightDataType;
|
|
|
|
bool m_flipQuadEdges;
|
|
|
|
bool m_useDiamondSubdivision;
|
|
|
|
bool m_useZigzagSubdivision;
|
|
|
|
bool m_flipTriangleWinding;
|
|
|
|
int m_upAxis;
|
|
|
|
|
|
|
|
btVector3 m_localScaling;
|
|
|
|
|
|
|
|
// Accelerator
|
|
|
|
btAlignedObjectArray<Range> m_vboundsGrid;
|
|
|
|
int m_vboundsGridWidth;
|
|
|
|
int m_vboundsGridLength;
|
|
|
|
int m_vboundsChunkSize;
|
|
|
|
|
|
|
|
|
|
|
|
btScalar m_userValue3;
|
|
|
|
|
|
|
|
struct btTriangleInfoMap* m_triangleInfoMap;
|
|
|
|
|
|
|
|
virtual btScalar getRawHeightFieldValue(int x, int y) const;
|
|
|
|
void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
|
|
|
|
|
|
|
|
/// protected initialization
|
|
|
|
/**
|
|
|
|
Handles the work of constructors so that public constructors can be
|
|
|
|
backwards-compatible without a lot of copy/paste.
|
|
|
|
*/
|
|
|
|
void initialize(int heightStickWidth, int heightStickLength,
|
|
|
|
const void* heightfieldData, btScalar heightScale,
|
|
|
|
btScalar minHeight, btScalar maxHeight, int upAxis,
|
|
|
|
PHY_ScalarType heightDataType, bool flipQuadEdges);
|
|
|
|
|
|
|
|
public:
|
|
|
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
|
|
|
|
2021-08-19 22:53:54 +08:00
|
|
|
/// preferred constructors
|
|
|
|
btHeightfieldTerrainShape(
|
|
|
|
int heightStickWidth, int heightStickLength,
|
|
|
|
const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
|
|
|
|
int upAxis, bool flipQuadEdges);
|
|
|
|
btHeightfieldTerrainShape(
|
|
|
|
int heightStickWidth, int heightStickLength,
|
|
|
|
const double* heightfieldData, btScalar minHeight, btScalar maxHeight,
|
|
|
|
int upAxis, bool flipQuadEdges);
|
|
|
|
btHeightfieldTerrainShape(
|
|
|
|
int heightStickWidth, int heightStickLength,
|
|
|
|
const short* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
|
|
|
|
int upAxis, bool flipQuadEdges);
|
|
|
|
btHeightfieldTerrainShape(
|
|
|
|
int heightStickWidth, int heightStickLength,
|
|
|
|
const unsigned char* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
|
|
|
|
int upAxis, bool flipQuadEdges);
|
|
|
|
|
|
|
|
/// legacy constructor
|
2020-11-16 14:47:43 +08:00
|
|
|
/**
|
|
|
|
This constructor supports a range of heightfield
|
|
|
|
data types, and allows for a non-zero minimum height value.
|
|
|
|
heightScale is needed for any integer-based heightfield data types.
|
2021-08-19 22:53:54 +08:00
|
|
|
|
|
|
|
This legacy constructor considers `PHY_FLOAT` to mean `btScalar`.
|
|
|
|
With `BT_USE_DOUBLE_PRECISION`, it will expect `heightfieldData`
|
|
|
|
to be double-precision.
|
2020-11-16 14:47:43 +08:00
|
|
|
*/
|
|
|
|
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,
|
|
|
|
const void* heightfieldData, btScalar heightScale,
|
|
|
|
btScalar minHeight, btScalar maxHeight,
|
|
|
|
int upAxis, PHY_ScalarType heightDataType,
|
|
|
|
bool flipQuadEdges);
|
|
|
|
|
|
|
|
/// legacy constructor
|
|
|
|
/**
|
|
|
|
The legacy constructor assumes the heightfield has a minimum height
|
2021-08-19 22:53:54 +08:00
|
|
|
of zero. Only unsigned char or btScalar data are supported. For legacy
|
2020-11-16 14:47:43 +08:00
|
|
|
compatibility reasons, heightScale is calculated as maxHeight / 65535
|
|
|
|
(and is only used when useFloatData = false).
|
|
|
|
*/
|
|
|
|
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges);
|
|
|
|
|
|
|
|
virtual ~btHeightfieldTerrainShape();
|
|
|
|
|
|
|
|
void setUseDiamondSubdivision(bool useDiamondSubdivision = true) { m_useDiamondSubdivision = useDiamondSubdivision; }
|
|
|
|
|
|
|
|
///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
|
|
|
|
void setUseZigzagSubdivision(bool useZigzagSubdivision = true) { m_useZigzagSubdivision = useZigzagSubdivision; }
|
|
|
|
|
|
|
|
void setFlipTriangleWinding(bool flipTriangleWinding)
|
|
|
|
{
|
|
|
|
m_flipTriangleWinding = flipTriangleWinding;
|
|
|
|
}
|
|
|
|
virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
|
|
|
|
|
|
|
|
virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
|
|
|
|
|
|
|
|
virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
|
|
|
|
|
|
|
|
virtual void setLocalScaling(const btVector3& scaling);
|
|
|
|
|
|
|
|
virtual const btVector3& getLocalScaling() const;
|
|
|
|
|
|
|
|
void getVertex(int x, int y, btVector3& vertex) const;
|
|
|
|
|
|
|
|
void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget) const;
|
|
|
|
|
|
|
|
void buildAccelerator(int chunkSize = 16);
|
|
|
|
void clearAccelerator();
|
|
|
|
|
|
|
|
int getUpAxis() const
|
|
|
|
{
|
|
|
|
return m_upAxis;
|
|
|
|
}
|
|
|
|
//debugging
|
|
|
|
virtual const char* getName() const { return "HEIGHTFIELD"; }
|
|
|
|
|
|
|
|
|
|
|
|
void setUserValue3(btScalar value)
|
|
|
|
{
|
|
|
|
m_userValue3 = value;
|
|
|
|
}
|
|
|
|
btScalar getUserValue3() const
|
|
|
|
{
|
|
|
|
return m_userValue3;
|
|
|
|
}
|
|
|
|
const struct btTriangleInfoMap* getTriangleInfoMap() const
|
|
|
|
{
|
|
|
|
return m_triangleInfoMap;
|
|
|
|
}
|
|
|
|
struct btTriangleInfoMap* getTriangleInfoMap()
|
|
|
|
{
|
|
|
|
return m_triangleInfoMap;
|
|
|
|
}
|
|
|
|
void setTriangleInfoMap(btTriangleInfoMap* map)
|
|
|
|
{
|
|
|
|
m_triangleInfoMap = map;
|
|
|
|
}
|
|
|
|
const unsigned char* getHeightfieldRawData() const
|
|
|
|
{
|
|
|
|
return m_heightfieldDataUnsignedChar;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-19 22:53:54 +08:00
|
|
|
#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
|