00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btOptimizedBvh.h"
00018 #include "btStridingMeshInterface.h"
00019 #include "LinearMath/btAabbUtil2.h"
00020 #include "LinearMath/btIDebugDraw.h"
00021
00022
00023 btOptimizedBvh::btOptimizedBvh()
00024 {
00025 }
00026
00027 btOptimizedBvh::~btOptimizedBvh()
00028 {
00029 }
00030
00031
00032 void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
00033 {
00034 m_useQuantization = useQuantizedAabbCompression;
00035
00036
00037
00038
00039 struct NodeTriangleCallback : public btInternalTriangleIndexCallback
00040 {
00041
00042 NodeArray& m_triangleNodes;
00043
00044 NodeTriangleCallback& operator=(NodeTriangleCallback& other)
00045 {
00046 m_triangleNodes.copyFromArray(other.m_triangleNodes);
00047 return *this;
00048 }
00049
00050 NodeTriangleCallback(NodeArray& triangleNodes)
00051 :m_triangleNodes(triangleNodes)
00052 {
00053 }
00054
00055 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
00056 {
00057 btOptimizedBvhNode node;
00058 btVector3 aabbMin,aabbMax;
00059 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00060 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00061 aabbMin.setMin(triangle[0]);
00062 aabbMax.setMax(triangle[0]);
00063 aabbMin.setMin(triangle[1]);
00064 aabbMax.setMax(triangle[1]);
00065 aabbMin.setMin(triangle[2]);
00066 aabbMax.setMax(triangle[2]);
00067
00068
00069 node.m_aabbMinOrg = aabbMin;
00070 node.m_aabbMaxOrg = aabbMax;
00071
00072 node.m_escapeIndex = -1;
00073
00074
00075 node.m_subPart = partId;
00076 node.m_triangleIndex = triangleIndex;
00077 m_triangleNodes.push_back(node);
00078 }
00079 };
00080 struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
00081 {
00082 QuantizedNodeArray& m_triangleNodes;
00083 const btQuantizedBvh* m_optimizedTree;
00084
00085 QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
00086 {
00087 m_triangleNodes.copyFromArray(other.m_triangleNodes);
00088 m_optimizedTree = other.m_optimizedTree;
00089 return *this;
00090 }
00091
00092 QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree)
00093 :m_triangleNodes(triangleNodes),m_optimizedTree(tree)
00094 {
00095 }
00096
00097 virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
00098 {
00099
00100 btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
00101 btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
00102
00103 btAssert(triangleIndex>=0);
00104
00105 btQuantizedBvhNode node;
00106 btVector3 aabbMin,aabbMax;
00107 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00108 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00109 aabbMin.setMin(triangle[0]);
00110 aabbMax.setMax(triangle[0]);
00111 aabbMin.setMin(triangle[1]);
00112 aabbMax.setMax(triangle[1]);
00113 aabbMin.setMin(triangle[2]);
00114 aabbMax.setMax(triangle[2]);
00115
00116
00117 const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
00118 const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
00119 if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
00120 {
00121 aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
00122 aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
00123 }
00124 if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
00125 {
00126 aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
00127 aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
00128 }
00129 if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
00130 {
00131 aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
00132 aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
00133 }
00134
00135 m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
00136 m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
00137
00138 node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
00139
00140 m_triangleNodes.push_back(node);
00141 }
00142 };
00143
00144
00145
00146 int numLeafNodes = 0;
00147
00148
00149 if (m_useQuantization)
00150 {
00151
00152
00153 setQuantizationValues(bvhAabbMin,bvhAabbMax);
00154
00155 QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this);
00156
00157
00158 triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
00159
00160
00161 numLeafNodes = m_quantizedLeafNodes.size();
00162
00163
00164 m_quantizedContiguousNodes.resize(2*numLeafNodes);
00165
00166
00167 } else
00168 {
00169 NodeTriangleCallback callback(m_leafNodes);
00170
00171 btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00172 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00173
00174 triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
00175
00176
00177 numLeafNodes = m_leafNodes.size();
00178
00179 m_contiguousNodes.resize(2*numLeafNodes);
00180 }
00181
00182 m_curNodeIndex = 0;
00183
00184 buildTree(0,numLeafNodes);
00185
00187 if(m_useQuantization && !m_SubtreeHeaders.size())
00188 {
00189 btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
00190 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
00191 subtree.m_rootNodeIndex = 0;
00192 subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
00193 }
00194
00195
00196 m_subtreeHeaderCount = m_SubtreeHeaders.size();
00197
00198
00199 m_quantizedLeafNodes.clear();
00200 m_leafNodes.clear();
00201 }
00202
00203
00204
00205
00206 void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
00207 {
00208 if (m_useQuantization)
00209 {
00210
00211 setQuantizationValues(aabbMin,aabbMax);
00212
00213 updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
00214
00216
00217 int i;
00218 for (i=0;i<m_SubtreeHeaders.size();i++)
00219 {
00220 btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
00221 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
00222 }
00223
00224 } else
00225 {
00226
00227 }
00228 }
00229
00230
00231
00232
00233 void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
00234 {
00235
00236 btAssert(m_useQuantization);
00237
00238 btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
00239 btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
00240 btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
00241
00242 btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
00243 btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
00244 btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
00245
00248
00249 unsigned short quantizedQueryAabbMin[3];
00250 unsigned short quantizedQueryAabbMax[3];
00251
00252 quantize(&quantizedQueryAabbMin[0],aabbMin,0);
00253 quantize(&quantizedQueryAabbMax[0],aabbMax,1);
00254
00255 int i;
00256 for (i=0;i<this->m_SubtreeHeaders.size();i++)
00257 {
00258 btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
00259
00260
00261 unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
00262 if (overlap != 0)
00263 {
00264 updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
00265
00266 subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
00267 }
00268 }
00269
00270 }
00271
00272 void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
00273 {
00274 (void)index;
00275
00276 btAssert(m_useQuantization);
00277
00278 int curNodeSubPart=-1;
00279
00280
00281 const unsigned char *vertexbase = 0;
00282 int numverts = 0;
00283 PHY_ScalarType type = PHY_INTEGER;
00284 int stride = 0;
00285 const unsigned char *indexbase = 0;
00286 int indexstride = 0;
00287 int numfaces = 0;
00288 PHY_ScalarType indicestype = PHY_INTEGER;
00289
00290 btVector3 triangleVerts[3];
00291 btVector3 aabbMin,aabbMax;
00292 const btVector3& meshScaling = meshInterface->getScaling();
00293
00294 int i;
00295 for (i=endNode-1;i>=firstNode;i--)
00296 {
00297
00298
00299 btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
00300 if (curNode.isLeafNode())
00301 {
00302
00303 int nodeSubPart = curNode.getPartId();
00304 int nodeTriangleIndex = curNode.getTriangleIndex();
00305 if (nodeSubPart != curNodeSubPart)
00306 {
00307 if (curNodeSubPart >= 0)
00308 meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
00309 meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
00310
00311 curNodeSubPart = nodeSubPart;
00312 btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
00313 }
00314
00315
00316 unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
00317
00318
00319 for (int j=2;j>=0;j--)
00320 {
00321
00322 int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
00323 if (type == PHY_FLOAT)
00324 {
00325 float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
00326 triangleVerts[j] = btVector3(
00327 graphicsbase[0]*meshScaling.getX(),
00328 graphicsbase[1]*meshScaling.getY(),
00329 graphicsbase[2]*meshScaling.getZ());
00330 }
00331 else
00332 {
00333 double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
00334 triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
00335 }
00336 }
00337
00338
00339
00340 aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
00341 aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
00342 aabbMin.setMin(triangleVerts[0]);
00343 aabbMax.setMax(triangleVerts[0]);
00344 aabbMin.setMin(triangleVerts[1]);
00345 aabbMax.setMax(triangleVerts[1]);
00346 aabbMin.setMin(triangleVerts[2]);
00347 aabbMax.setMax(triangleVerts[2]);
00348
00349 quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
00350 quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
00351
00352 } else
00353 {
00354
00355
00356 btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
00357
00358 btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
00359 &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
00360
00361
00362 {
00363 for (int i=0;i<3;i++)
00364 {
00365 curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
00366 if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
00367 curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
00368
00369 curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
00370 if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
00371 curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
00372 }
00373 }
00374 }
00375
00376 }
00377
00378 if (curNodeSubPart >= 0)
00379 meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
00380
00381
00382 }
00383
00385 btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
00386 {
00387 btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
00388
00389
00390 return static_cast<btOptimizedBvh*>(bvh);
00391 }