Blender  V2.59
btQuantizedBvh.h
Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #ifndef QUANTIZED_BVH_H
00017 #define QUANTIZED_BVH_H
00018 
00019 class btSerializer;
00020 
00021 //#define DEBUG_CHECK_DEQUANTIZATION 1
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 //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
00047 
00048 
00049 //Note: currently we have 16 bytes per quantized node
00050 #define MAX_SUBTREE_SIZE_IN_BYTES  2048
00051 
00052 // 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
00053 // actually) triangles each (since the sign bit is reserved
00054 #define MAX_NUM_PARTS_IN_BITS 10
00055 
00058 ATTRIBUTE_ALIGNED16     (struct) btQuantizedBvhNode
00059 {
00060         BT_DECLARE_ALIGNED_ALLOCATOR();
00061 
00062         //12 bytes
00063         unsigned short int      m_quantizedAabbMin[3];
00064         unsigned short int      m_quantizedAabbMax[3];
00065         //4 bytes
00066         int     m_escapeIndexOrTriangleIndex;
00067 
00068         bool isLeafNode() const
00069         {
00070                 //skipindex is negative (internal node), triangleindex >=0 (leafnode)
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                 // Get only the lower bits where the triangle index is stored
00082                 return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
00083         }
00084         int     getPartId() const
00085         {
00086                 btAssert(isLeafNode());
00087                 // Get only the highest bits where the part index is stored
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         //32 bytes
00100         btVector3       m_aabbMinOrg;
00101         btVector3       m_aabbMaxOrg;
00102 
00103         //4
00104         int     m_escapeIndex;
00105 
00106         //8
00107         //for child nodes
00108         int     m_subPart;
00109         int     m_triangleIndex;
00110         int:5*8*sizeof(int);
00111 //      int     m_padding[5];//bad, due to alignment
00112 
00113 
00114 };
00115 
00116 
00118 ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
00119 {
00120 public:
00121         BT_DECLARE_ALIGNED_ALLOCATOR();
00122 
00123         //12 bytes
00124         unsigned short int      m_quantizedAabbMin[3];
00125         unsigned short int      m_quantizedAabbMax[3];
00126         //4 bytes, points to the root of the subtree
00127         int                     m_rootNodeIndex;
00128         //4 bytes
00129         int                     m_subtreeSize;
00130         int                     m_padding[3];
00131 
00132         btBvhSubtreeInfo()
00133         {
00134                 //memset(&m_padding[0], 0, sizeof(m_padding));
00135         }
00136 
00137 
00138         void    setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
00139         {
00140                 m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
00141                 m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
00142                 m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
00143                 m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
00144                 m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
00145                 m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
00146         }
00147 }
00148 ;
00149 
00150 
00151 class btNodeOverlapCallback
00152 {
00153 public:
00154         virtual ~btNodeOverlapCallback() {};
00155 
00156         virtual void processNode(int subPart, int triangleIndex) = 0;
00157 };
00158 
00159 #include "LinearMath/btAlignedAllocator.h"
00160 #include "LinearMath/btAlignedObjectArray.h"
00161 
00162 
00163 
00165 typedef btAlignedObjectArray<btOptimizedBvhNode>        NodeArray;
00166 typedef btAlignedObjectArray<btQuantizedBvhNode>        QuantizedNodeArray;
00167 typedef btAlignedObjectArray<btBvhSubtreeInfo>          BvhSubtreeInfoArray;
00168 
00169 
00173 ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
00174 {
00175 public:
00176         enum btTraversalMode
00177         {
00178                 TRAVERSAL_STACKLESS = 0,
00179                 TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
00180                 TRAVERSAL_RECURSIVE
00181         };
00182 
00183 protected:
00184 
00185 
00186         btVector3                       m_bvhAabbMin;
00187         btVector3                       m_bvhAabbMax;
00188         btVector3                       m_bvhQuantization;
00189 
00190         int                                     m_bulletVersion;        //for serialization versioning. It could also be used to detect endianess.
00191 
00192         int                                     m_curNodeIndex;
00193         //quantization data
00194         bool                            m_useQuantization;
00195 
00196 
00197 
00198         NodeArray                       m_leafNodes;
00199         NodeArray                       m_contiguousNodes;
00200         QuantizedNodeArray      m_quantizedLeafNodes;
00201         QuantizedNodeArray      m_quantizedContiguousNodes;
00202         
00203         btTraversalMode m_traversalMode;
00204         BvhSubtreeInfoArray             m_SubtreeHeaders;
00205 
00206         //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
00207         mutable int m_subtreeHeaderCount;
00208 
00209         
00210 
00211 
00212 
00215         void    setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
00216         {
00217                 if (m_useQuantization)
00218                 {
00219                         quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
00220                 } else
00221                 {
00222                         m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
00223 
00224                 }
00225         }
00226         void    setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
00227         {
00228                 if (m_useQuantization)
00229                 {
00230                         quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
00231                 } else
00232                 {
00233                         m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
00234                 }
00235         }
00236 
00237         btVector3 getAabbMin(int nodeIndex) const
00238         {
00239                 if (m_useQuantization)
00240                 {
00241                         return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
00242                 }
00243                 //non-quantized
00244                 return m_leafNodes[nodeIndex].m_aabbMinOrg;
00245 
00246         }
00247         btVector3 getAabbMax(int nodeIndex) const
00248         {
00249                 if (m_useQuantization)
00250                 {
00251                         return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
00252                 } 
00253                 //non-quantized
00254                 return m_leafNodes[nodeIndex].m_aabbMaxOrg;
00255                 
00256         }
00257 
00258         
00259         void    setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
00260         {
00261                 if (m_useQuantization)
00262                 {
00263                         m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
00264                 } 
00265                 else
00266                 {
00267                         m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
00268                 }
00269 
00270         }
00271 
00272         void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) 
00273         {
00274                 if (m_useQuantization)
00275                 {
00276                         unsigned short int quantizedAabbMin[3];
00277                         unsigned short int quantizedAabbMax[3];
00278                         quantize(quantizedAabbMin,newAabbMin,0);
00279                         quantize(quantizedAabbMax,newAabbMax,1);
00280                         for (int i=0;i<3;i++)
00281                         {
00282                                 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
00283                                         m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
00284 
00285                                 if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
00286                                         m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
00287 
00288                         }
00289                 } else
00290                 {
00291                         //non-quantized
00292                         m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
00293                         m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);           
00294                 }
00295         }
00296 
00297         void    swapLeafNodes(int firstIndex,int secondIndex);
00298 
00299         void    assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
00300 
00301 protected:
00302 
00303         
00304 
00305         void    buildTree       (int startIndex,int endIndex);
00306 
00307         int     calcSplittingAxis(int startIndex,int endIndex);
00308 
00309         int     sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
00310         
00311         void    walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00312 
00313         void    walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00314         void    walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
00315         void    walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
00316 
00318         void    walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00319 
00321         void    walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
00322 
00324         void    walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
00325         
00326 
00327 
00328 
00329         void    updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
00330 
00331 public:
00332         
00333         BT_DECLARE_ALIGNED_ALLOCATOR();
00334 
00335         btQuantizedBvh();
00336 
00337         virtual ~btQuantizedBvh();
00338 
00339         
00341         void    setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
00342         QuantizedNodeArray&     getLeafNodeArray() {                    return  m_quantizedLeafNodes;   }
00344         void    buildInternal();
00346 
00347         void    reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
00348         void    reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
00349         void    reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
00350 
00351                 SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
00352         {
00353 
00354                 btAssert(m_useQuantization);
00355 
00356                 btAssert(point.getX() <= m_bvhAabbMax.getX());
00357                 btAssert(point.getY() <= m_bvhAabbMax.getY());
00358                 btAssert(point.getZ() <= m_bvhAabbMax.getZ());
00359 
00360                 btAssert(point.getX() >= m_bvhAabbMin.getX());
00361                 btAssert(point.getY() >= m_bvhAabbMin.getY());
00362                 btAssert(point.getZ() >= m_bvhAabbMin.getZ());
00363 
00364                 btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
00368                 if (isMax)
00369                 {
00370                         out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
00371                         out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
00372                         out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
00373                 } else
00374                 {
00375                         out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
00376                         out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
00377                         out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
00378                 }
00379 
00380 
00381 #ifdef DEBUG_CHECK_DEQUANTIZATION
00382                 btVector3 newPoint = unQuantize(out);
00383                 if (isMax)
00384                 {
00385                         if (newPoint.getX() < point.getX())
00386                         {
00387                                 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00388                         }
00389                         if (newPoint.getY() < point.getY())
00390                         {
00391                                 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00392                         }
00393                         if (newPoint.getZ() < point.getZ())
00394                         {
00395 
00396                                 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00397                         }
00398                 } else
00399                 {
00400                         if (newPoint.getX() > point.getX())
00401                         {
00402                                 printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
00403                         }
00404                         if (newPoint.getY() > point.getY())
00405                         {
00406                                 printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
00407                         }
00408                         if (newPoint.getZ() > point.getZ())
00409                         {
00410                                 printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
00411                         }
00412                 }
00413 #endif //DEBUG_CHECK_DEQUANTIZATION
00414 
00415         }
00416 
00417 
00418         SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
00419         {
00420 
00421                 btAssert(m_useQuantization);
00422 
00423                 btVector3 clampedPoint(point2);
00424                 clampedPoint.setMax(m_bvhAabbMin);
00425                 clampedPoint.setMin(m_bvhAabbMax);
00426 
00427                 quantize(out,clampedPoint,isMax);
00428 
00429         }
00430         
00431         SIMD_FORCE_INLINE btVector3     unQuantize(const unsigned short* vecIn) const
00432         {
00433                         btVector3       vecOut;
00434                         vecOut.setValue(
00435                         (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
00436                         (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
00437                         (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
00438                         vecOut += m_bvhAabbMin;
00439                         return vecOut;
00440         }
00441 
00443         void    setTraversalMode(btTraversalMode        traversalMode)
00444         {
00445                 m_traversalMode = traversalMode;
00446         }
00447 
00448 
00449         SIMD_FORCE_INLINE QuantizedNodeArray&   getQuantizedNodeArray()
00450         {       
00451                 return  m_quantizedContiguousNodes;
00452         }
00453 
00454 
00455         SIMD_FORCE_INLINE BvhSubtreeInfoArray&  getSubtreeInfoArray()
00456         {
00457                 return m_SubtreeHeaders;
00458         }
00459 
00461 
00463         unsigned calculateSerializeBufferSize() const;
00464 
00466         virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
00467 
00469         static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
00470 
00471         static unsigned int getAlignmentSerializationPadding();
00473 
00474         
00475         virtual int     calculateSerializeBufferSizeNew() const;
00476 
00478         virtual const char*     serialize(void* dataBuffer, btSerializer* serializer) const;
00479 
00480         virtual void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
00481 
00482         virtual void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
00483 
00484 
00486 
00487         SIMD_FORCE_INLINE bool isQuantized()
00488         {
00489                 return m_useQuantization;
00490         }
00491 
00492 private:
00493         // Special "copy" constructor that allows for in-place deserialization
00494         // Prevents btVector3's default constructor from being called, but doesn't inialize much else
00495         // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
00496         btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
00497 
00498 }
00499 ;
00500 
00501 
00502 struct  btBvhSubtreeInfoData
00503 {
00504         int                     m_rootNodeIndex;
00505         int                     m_subtreeSize;
00506         unsigned short m_quantizedAabbMin[3];
00507         unsigned short m_quantizedAabbMax[3];
00508 };
00509 
00510 struct btOptimizedBvhNodeFloatData
00511 {
00512         btVector3FloatData      m_aabbMinOrg;
00513         btVector3FloatData      m_aabbMaxOrg;
00514         int     m_escapeIndex;
00515         int     m_subPart;
00516         int     m_triangleIndex;
00517         char m_pad[4];
00518 };
00519 
00520 struct btOptimizedBvhNodeDoubleData
00521 {
00522         btVector3DoubleData     m_aabbMinOrg;
00523         btVector3DoubleData     m_aabbMaxOrg;
00524         int     m_escapeIndex;
00525         int     m_subPart;
00526         int     m_triangleIndex;
00527         char    m_pad[4];
00528 };
00529 
00530 
00531 struct btQuantizedBvhNodeData
00532 {
00533         unsigned short m_quantizedAabbMin[3];
00534         unsigned short m_quantizedAabbMax[3];
00535         int     m_escapeIndexOrTriangleIndex;
00536 };
00537 
00538 struct  btQuantizedBvhFloatData
00539 {
00540         btVector3FloatData                      m_bvhAabbMin;
00541         btVector3FloatData                      m_bvhAabbMax;
00542         btVector3FloatData                      m_bvhQuantization;
00543         int                                     m_curNodeIndex;
00544         int                                     m_useQuantization;
00545         int                                     m_numContiguousLeafNodes;
00546         int                                     m_numQuantizedContiguousNodes;
00547         btOptimizedBvhNodeFloatData     *m_contiguousNodesPtr;
00548         btQuantizedBvhNodeData          *m_quantizedContiguousNodesPtr;
00549         btBvhSubtreeInfoData    *m_subTreeInfoPtr;
00550         int                                     m_traversalMode;
00551         int                                     m_numSubtreeHeaders;
00552         
00553 };
00554 
00555 struct  btQuantizedBvhDoubleData
00556 {
00557         btVector3DoubleData                     m_bvhAabbMin;
00558         btVector3DoubleData                     m_bvhAabbMax;
00559         btVector3DoubleData                     m_bvhQuantization;
00560         int                                                     m_curNodeIndex;
00561         int                                                     m_useQuantization;
00562         int                                                     m_numContiguousLeafNodes;
00563         int                                                     m_numQuantizedContiguousNodes;
00564         btOptimizedBvhNodeDoubleData    *m_contiguousNodesPtr;
00565         btQuantizedBvhNodeData                  *m_quantizedContiguousNodesPtr;
00566 
00567         int                                                     m_traversalMode;
00568         int                                                     m_numSubtreeHeaders;
00569         btBvhSubtreeInfoData            *m_subTreeInfoPtr;
00570 };
00571 
00572 
00573 SIMD_FORCE_INLINE       int     btQuantizedBvh::calculateSerializeBufferSizeNew() const
00574 {
00575         return sizeof(btQuantizedBvhData);
00576 }
00577 
00578 
00579 
00580 #endif //QUANTIZED_BVH_H