Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp @ 1963

Last change on this file since 1963 was 1963, checked in by rgrieder, 15 years ago

Added Bullet physics engine.

  • Property svn:eol-style set to native
File size: 8.4 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
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
16#include "btHeightfieldTerrainShape.h"
17
18#include "LinearMath/btTransformUtil.h"
19
20
21btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
22: btConcaveShape (), m_heightStickWidth(heightStickWidth),
23m_heightStickLength(heightStickLength),
24m_maxHeight(maxHeight),
25m_width((btScalar)heightStickWidth-1),
26m_length((btScalar)heightStickLength-1),
27m_heightfieldDataUnknown(heightfieldData),
28m_useFloatData(useFloatData),
29m_flipQuadEdges(flipQuadEdges),
30m_useDiamondSubdivision(false),
31m_upAxis(upAxis),
32m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
33{
34        m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
35
36        btScalar        quantizationMargin = 1.f;
37
38        //enlarge the AABB to avoid division by zero when initializing the quantization values
39        btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
40
41        btVector3       halfExtents(0,0,0);
42
43        switch (m_upAxis)
44        {
45        case 0:
46                {
47                        halfExtents.setValue(
48                                btScalar(m_maxHeight),
49                                btScalar(m_width), //?? don't know if this should change
50                                btScalar(m_length));
51                        break;
52                }
53        case 1:
54                {
55                        halfExtents.setValue(
56                                btScalar(m_width),
57                                btScalar(m_maxHeight),
58                                btScalar(m_length));
59                        break;
60                };
61        case 2:
62                {
63                        halfExtents.setValue(
64                                btScalar(m_width),
65                                btScalar(m_length),
66                                btScalar(m_maxHeight)
67                        );
68                        break;
69                }
70        default:
71                {
72                        //need to get valid m_upAxis
73                        btAssert(0);
74                }
75        }
76
77        halfExtents*= btScalar(0.5);
78       
79        m_localAabbMin = -halfExtents - clampValue;
80        m_localAabbMax = halfExtents + clampValue;
81        btVector3 aabbSize = m_localAabbMax - m_localAabbMin;
82
83}
84
85
86btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
87{
88}
89
90
91
92void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
93{
94        btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
95        halfExtents += btVector3(getMargin(),getMargin(),getMargin());
96
97        btMatrix3x3 abs_b = t.getBasis().absolute(); 
98        btPoint3 center = t.getOrigin();
99        btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
100                   abs_b[1].dot(halfExtents),
101                  abs_b[2].dot(halfExtents));
102       
103
104        aabbMin = center - extent;
105        aabbMax = center + extent;
106
107
108}
109
110btScalar        btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
111{
112        btScalar val = 0.f;
113        if (m_useFloatData)
114        {
115                val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
116        } else
117        {
118                //assume unsigned short int
119                unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
120                val = heightFieldValue* (m_maxHeight/btScalar(65535));
121        }
122        return val;
123}
124
125
126
127
128
129void    btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
130{
131
132        btAssert(x>=0);
133        btAssert(y>=0);
134        btAssert(x<m_heightStickWidth);
135        btAssert(y<m_heightStickLength);
136
137
138        btScalar        height = getHeightFieldValue(x,y);
139
140        switch (m_upAxis)
141        {
142        case 0:
143                {
144                vertex.setValue(
145                        height,
146                        (-m_width/btScalar(2.0)) + x,
147                        (-m_length/btScalar(2.0) ) + y
148                        );
149                        break;
150                }
151        case 1:
152                {
153                        vertex.setValue(
154                        (-m_width/btScalar(2.0)) + x,
155                        height,
156                        (-m_length/btScalar(2.0)) + y
157                        );
158                        break;
159                };
160        case 2:
161                {
162                        vertex.setValue(
163                        (-m_width/btScalar(2.0)) + x,
164                        (-m_length/btScalar(2.0)) + y,
165                        height
166                        );
167                        break;
168                }
169        default:
170                {
171                        //need to get valid m_upAxis
172                        btAssert(0);
173                }
174        }
175
176        vertex*=m_localScaling;
177       
178}
179
180
181void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
182{
183        btVector3 clampedPoint(point);
184        clampedPoint.setMax(m_localAabbMin);
185        clampedPoint.setMin(m_localAabbMax);
186
187        btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
188
189        //TODO: optimization: check out how to removed this btFabs
190               
191        out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
192        out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
193        out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
194       
195}
196
197
198void    btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
199{
200        (void)callback;
201        (void)aabbMax;
202        (void)aabbMin;
203
204        //quantize the aabbMin and aabbMax, and adjust the start/end ranges
205
206        int     quantizedAabbMin[3];
207        int     quantizedAabbMax[3];
208
209        btVector3       localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
210        btVector3       localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
211       
212        quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
213        quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
214       
215       
216
217        int startX=0;
218        int endX=m_heightStickWidth-1;
219        int startJ=0;
220        int endJ=m_heightStickLength-1;
221
222        switch (m_upAxis)
223        {
224        case 0:
225                {
226                        quantizedAabbMin[1]+=m_heightStickWidth/2-1;
227                        quantizedAabbMax[1]+=m_heightStickWidth/2+1;
228                        quantizedAabbMin[2]+=m_heightStickLength/2-1;
229                        quantizedAabbMax[2]+=m_heightStickLength/2+1;
230
231                        if (quantizedAabbMin[1]>startX)
232                                startX = quantizedAabbMin[1];
233                        if (quantizedAabbMax[1]<endX)
234                                endX = quantizedAabbMax[1];
235                        if (quantizedAabbMin[2]>startJ)
236                                startJ = quantizedAabbMin[2];
237                        if (quantizedAabbMax[2]<endJ)
238                                endJ = quantizedAabbMax[2];
239                        break;
240                }
241        case 1:
242                {
243                        quantizedAabbMin[0]+=m_heightStickWidth/2-1;
244                        quantizedAabbMax[0]+=m_heightStickWidth/2+1;
245                        quantizedAabbMin[2]+=m_heightStickLength/2-1;
246                        quantizedAabbMax[2]+=m_heightStickLength/2+1;
247
248                        if (quantizedAabbMin[0]>startX)
249                                startX = quantizedAabbMin[0];
250                        if (quantizedAabbMax[0]<endX)
251                                endX = quantizedAabbMax[0];
252                        if (quantizedAabbMin[2]>startJ)
253                                startJ = quantizedAabbMin[2];
254                        if (quantizedAabbMax[2]<endJ)
255                                endJ = quantizedAabbMax[2];
256                        break;
257                };
258        case 2:
259                {
260                        quantizedAabbMin[0]+=m_heightStickWidth/2-1;
261                        quantizedAabbMax[0]+=m_heightStickWidth/2+1;
262                        quantizedAabbMin[1]+=m_heightStickLength/2-1;
263                        quantizedAabbMax[1]+=m_heightStickLength/2+1;
264
265                        if (quantizedAabbMin[0]>startX)
266                                startX = quantizedAabbMin[0];
267                        if (quantizedAabbMax[0]<endX)
268                                endX = quantizedAabbMax[0];
269                        if (quantizedAabbMin[1]>startJ)
270                                startJ = quantizedAabbMin[1];
271                        if (quantizedAabbMax[1]<endJ)
272                                endJ = quantizedAabbMax[1];
273                        break;
274                }
275        default:
276                {
277                        //need to get valid m_upAxis
278                        btAssert(0);
279                }
280        }
281
282       
283 
284
285        for(int j=startJ; j<endJ; j++)
286        {
287                for(int x=startX; x<endX; x++)
288                {
289                        btVector3 vertices[3];
290                        if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
291                        {
292        //first triangle
293        getVertex(x,j,vertices[0]);
294        getVertex(x+1,j,vertices[1]);
295        getVertex(x+1,j+1,vertices[2]);
296        callback->processTriangle(vertices,x,j);
297        //second triangle
298        getVertex(x,j,vertices[0]);
299        getVertex(x+1,j+1,vertices[1]);
300        getVertex(x,j+1,vertices[2]);
301        callback->processTriangle(vertices,x,j);                               
302                        } else
303                        {
304        //first triangle
305        getVertex(x,j,vertices[0]);
306        getVertex(x,j+1,vertices[1]);
307        getVertex(x+1,j,vertices[2]);
308        callback->processTriangle(vertices,x,j);
309        //second triangle
310        getVertex(x+1,j,vertices[0]);
311        getVertex(x,j+1,vertices[1]);
312        getVertex(x+1,j+1,vertices[2]);
313        callback->processTriangle(vertices,x,j);
314                        }
315                }
316        }
317
318       
319
320}
321
322void    btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
323{
324        //moving concave objects not supported
325       
326        inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
327}
328
329void    btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
330{
331        m_localScaling = scaling;
332}
333const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
334{
335        return m_localScaling;
336}
Note: See TracBrowser for help on using the repository browser.