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 //#define DEBUG_CHECK_DEQUANTIZATION 1
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 //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
00034 
00035 
00036 //Note: currently we have 16 bytes per quantized node
00037 #define MAX_SUBTREE_SIZE_IN_BYTES  2048
00038 
00039 // 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
00040 // actually) triangles each (since the sign bit is reserved
00041 #define MAX_NUM_PARTS_IN_BITS 10
00042 
00045 struct btQuantizedBvhNode
00046 {
00047         BT_DECLARE_ALIGNED_ALLOCATOR();
00048 
00049         //12 bytes
00050         unsigned short int      m_quantizedAabbMin[3];
00051         unsigned short int      m_quantizedAabbMax[3];
00052         //4 bytes
00053         int     m_escapeIndexOrTriangleIndex;
00054 
00055         bool isLeafNode() const
00056         {
00057                 //skipindex is negative (internal node), triangleindex >=0 (leafnode)
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                 // Get only the lower bits where the triangle index is stored
00069                 return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
00070         }
00071         int     getPartId() const
00072         {
00073                 btAssert(isLeafNode());
00074                 // Get only the highest bits where the part index is stored
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         //32 bytes
00087         btVector3       m_aabbMinOrg;
00088         btVector3       m_aabbMaxOrg;
00089 
00090         //4
00091         int     m_escapeIndex;
00092 
00093         //8
00094         //for child nodes
00095         int     m_subPart;
00096         int     m_triangleIndex;
00097         int     m_padding[5];//bad, due to alignment
00098 
00099 
00100 };
00101 
00102 
00104 class btBvhSubtreeInfo
00105 {
00106 public:
00107         BT_DECLARE_ALIGNED_ALLOCATOR();
00108 
00109         //12 bytes
00110         unsigned short int      m_quantizedAabbMin[3];
00111         unsigned short int      m_quantizedAabbMax[3];
00112         //4 bytes, points to the root of the subtree
00113         int                     m_rootNodeIndex;
00114         //4 bytes
00115         int                     m_subtreeSize;
00116         int                     m_padding[3];
00117 
00118         btBvhSubtreeInfo()
00119         {
00120                 //memset(&m_padding[0], 0, sizeof(m_padding));
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;        //for serialization versioning. It could also be used to detect endianess.
00177 
00178         int                                     m_curNodeIndex;
00179         //quantization data
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         //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
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                 //non-quantized
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                 //non-quantized
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                         //non-quantized
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         // Special "copy" constructor that allows for in-place deserialization
00465         // Prevents btVector3's default constructor from being called, but doesn't inialize much else
00466         // 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)
00467         btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
00468 
00469 }
00470 ;
00471 
00472 
00473 #endif //QUANTIZED_BVH_H

Generated on Mon Feb 15 22:17:05 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1