00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BT_QUANTIZED_BVH_H
00017 #define BT_QUANTIZED_BVH_H
00018
00019 class btSerializer;
00020
00021
00022 #ifdef DEBUG_CHECK_DEQUANTIZATION
00023 #ifdef __SPU__
00024 #define printf spu_printf
00025 #endif //__SPU__
00026
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #endif //DEBUG_CHECK_DEQUANTIZATION
00030
00031 #include "LinearMath/btVector3.h"
00032 #include "LinearMath/btAlignedAllocator.h"
00033
00034 #ifdef BT_USE_DOUBLE_PRECISION
00035 #define btQuantizedBvhData btQuantizedBvhDoubleData
00036 #define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
00037 #define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
00038 #else
00039 #define btQuantizedBvhData btQuantizedBvhFloatData
00040 #define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
00041 #define btQuantizedBvhDataName "btQuantizedBvhFloatData"
00042 #endif
00043
00044
00045
00046
00047
00048
00049
00050 #define MAX_SUBTREE_SIZE_IN_BYTES 2048
00051
00052
00053
00054 #define MAX_NUM_PARTS_IN_BITS 10
00055
00058 ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode
00059 {
00060 BT_DECLARE_ALIGNED_ALLOCATOR();
00061
00062
00063 unsigned short int m_quantizedAabbMin[3];
00064 unsigned short int m_quantizedAabbMax[3];
00065
00066 int m_escapeIndexOrTriangleIndex;
00067
00068 bool isLeafNode() const
00069 {
00070
00071 return (m_escapeIndexOrTriangleIndex >= 0);
00072 }
00073 int getEscapeIndex() const
00074 {
00075 btAssert(!isLeafNode());
00076 return -m_escapeIndexOrTriangleIndex;
00077 }
00078 int getTriangleIndex() const
00079 {
00080 btAssert(isLeafNode());
00081
00082 return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
00083 }
00084 int getPartId() const
00085 {
00086 btAssert(isLeafNode());
00087
00088 return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
00089 }
00090 }
00091 ;
00092
00095 ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
00096 {
00097 BT_DECLARE_ALIGNED_ALLOCATOR();
00098
00099
00100 btVector3 m_aabbMinOrg;
00101 btVector3 m_aabbMaxOrg;
00102
00103
00104 int m_escapeIndex;
00105
00106
00107
00108 int m_subPart;
00109 int m_triangleIndex;
00110
00111
00112 char m_padding[20];
00113 };
00114
00115
00117 ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
00118 {
00119 public:
00120 BT_DECLARE_ALIGNED_ALLOCATOR();
00121
00122
00123 unsigned short int m_quantizedAabbMin[3];
00124 unsigned short int m_quantizedAabbMax[3];
00125
00126 int m_rootNodeIndex;
00127
00128 int m_subtreeSize;
00129 int m_padding[3];
00130
00131 btBvhSubtreeInfo()
00132 {
00133
00134 }
00135
00136
00137 void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
00138 {
00139 m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
00140 m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
00141 m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
00142 m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
00143 m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
00144 m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
00145 }
00146 }
00147 ;
00148
00149
00150 class btNodeOverlapCallback
00151 {
00152 public:
00153 virtual ~btNodeOverlapCallback() {};
00154
00155 virtual void processNode(int subPart, int triangleIndex) = 0;
00156 };
00157
00158 #include "LinearMath/btAlignedAllocator.h"
00159 #include "LinearMath/btAlignedObjectArray.h"
00160
00161
00162
00164 typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
00165 typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
00166 typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
00167
00168
00172 ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
00173 {
00174 public:
00175 enum btTraversalMode
00176 {
00177 TRAVERSAL_STACKLESS = 0,
00178 TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
00179 TRAVERSAL_RECURSIVE
00180 };
00181
00182 protected:
00183
00184
00185 btVector3 m_bvhAabbMin;
00186 btVector3 m_bvhAabbMax;
00187 btVector3 m_bvhQuantization;
00188
00189 int m_bulletVersion;
00190
00191 int m_curNodeIndex;
00192
00193 bool m_useQuantization;
00194
00195
00196
00197 NodeArray m_leafNodes;
00198 NodeArray m_contiguousNodes;
00199 QuantizedNodeArray m_quantizedLeafNodes;
00200 QuantizedNodeArray m_quantizedContiguousNodes;
00201
00202 btTraversalMode m_traversalMode;
00203 BvhSubtreeInfoArray m_SubtreeHeaders;
00204
00205
00206 mutable int m_subtreeHeaderCount;
00207
00208
00209
00210
00211
00214 void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
00215 {
00216 if (m_useQuantization)
00217 {
00218 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
00219 } else
00220 {
00221 m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
00222
00223 }
00224 }
00225 void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
00226 {
00227 if (m_useQuantization)
00228 {
00229 quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
00230 } else
00231 {
00232 m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
00233 }
00234 }
00235
00236 btVector3 getAabbMin(int nodeIndex) const
00237 {
00238 if (m_useQuantization)
00239 {
00240 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
00241 }
00242
00243 return m_leafNodes[nodeIndex].m_aabbMinOrg;
00244
00245 }
00246 btVector3 getAabbMax(int nodeIndex) const
00247 {
00248 if (m_useQuantization)
00249 {
00250 return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
00251 }
00252
00253 return m_leafNodes[nodeIndex].m_aabbMaxOrg;
00254
00255 }
00256
00257
00258 void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
00259 {
00260 if (m_useQuantization)
00261 {
00262 m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
00263 }
00264 else
00265 {
00266 m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
00267 }
00268
00269 }
00270
00271 void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax)
00272 {
00273 if (m_useQuantization)
00274 {
00275 unsigned short int quantizedAabbMin[3];
00276 unsigned short int quantizedAabbMax[3];
00277 quantize(quantizedAabbMin,newAabbMin,0);
00278 quantize(quantizedAabbMax,newAabbMax,1);
00279 for (int i=0;i<3;i++)
00280 {
00281 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
00282 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
00283
00284 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
00285 m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
00286
00287 }
00288 } else
00289 {
00290
00291 m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
00292 m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
00293 }
00294 }
00295
00296 void swapLeafNodes(int firstIndex,int secondIndex);
00297
00298 void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
00299
00300 protected:
00301
00302
00303
00304 void buildTree (int startIndex,int endIndex);
00305
00306 int calcSplittingAxis(int startIndex,int endIndex);
00307
00308 int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
00309
00310 void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00311
00312 void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00313 void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
00314 void walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00315
00317 void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00318
00320 void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00321
00323 void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
00324
00325
00326
00327
00328 void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
00329
00330 public:
00331
00332 BT_DECLARE_ALIGNED_ALLOCATOR();
00333
00334 btQuantizedBvh();
00335
00336 virtual ~btQuantizedBvh();
00337
00338
00340 void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
00341 QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
00343 void buildInternal();
00345
00346 void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00347 void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
00348 void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
00349
00350 SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
00351 {
00352
00353 btAssert(m_useQuantization);
00354
00355 btAssert(point.getX() <= m_bvhAabbMax.getX());
00356 btAssert(point.getY() <= m_bvhAabbMax.getY());
00357 btAssert(point.getZ() <= m_bvhAabbMax.getZ());
00358
00359 btAssert(point.getX() >= m_bvhAabbMin.getX());
00360 btAssert(point.getY() >= m_bvhAabbMin.getY());
00361 btAssert(point.getZ() >= m_bvhAabbMin.getZ());
00362
00363 btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
00367 if (isMax)
00368 {
00369 out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
00370 out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
00371 out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
00372 } else
00373 {
00374 out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
00375 out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
00376 out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
00377 }
00378
00379
00380 #ifdef DEBUG_CHECK_DEQUANTIZATION
00381 btVector3 newPoint = unQuantize(out);
00382 if (isMax)
00383 {
00384 if (newPoint.getX() < point.getX())
00385 {
00386 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00387 }
00388 if (newPoint.getY() < point.getY())
00389 {
00390 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00391 }
00392 if (newPoint.getZ() < point.getZ())
00393 {
00394
00395 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00396 }
00397 } else
00398 {
00399 if (newPoint.getX() > point.getX())
00400 {
00401 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00402 }
00403 if (newPoint.getY() > point.getY())
00404 {
00405 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00406 }
00407 if (newPoint.getZ() > point.getZ())
00408 {
00409 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00410 }
00411 }
00412 #endif //DEBUG_CHECK_DEQUANTIZATION
00413
00414 }
00415
00416
00417 SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
00418 {
00419
00420 btAssert(m_useQuantization);
00421
00422 btVector3 clampedPoint(point2);
00423 clampedPoint.setMax(m_bvhAabbMin);
00424 clampedPoint.setMin(m_bvhAabbMax);
00425
00426 quantize(out,clampedPoint,isMax);
00427
00428 }
00429
00430 SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
00431 {
00432 btVector3 vecOut;
00433 vecOut.setValue(
00434 (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
00435 (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
00436 (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
00437 vecOut += m_bvhAabbMin;
00438 return vecOut;
00439 }
00440
00442 void setTraversalMode(btTraversalMode traversalMode)
00443 {
00444 m_traversalMode = traversalMode;
00445 }
00446
00447
00448 SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
00449 {
00450 return m_quantizedContiguousNodes;
00451 }
00452
00453
00454 SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
00455 {
00456 return m_SubtreeHeaders;
00457 }
00458
00460
00462 unsigned calculateSerializeBufferSize() const;
00463
00465 virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
00466
00468 static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
00469
00470 static unsigned int getAlignmentSerializationPadding();
00472
00473
00474 virtual int calculateSerializeBufferSizeNew() const;
00475
00477 virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
00478
00479 virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
00480
00481 virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
00482
00483
00485
00486 SIMD_FORCE_INLINE bool isQuantized()
00487 {
00488 return m_useQuantization;
00489 }
00490
00491 private:
00492
00493
00494
00495 btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
00496
00497 }
00498 ;
00499
00500
00501 struct btBvhSubtreeInfoData
00502 {
00503 int m_rootNodeIndex;
00504 int m_subtreeSize;
00505 unsigned short m_quantizedAabbMin[3];
00506 unsigned short m_quantizedAabbMax[3];
00507 };
00508
00509 struct btOptimizedBvhNodeFloatData
00510 {
00511 btVector3FloatData m_aabbMinOrg;
00512 btVector3FloatData m_aabbMaxOrg;
00513 int m_escapeIndex;
00514 int m_subPart;
00515 int m_triangleIndex;
00516 char m_pad[4];
00517 };
00518
00519 struct btOptimizedBvhNodeDoubleData
00520 {
00521 btVector3DoubleData m_aabbMinOrg;
00522 btVector3DoubleData m_aabbMaxOrg;
00523 int m_escapeIndex;
00524 int m_subPart;
00525 int m_triangleIndex;
00526 char m_pad[4];
00527 };
00528
00529
00530 struct btQuantizedBvhNodeData
00531 {
00532 unsigned short m_quantizedAabbMin[3];
00533 unsigned short m_quantizedAabbMax[3];
00534 int m_escapeIndexOrTriangleIndex;
00535 };
00536
00537 struct btQuantizedBvhFloatData
00538 {
00539 btVector3FloatData m_bvhAabbMin;
00540 btVector3FloatData m_bvhAabbMax;
00541 btVector3FloatData m_bvhQuantization;
00542 int m_curNodeIndex;
00543 int m_useQuantization;
00544 int m_numContiguousLeafNodes;
00545 int m_numQuantizedContiguousNodes;
00546 btOptimizedBvhNodeFloatData *m_contiguousNodesPtr;
00547 btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
00548 btBvhSubtreeInfoData *m_subTreeInfoPtr;
00549 int m_traversalMode;
00550 int m_numSubtreeHeaders;
00551
00552 };
00553
00554 struct btQuantizedBvhDoubleData
00555 {
00556 btVector3DoubleData m_bvhAabbMin;
00557 btVector3DoubleData m_bvhAabbMax;
00558 btVector3DoubleData m_bvhQuantization;
00559 int m_curNodeIndex;
00560 int m_useQuantization;
00561 int m_numContiguousLeafNodes;
00562 int m_numQuantizedContiguousNodes;
00563 btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
00564 btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
00565
00566 int m_traversalMode;
00567 int m_numSubtreeHeaders;
00568 btBvhSubtreeInfoData *m_subTreeInfoPtr;
00569 };
00570
00571
00572 SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
00573 {
00574 return sizeof(btQuantizedBvhData);
00575 }
00576
00577
00578
00579 #endif //BT_QUANTIZED_BVH_H