Blender V2.61 - r43446

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 m_padding[5];//bad, due to alignment
00111 
00112 
00113 };
00114 
00115 
00117 ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
00118 {
00119 public:
00120     BT_DECLARE_ALIGNED_ALLOCATOR();
00121 
00122     //12 bytes
00123     unsigned short int  m_quantizedAabbMin[3];
00124     unsigned short int  m_quantizedAabbMax[3];
00125     //4 bytes, points to the root of the subtree
00126     int         m_rootNodeIndex;
00127     //4 bytes
00128     int         m_subtreeSize;
00129     int         m_padding[3];
00130 
00131     btBvhSubtreeInfo()
00132     {
00133         //memset(&m_padding[0], 0, sizeof(m_padding));
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;    //for serialization versioning. It could also be used to detect endianess.
00190 
00191     int                 m_curNodeIndex;
00192     //quantization data
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     //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
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         //non-quantized
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         //non-quantized
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             //non-quantized
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     // Special "copy" constructor that allows for in-place deserialization
00493     // Prevents btVector3's default constructor from being called, but doesn't inialize much else
00494     // 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)
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 //QUANTIZED_BVH_H