Changeset 2430 for code/branches/physics/src/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
- Timestamp:
- Dec 13, 2008, 11:45:51 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/physics/src/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
r2192 r2430 19 19 20 20 21 22 btHeightfieldTerrainShape::btHeightfieldTerrainShape 23 ( 24 int heightStickWidth, int heightStickLength, void* heightfieldData, 25 btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis, 26 PHY_ScalarType hdt, bool flipQuadEdges 27 ) 28 { 29 initialize(heightStickWidth, heightStickLength, heightfieldData, 30 heightScale, minHeight, maxHeight, upAxis, hdt, 31 flipQuadEdges); 32 } 33 34 35 21 36 btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges) 22 : btConcaveShape (), m_heightStickWidth(heightStickWidth), 23 m_heightStickLength(heightStickLength), 24 m_maxHeight(maxHeight), 25 m_width((btScalar)heightStickWidth-1), 26 m_length((btScalar)heightStickLength-1), 27 m_heightfieldDataUnknown(heightfieldData), 28 m_useFloatData(useFloatData), 29 m_flipQuadEdges(flipQuadEdges), 30 m_useDiamondSubdivision(false), 31 m_upAxis(upAxis), 32 m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) 33 { 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.0; 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 54 void btHeightfieldTerrainShape::initialize 55 ( 56 int heightStickWidth, int heightStickLength, void* heightfieldData, 57 btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis, 58 PHY_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 && 68 "bad upAxis--should be in range [0,2]"); 69 btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT && 70 "Bad height data type enum"); 71 72 // initialize member variables 34 73 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 74 m_heightStickWidth = heightStickWidth; 75 m_heightStickLength = heightStickLength; 76 m_minHeight = minHeight; 77 m_maxHeight = maxHeight; 78 m_width = (btScalar) (heightStickWidth - 1); 79 m_length = (btScalar) (heightStickLength - 1); 80 m_heightScale = heightScale; 81 m_heightfieldDataUnknown = heightfieldData; 82 m_heightDataType = hdt; 83 m_flipQuadEdges = flipQuadEdges; 84 m_useDiamondSubdivision = false; 85 m_upAxis = upAxis; 86 m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.)); 87 88 // determine min/max axis-aligned bounding box (aabb) values 43 89 switch (m_upAxis) 44 90 { 45 91 case 0: 46 92 { 47 halfExtents.setValue( 48 btScalar(m_maxHeight), 49 btScalar(m_width), //?? don't know if this should change 50 btScalar(m_length)); 93 m_localAabbMin.setValue(m_minHeight, 0, 0); 94 m_localAabbMax.setValue(m_maxHeight, m_width, m_length); 51 95 break; 52 96 } 53 97 case 1: 54 98 { 55 halfExtents.setValue( 56 btScalar(m_width), 57 btScalar(m_maxHeight), 58 btScalar(m_length)); 99 m_localAabbMin.setValue(0, m_minHeight, 0); 100 m_localAabbMax.setValue(m_width, m_maxHeight, m_length); 59 101 break; 60 102 }; 61 103 case 2: 62 104 { 63 halfExtents.setValue( 64 btScalar(m_width), 65 btScalar(m_length), 66 btScalar(m_maxHeight) 67 ); 105 m_localAabbMin.setValue(0, 0, m_minHeight); 106 m_localAabbMax.setValue(m_width, m_length, m_maxHeight); 68 107 break; 69 108 } … … 71 110 { 72 111 //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 } 112 btAssert(0 && "Bad m_upAxis"); 113 } 114 } 115 116 // remember origin (defined as exact middle of aabb) 117 m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax); 118 } 119 84 120 85 121 … … 93 129 { 94 130 btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); 95 halfExtents += btVector3(getMargin(),getMargin(),getMargin()); 131 132 btVector3 localOrigin(0, 0, 0); 133 localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5); 134 localOrigin *= m_localScaling; 96 135 97 136 btMatrix3x3 abs_b = t.getBasis().absolute(); 98 bt Point3 center = t.getOrigin();137 btVector3 center = t.getOrigin(); 99 138 btVector3 extent = btVector3(abs_b[0].dot(halfExtents), 100 139 abs_b[1].dot(halfExtents), 101 140 abs_b[2].dot(halfExtents)); 102 141 extent += btVector3(getMargin(),getMargin(),getMargin()); 103 142 104 143 aabbMin = center - extent; 105 144 aabbMax = center + extent; 106 107 108 145 } 109 146 … … 111 148 { 112 149 btScalar val = 0.f; 113 if (m_useFloatData)150 switch (m_heightDataType) 114 151 { 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 } 152 case PHY_FLOAT: 153 { 154 val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x]; 155 break; 156 } 157 158 case PHY_UCHAR: 159 { 160 unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x]; 161 val = heightFieldValue * m_heightScale; 162 break; 163 } 164 165 case PHY_SHORT: 166 { 167 short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x]; 168 val = hfValue * m_heightScale; 169 break; 170 } 171 172 default: 173 { 174 btAssert(!"Bad m_heightDataType"); 175 } 176 } 177 122 178 return val; 123 179 } … … 179 235 180 236 237 238 static inline int 239 getQuantized 240 ( 241 float x 242 ) 243 { 244 if (x < 0.0) { 245 return (int) (x - 0.5); 246 } 247 return (int) (x + 0.5); 248 } 249 250 251 252 /// given input vector, return quantized version 253 /** 254 This routine is basically determining the gridpoint indices for a given 255 input vector, answering the question: "which gridpoint is closest to the 256 provided point?". 257 258 "with clamp" means that we restrict the point to be in the heightfield's 259 axis-aligned bounding box. 260 */ 181 261 void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const 182 262 { … … 185 265 clampedPoint.setMin(m_localAabbMax); 186 266 187 btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;188 189 //TODO: optimization: check out how to removed this btFabs267 out[0] = getQuantized(clampedPoint.getX()); 268 out[1] = getQuantized(clampedPoint.getY()); 269 out[2] = getQuantized(clampedPoint.getZ()); 190 270 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 271 } 272 273 274 275 /// process all triangles within the provided axis-aligned bounding box 276 /** 277 basic algorithm: 278 - convert input aabb to local coordinates (scale down and shift for local origin) 279 - convert input aabb to a range of heightfield grid points (quantize) 280 - iterate over all triangles in that subset of the grid 281 */ 198 282 void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const 199 283 { 200 (void)callback; 201 (void)aabbMax; 202 (void)aabbMin; 284 // scale down the input aabb's so they are in local (non-scaled) coordinates 285 btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]); 286 btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]); 287 288 // account for local origin 289 localAabbMin += m_localOrigin; 290 localAabbMax += m_localOrigin; 203 291 204 292 //quantize the aabbMin and aabbMax, and adjust the start/end ranges 205 206 293 int quantizedAabbMin[3]; 207 294 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 295 quantizeWithClamp(quantizedAabbMin, localAabbMin,0); 213 296 quantizeWithClamp(quantizedAabbMax, localAabbMax,1); 214 297 215 298 // expand the min/max quantized values 299 // this is to catch the case where the input aabb falls between grid points! 300 for (int i = 0; i < 3; ++i) { 301 quantizedAabbMin[i]--; 302 quantizedAabbMax[i]++; 303 } 216 304 217 305 int startX=0; … … 224 312 case 0: 225 313 { 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 314 if (quantizedAabbMin[1]>startX) 232 315 startX = quantizedAabbMin[1]; … … 241 324 case 1: 242 325 { 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 326 if (quantizedAabbMin[0]>startX) 249 327 startX = quantizedAabbMin[0]; … … 258 336 case 2: 259 337 { 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 338 if (quantizedAabbMin[0]>startX) 266 339 startX = quantizedAabbMin[0];
Note: See TracChangeset
for help on using the changeset viewer.