00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef QUANTIZED_BVH_H
00017 #define QUANTIZED_BVH_H
00018
00019
00020 #ifdef DEBUG_CHECK_DEQUANTIZATION
00021 #ifdef __SPU__
00022 #define printf spu_printf
00023 #endif //__SPU__
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #endif //DEBUG_CHECK_DEQUANTIZATION
00028
00029 #include "LinearMath/btVector3.h"
00030 #include "LinearMath/btAlignedAllocator.h"
00031
00032
00033
00034
00035
00036
00037 #define MAX_SUBTREE_SIZE_IN_BYTES 2048
00038
00039
00040
00041 #define MAX_NUM_PARTS_IN_BITS 10
00042
00045 struct btQuantizedBvhNode
00046 {
00047 BT_DECLARE_ALIGNED_ALLOCATOR();
00048
00049
00050 unsigned short int m_quantizedAabbMin[3];
00051 unsigned short int m_quantizedAabbMax[3];
00052
00053 int m_escapeIndexOrTriangleIndex;
00054
00055 bool isLeafNode() const
00056 {
00057
00058 return (m_escapeIndexOrTriangleIndex >= 0);
00059 }
00060 int getEscapeIndex() const
00061 {
00062 btAssert(!isLeafNode());
00063 return -m_escapeIndexOrTriangleIndex;
00064 }
00065 int getTriangleIndex() const
00066 {
00067 btAssert(isLeafNode());
00068
00069 return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
00070 }
00071 int getPartId() const
00072 {
00073 btAssert(isLeafNode());
00074
00075 return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
00076 }
00077 }
00078 ;
00079
00082 struct btOptimizedBvhNode
00083 {
00084 BT_DECLARE_ALIGNED_ALLOCATOR();
00085
00086
00087 btVector3 m_aabbMinOrg;
00088 btVector3 m_aabbMaxOrg;
00089
00090
00091 int m_escapeIndex;
00092
00093
00094
00095 int m_subPart;
00096 int m_triangleIndex;
00097 int m_padding[5];
00098
00099
00100 };
00101
00102
00104 class btBvhSubtreeInfo
00105 {
00106 public:
00107 BT_DECLARE_ALIGNED_ALLOCATOR();
00108
00109
00110 unsigned short int m_quantizedAabbMin[3];
00111 unsigned short int m_quantizedAabbMax[3];
00112
00113 int m_rootNodeIndex;
00114
00115 int m_subtreeSize;
00116 int m_padding[3];
00117
00118 btBvhSubtreeInfo()
00119 {
00120
00121 }
00122
00123
00124 void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
00125 {
00126 m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
00127 m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
00128 m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
00129 m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
00130 m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
00131 m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
00132 }
00133 }
00134 ;
00135
00136
00137 class btNodeOverlapCallback
00138 {
00139 public:
00140 virtual ~btNodeOverlapCallback() {};
00141
00142 virtual void processNode(int subPart, int triangleIndex) = 0;
00143 };
00144
00145 #include "LinearMath/btAlignedAllocator.h"
00146 #include "LinearMath/btAlignedObjectArray.h"
00147
00148
00149
00151 typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
00152 typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
00153 typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
00154
00155
00159 class btQuantizedBvh
00160 {
00161 public:
00162 enum btTraversalMode
00163 {
00164 TRAVERSAL_STACKLESS = 0,
00165 TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
00166 TRAVERSAL_RECURSIVE
00167 };
00168
00169 protected:
00170
00171
00172 btVector3 m_bvhAabbMin;
00173 btVector3 m_bvhAabbMax;
00174 btVector3 m_bvhQuantization;
00175
00176 int m_bulletVersion;
00177
00178 int m_curNodeIndex;
00179
00180 bool m_useQuantization;
00181
00182
00183
00184 NodeArray m_leafNodes;
00185 NodeArray m_contiguousNodes;
00186 QuantizedNodeArray m_quantizedLeafNodes;
00187 QuantizedNodeArray m_quantizedContiguousNodes;
00188
00189 btTraversalMode m_traversalMode;
00190 BvhSubtreeInfoArray m_SubtreeHeaders;
00191
00192
00193 mutable int m_subtreeHeaderCount;
00194
00195
00196
00197
00198
00201 void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
00202 {
00203 if (m_useQuantization)
00204 {
00205 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
00206 } else
00207 {
00208 m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
00209
00210 }
00211 }
00212 void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
00213 {
00214 if (m_useQuantization)
00215 {
00216 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
00217 } else
00218 {
00219 m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
00220 }
00221 }
00222
00223 btVector3 getAabbMin(int nodeIndex) const
00224 {
00225 if (m_useQuantization)
00226 {
00227 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
00228 }
00229
00230 return m_leafNodes[nodeIndex].m_aabbMinOrg;
00231
00232 }
00233 btVector3 getAabbMax(int nodeIndex) const
00234 {
00235 if (m_useQuantization)
00236 {
00237 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
00238 }
00239
00240 return m_leafNodes[nodeIndex].m_aabbMaxOrg;
00241
00242 }
00243
00244
00245 void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
00246 {
00247 if (m_useQuantization)
00248 {
00249 m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
00250 }
00251 else
00252 {
00253 m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
00254 }
00255
00256 }
00257
00258 void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
00259 {
00260 if (m_useQuantization)
00261 {
00262 unsigned short int quantizedAabbMin[3];
00263 unsigned short int quantizedAabbMax[3];
00264 quantize(quantizedAabbMin,newAabbMin,0);
00265 quantize(quantizedAabbMax,newAabbMax,1);
00266 for (int i=0;i<3;i++)
00267 {
00268 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
00269 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
00270
00271 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
00272 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
00273
00274 }
00275 } else
00276 {
00277
00278 m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
00279 m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
00280 }
00281 }
00282
00283 void swapLeafNodes(int firstIndex,int secondIndex);
00284
00285 void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
00286
00287 protected:
00288
00289
00290
00291 void buildTree (int startIndex,int endIndex);
00292
00293 int calcSplittingAxis(int startIndex,int endIndex);
00294
00295 int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
00296
00297 void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00298
00299 void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00300 void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
00301 void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00302
00304 void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00305
00307 void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00308
00310 void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
00311
00312
00313
00314
00315 void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
00316
00317 public:
00318
00319 BT_DECLARE_ALIGNED_ALLOCATOR();
00320
00321 btQuantizedBvh();
00322
00323 virtual ~btQuantizedBvh();
00324
00325
00327 void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
00328 QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
00330 void buildInternal();
00332
00333 void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00334 void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
00335 void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
00336
00337 SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
00338 {
00339
00340 btAssert(m_useQuantization);
00341
00342 btAssert(point.getX() <= m_bvhAabbMax.getX());
00343 btAssert(point.getY() <= m_bvhAabbMax.getY());
00344 btAssert(point.getZ() <= m_bvhAabbMax.getZ());
00345
00346 btAssert(point.getX() >= m_bvhAabbMin.getX());
00347 btAssert(point.getY() >= m_bvhAabbMin.getY());
00348 btAssert(point.getZ() >= m_bvhAabbMin.getZ());
00349
00350 btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
00354 if (isMax)
00355 {
00356 out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
00357 out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
00358 out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
00359 } else
00360 {
00361 out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
00362 out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
00363 out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
00364 }
00365
00366
00367 #ifdef DEBUG_CHECK_DEQUANTIZATION
00368 btVector3 newPoint = unQuantize(out);
00369 if (isMax)
00370 {
00371 if (newPoint.getX() < point.getX())
00372 {
00373 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00374 }
00375 if (newPoint.getY() < point.getY())
00376 {
00377 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00378 }
00379 if (newPoint.getZ() < point.getZ())
00380 {
00381
00382 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00383 }
00384 } else
00385 {
00386 if (newPoint.getX() > point.getX())
00387 {
00388 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00389 }
00390 if (newPoint.getY() > point.getY())
00391 {
00392 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00393 }
00394 if (newPoint.getZ() > point.getZ())
00395 {
00396 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00397 }
00398 }
00399 #endif //DEBUG_CHECK_DEQUANTIZATION
00400
00401 }
00402
00403
00404 SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
00405 {
00406
00407 btAssert(m_useQuantization);
00408
00409 btVector3 clampedPoint(point2);
00410 clampedPoint.setMax(m_bvhAabbMin);
00411 clampedPoint.setMin(m_bvhAabbMax);
00412
00413 quantize(out,clampedPoint,isMax);
00414
00415 }
00416
00417 SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
00418 {
00419 btVector3 vecOut;
00420 vecOut.setValue(
00421 (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
00422 (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
00423 (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
00424 vecOut += m_bvhAabbMin;
00425 return vecOut;
00426 }
00427
00429 void setTraversalMode(btTraversalMode traversalMode)
00430 {
00431 m_traversalMode = traversalMode;
00432 }
00433
00434
00435 SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
00436 {
00437 return m_quantizedContiguousNodes;
00438 }
00439
00440
00441 SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
00442 {
00443 return m_SubtreeHeaders;
00444 }
00445
00446
00448 unsigned calculateSerializeBufferSize() const;
00449
00451 virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
00452
00454 static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
00455
00456 static unsigned int getAlignmentSerializationPadding();
00457
00458 SIMD_FORCE_INLINE bool isQuantized()
00459 {
00460 return m_useQuantization;
00461 }
00462
00463 private:
00464
00465
00466
00467 btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
00468
00469 }
00470 ;
00471
00472
00473 #endif //QUANTIZED_BVH_H