Back to index

supertuxkart  0.5+dfsg1
btHeightfieldTerrainShape.cpp
Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "btHeightfieldTerrainShape.h"
00017 
00018 #include "LinearMath/btTransformUtil.h"
00019 
00020 
00021 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
00022 : m_heightStickWidth(heightStickWidth),
00023 m_heightStickLength(heightStickLength),
00024 m_width((btScalar)heightStickWidth-1),
00025 m_length((btScalar)heightStickLength-1),
00026 m_maxHeight(maxHeight),
00027 m_heightfieldDataUnknown(heightfieldData),
00028 m_useFloatData(useFloatData),
00029 m_flipQuadEdges(flipQuadEdges),
00030 m_useDiamondSubdivision(false),
00031 m_upAxis(upAxis),
00032 m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
00033 {
00034 
00035 
00036        btScalar      quantizationMargin = 1.f;
00037 
00038        //enlarge the AABB to avoid division by zero when initializing the quantization values
00039        btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
00040 
00041        btVector3     halfExtents(0,0,0);
00042 
00043        switch (m_upAxis)
00044        {
00045        case 0:
00046               {
00047                      halfExtents.setValue(
00048                             btScalar(m_maxHeight),
00049                             btScalar(m_width), //?? don't know if this should change
00050                             btScalar(m_length));
00051                      break;
00052               }
00053        case 1:
00054               {
00055                      halfExtents.setValue(
00056                             btScalar(m_width),
00057                             btScalar(m_maxHeight),
00058                             btScalar(m_length));
00059                      break;
00060               };
00061        case 2:
00062               {
00063                      halfExtents.setValue(
00064                             btScalar(m_width),
00065                             btScalar(m_length),
00066                             btScalar(m_maxHeight)
00067                      );
00068                      break;
00069               }
00070        default:
00071               {
00072                      //need to get valid m_upAxis
00073                      btAssert(0);
00074               }
00075        }
00076 
00077        halfExtents*= btScalar(0.5);
00078        
00079        m_localAabbMin = -halfExtents - clampValue;
00080        m_localAabbMax = halfExtents + clampValue;
00081        btVector3 aabbSize = m_localAabbMax - m_localAabbMin;
00082 
00083 }
00084 
00085 
00086 btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
00087 {
00088 }
00089 
00090 
00091 
00092 void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
00093 {
00094 /*
00095        aabbMin.setValue(-1e30f,-1e30f,-1e30f);
00096        aabbMax.setValue(1e30f,1e30f,1e30f);
00097 */
00098 
00099        btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
00100 
00101        btMatrix3x3 abs_b = t.getBasis().absolute();  
00102        btPoint3 center = t.getOrigin();
00103        btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
00104                  abs_b[1].dot(halfExtents),
00105                 abs_b[2].dot(halfExtents));
00106        extent += btVector3(getMargin(),getMargin(),getMargin());
00107 
00108        aabbMin = center - extent;
00109        aabbMax = center + extent;
00110 
00111 
00112 }
00113 
00114 btScalar      btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
00115 {
00116        btScalar val = 0.f;
00117        if (m_useFloatData)
00118        {
00119               val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
00120        } else
00121        {
00122               //assume unsigned short int
00123               unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
00124               val = heightFieldValue* (m_maxHeight/btScalar(65535));
00125        }
00126        return val;
00127 }
00128 
00129 
00130 
00131 
00132 
00133 void   btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
00134 {
00135 
00136        btAssert(x>=0);
00137        btAssert(y>=0);
00138        btAssert(x<m_heightStickWidth);
00139        btAssert(y<m_heightStickLength);
00140 
00141 
00142        btScalar      height = getHeightFieldValue(x,y);
00143 
00144        switch (m_upAxis)
00145        {
00146        case 0:
00147               {
00148               vertex.setValue(
00149                      height,
00150                      (-m_width/btScalar(2.0)) + x,
00151                      (-m_length/btScalar(2.0) ) + y
00152                      );
00153                      break;
00154               }
00155        case 1:
00156               {
00157                      vertex.setValue(
00158                      (-m_width/btScalar(2.0)) + x,
00159                      height,
00160                      (-m_length/btScalar(2.0)) + y
00161                      );
00162                      break;
00163               };
00164        case 2:
00165               {
00166                      vertex.setValue(
00167                      (-m_width/btScalar(2.0)) + x,
00168                      (-m_length/btScalar(2.0)) + y,
00169                      height
00170                      );
00171                      break;
00172               }
00173        default:
00174               {
00175                      //need to get valid m_upAxis
00176                      btAssert(0);
00177               }
00178        }
00179 
00180        vertex*=m_localScaling;
00181        
00182 }
00183 
00184 
00185 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int isMax) const
00186 {
00187        btVector3 clampedPoint(point);
00188        clampedPoint.setMax(m_localAabbMin);
00189        clampedPoint.setMin(m_localAabbMax);
00190 
00191        btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
00192 
00193        //TODO: optimization: check out how to removed this btFabs
00194               
00195        out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
00196        out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
00197        out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
00198        
00199 }
00200 
00201 
00202 void   btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00203 {
00204        (void)callback;
00205        (void)aabbMax;
00206        (void)aabbMin;
00207 
00208        //quantize the aabbMin and aabbMax, and adjust the start/end ranges
00209 
00210        int    quantizedAabbMin[3];
00211        int    quantizedAabbMax[3];
00212 
00213        btVector3     localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00214        btVector3     localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00215        
00216        quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
00217        quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
00218        
00219        
00220 
00221        int startX=0;
00222        int endX=m_heightStickWidth-1;
00223        int startJ=0;
00224        int endJ=m_heightStickLength-1;
00225 
00226        switch (m_upAxis)
00227        {
00228        case 0:
00229               {
00230                      quantizedAabbMin[1]+=m_heightStickWidth/2-1;
00231                      quantizedAabbMax[1]+=m_heightStickWidth/2+1;
00232                      quantizedAabbMin[2]+=m_heightStickLength/2-1;
00233                      quantizedAabbMax[2]+=m_heightStickLength/2+1;
00234 
00235                      if (quantizedAabbMin[1]>startX)
00236                             startX = quantizedAabbMin[1];
00237                      if (quantizedAabbMax[1]<endX)
00238                             endX = quantizedAabbMax[1];
00239                      if (quantizedAabbMin[2]>startJ)
00240                             startJ = quantizedAabbMin[2];
00241                      if (quantizedAabbMax[2]<endJ)
00242                             endJ = quantizedAabbMax[2];
00243                      break;
00244               }
00245        case 1:
00246               {
00247                      quantizedAabbMin[0]+=m_heightStickWidth/2-1;
00248                      quantizedAabbMax[0]+=m_heightStickWidth/2+1;
00249                      quantizedAabbMin[2]+=m_heightStickLength/2-1;
00250                      quantizedAabbMax[2]+=m_heightStickLength/2+1;
00251 
00252                      if (quantizedAabbMin[0]>startX)
00253                             startX = quantizedAabbMin[0];
00254                      if (quantizedAabbMax[0]<endX)
00255                             endX = quantizedAabbMax[0];
00256                      if (quantizedAabbMin[2]>startJ)
00257                             startJ = quantizedAabbMin[2];
00258                      if (quantizedAabbMax[2]<endJ)
00259                             endJ = quantizedAabbMax[2];
00260                      break;
00261               };
00262        case 2:
00263               {
00264                      quantizedAabbMin[0]+=m_heightStickWidth/2-1;
00265                      quantizedAabbMax[0]+=m_heightStickWidth/2+1;
00266                      quantizedAabbMin[1]+=m_heightStickLength/2-1;
00267                      quantizedAabbMax[1]+=m_heightStickLength/2+1;
00268 
00269                      if (quantizedAabbMin[0]>startX)
00270                             startX = quantizedAabbMin[0];
00271                      if (quantizedAabbMax[0]<endX)
00272                             endX = quantizedAabbMax[0];
00273                      if (quantizedAabbMin[1]>startJ)
00274                             startJ = quantizedAabbMin[1];
00275                      if (quantizedAabbMax[1]<endJ)
00276                             endJ = quantizedAabbMax[1];
00277                      break;
00278               }
00279        default:
00280               {
00281                      //need to get valid m_upAxis
00282                      btAssert(0);
00283               }
00284        }
00285 
00286        
00287   
00288 
00289        for(int j=startJ; j<endJ; j++)
00290        {
00291               for(int x=startX; x<endX; x++)
00292               {
00293                      btVector3 vertices[3];
00294                      if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
00295                      {
00296         //first triangle
00297         getVertex(x,j,vertices[0]);
00298         getVertex(x+1,j,vertices[1]);
00299         getVertex(x+1,j+1,vertices[2]);
00300         callback->processTriangle(vertices,x,j);
00301         //second triangle
00302         getVertex(x,j,vertices[0]);
00303         getVertex(x+1,j+1,vertices[1]);
00304         getVertex(x,j+1,vertices[2]);
00305         callback->processTriangle(vertices,x,j);                      
00306                      } else
00307                      {
00308         //first triangle
00309         getVertex(x,j,vertices[0]);
00310         getVertex(x,j+1,vertices[1]);
00311         getVertex(x+1,j,vertices[2]);
00312         callback->processTriangle(vertices,x,j);
00313         //second triangle
00314         getVertex(x+1,j,vertices[0]);
00315         getVertex(x,j+1,vertices[1]);
00316         getVertex(x+1,j+1,vertices[2]);
00317         callback->processTriangle(vertices,x,j);
00318                      }
00319               }
00320        }
00321 
00322        
00323 
00324 }
00325 
00326 void   btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
00327 {
00328        //moving concave objects not supported
00329        
00330        inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00331 }
00332 
00333 void   btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
00334 {
00335        m_localScaling = scaling;
00336 }
00337 const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
00338 {
00339        return m_localScaling;
00340 }