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

Bullet Collision Detection & Physics Library

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
21
22 btHeightfieldTerrainShape::btHeightfieldTerrainShape
23 (
24 int heightStickWidth, int heightStickLength, const void* heightfieldData,
25 btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
26 PHY_ScalarType hdt, bool flipQuadEdges
27 )
28 {
29 initialize(heightStickWidth, heightStickLength, heightfieldData,
30 heightScale, minHeight, maxHeight, upAxis, hdt,
31 flipQuadEdges);
32 }
33
34
35
36 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,const void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
37 {
38 // legacy constructor: support only float or unsigned char,
39 // and min height is zero
40 PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
41 btScalar minHeight = 0.0f;
42
43 // previously, height = uchar * maxHeight / 65535.
44 // So to preserve legacy behavior, heightScale = maxHeight / 65535
45 btScalar heightScale = maxHeight / 65535;
46
47 initialize(heightStickWidth, heightStickLength, heightfieldData,
48 heightScale, minHeight, maxHeight, upAxis, hdt,
49 flipQuadEdges);
50 }
51
52
53
54 void btHeightfieldTerrainShape::initialize
55 (
56 int heightStickWidth, int heightStickLength, const void* heightfieldData,
57 btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
58 PHY_ScalarType hdt, bool flipQuadEdges
59 )
60 {
61 // validation
62 btAssert(heightStickWidth > 1 && "bad width");
63 btAssert(heightStickLength > 1 && "bad length");
64 btAssert(heightfieldData && "null heightfield data");
65 // btAssert(heightScale) -- do we care? Trust caller here
66 btAssert(minHeight <= maxHeight && "bad min/max height");
67 btAssert(upAxis >= 0 && upAxis < 3 &&
68 "bad upAxis--should be in range [0,2]");
69 btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
70 "Bad height data type enum");
71
72 // initialize member variables
73 m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
74 m_heightStickWidth = heightStickWidth;
75 m_heightStickLength = heightStickLength;
76 m_minHeight = minHeight;
77 m_maxHeight = maxHeight;
78 m_width = (btScalar) (heightStickWidth - 1);
79 m_length = (btScalar) (heightStickLength - 1);
80 m_heightScale = heightScale;
81 m_heightfieldDataUnknown = heightfieldData;
82 m_heightDataType = hdt;
83 m_flipQuadEdges = flipQuadEdges;
84 m_useDiamondSubdivision = false;
85 m_useZigzagSubdivision = false;
86 m_upAxis = upAxis;
87 m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
88
89 // determine min/max axis-aligned bounding box (aabb) values
90 switch (m_upAxis)
91 {
92 case 0:
93 {
94 m_localAabbMin.setValue(m_minHeight, 0, 0);
95 m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
96 break;
97 }
98 case 1:
99 {
100 m_localAabbMin.setValue(0, m_minHeight, 0);
101 m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
102 break;
103 };
104 case 2:
105 {
106 m_localAabbMin.setValue(0, 0, m_minHeight);
107 m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
108 break;
109 }
110 default:
111 {
112 //need to get valid m_upAxis
113 btAssert(0 && "Bad m_upAxis");
114 }
115 }
116
117 // remember origin (defined as exact middle of aabb)
118 m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
119 }
120
121
122
123 btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
124 {
125 }
126
127
128
129 void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
130 {
131 btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
132
133 btVector3 localOrigin(0, 0, 0);
134 localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
135 localOrigin *= m_localScaling;
136
137 btMatrix3x3 abs_b = t.getBasis().absolute();
138 btVector3 center = t.getOrigin();
139 btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
140 extent += btVector3(getMargin(),getMargin(),getMargin());
141
142 aabbMin = center - extent;
143 aabbMax = center + extent;
144 }
145
146
150 btScalar
151 btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
152 {
153 btScalar val = 0.f;
154 switch (m_heightDataType)
155 {
156 case PHY_FLOAT:
157 {
158 val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
159 break;
160 }
161
162 case PHY_UCHAR:
163 {
164 unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
165 val = heightFieldValue * m_heightScale;
166 break;
167 }
168
169 case PHY_SHORT:
170 {
171 short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
172 val = hfValue * m_heightScale;
173 break;
174 }
175
176 default:
177 {
178 btAssert(!"Bad m_heightDataType");
179 }
180 }
181
182 return val;
183 }
184
185
186
187
189 void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
190 {
191 btAssert(x>=0);
192 btAssert(y>=0);
193 btAssert(x<m_heightStickWidth);
194 btAssert(y<m_heightStickLength);
195
196 btScalar height = getRawHeightFieldValue(x,y);
197
198 switch (m_upAxis)
199 {
200 case 0:
201 {
202 vertex.setValue(
203 height - m_localOrigin.getX(),
204 (-m_width/btScalar(2.0)) + x,
205 (-m_length/btScalar(2.0) ) + y
206 );
207 break;
208 }
209 case 1:
210 {
211 vertex.setValue(
212 (-m_width/btScalar(2.0)) + x,
213 height - m_localOrigin.getY(),
214 (-m_length/btScalar(2.0)) + y
215 );
216 break;
217 };
218 case 2:
219 {
220 vertex.setValue(
221 (-m_width/btScalar(2.0)) + x,
222 (-m_length/btScalar(2.0)) + y,
223 height - m_localOrigin.getZ()
224 );
225 break;
226 }
227 default:
228 {
229 //need to get valid m_upAxis
230 btAssert(0);
231 }
232 }
233
234 vertex*=m_localScaling;
235 }
236
237
238
239 static inline int
240 getQuantized
241 (
242 btScalar x
243 )
244 {
245 if (x < 0.0) {
246 return (int) (x - 0.5);
247 }
248 return (int) (x + 0.5);
249 }
250
251
252
254
262 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
263 {
264 btVector3 clampedPoint(point);
265 clampedPoint.setMax(m_localAabbMin);
266 clampedPoint.setMin(m_localAabbMax);
267
268 out[0] = getQuantized(clampedPoint.getX());
269 out[1] = getQuantized(clampedPoint.getY());
270 out[2] = getQuantized(clampedPoint.getZ());
271
272 }
273
274
275
277
283 void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
284 {
285 // scale down the input aabb's so they are in local (non-scaled) coordinates
286 btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
287 btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
288
289 // account for local origin
290 localAabbMin += m_localOrigin;
291 localAabbMax += m_localOrigin;
292
293 //quantize the aabbMin and aabbMax, and adjust the start/end ranges
294 int quantizedAabbMin[3];
295 int quantizedAabbMax[3];
296 quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
297 quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
298
299 // expand the min/max quantized values
300 // this is to catch the case where the input aabb falls between grid points!
301 for (int i = 0; i < 3; ++i) {
302 quantizedAabbMin[i]--;
303 quantizedAabbMax[i]++;
304 }
305
306 int startX=0;
307 int endX=m_heightStickWidth-1;
308 int startJ=0;
309 int endJ=m_heightStickLength-1;
310
311 switch (m_upAxis)
312 {
313 case 0:
314 {
315 if (quantizedAabbMin[1]>startX)
316 startX = quantizedAabbMin[1];
317 if (quantizedAabbMax[1]<endX)
318 endX = quantizedAabbMax[1];
319 if (quantizedAabbMin[2]>startJ)
320 startJ = quantizedAabbMin[2];
321 if (quantizedAabbMax[2]<endJ)
322 endJ = quantizedAabbMax[2];
323 break;
324 }
325 case 1:
326 {
327 if (quantizedAabbMin[0]>startX)
328 startX = quantizedAabbMin[0];
329 if (quantizedAabbMax[0]<endX)
330 endX = quantizedAabbMax[0];
331 if (quantizedAabbMin[2]>startJ)
332 startJ = quantizedAabbMin[2];
333 if (quantizedAabbMax[2]<endJ)
334 endJ = quantizedAabbMax[2];
335 break;
336 };
337 case 2:
338 {
339 if (quantizedAabbMin[0]>startX)
340 startX = quantizedAabbMin[0];
341 if (quantizedAabbMax[0]<endX)
342 endX = quantizedAabbMax[0];
343 if (quantizedAabbMin[1]>startJ)
344 startJ = quantizedAabbMin[1];
345 if (quantizedAabbMax[1]<endJ)
346 endJ = quantizedAabbMax[1];
347 break;
348 }
349 default:
350 {
351 //need to get valid m_upAxis
352 btAssert(0);
353 }
354 }
355
356
357
358
359 for(int j=startJ; j<endJ; j++)
360 {
361 for(int x=startX; x<endX; x++)
362 {
363 btVector3 vertices[3];
364 if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
365 {
366 //first triangle
367 getVertex(x,j,vertices[0]);
368 getVertex(x, j + 1, vertices[1]);
369 getVertex(x + 1, j + 1, vertices[2]);
370 callback->processTriangle(vertices,x,j);
371 //second triangle
372 // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
373 getVertex(x+1,j+1,vertices[1]);
374 getVertex(x + 1, j, vertices[2]);
375 callback->processTriangle(vertices, x, j);
376
377 } else
378 {
379 //first triangle
380 getVertex(x,j,vertices[0]);
381 getVertex(x,j+1,vertices[1]);
382 getVertex(x+1,j,vertices[2]);
383 callback->processTriangle(vertices,x,j);
384 //second triangle
385 getVertex(x+1,j,vertices[0]);
386 //getVertex(x,j+1,vertices[1]);
387 getVertex(x+1,j+1,vertices[2]);
388 callback->processTriangle(vertices,x,j);
389 }
390 }
391 }
392
393
394
395 }
396
397 void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
398 {
399 //moving concave objects not supported
400
401 inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
402 }
403
404 void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
405 {
406 m_localScaling = scaling;
407 }
408 const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
409 {
410 return m_localScaling;
411 }
btHeightfieldTerrainShape::m_flipQuadEdges
bool m_flipQuadEdges
Definition: btHeightfieldTerrainShape.h:95
btHeightfieldTerrainShape::m_localAabbMax
btVector3 m_localAabbMax
Definition: btHeightfieldTerrainShape.h:75
btTransformUtil.h
btHeightfieldTerrainShape::m_maxHeight
btScalar m_maxHeight
Definition: btHeightfieldTerrainShape.h:82
PHY_UCHAR
Definition: btConcaveShape.h:31
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:404
btHeightfieldTerrainShape::m_heightStickLength
int m_heightStickLength
Definition: btHeightfieldTerrainShape.h:80
btHeightfieldTerrainShape::m_useDiamondSubdivision
bool m_useDiamondSubdivision
Definition: btHeightfieldTerrainShape.h:96
btHeightfieldTerrainShape::m_length
btScalar m_length
Definition: btHeightfieldTerrainShape.h:84
btHeightfieldTerrainShape::m_heightfieldDataFloat
const btScalar * m_heightfieldDataFloat
Definition: btHeightfieldTerrainShape.h:90
btTriangleCallback::processTriangle
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
btAssert
#define btAssert(x)
Definition: btScalar.h:113
btHeightfieldTerrainShape::~btHeightfieldTerrainShape
virtual ~btHeightfieldTerrainShape()
Definition: btHeightfieldTerrainShape.cpp:123
btHeightfieldTerrainShape::m_heightDataType
PHY_ScalarType m_heightDataType
Definition: btHeightfieldTerrainShape.h:94
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:283
btHeightfieldTerrainShape::m_localScaling
btVector3 m_localScaling
Definition: btHeightfieldTerrainShape.h:101
btHeightfieldTerrainShape::m_useZigzagSubdivision
bool m_useZigzagSubdivision
Definition: btHeightfieldTerrainShape.h:97
btHeightfieldTerrainShape::quantizeWithClamp
void quantizeWithClamp(int *out, const btVector3 &point, int isMax) const
given input vector, return quantized version
Definition: btHeightfieldTerrainShape.cpp:262
btVector3::getZ
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:565
btHeightfieldTerrainShape::m_heightfieldDataUnsignedChar
const unsigned char * m_heightfieldDataUnsignedChar
Definition: btHeightfieldTerrainShape.h:88
btHeightfieldTerrainShape::m_minHeight
btScalar m_minHeight
Definition: btHeightfieldTerrainShape.h:81
btHeightfieldTerrainShape::m_heightScale
btScalar m_heightScale
Definition: btHeightfieldTerrainShape.h:85
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:55
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:151
btTransform::getOrigin
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
btMatrix3x3::absolute
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:980
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:23
btTriangleCallback
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
Definition: btTriangleCallback.h:24
PHY_SHORT
Definition: btConcaveShape.h:29
btHeightfieldTerrainShape::getVertex
void getVertex(int x, int y, btVector3 &vertex) const
this returns the vertex in bullet-local coordinates
Definition: btHeightfieldTerrainShape.cpp:189
btVector3::getY
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:563
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btVector3::getX
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:561
btHeightfieldTerrainShape::m_localAabbMin
btVector3 m_localAabbMin
Definition: btHeightfieldTerrainShape.h:74
getQuantized
static int getQuantized(btScalar x)
Definition: btHeightfieldTerrainShape.cpp:241
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:129
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
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:34
btHeightfieldTerrainShape::m_upAxis
int m_upAxis
Definition: btHeightfieldTerrainShape.h:99
TERRAIN_SHAPE_PROXYTYPE
Definition: btBroadphaseProxy.h:60
btHeightfieldTerrainShape::m_width
btScalar m_width
Definition: btHeightfieldTerrainShape.h:83
btHeightfieldTerrainShape.h
btVector3::dot3
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:719
btHeightfieldTerrainShape::getLocalScaling
virtual const btVector3 & getLocalScaling() const
Definition: btHeightfieldTerrainShape.cpp:408
btHeightfieldTerrainShape::m_localOrigin
btVector3 m_localOrigin
Definition: btHeightfieldTerrainShape.h:76
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
btConcaveShape::getMargin
virtual btScalar getMargin() const
Definition: btConcaveShape.h:50
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::calculateLocalInertia
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
Definition: btHeightfieldTerrainShape.cpp:397
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:278
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:79
PHY_FLOAT
Definition: btConcaveShape.h:26