Bullet Collision Detection & Physics Library
btHeightfieldTerrainShape.cpp
Go to the documentation of this file.
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
17
19
20
21
23(
24int heightStickWidth, int heightStickLength, const void* heightfieldData,
25btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
26PHY_ScalarType hdt, bool flipQuadEdges
27)
28{
29 initialize(heightStickWidth, heightStickLength, heightfieldData,
30 heightScale, minHeight, maxHeight, upAxis, hdt,
31 flipQuadEdges);
32}
33
34
35
36btHeightfieldTerrainShape::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
55(
56int heightStickWidth, int heightStickLength, const void* heightfieldData,
57btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
58PHY_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);// && "bad upAxis--should be in range [0,2]");
68 btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT);// && "Bad height data type enum");
69
70 // initialize member variables
72 m_heightStickWidth = heightStickWidth;
73 m_heightStickLength = heightStickLength;
74 m_minHeight = minHeight;
75 m_maxHeight = maxHeight;
76 m_width = (btScalar) (heightStickWidth - 1);
77 m_length = (btScalar) (heightStickLength - 1);
78 m_heightScale = heightScale;
79 m_heightfieldDataUnknown = heightfieldData;
80 m_heightDataType = hdt;
81 m_flipQuadEdges = flipQuadEdges;
84 m_upAxis = upAxis;
86
87 // determine min/max axis-aligned bounding box (aabb) values
88 switch (m_upAxis)
89 {
90 case 0:
91 {
94 break;
95 }
96 case 1:
97 {
100 break;
101 };
102 case 2:
103 {
106 break;
107 }
108 default:
109 {
110 //need to get valid m_upAxis
111 btAssert(0);// && "Bad m_upAxis");
112 }
113 }
114
115 // remember origin (defined as exact middle of aabb)
117}
118
119
120
122{
123}
124
125
126
128{
130
131 btVector3 localOrigin(0, 0, 0);
132 localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
133 localOrigin *= m_localScaling;
134
135 btMatrix3x3 abs_b = t.getBasis().absolute();
136 btVector3 center = t.getOrigin();
137 btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
138 extent += btVector3(getMargin(),getMargin(),getMargin());
139
140 aabbMin = center - extent;
141 aabbMax = center + extent;
142}
143
144
150{
151 btScalar val = 0.f;
152 switch (m_heightDataType)
153 {
154 case PHY_FLOAT:
155 {
157 break;
158 }
159
160 case PHY_UCHAR:
161 {
162 unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
163 val = heightFieldValue * m_heightScale;
164 break;
165 }
166
167 case PHY_SHORT:
168 {
169 short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
170 val = hfValue * m_heightScale;
171 break;
172 }
173
174 default:
175 {
176 btAssert(!"Bad m_heightDataType");
177 }
178 }
179
180 return val;
181}
182
183
184
185
187void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
188{
189 btAssert(x>=0);
190 btAssert(y>=0);
193
194 btScalar height = getRawHeightFieldValue(x,y);
195
196 switch (m_upAxis)
197 {
198 case 0:
199 {
200 vertex.setValue(
201 height - m_localOrigin.getX(),
202 (-m_width/btScalar(2.0)) + x,
203 (-m_length/btScalar(2.0) ) + y
204 );
205 break;
206 }
207 case 1:
208 {
209 vertex.setValue(
210 (-m_width/btScalar(2.0)) + x,
211 height - m_localOrigin.getY(),
212 (-m_length/btScalar(2.0)) + y
213 );
214 break;
215 };
216 case 2:
217 {
218 vertex.setValue(
219 (-m_width/btScalar(2.0)) + x,
220 (-m_length/btScalar(2.0)) + y,
221 height - m_localOrigin.getZ()
222 );
223 break;
224 }
225 default:
226 {
227 //need to get valid m_upAxis
228 btAssert(0);
229 }
230 }
231
232 vertex*=m_localScaling;
233}
234
235
236
237static inline int
239(
240btScalar x
241)
242{
243 if (x < 0.0) {
244 return (int) (x - 0.5);
245 }
246 return (int) (x + 0.5);
247}
248
249
250
252
260void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
261{
262 btVector3 clampedPoint(point);
263 clampedPoint.setMax(m_localAabbMin);
264 clampedPoint.setMin(m_localAabbMax);
265
266 out[0] = getQuantized(clampedPoint.getX());
267 out[1] = getQuantized(clampedPoint.getY());
268 out[2] = getQuantized(clampedPoint.getZ());
269
270}
271
272
273
275
282{
283 // scale down the input aabb's so they are in local (non-scaled) coordinates
284 btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
285 btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
286
287 // account for local origin
288 localAabbMin += m_localOrigin;
289 localAabbMax += m_localOrigin;
290
291 //quantize the aabbMin and aabbMax, and adjust the start/end ranges
292 int quantizedAabbMin[3];
293 int quantizedAabbMax[3];
294 quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
295 quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
296
297 // expand the min/max quantized values
298 // this is to catch the case where the input aabb falls between grid points!
299 for (int i = 0; i < 3; ++i) {
300 quantizedAabbMin[i]--;
301 quantizedAabbMax[i]++;
302 }
303
304 int startX=0;
305 int endX=m_heightStickWidth-1;
306 int startJ=0;
307 int endJ=m_heightStickLength-1;
308
309 switch (m_upAxis)
310 {
311 case 0:
312 {
313 if (quantizedAabbMin[1]>startX)
314 startX = quantizedAabbMin[1];
315 if (quantizedAabbMax[1]<endX)
316 endX = quantizedAabbMax[1];
317 if (quantizedAabbMin[2]>startJ)
318 startJ = quantizedAabbMin[2];
319 if (quantizedAabbMax[2]<endJ)
320 endJ = quantizedAabbMax[2];
321 break;
322 }
323 case 1:
324 {
325 if (quantizedAabbMin[0]>startX)
326 startX = quantizedAabbMin[0];
327 if (quantizedAabbMax[0]<endX)
328 endX = quantizedAabbMax[0];
329 if (quantizedAabbMin[2]>startJ)
330 startJ = quantizedAabbMin[2];
331 if (quantizedAabbMax[2]<endJ)
332 endJ = quantizedAabbMax[2];
333 break;
334 };
335 case 2:
336 {
337 if (quantizedAabbMin[0]>startX)
338 startX = quantizedAabbMin[0];
339 if (quantizedAabbMax[0]<endX)
340 endX = quantizedAabbMax[0];
341 if (quantizedAabbMin[1]>startJ)
342 startJ = quantizedAabbMin[1];
343 if (quantizedAabbMax[1]<endJ)
344 endJ = quantizedAabbMax[1];
345 break;
346 }
347 default:
348 {
349 //need to get valid m_upAxis
350 btAssert(0);
351 }
352 }
353
354
355
356
357 for(int j=startJ; j<endJ; j++)
358 {
359 for(int x=startX; x<endX; x++)
360 {
361 btVector3 vertices[3];
362 if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
363 {
364 //first triangle
365 getVertex(x,j,vertices[0]);
366 getVertex(x, j + 1, vertices[1]);
367 getVertex(x + 1, j + 1, vertices[2]);
368 callback->processTriangle(vertices,x,j);
369 //second triangle
370 // getVertex(x,j,vertices[0]);//already got this vertex before, thanks to Danny Chapman
371 getVertex(x+1,j+1,vertices[1]);
372 getVertex(x + 1, j, vertices[2]);
373 callback->processTriangle(vertices, x, j);
374
375 } else
376 {
377 //first triangle
378 getVertex(x,j,vertices[0]);
379 getVertex(x,j+1,vertices[1]);
380 getVertex(x+1,j,vertices[2]);
381 callback->processTriangle(vertices,x,j);
382 //second triangle
383 getVertex(x+1,j,vertices[0]);
384 //getVertex(x,j+1,vertices[1]);
385 getVertex(x+1,j+1,vertices[2]);
386 callback->processTriangle(vertices,x,j);
387 }
388 }
389 }
390
391
392
393}
394
396{
397 //moving concave objects not supported
398
399 inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
400}
401
403{
404 m_localScaling = scaling;
405}
407{
408 return m_localScaling;
409}
@ TERRAIN_SHAPE_PROXYTYPE
PHY_ScalarType
PHY_ScalarType enumerates possible scalar types.
@ PHY_FLOAT
@ PHY_UCHAR
@ PHY_SHORT
static int getQuantized(btScalar x)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
#define btAssert(x)
Definition: btScalar.h:131
virtual btScalar getMargin() const
virtual btScalar getRawHeightFieldValue(int x, int y) const
This returns the "raw" (user's initial) height, not the actual height.
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.
void quantizeWithClamp(int *out, const btVector3 &point, int isMax) const
given input vector, return quantized version
void getVertex(int x, int y, btVector3 &vertex) const
this returns the vertex in bullet-local coordinates
virtual void calculateLocalInertia(btScalar mass, btVector3 &inertia) const
btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
preferred constructor
const unsigned char * m_heightfieldDataUnsignedChar
virtual void setLocalScaling(const btVector3 &scaling)
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const
process all triangles within the provided axis-aligned bounding box
virtual const btVector3 & getLocalScaling() const
void initialize(int heightStickWidth, int heightStickLength, const void *heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, PHY_ScalarType heightDataType, bool flipQuadEdges)
protected initialization
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
btMatrix3x3 absolute() const
Return the matrix with all values non negative.
Definition: btMatrix3x3.h:937
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)=0
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:84
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:577
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:621
btVector3 dot3(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) const
Definition: btVector3.h:731
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:652
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:575
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:638
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:573