Bullet Collision Detection & Physics Library
btHeightfieldTerrainShape.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
17 
19 
21  int heightStickWidth, int heightStickLength, const void* heightfieldData,
22  btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
23  PHY_ScalarType hdt, bool flipQuadEdges)
24 {
25  initialize(heightStickWidth, heightStickLength, heightfieldData,
26  heightScale, minHeight, maxHeight, upAxis, hdt,
27  flipQuadEdges);
28 }
29 
30 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
31 {
32  // legacy constructor: support only float or unsigned char,
33  // and min height is zero
34  PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
35  btScalar minHeight = 0.0f;
36 
37  // previously, height = uchar * maxHeight / 65535.
38  // So to preserve legacy behavior, heightScale = maxHeight / 65535
39  btScalar heightScale = maxHeight / 65535;
40 
41  initialize(heightStickWidth, heightStickLength, heightfieldData,
42  heightScale, minHeight, maxHeight, upAxis, hdt,
43  flipQuadEdges);
44 }
45 
47  int heightStickWidth, int heightStickLength, const void* heightfieldData,
48  btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
49  PHY_ScalarType hdt, bool flipQuadEdges)
50 {
51  // validation
52  btAssert(heightStickWidth > 1); // && "bad width");
53  btAssert(heightStickLength > 1); // && "bad length");
54  btAssert(heightfieldData); // && "null heightfield data");
55  // btAssert(heightScale) -- do we care? Trust caller here
56  btAssert(minHeight <= maxHeight); // && "bad min/max height");
57  btAssert(upAxis >= 0 && upAxis < 3); // && "bad upAxis--should be in range [0,2]");
58  btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT); // && "Bad height data type enum");
59 
60  // initialize member variables
62  m_heightStickWidth = heightStickWidth;
63  m_heightStickLength = heightStickLength;
64  m_minHeight = minHeight;
65  m_maxHeight = maxHeight;
66  m_width = (btScalar)(heightStickWidth - 1);
67  m_length = (btScalar)(heightStickLength - 1);
68  m_heightScale = heightScale;
69  m_heightfieldDataUnknown = heightfieldData;
70  m_heightDataType = hdt;
71  m_flipQuadEdges = flipQuadEdges;
73  m_useZigzagSubdivision = false;
74  m_upAxis = upAxis;
76 
77  // determine min/max axis-aligned bounding box (aabb) values
78  switch (m_upAxis)
79  {
80  case 0:
81  {
84  break;
85  }
86  case 1:
87  {
90  break;
91  };
92  case 2:
93  {
96  break;
97  }
98  default:
99  {
100  //need to get valid m_upAxis
101  btAssert(0); // && "Bad m_upAxis");
102  }
103  }
104 
105  // remember origin (defined as exact middle of aabb)
107 }
108 
110 {
111 }
112 
113 void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
114 {
116 
117  btVector3 localOrigin(0, 0, 0);
118  localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
119  localOrigin *= m_localScaling;
120 
121  btMatrix3x3 abs_b = t.getBasis().absolute();
122  btVector3 center = t.getOrigin();
123  btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
124  extent += btVector3(getMargin(), getMargin(), getMargin());
125 
126  aabbMin = center - extent;
127  aabbMax = center + extent;
128 }
129 
133 btScalar
135 {
136  btScalar val = 0.f;
137  switch (m_heightDataType)
138  {
139  case PHY_FLOAT:
140  {
142  break;
143  }
144 
145  case PHY_UCHAR:
146  {
147  unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
148  val = heightFieldValue * m_heightScale;
149  break;
150  }
151 
152  case PHY_SHORT:
153  {
154  short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
155  val = hfValue * m_heightScale;
156  break;
157  }
158 
159  default:
160  {
161  btAssert(!"Bad m_heightDataType");
162  }
163  }
164 
165  return val;
166 }
167 
169 void btHeightfieldTerrainShape::getVertex(int x, int y, btVector3& vertex) const
170 {
171  btAssert(x >= 0);
172  btAssert(y >= 0);
175 
176  btScalar height = getRawHeightFieldValue(x, y);
177 
178  switch (m_upAxis)
179  {
180  case 0:
181  {
182  vertex.setValue(
183  height - m_localOrigin.getX(),
184  (-m_width / btScalar(2.0)) + x,
185  (-m_length / btScalar(2.0)) + y);
186  break;
187  }
188  case 1:
189  {
190  vertex.setValue(
191  (-m_width / btScalar(2.0)) + x,
192  height - m_localOrigin.getY(),
193  (-m_length / btScalar(2.0)) + y);
194  break;
195  };
196  case 2:
197  {
198  vertex.setValue(
199  (-m_width / btScalar(2.0)) + x,
200  (-m_length / btScalar(2.0)) + y,
201  height - m_localOrigin.getZ());
202  break;
203  }
204  default:
205  {
206  //need to get valid m_upAxis
207  btAssert(0);
208  }
209  }
210 
211  vertex *= m_localScaling;
212 }
213 
214 static inline int
216  btScalar x)
217 {
218  if (x < 0.0)
219  {
220  return (int)(x - 0.5);
221  }
222  return (int)(x + 0.5);
223 }
224 
226 
234 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point, int /*isMax*/) const
235 {
236  btVector3 clampedPoint(point);
237  clampedPoint.setMax(m_localAabbMin);
238  clampedPoint.setMin(m_localAabbMax);
239 
240  out[0] = getQuantized(clampedPoint.getX());
241  out[1] = getQuantized(clampedPoint.getY());
242  out[2] = getQuantized(clampedPoint.getZ());
243 }
244 
246 
252 void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
253 {
254  // scale down the input aabb's so they are in local (non-scaled) coordinates
255  btVector3 localAabbMin = aabbMin * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
256  btVector3 localAabbMax = aabbMax * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
257 
258  // account for local origin
259  localAabbMin += m_localOrigin;
260  localAabbMax += m_localOrigin;
261 
262  //quantize the aabbMin and aabbMax, and adjust the start/end ranges
263  int quantizedAabbMin[3];
264  int quantizedAabbMax[3];
265  quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
266  quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
267 
268  // expand the min/max quantized values
269  // this is to catch the case where the input aabb falls between grid points!
270  for (int i = 0; i < 3; ++i)
271  {
272  quantizedAabbMin[i]--;
273  quantizedAabbMax[i]++;
274  }
275 
276  int startX = 0;
277  int endX = m_heightStickWidth - 1;
278  int startJ = 0;
279  int endJ = m_heightStickLength - 1;
280 
281  switch (m_upAxis)
282  {
283  case 0:
284  {
285  if (quantizedAabbMin[1] > startX)
286  startX = quantizedAabbMin[1];
287  if (quantizedAabbMax[1] < endX)
288  endX = quantizedAabbMax[1];
289  if (quantizedAabbMin[2] > startJ)
290  startJ = quantizedAabbMin[2];
291  if (quantizedAabbMax[2] < endJ)
292  endJ = quantizedAabbMax[2];
293  break;
294  }
295  case 1:
296  {
297  if (quantizedAabbMin[0] > startX)
298  startX = quantizedAabbMin[0];
299  if (quantizedAabbMax[0] < endX)
300  endX = quantizedAabbMax[0];
301  if (quantizedAabbMin[2] > startJ)
302  startJ = quantizedAabbMin[2];
303  if (quantizedAabbMax[2] < endJ)
304  endJ = quantizedAabbMax[2];
305  break;
306  };
307  case 2:
308  {
309  if (quantizedAabbMin[0] > startX)
310  startX = quantizedAabbMin[0];
311  if (quantizedAabbMax[0] < endX)
312  endX = quantizedAabbMax[0];
313  if (quantizedAabbMin[1] > startJ)
314  startJ = quantizedAabbMin[1];
315  if (quantizedAabbMax[1] < endJ)
316  endJ = quantizedAabbMax[1];
317  break;
318  }
319  default:
320  {
321  //need to get valid m_upAxis
322  btAssert(0);
323  }
324  }
325 
326  for (int j = startJ; j < endJ; j++)
327  {
328  for (int x = startX; x < endX; x++)
329  {
330  btVector3 vertices[3];
331  if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
332  {
333  //first triangle
334  getVertex(x, j, vertices[0]);
335  getVertex(x, j + 1, vertices[1]);
336  getVertex(x + 1, j + 1, vertices[2]);
337  callback->processTriangle(vertices, x, j);
338  //second triangle
339  // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
340  getVertex(x + 1, j + 1, vertices[1]);
341  getVertex(x + 1, j, vertices[2]);
342  callback->processTriangle(vertices, x, j);
343  }
344  else
345  {
346  //first triangle
347  getVertex(x, j, vertices[0]);
348  getVertex(x, j + 1, vertices[1]);
349  getVertex(x + 1, j, vertices[2]);
350  callback->processTriangle(vertices, x, j);
351  //second triangle
352  getVertex(x + 1, j, vertices[0]);
353  //getVertex(x,j+1,vertices[1]);
354  getVertex(x + 1, j + 1, vertices[2]);
355  callback->processTriangle(vertices, x, j);
356  }
357  }
358  }
359 }
360 
362 {
363  //moving concave objects not supported
364 
365  inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
366 }
367 
369 {
370  m_localScaling = scaling;
371 }
373 {
374  return m_localScaling;
375 }
btHeightfieldTerrainShape::m_localAabbMin
btVector3 m_localAabbMin
Definition: btHeightfieldTerrainShape.h:75
btHeightfieldTerrainShape::m_heightStickLength
int m_heightStickLength
Definition: btHeightfieldTerrainShape.h:81
btHeightfieldTerrainShape::initialize
void initialize(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
protected initialization
Definition: btHeightfieldTerrainShape.cpp:46
TERRAIN_SHAPE_PROXYTYPE
Definition: btBroadphaseProxy.h:59
btHeightfieldTerrainShape::m_heightDataType
PHY_ScalarType m_heightDataType
Definition: btHeightfieldTerrainShape.h:94
btHeightfieldTerrainShape::getVertex
void getVertex(int x, int y, btVector3 &vertex) const
this returns the vertex in bullet-local coordinates
Definition: btHeightfieldTerrainShape.cpp:169
btVector3::dot3
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:720
btHeightfieldTerrainShape::quantizeWithClamp
void quantizeWithClamp(int *out, const btVector3 &point, int isMax) const
given input vector, return quantized version
Definition: btHeightfieldTerrainShape.cpp:234
btVector3::setValue
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
btHeightfieldTerrainShape::setLocalScaling
virtual void setLocalScaling(const btVector3 &scaling)
Definition: btHeightfieldTerrainShape.cpp:368
getQuantized
static int getQuantized(btScalar x)
Definition: btHeightfieldTerrainShape.cpp:215
PHY_FLOAT
Definition: btConcaveShape.h:27
btTransformUtil.h
btHeightfieldTerrainShape::calculateLocalInertia
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
Definition: btHeightfieldTerrainShape.cpp:361
btHeightfieldTerrainShape::m_localAabbMax
btVector3 m_localAabbMax
Definition: btHeightfieldTerrainShape.h:76
btVector3::getX
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
btCollisionShape::m_shapeType
int m_shapeType
Definition: btCollisionShape.h:30
btHeightfieldTerrainShape::m_useDiamondSubdivision
bool m_useDiamondSubdivision
Definition: btHeightfieldTerrainShape.h:96
btHeightfieldTerrainShape::m_width
btScalar m_width
Definition: btHeightfieldTerrainShape.h:84
btAssert
#define btAssert(x)
Definition: btScalar.h:133
btHeightfieldTerrainShape::processAllTriangles
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
process all triangles within the provided axis-aligned bounding box
Definition: btHeightfieldTerrainShape.cpp:252
btHeightfieldTerrainShape::m_heightfieldDataFloat
const btScalar * m_heightfieldDataFloat
Definition: btHeightfieldTerrainShape.h:90
btHeightfieldTerrainShape::m_upAxis
int m_upAxis
Definition: btHeightfieldTerrainShape.h:99
btHeightfieldTerrainShape::getLocalScaling
virtual const btVector3 & getLocalScaling() const
Definition: btHeightfieldTerrainShape.cpp:372
btHeightfieldTerrainShape::m_heightfieldDataUnknown
const void * m_heightfieldDataUnknown
Definition: btHeightfieldTerrainShape.h:91
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:108
btVector3::setMax
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:609
btHeightfieldTerrainShape::getRawHeightFieldValue
virtual btScalar getRawHeightFieldValue(int x, int y) const
This returns the "raw" (user's initial) height, not the actual height.
Definition: btHeightfieldTerrainShape.cpp:134
PHY_ScalarType
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
Definition: btConcaveShape.h:25
btHeightfieldTerrainShape::m_flipQuadEdges
bool m_flipQuadEdges
Definition: btHeightfieldTerrainShape.h:95
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:46
btTriangleCallback
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
Definition: btTriangleCallback.h:23
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
btHeightfieldTerrainShape::getAabb
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const
getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
Definition: btHeightfieldTerrainShape.cpp:113
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
btHeightfieldTerrainShape::m_length
btScalar m_length
Definition: btHeightfieldTerrainShape.h:85
btHeightfieldTerrainShape::m_minHeight
btScalar m_minHeight
Definition: btHeightfieldTerrainShape.h:82
btHeightfieldTerrainShape::m_useZigzagSubdivision
bool m_useZigzagSubdivision
Definition: btHeightfieldTerrainShape.h:97
btHeightfieldTerrainShape::m_heightfieldDataUnsignedChar
const unsigned char * m_heightfieldDataUnsignedChar
Definition: btHeightfieldTerrainShape.h:88
btTransform::getOrigin
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:113
btHeightfieldTerrainShape::btHeightfieldTerrainShape
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
preferred constructor
Definition: btHeightfieldTerrainShape.cpp:20
btHeightfieldTerrainShape::~btHeightfieldTerrainShape
virtual ~btHeightfieldTerrainShape()
Definition: btHeightfieldTerrainShape.cpp:109
btTriangleCallback::processTriangle
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
btVector3::getZ
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
btHeightfieldTerrainShape.h
btHeightfieldTerrainShape::m_heightStickWidth
int m_heightStickWidth
terrain data
Definition: btHeightfieldTerrainShape.h:80
btVector3::getY
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btVector3::setMin
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:626
btHeightfieldTerrainShape::m_heightfieldDataShort
const short * m_heightfieldDataShort
Definition: btHeightfieldTerrainShape.h:89
btMatrix3x3::absolute
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:1005
btConcaveShape::getMargin
virtual btScalar getMargin() const
Definition: btConcaveShape.h:52
PHY_UCHAR
Definition: btConcaveShape.h:32
btHeightfieldTerrainShape::m_localOrigin
btVector3 m_localOrigin
Definition: btHeightfieldTerrainShape.h:77
btHeightfieldTerrainShape::m_localScaling
btVector3 m_localScaling
Definition: btHeightfieldTerrainShape.h:101
btHeightfieldTerrainShape::m_maxHeight
btScalar m_maxHeight
Definition: btHeightfieldTerrainShape.h:83
btHeightfieldTerrainShape::m_heightScale
btScalar m_heightScale
Definition: btHeightfieldTerrainShape.h:86
PHY_SHORT
Definition: btConcaveShape.h:30