Bullet Collision Detection & Physics Library: btHeightfieldTerrainShape.cpp Source File

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
16 #include "btHeightfieldTerrainShape.h"
17
18 #include "LinearMath/btTransformUtil.h"
19
20 btHeightfieldTerrainShape::btHeightfieldTerrainShape(
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
46 void btHeightfieldTerrainShape::initialize(
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
61 m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
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;
72 m_useDiamondSubdivision = false;
73 m_useZigzagSubdivision = false;
74 m_upAxis = upAxis;
75 m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
76
77 // determine min/max axis-aligned bounding box (aabb) values
78 switch (m_upAxis)
79 {
80 case 0:
81 {
82 m_localAabbMin.setValue(m_minHeight, 0, 0);
83 m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
84 break;
85 }
86 case 1:
87 {
88 m_localAabbMin.setValue(0, m_minHeight, 0);
89 m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
90 break;
91 };
92 case 2:
93 {
94 m_localAabbMin.setValue(0, 0, m_minHeight);
95 m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
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)
106 m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
107 }
108
109 btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
110 {
111 }
112
113 void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
114 {
115 btVector3 halfExtents = (m_localAabbMax - m_localAabbMin) * m_localScaling * btScalar(0.5);
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
134 btHeightfieldTerrainShape::getRawHeightFieldValue(int x, int y) const
135 {
136 btScalar val = 0.f;
137 switch (m_heightDataType)
138 {
139 case PHY_FLOAT:
140 {
141 val = m_heightfieldDataFloat[(y * m_heightStickWidth) + x];
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);
173 btAssert(x < m_heightStickWidth);
174 btAssert(y < m_heightStickLength);
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
215 getQuantized(
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
361 void btHeightfieldTerrainShape::calculateLocalInertia(btScalar, btVector3& inertia) const
362 {
363 //moving concave objects not supported
364
365 inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
366 }
367
368 void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
369 {
370 m_localScaling = scaling;
371 }
372 const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
373 {
374 return m_localScaling;
375 }
btHeightfieldTerrainShape::calculateLocalInertia
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
Definition: btHeightfieldTerrainShape.cpp:361
btHeightfieldTerrainShape::m_flipQuadEdges
bool m_flipQuadEdges
Definition: btHeightfieldTerrainShape.h:95
btHeightfieldTerrainShape::m_localAabbMax
btVector3 m_localAabbMax
Definition: btHeightfieldTerrainShape.h:76
btTransformUtil.h
btHeightfieldTerrainShape::quantizeWithClamp
void quantizeWithClamp(int *out, const btVector3 &point, int isMax) const
given input vector, return quantized version
Definition: btHeightfieldTerrainShape.cpp:234
btHeightfieldTerrainShape::m_maxHeight
btScalar m_maxHeight
Definition: btHeightfieldTerrainShape.h:83
PHY_UCHAR
Definition: btConcaveShape.h:32
btVector3::setValue
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
btHeightfieldTerrainShape::setLocalScaling
virtual void setLocalScaling(const btVector3 &scaling)
Definition: btHeightfieldTerrainShape.cpp:368
btVector3::dot3
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:720
btHeightfieldTerrainShape::m_heightStickLength
int m_heightStickLength
Definition: btHeightfieldTerrainShape.h:81
btHeightfieldTerrainShape::m_useDiamondSubdivision
bool m_useDiamondSubdivision
Definition: btHeightfieldTerrainShape.h:96
btHeightfieldTerrainShape::m_length
btScalar m_length
Definition: btHeightfieldTerrainShape.h:85
btHeightfieldTerrainShape::m_heightfieldDataFloat
const btScalar * m_heightfieldDataFloat
Definition: btHeightfieldTerrainShape.h:90
btHeightfieldTerrainShape::getLocalScaling
virtual const btVector3 & getLocalScaling() const
Definition: btHeightfieldTerrainShape.cpp:372
btTriangleCallback::processTriangle
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
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::~btHeightfieldTerrainShape
virtual ~btHeightfieldTerrainShape()
Definition: btHeightfieldTerrainShape.cpp:109
btVector3::getY
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btHeightfieldTerrainShape::m_heightDataType
PHY_ScalarType m_heightDataType
Definition: btHeightfieldTerrainShape.h:94
btHeightfieldTerrainShape::m_localScaling
btVector3 m_localScaling
Definition: btHeightfieldTerrainShape.h:101
btHeightfieldTerrainShape::getVertex
void getVertex(int x, int y, btVector3 &vertex) const
this returns the vertex in bullet-local coordinates
Definition: btHeightfieldTerrainShape.cpp:169
btHeightfieldTerrainShape::m_useZigzagSubdivision
bool m_useZigzagSubdivision
Definition: btHeightfieldTerrainShape.h:97
btHeightfieldTerrainShape::m_heightfieldDataUnsignedChar
const unsigned char * m_heightfieldDataUnsignedChar
Definition: btHeightfieldTerrainShape.h:88
btHeightfieldTerrainShape::m_minHeight
btScalar m_minHeight
Definition: btHeightfieldTerrainShape.h:82
btVector3::getZ
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
btHeightfieldTerrainShape::m_heightScale
btScalar m_heightScale
Definition: btHeightfieldTerrainShape.h:86
btHeightfieldTerrainShape::getRawHeightFieldValue
virtual btScalar getRawHeightFieldValue(int x, int y) const
This returns the "raw" (user&#39;s initial) height, not the actual height.
Definition: btHeightfieldTerrainShape.cpp:134
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
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
btTriangleCallback
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
Definition: btTriangleCallback.h:23
PHY_SHORT
Definition: btConcaveShape.h:30
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:108
btHeightfieldTerrainShape::m_localAabbMin
btVector3 m_localAabbMin
Definition: btHeightfieldTerrainShape.h:75
getQuantized
static int getQuantized(btScalar x)
Definition: btHeightfieldTerrainShape.cpp:215
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
btHeightfieldTerrainShape::m_heightfieldDataShort
const short * m_heightfieldDataShort
Definition: btHeightfieldTerrainShape.h:89
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
btHeightfieldTerrainShape::m_upAxis
int m_upAxis
Definition: btHeightfieldTerrainShape.h:99
btMatrix3x3::absolute
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:1005
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
TERRAIN_SHAPE_PROXYTYPE
Definition: btBroadphaseProxy.h:59
btHeightfieldTerrainShape::m_width
btScalar m_width
Definition: btHeightfieldTerrainShape.h:84
btHeightfieldTerrainShape.h
btHeightfieldTerrainShape::m_localOrigin
btVector3 m_localOrigin
Definition: btHeightfieldTerrainShape.h:77
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:46
btConcaveShape::getMargin
virtual btScalar getMargin() const
Definition: btConcaveShape.h:52
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::m_heightfieldDataUnknown
const void * m_heightfieldDataUnknown
Definition: btHeightfieldTerrainShape.h:91
btCollisionShape::m_shapeType
int m_shapeType
Definition: btCollisionShape.h:30
btVector3::getX
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
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
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
PHY_ScalarType
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
Definition: btConcaveShape.h:25
btHeightfieldTerrainShape::m_heightStickWidth
int m_heightStickWidth
terrain data
Definition: btHeightfieldTerrainShape.h:80
PHY_FLOAT
Definition: btConcaveShape.h:27