00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "btHeightfieldTerrainShape.h"
00017
00018 #include "LinearMath/btTransformUtil.h"
00019
00020
00021
00022 btHeightfieldTerrainShape::btHeightfieldTerrainShape
00023 (
00024 int heightStickWidth, int heightStickLength, void* heightfieldData,
00025 btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
00026 PHY_ScalarType hdt, bool flipQuadEdges
00027 )
00028 {
00029 initialize(heightStickWidth, heightStickLength, heightfieldData,
00030 heightScale, minHeight, maxHeight, upAxis, hdt,
00031 flipQuadEdges);
00032 }
00033
00034
00035
00036 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
00037 {
00038
00039
00040 PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
00041 btScalar minHeight = 0.0;
00042
00043
00044
00045 btScalar heightScale = maxHeight / 65535;
00046
00047 initialize(heightStickWidth, heightStickLength, heightfieldData,
00048 heightScale, minHeight, maxHeight, upAxis, hdt,
00049 flipQuadEdges);
00050 }
00051
00052
00053
00054 void btHeightfieldTerrainShape::initialize
00055 (
00056 int heightStickWidth, int heightStickLength, void* heightfieldData,
00057 btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
00058 PHY_ScalarType hdt, bool flipQuadEdges
00059 )
00060 {
00061
00062 btAssert(heightStickWidth > 1 && "bad width");
00063 btAssert(heightStickLength > 1 && "bad length");
00064 btAssert(heightfieldData && "null heightfield data");
00065
00066 btAssert(minHeight <= maxHeight && "bad min/max height");
00067 btAssert(upAxis >= 0 && upAxis < 3 &&
00068 "bad upAxis--should be in range [0,2]");
00069 btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
00070 "Bad height data type enum");
00071
00072
00073 m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
00074 m_heightStickWidth = heightStickWidth;
00075 m_heightStickLength = heightStickLength;
00076 m_minHeight = minHeight;
00077 m_maxHeight = maxHeight;
00078 m_width = (btScalar) (heightStickWidth - 1);
00079 m_length = (btScalar) (heightStickLength - 1);
00080 m_heightScale = heightScale;
00081 m_heightfieldDataUnknown = heightfieldData;
00082 m_heightDataType = hdt;
00083 m_flipQuadEdges = flipQuadEdges;
00084 m_useDiamondSubdivision = false;
00085 m_upAxis = upAxis;
00086 m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
00087
00088
00089 switch (m_upAxis)
00090 {
00091 case 0:
00092 {
00093 m_localAabbMin.setValue(m_minHeight, 0, 0);
00094 m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
00095 break;
00096 }
00097 case 1:
00098 {
00099 m_localAabbMin.setValue(0, m_minHeight, 0);
00100 m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
00101 break;
00102 };
00103 case 2:
00104 {
00105 m_localAabbMin.setValue(0, 0, m_minHeight);
00106 m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
00107 break;
00108 }
00109 default:
00110 {
00111
00112 btAssert(0 && "Bad m_upAxis");
00113 }
00114 }
00115
00116
00117 m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
00118 }
00119
00120
00121
00122 btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
00123 {
00124 }
00125
00126
00127
00128 void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
00129 {
00130 btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
00131
00132 btVector3 localOrigin(0, 0, 0);
00133 localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
00134 localOrigin *= m_localScaling;
00135
00136 btMatrix3x3 abs_b = t.getBasis().absolute();
00137 btVector3 center = t.getOrigin();
00138 btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
00139 abs_b[1].dot(halfExtents),
00140 abs_b[2].dot(halfExtents));
00141 extent += btVector3(getMargin(),getMargin(),getMargin());
00142
00143 aabbMin = center - extent;
00144 aabbMax = center + extent;
00145 }
00146
00147
00151 btScalar
00152 btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
00153 {
00154 btScalar val = 0.f;
00155 switch (m_heightDataType)
00156 {
00157 case PHY_FLOAT:
00158 {
00159 val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
00160 break;
00161 }
00162
00163 case PHY_UCHAR:
00164 {
00165 unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
00166 val = heightFieldValue * m_heightScale;
00167 break;
00168 }
00169
00170 case PHY_SHORT:
00171 {
00172 short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
00173 val = hfValue * m_heightScale;
00174 break;
00175 }
00176
00177 default:
00178 {
00179 btAssert(!"Bad m_heightDataType");
00180 }
00181 }
00182
00183 return val;
00184 }
00185
00186
00187
00188
00190 void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
00191 {
00192 btAssert(x>=0);
00193 btAssert(y>=0);
00194 btAssert(x<m_heightStickWidth);
00195 btAssert(y<m_heightStickLength);
00196
00197 btScalar height = getRawHeightFieldValue(x,y);
00198
00199 switch (m_upAxis)
00200 {
00201 case 0:
00202 {
00203 vertex.setValue(
00204 height - m_localOrigin.getX(),
00205 (-m_width/btScalar(2.0)) + x,
00206 (-m_length/btScalar(2.0) ) + y
00207 );
00208 break;
00209 }
00210 case 1:
00211 {
00212 vertex.setValue(
00213 (-m_width/btScalar(2.0)) + x,
00214 height - m_localOrigin.getY(),
00215 (-m_length/btScalar(2.0)) + y
00216 );
00217 break;
00218 };
00219 case 2:
00220 {
00221 vertex.setValue(
00222 (-m_width/btScalar(2.0)) + x,
00223 (-m_length/btScalar(2.0)) + y,
00224 height - m_localOrigin.getZ()
00225 );
00226 break;
00227 }
00228 default:
00229 {
00230
00231 btAssert(0);
00232 }
00233 }
00234
00235 vertex*=m_localScaling;
00236 }
00237
00238
00239
00240 static inline int
00241 getQuantized
00242 (
00243 btScalar x
00244 )
00245 {
00246 if (x < 0.0) {
00247 return (int) (x - 0.5);
00248 }
00249 return (int) (x + 0.5);
00250 }
00251
00252
00253
00255
00263 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int ) const
00264 {
00265 btVector3 clampedPoint(point);
00266 clampedPoint.setMax(m_localAabbMin);
00267 clampedPoint.setMin(m_localAabbMax);
00268
00269 out[0] = getQuantized(clampedPoint.getX());
00270 out[1] = getQuantized(clampedPoint.getY());
00271 out[2] = getQuantized(clampedPoint.getZ());
00272
00273 }
00274
00275
00276
00278
00284 void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00285 {
00286
00287 btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00288 btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00289
00290
00291 localAabbMin += m_localOrigin;
00292 localAabbMax += m_localOrigin;
00293
00294
00295 int quantizedAabbMin[3];
00296 int quantizedAabbMax[3];
00297 quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
00298 quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
00299
00300
00301
00302 for (int i = 0; i < 3; ++i) {
00303 quantizedAabbMin[i]--;
00304 quantizedAabbMax[i]++;
00305 }
00306
00307 int startX=0;
00308 int endX=m_heightStickWidth-1;
00309 int startJ=0;
00310 int endJ=m_heightStickLength-1;
00311
00312 switch (m_upAxis)
00313 {
00314 case 0:
00315 {
00316 if (quantizedAabbMin[1]>startX)
00317 startX = quantizedAabbMin[1];
00318 if (quantizedAabbMax[1]<endX)
00319 endX = quantizedAabbMax[1];
00320 if (quantizedAabbMin[2]>startJ)
00321 startJ = quantizedAabbMin[2];
00322 if (quantizedAabbMax[2]<endJ)
00323 endJ = quantizedAabbMax[2];
00324 break;
00325 }
00326 case 1:
00327 {
00328 if (quantizedAabbMin[0]>startX)
00329 startX = quantizedAabbMin[0];
00330 if (quantizedAabbMax[0]<endX)
00331 endX = quantizedAabbMax[0];
00332 if (quantizedAabbMin[2]>startJ)
00333 startJ = quantizedAabbMin[2];
00334 if (quantizedAabbMax[2]<endJ)
00335 endJ = quantizedAabbMax[2];
00336 break;
00337 };
00338 case 2:
00339 {
00340 if (quantizedAabbMin[0]>startX)
00341 startX = quantizedAabbMin[0];
00342 if (quantizedAabbMax[0]<endX)
00343 endX = quantizedAabbMax[0];
00344 if (quantizedAabbMin[1]>startJ)
00345 startJ = quantizedAabbMin[1];
00346 if (quantizedAabbMax[1]<endJ)
00347 endJ = quantizedAabbMax[1];
00348 break;
00349 }
00350 default:
00351 {
00352
00353 btAssert(0);
00354 }
00355 }
00356
00357
00358
00359
00360 for(int j=startJ; j<endJ; j++)
00361 {
00362 for(int x=startX; x<endX; x++)
00363 {
00364 btVector3 vertices[3];
00365 if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
00366 {
00367
00368 getVertex(x,j,vertices[0]);
00369 getVertex(x+1,j,vertices[1]);
00370 getVertex(x+1,j+1,vertices[2]);
00371 callback->processTriangle(vertices,x,j);
00372
00373 getVertex(x,j,vertices[0]);
00374 getVertex(x+1,j+1,vertices[1]);
00375 getVertex(x,j+1,vertices[2]);
00376 callback->processTriangle(vertices,x,j);
00377 } else
00378 {
00379
00380 getVertex(x,j,vertices[0]);
00381 getVertex(x,j+1,vertices[1]);
00382 getVertex(x+1,j,vertices[2]);
00383 callback->processTriangle(vertices,x,j);
00384
00385 getVertex(x+1,j,vertices[0]);
00386 getVertex(x,j+1,vertices[1]);
00387 getVertex(x+1,j+1,vertices[2]);
00388 callback->processTriangle(vertices,x,j);
00389 }
00390 }
00391 }
00392
00393
00394
00395 }
00396
00397 void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
00398 {
00399
00400
00401 inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00402 }
00403
00404 void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
00405 {
00406 m_localScaling = scaling;
00407 }
00408 const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
00409 {
00410 return m_localScaling;
00411 }