1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 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. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 16 17 #include "btOptimizedBvh.h" 18 #include "btStridingMeshInterface.h" 19 #include "LinearMath/btAabbUtil2.h" 20 #include "LinearMath/btIDebugDraw.h" 21 22 23 btOptimizedBvh::btOptimizedBvh() 24 { 25 } 26 27 btOptimizedBvh::~btOptimizedBvh() 28 { 29 } 30 31 32 void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax) 33 { 34 m_useQuantization = useQuantizedAabbCompression; 35 36 37 // NodeArray triangleNodes; 38 39 struct NodeTriangleCallback : public btInternalTriangleIndexCallback 40 { 41 42 NodeArray& m_triangleNodes; 43 44 NodeTriangleCallback& operator=(NodeTriangleCallback& other) 45 { 46 m_triangleNodes.copyFromArray(other.m_triangleNodes); 47 return *this; 48 } 49 50 NodeTriangleCallback(NodeArray& triangleNodes) 51 :m_triangleNodes(triangleNodes) 52 { 53 } 54 55 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) 56 { 57 btOptimizedBvhNode node; 58 btVector3 aabbMin,aabbMax; 59 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 60 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 61 aabbMin.setMin(triangle[0]); 62 aabbMax.setMax(triangle[0]); 63 aabbMin.setMin(triangle[1]); 64 aabbMax.setMax(triangle[1]); 65 aabbMin.setMin(triangle[2]); 66 aabbMax.setMax(triangle[2]); 67 68 //with quantization? 69 node.m_aabbMinOrg = aabbMin; 70 node.m_aabbMaxOrg = aabbMax; 71 72 node.m_escapeIndex = -1; 73 74 //for child nodes 75 node.m_subPart = partId; 76 node.m_triangleIndex = triangleIndex; 77 m_triangleNodes.push_back(node); 78 } 79 }; 80 struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback 81 { 82 QuantizedNodeArray& m_triangleNodes; 83 const btQuantizedBvh* m_optimizedTree; // for quantization 84 85 QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) 86 { 87 m_triangleNodes.copyFromArray(other.m_triangleNodes); 88 m_optimizedTree = other.m_optimizedTree; 89 return *this; 90 } 91 92 QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) 93 :m_triangleNodes(triangleNodes),m_optimizedTree(tree) 94 { 95 } 96 97 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) 98 { 99 // The partId and triangle index must fit in the same (positive) integer 100 btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS)); 101 btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS))); 102 //negative indices are reserved for escapeIndex 103 btAssert(triangleIndex>=0); 104 105 btQuantizedBvhNode node; 106 btVector3 aabbMin,aabbMax; 107 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 108 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 109 aabbMin.setMin(triangle[0]); 110 aabbMax.setMax(triangle[0]); 111 aabbMin.setMin(triangle[1]); 112 aabbMax.setMax(triangle[1]); 113 aabbMin.setMin(triangle[2]); 114 aabbMax.setMax(triangle[2]); 115 116 //PCK: add these checks for zero dimensions of aabb 117 const btScalar MIN_AABB_DIMENSION = btScalar(0.002); 118 const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); 119 if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) 120 { 121 aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); 122 aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); 123 } 124 if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) 125 { 126 aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); 127 aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); 128 } 129 if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) 130 { 131 aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); 132 aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); 133 } 134 135 m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); 136 m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); 137 138 node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; 139 140 m_triangleNodes.push_back(node); 141 } 142 }; 143 144 145 146 int numLeafNodes = 0; 147 148 149 if (m_useQuantization) 150 { 151 152 //initialize quantization values 153 setQuantizationValues(bvhAabbMin,bvhAabbMax); 154 155 QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this); 156 157 158 triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax); 159 160 //now we have an array of leafnodes in m_leafNodes 161 numLeafNodes = m_quantizedLeafNodes.size(); 162 163 164 m_quantizedContiguousNodes.resize(2*numLeafNodes); 165 166 167 } else 168 { 169 NodeTriangleCallback callback(m_leafNodes); 170 171 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 172 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 173 174 triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax); 175 176 //now we have an array of leafnodes in m_leafNodes 177 numLeafNodes = m_leafNodes.size(); 178 179 m_contiguousNodes.resize(2*numLeafNodes); 180 } 181 182 m_curNodeIndex = 0; 183 184 buildTree(0,numLeafNodes); 185 186 ///if the entire tree is small then subtree size, we need to create a header info for the tree 187 if(m_useQuantization && !m_SubtreeHeaders.size()) 188 { 189 btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); 190 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); 191 subtree.m_rootNodeIndex = 0; 192 subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); 193 } 194 195 //PCK: update the copy of the size 196 m_subtreeHeaderCount = m_SubtreeHeaders.size(); 197 198 //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary 199 m_quantizedLeafNodes.clear(); 200 m_leafNodes.clear(); 201 } 202 203 204 205 206 void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) 207 { 208 if (m_useQuantization) 209 { 210 211 setQuantizationValues(aabbMin,aabbMax); 212 213 updateBvhNodes(meshInterface,0,m_curNodeIndex,0); 214 215 ///now update all subtree headers 216 217 int i; 218 for (i=0;i<m_SubtreeHeaders.size();i++) 219 { 220 btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; 221 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); 222 } 223 224 } else 225 { 226 227 } 228 } 229 230 231 232 233 void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) 234 { 235 //incrementally initialize quantization values 236 btAssert(m_useQuantization); 237 238 btAssert(aabbMin.getX() > m_bvhAabbMin.getX()); 239 btAssert(aabbMin.getY() > m_bvhAabbMin.getY()); 240 btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ()); 241 242 btAssert(aabbMax.getX() < m_bvhAabbMax.getX()); 243 btAssert(aabbMax.getY() < m_bvhAabbMax.getY()); 244 btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ()); 245 246 ///we should update all quantization values, using updateBvhNodes(meshInterface); 247 ///but we only update chunks that overlap the given aabb 248 249 unsigned short quantizedQueryAabbMin[3]; 250 unsigned short quantizedQueryAabbMax[3]; 251 252 quantize(&quantizedQueryAabbMin[0],aabbMin,0); 253 quantize(&quantizedQueryAabbMax[0],aabbMax,1); 254 255 int i; 256 for (i=0;i<this->m_SubtreeHeaders.size();i++) 257 { 258 btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; 259 260 //PCK: unsigned instead of bool 261 unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); 262 if (overlap != 0) 263 { 264 updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); 265 266 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); 267 } 268 } 269 270 } 271 272 void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) 273 { 274 (void)index; 275 276 btAssert(m_useQuantization); 277 278 int curNodeSubPart=-1; 279 280 //get access info to trianglemesh data 281 const unsigned char *vertexbase = 0; 282 int numverts = 0; 283 PHY_ScalarType type = PHY_INTEGER; 284 int stride = 0; 285 const unsigned char *indexbase = 0; 286 int indexstride = 0; 287 int numfaces = 0; 288 PHY_ScalarType indicestype = PHY_INTEGER; 289 290 btVector3 triangleVerts[3]; 291 btVector3 aabbMin,aabbMax; 292 const btVector3& meshScaling = meshInterface->getScaling(); 293 294 int i; 295 for (i=endNode-1;i>=firstNode;i--) 296 { 297 298 299 btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i]; 300 if (curNode.isLeafNode()) 301 { 302 //recalc aabb from triangle data 303 int nodeSubPart = curNode.getPartId(); 304 int nodeTriangleIndex = curNode.getTriangleIndex(); 305 if (nodeSubPart != curNodeSubPart) 306 { 307 if (curNodeSubPart >= 0) 308 meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); 309 meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); 310 311 curNodeSubPart = nodeSubPart; 312 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); 313 } 314 //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, 315 316 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); 317 318 319 for (int j=2;j>=0;j--) 320 { 321 322 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; 323 if (type == PHY_FLOAT) 324 { 325 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride); 326 triangleVerts[j] = btVector3( 327 graphicsbase[0]*meshScaling.getX(), 328 graphicsbase[1]*meshScaling.getY(), 329 graphicsbase[2]*meshScaling.getZ()); 330 } 331 else 332 { 333 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride); 334 triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ())); 335 } 336 } 337 338 339 340 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)); 341 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 342 aabbMin.setMin(triangleVerts[0]); 343 aabbMax.setMax(triangleVerts[0]); 344 aabbMin.setMin(triangleVerts[1]); 345 aabbMax.setMax(triangleVerts[1]); 346 aabbMin.setMin(triangleVerts[2]); 347 aabbMax.setMax(triangleVerts[2]); 348 349 quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); 350 quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); 351 352 } else 353 { 354 //combine aabb from both children 355 356 btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1]; 357 358 btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] : 359 &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()]; 360 361 362 { 363 for (int i=0;i<3;i++) 364 { 365 curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i]; 366 if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i]) 367 curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i]; 368 369 curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i]; 370 if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i]) 371 curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i]; 372 } 373 } 374 } 375 376 } 377 378 if (curNodeSubPart >= 0) 379 meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); 380 381 382 } 383 384 ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' 385 btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) 386 { 387 btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); 388 389 //we don't add additional data so just do a static upcast 390 return static_cast<btOptimizedBvh*>(bvh); 391 } 392