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, const 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,const 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.0f;
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, const 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_useZigzagSubdivision = false;
00086 m_upAxis = upAxis;
00087 m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
00088
00089
00090 switch (m_upAxis)
00091 {
00092 case 0:
00093 {
00094 m_localAabbMin.setValue(m_minHeight, 0, 0);
00095 m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
00096 break;
00097 }
00098 case 1:
00099 {
00100 m_localAabbMin.setValue(0, m_minHeight, 0);
00101 m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
00102 break;
00103 };
00104 case 2:
00105 {
00106 m_localAabbMin.setValue(0, 0, m_minHeight);
00107 m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
00108 break;
00109 }
00110 default:
00111 {
00112
00113 btAssert(0 && "Bad m_upAxis");
00114 }
00115 }
00116
00117
00118 m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
00119 }
00120
00121
00122
00123 btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
00124 {
00125 }
00126
00127
00128
00129 void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
00130 {
00131 btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
00132
00133 btVector3 localOrigin(0, 0, 0);
00134 localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
00135 localOrigin *= m_localScaling;
00136
00137 btMatrix3x3 abs_b = t.getBasis().absolute();
00138 btVector3 center = t.getOrigin();
00139 btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
00140 extent += btVector3(getMargin(),getMargin(),getMargin());
00141
00142 aabbMin = center - extent;
00143 aabbMax = center + extent;
00144 }
00145
00146
00150 btScalar
00151 btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
00152 {
00153 btScalar val = 0.f;
00154 switch (m_heightDataType)
00155 {
00156 case PHY_FLOAT:
00157 {
00158 val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
00159 break;
00160 }
00161
00162 case PHY_UCHAR:
00163 {
00164 unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
00165 val = heightFieldValue * m_heightScale;
00166 break;
00167 }
00168
00169 case PHY_SHORT:
00170 {
00171 short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
00172 val = hfValue * m_heightScale;
00173 break;
00174 }
00175
00176 default:
00177 {
00178 btAssert(!"Bad m_heightDataType");
00179 }
00180 }
00181
00182 return val;
00183 }
00184
00185
00186
00187
00189 void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
00190 {
00191 btAssert(x>=0);
00192 btAssert(y>=0);
00193 btAssert(x<m_heightStickWidth);
00194 btAssert(y<m_heightStickLength);
00195
00196 btScalar height = getRawHeightFieldValue(x,y);
00197
00198 switch (m_upAxis)
00199 {
00200 case 0:
00201 {
00202 vertex.setValue(
00203 height - m_localOrigin.getX(),
00204 (-m_width/btScalar(2.0)) + x,
00205 (-m_length/btScalar(2.0) ) + y
00206 );
00207 break;
00208 }
00209 case 1:
00210 {
00211 vertex.setValue(
00212 (-m_width/btScalar(2.0)) + x,
00213 height - m_localOrigin.getY(),
00214 (-m_length/btScalar(2.0)) + y
00215 );
00216 break;
00217 };
00218 case 2:
00219 {
00220 vertex.setValue(
00221 (-m_width/btScalar(2.0)) + x,
00222 (-m_length/btScalar(2.0)) + y,
00223 height - m_localOrigin.getZ()
00224 );
00225 break;
00226 }
00227 default:
00228 {
00229
00230 btAssert(0);
00231 }
00232 }
00233
00234 vertex*=m_localScaling;
00235 }
00236
00237
00238
00239 static inline int
00240 getQuantized
00241 (
00242 btScalar x
00243 )
00244 {
00245 if (x < 0.0) {
00246 return (int) (x - 0.5);
00247 }
00248 return (int) (x + 0.5);
00249 }
00250
00251
00252
00254
00262 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int ) const
00263 {
00264 btVector3 clampedPoint(point);
00265 clampedPoint.setMax(m_localAabbMin);
00266 clampedPoint.setMin(m_localAabbMax);
00267
00268 out[0] = getQuantized(clampedPoint.getX());
00269 out[1] = getQuantized(clampedPoint.getY());
00270 out[2] = getQuantized(clampedPoint.getZ());
00271
00272 }
00273
00274
00275
00277
00283 void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
00284 {
00285
00286 btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00287 btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
00288
00289
00290 localAabbMin += m_localOrigin;
00291 localAabbMax += m_localOrigin;
00292
00293
00294 int quantizedAabbMin[3];
00295 int quantizedAabbMax[3];
00296 quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
00297 quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
00298
00299
00300
00301 for (int i = 0; i < 3; ++i) {
00302 quantizedAabbMin[i]--;
00303 quantizedAabbMax[i]++;
00304 }
00305
00306 int startX=0;
00307 int endX=m_heightStickWidth-1;
00308 int startJ=0;
00309 int endJ=m_heightStickLength-1;
00310
00311 switch (m_upAxis)
00312 {
00313 case 0:
00314 {
00315 if (quantizedAabbMin[1]>startX)
00316 startX = quantizedAabbMin[1];
00317 if (quantizedAabbMax[1]<endX)
00318 endX = quantizedAabbMax[1];
00319 if (quantizedAabbMin[2]>startJ)
00320 startJ = quantizedAabbMin[2];
00321 if (quantizedAabbMax[2]<endJ)
00322 endJ = quantizedAabbMax[2];
00323 break;
00324 }
00325 case 1:
00326 {
00327 if (quantizedAabbMin[0]>startX)
00328 startX = quantizedAabbMin[0];
00329 if (quantizedAabbMax[0]<endX)
00330 endX = quantizedAabbMax[0];
00331 if (quantizedAabbMin[2]>startJ)
00332 startJ = quantizedAabbMin[2];
00333 if (quantizedAabbMax[2]<endJ)
00334 endJ = quantizedAabbMax[2];
00335 break;
00336 };
00337 case 2:
00338 {
00339 if (quantizedAabbMin[0]>startX)
00340 startX = quantizedAabbMin[0];
00341 if (quantizedAabbMax[0]<endX)
00342 endX = quantizedAabbMax[0];
00343 if (quantizedAabbMin[1]>startJ)
00344 startJ = quantizedAabbMin[1];
00345 if (quantizedAabbMax[1]<endJ)
00346 endJ = quantizedAabbMax[1];
00347 break;
00348 }
00349 default:
00350 {
00351
00352 btAssert(0);
00353 }
00354 }
00355
00356
00357
00358
00359 for(int j=startJ; j<endJ; j++)
00360 {
00361 for(int x=startX; x<endX; x++)
00362 {
00363 btVector3 vertices[3];
00364 if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1))|| (m_useZigzagSubdivision && !(j & 1)))
00365 {
00366
00367 getVertex(x,j,vertices[0]);
00368 getVertex(x+1,j,vertices[1]);
00369 getVertex(x+1,j+1,vertices[2]);
00370 callback->processTriangle(vertices,x,j);
00371
00372 getVertex(x,j,vertices[0]);
00373 getVertex(x+1,j+1,vertices[1]);
00374 getVertex(x,j+1,vertices[2]);
00375 callback->processTriangle(vertices,x,j);
00376 } else
00377 {
00378
00379 getVertex(x,j,vertices[0]);
00380 getVertex(x,j+1,vertices[1]);
00381 getVertex(x+1,j,vertices[2]);
00382 callback->processTriangle(vertices,x,j);
00383
00384 getVertex(x+1,j,vertices[0]);
00385 getVertex(x,j+1,vertices[1]);
00386 getVertex(x+1,j+1,vertices[2]);
00387 callback->processTriangle(vertices,x,j);
00388 }
00389 }
00390 }
00391
00392
00393
00394 }
00395
00396 void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
00397 {
00398
00399
00400 inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
00401 }
00402
00403 void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
00404 {
00405 m_localScaling = scaling;
00406 }
00407 const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
00408 {
00409 return m_localScaling;
00410 }