Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @ 1963

Last change on this file since 1963 was 1963, checked in by rgrieder, 16 years ago

Added Bullet physics engine.

  • Property svn:eol-style set to native
File size: 39.3 KB
Line 
1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. 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.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#include "btQuantizedBvh.h"
17
18#include "LinearMath/btAabbUtil2.h"
19#include "LinearMath/btIDebugDraw.h"
20
21#define RAYAABB2
22
23btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), 
24                                        //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
25                                        m_traversalMode(TRAVERSAL_STACKLESS)
26                                        //m_traversalMode(TRAVERSAL_RECURSIVE)
27                                        ,m_subtreeHeaderCount(0) //PCK: add this line
28{
29        m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
30        m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
31}
32
33
34
35
36
37void btQuantizedBvh::buildInternal()
38{
39        ///assumes that caller filled in the m_quantizedLeafNodes
40        m_useQuantization = true;
41        int numLeafNodes = 0;
42       
43        if (m_useQuantization)
44        {
45                //now we have an array of leafnodes in m_leafNodes
46                numLeafNodes = m_quantizedLeafNodes.size();
47
48                m_quantizedContiguousNodes.resize(2*numLeafNodes);
49
50        }
51
52        m_curNodeIndex = 0;
53
54        buildTree(0,numLeafNodes);
55
56        ///if the entire tree is small then subtree size, we need to create a header info for the tree
57        if(m_useQuantization && !m_SubtreeHeaders.size())
58        {
59                btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
60                subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
61                subtree.m_rootNodeIndex = 0;
62                subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
63        }
64
65        //PCK: update the copy of the size
66        m_subtreeHeaderCount = m_SubtreeHeaders.size();
67
68        //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
69        m_quantizedLeafNodes.clear();
70        m_leafNodes.clear();
71}
72
73
74
75///just for debugging, to visualize the individual patches/subtrees
76#ifdef DEBUG_PATCH_COLORS
77btVector3 color[4]=
78{
79        btVector3(255,0,0),
80        btVector3(0,255,0),
81        btVector3(0,0,255),
82        btVector3(0,255,255)
83};
84#endif //DEBUG_PATCH_COLORS
85
86
87
88void    btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
89{
90        //enlarge the AABB to avoid division by zero when initializing the quantization values
91        btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
92        m_bvhAabbMin = bvhAabbMin - clampValue;
93        m_bvhAabbMax = bvhAabbMax + clampValue;
94        btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
95        m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
96        m_useQuantization = true;
97}
98
99
100
101
102btQuantizedBvh::~btQuantizedBvh()
103{
104}
105
106#ifdef DEBUG_TREE_BUILDING
107int gStackDepth = 0;
108int gMaxStackDepth = 0;
109#endif //DEBUG_TREE_BUILDING
110
111void    btQuantizedBvh::buildTree       (int startIndex,int endIndex)
112{
113#ifdef DEBUG_TREE_BUILDING
114        gStackDepth++;
115        if (gStackDepth > gMaxStackDepth)
116                gMaxStackDepth = gStackDepth;
117#endif //DEBUG_TREE_BUILDING
118
119
120        int splitAxis, splitIndex, i;
121        int numIndices =endIndex-startIndex;
122        int curIndex = m_curNodeIndex;
123
124        btAssert(numIndices>0);
125
126        if (numIndices==1)
127        {
128#ifdef DEBUG_TREE_BUILDING
129                gStackDepth--;
130#endif //DEBUG_TREE_BUILDING
131               
132                assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
133
134                m_curNodeIndex++;
135                return; 
136        }
137        //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
138       
139        splitAxis = calcSplittingAxis(startIndex,endIndex);
140
141        splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
142
143        int internalNodeIndex = m_curNodeIndex;
144       
145        //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
146        //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
147        setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
148        setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
149       
150       
151        for (i=startIndex;i<endIndex;i++)
152        {
153                mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
154        }
155
156        m_curNodeIndex++;
157       
158
159        //internalNode->m_escapeIndex;
160       
161        int leftChildNodexIndex = m_curNodeIndex;
162
163        //build left child tree
164        buildTree(startIndex,splitIndex);
165
166        int rightChildNodexIndex = m_curNodeIndex;
167        //build right child tree
168        buildTree(splitIndex,endIndex);
169
170#ifdef DEBUG_TREE_BUILDING
171        gStackDepth--;
172#endif //DEBUG_TREE_BUILDING
173
174        int escapeIndex = m_curNodeIndex - curIndex;
175
176        if (m_useQuantization)
177        {
178                //escapeIndex is the number of nodes of this subtree
179                const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
180                const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
181                if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
182                {
183                        updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
184                }
185        } else
186        {
187
188        }
189
190        setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
191
192}
193
194void    btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
195{
196        btAssert(m_useQuantization);
197
198        btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
199        int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
200        int leftSubTreeSizeInBytes =  leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
201       
202        btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
203        int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
204        int rightSubTreeSizeInBytes =  rightSubTreeSize *  static_cast<int>(sizeof(btQuantizedBvhNode));
205
206        if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
207        {
208                btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
209                subtree.setAabbFromQuantizeNode(leftChildNode);
210                subtree.m_rootNodeIndex = leftChildNodexIndex;
211                subtree.m_subtreeSize = leftSubTreeSize;
212        }
213
214        if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
215        {
216                btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
217                subtree.setAabbFromQuantizeNode(rightChildNode);
218                subtree.m_rootNodeIndex = rightChildNodexIndex;
219                subtree.m_subtreeSize = rightSubTreeSize;
220        }
221
222        //PCK: update the copy of the size
223        m_subtreeHeaderCount = m_SubtreeHeaders.size();
224}
225
226
227int     btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
228{
229        int i;
230        int splitIndex =startIndex;
231        int numIndices = endIndex - startIndex;
232        btScalar splitValue;
233
234        btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
235        for (i=startIndex;i<endIndex;i++)
236        {
237                btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
238                means+=center;
239        }
240        means *= (btScalar(1.)/(btScalar)numIndices);
241       
242        splitValue = means[splitAxis];
243       
244        //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
245        for (i=startIndex;i<endIndex;i++)
246        {
247                btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
248                if (center[splitAxis] > splitValue)
249                {
250                        //swap
251                        swapLeafNodes(i,splitIndex);
252                        splitIndex++;
253                }
254        }
255
256        //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
257        //otherwise the tree-building might fail due to stack-overflows in certain cases.
258        //unbalanced1 is unsafe: it can cause stack overflows
259        //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
260
261        //unbalanced2 should work too: always use center (perfect balanced trees)       
262        //bool unbalanced2 = true;
263
264        //this should be safe too:
265        int rangeBalancedIndices = numIndices/3;
266        bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
267       
268        if (unbalanced)
269        {
270                splitIndex = startIndex+ (numIndices>>1);
271        }
272
273        bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
274        (void)unbal;
275        btAssert(!unbal);
276
277        return splitIndex;
278}
279
280
281int     btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
282{
283        int i;
284
285        btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
286        btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
287        int numIndices = endIndex-startIndex;
288
289        for (i=startIndex;i<endIndex;i++)
290        {
291                btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
292                means+=center;
293        }
294        means *= (btScalar(1.)/(btScalar)numIndices);
295               
296        for (i=startIndex;i<endIndex;i++)
297        {
298                btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
299                btVector3 diff2 = center-means;
300                diff2 = diff2 * diff2;
301                variance += diff2;
302        }
303        variance *= (btScalar(1.)/      ((btScalar)numIndices-1)        );
304       
305        return variance.maxAxis();
306}
307
308
309
310void    btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
311{
312        //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
313
314        if (m_useQuantization)
315        {
316                ///quantize query AABB
317                unsigned short int quantizedQueryAabbMin[3];
318                unsigned short int quantizedQueryAabbMax[3];
319                quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
320                quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
321
322                switch (m_traversalMode)
323                {
324                case TRAVERSAL_STACKLESS:
325                                walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
326                        break;
327                case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
328                                walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
329                        break;
330                case TRAVERSAL_RECURSIVE:
331                        {
332                                const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
333                                walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
334                        }
335                        break;
336                default:
337                        //unsupported
338                        btAssert(0);
339                }
340        } else
341        {
342                walkStacklessTree(nodeCallback,aabbMin,aabbMax);
343        }
344}
345
346
347int maxIterations = 0;
348
349
350void    btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
351{
352        btAssert(!m_useQuantization);
353
354        const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
355        int escapeIndex, curIndex = 0;
356        int walkIterations = 0;
357        bool isLeafNode;
358        //PCK: unsigned instead of bool
359        unsigned aabbOverlap;
360
361        while (curIndex < m_curNodeIndex)
362        {
363                //catch bugs in tree data
364                btAssert (walkIterations < m_curNodeIndex);
365
366                walkIterations++;
367                aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
368                isLeafNode = rootNode->m_escapeIndex == -1;
369               
370                //PCK: unsigned instead of bool
371                if (isLeafNode && (aabbOverlap != 0))
372                {
373                        nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
374                } 
375               
376                //PCK: unsigned instead of bool
377                if ((aabbOverlap != 0) || isLeafNode)
378                {
379                        rootNode++;
380                        curIndex++;
381                } else
382                {
383                        escapeIndex = rootNode->m_escapeIndex;
384                        rootNode += escapeIndex;
385                        curIndex += escapeIndex;
386                }
387        }
388        if (maxIterations < walkIterations)
389                maxIterations = walkIterations;
390
391}
392
393/*
394///this was the original recursive traversal, before we optimized towards stackless traversal
395void    btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
396{
397        bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
398        if (aabbOverlap)
399        {
400                isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
401                if (isLeafNode)
402                {
403                        nodeCallback->processNode(rootNode);
404                } else
405                {
406                        walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
407                        walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
408                }
409        }
410
411}
412*/
413
414void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
415{
416        btAssert(m_useQuantization);
417       
418        bool isLeafNode;
419        //PCK: unsigned instead of bool
420        unsigned aabbOverlap;
421
422        //PCK: unsigned instead of bool
423        aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
424        isLeafNode = currentNode->isLeafNode();
425               
426        //PCK: unsigned instead of bool
427        if (aabbOverlap != 0)
428        {
429                if (isLeafNode)
430                {
431                        nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
432                } else
433                {
434                        //process left and right children
435                        const btQuantizedBvhNode* leftChildNode = currentNode+1;
436                        walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
437
438                        const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
439                        walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
440                }
441        }               
442}
443
444
445
446void    btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
447{
448        btAssert(!m_useQuantization);
449
450        const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
451        int escapeIndex, curIndex = 0;
452        int walkIterations = 0;
453        bool isLeafNode;
454        //PCK: unsigned instead of bool
455        unsigned aabbOverlap=0;
456        unsigned rayBoxOverlap=0;
457        btScalar lambda_max = 1.0;
458       
459                /* Quick pruning by quantized box */
460        btVector3 rayAabbMin = raySource;
461        btVector3 rayAabbMax = raySource;
462        rayAabbMin.setMin(rayTarget);
463        rayAabbMax.setMax(rayTarget);
464
465        /* Add box cast extents to bounding box */
466        rayAabbMin += aabbMin;
467        rayAabbMax += aabbMax;
468
469#ifdef RAYAABB2
470        btVector3 rayFrom = raySource;
471        btVector3 rayDir = (rayTarget-raySource);
472        rayDir.normalize ();
473        lambda_max = rayDir.dot(rayTarget-raySource);
474        ///what about division by zero? --> just set rayDirection[i] to 1.0
475        btVector3 rayDirectionInverse;
476        rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
477        rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
478        rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
479        unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
480#endif
481
482        btVector3 bounds[2];
483
484        while (curIndex < m_curNodeIndex)
485        {
486                btScalar param = 1.0;
487                //catch bugs in tree data
488                btAssert (walkIterations < m_curNodeIndex);
489
490                walkIterations++;
491
492                bounds[0] = rootNode->m_aabbMinOrg;
493                bounds[1] = rootNode->m_aabbMaxOrg;
494                /* Add box cast extents */
495                bounds[0] += aabbMin;
496                bounds[1] += aabbMax;
497
498                aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
499                //perhaps profile if it is worth doing the aabbOverlap test first
500
501#ifdef RAYAABB2
502                        ///careful with this check: need to check division by zero (above) and fix the unQuantize method
503                        ///thanks Joerg/hiker for the reproduction case!
504                        ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
505                rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
506
507#else
508                btVector3 normal;
509                rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
510#endif
511
512                isLeafNode = rootNode->m_escapeIndex == -1;
513               
514                //PCK: unsigned instead of bool
515                if (isLeafNode && (rayBoxOverlap != 0))
516                {
517                        nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
518                } 
519               
520                //PCK: unsigned instead of bool
521                if ((rayBoxOverlap != 0) || isLeafNode)
522                {
523                        rootNode++;
524                        curIndex++;
525                } else
526                {
527                        escapeIndex = rootNode->m_escapeIndex;
528                        rootNode += escapeIndex;
529                        curIndex += escapeIndex;
530                }
531        }
532        if (maxIterations < walkIterations)
533                maxIterations = walkIterations;
534
535}
536
537
538
539void    btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
540{
541        btAssert(m_useQuantization);
542       
543        int curIndex = startNodeIndex;
544        int walkIterations = 0;
545        int subTreeSize = endNodeIndex - startNodeIndex;
546        (void)subTreeSize;
547
548        const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
549        int escapeIndex;
550       
551        bool isLeafNode;
552        //PCK: unsigned instead of bool
553        unsigned boxBoxOverlap = 0;
554        unsigned rayBoxOverlap = 0;
555
556        btScalar lambda_max = 1.0;
557
558#ifdef RAYAABB2
559        btVector3 rayFrom = raySource;
560        btVector3 rayDirection = (rayTarget-raySource);
561        rayDirection.normalize ();
562        lambda_max = rayDirection.dot(rayTarget-raySource);
563        ///what about division by zero? --> just set rayDirection[i] to 1.0
564        rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0];
565        rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1];
566        rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2];
567        unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
568#endif
569
570        /* Quick pruning by quantized box */
571        btVector3 rayAabbMin = raySource;
572        btVector3 rayAabbMax = raySource;
573        rayAabbMin.setMin(rayTarget);
574        rayAabbMax.setMax(rayTarget);
575
576        /* Add box cast extents to bounding box */
577        rayAabbMin += aabbMin;
578        rayAabbMax += aabbMax;
579
580        unsigned short int quantizedQueryAabbMin[3];
581        unsigned short int quantizedQueryAabbMax[3];
582        quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
583        quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
584
585        while (curIndex < endNodeIndex)
586        {
587
588//#define VISUALLY_ANALYZE_BVH 1
589#ifdef VISUALLY_ANALYZE_BVH
590                //some code snippet to debugDraw aabb, to visually analyze bvh structure
591                static int drawPatch = 0;
592                //need some global access to a debugDrawer
593                extern btIDebugDraw* debugDrawerPtr;
594                if (curIndex==drawPatch)
595                {
596                        btVector3 aabbMin,aabbMax;
597                        aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
598                        aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
599                        btVector3       color(1,0,0);
600                        debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
601                }
602#endif//VISUALLY_ANALYZE_BVH
603
604                //catch bugs in tree data
605                btAssert (walkIterations < subTreeSize);
606
607                walkIterations++;
608                //PCK: unsigned instead of bool
609                // only interested if this is closer than any previous hit
610                btScalar param = 1.0;
611                rayBoxOverlap = 0;
612                boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
613                isLeafNode = rootNode->isLeafNode();
614                if (boxBoxOverlap)
615                {
616                        btVector3 bounds[2];
617                        bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
618                        bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
619                        /* Add box cast extents */
620                        bounds[0] += aabbMin;
621                        bounds[1] += aabbMax;
622                        btVector3 normal;
623#if 0
624                        bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
625                        bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
626                        if (ra2 != ra)
627                        {
628                                printf("functions don't match\n");
629                        }
630#endif
631#ifdef RAYAABB2
632                        ///careful with this check: need to check division by zero (above) and fix the unQuantize method
633                        ///thanks Joerg/hiker for the reproduction case!
634                        ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
635
636                        //BT_PROFILE("btRayAabb2");
637                        rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
638                       
639#else
640                        rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
641#endif
642                }
643               
644                if (isLeafNode && rayBoxOverlap)
645                {
646                        nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
647                }
648               
649                //PCK: unsigned instead of bool
650                if ((rayBoxOverlap != 0) || isLeafNode)
651                {
652                        rootNode++;
653                        curIndex++;
654                } else
655                {
656                        escapeIndex = rootNode->getEscapeIndex();
657                        rootNode += escapeIndex;
658                        curIndex += escapeIndex;
659                }
660        }
661        if (maxIterations < walkIterations)
662                maxIterations = walkIterations;
663
664}
665
666void    btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
667{
668        btAssert(m_useQuantization);
669       
670        int curIndex = startNodeIndex;
671        int walkIterations = 0;
672        int subTreeSize = endNodeIndex - startNodeIndex;
673        (void)subTreeSize;
674
675        const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
676        int escapeIndex;
677       
678        bool isLeafNode;
679        //PCK: unsigned instead of bool
680        unsigned aabbOverlap;
681
682        while (curIndex < endNodeIndex)
683        {
684
685//#define VISUALLY_ANALYZE_BVH 1
686#ifdef VISUALLY_ANALYZE_BVH
687                //some code snippet to debugDraw aabb, to visually analyze bvh structure
688                static int drawPatch = 0;
689                //need some global access to a debugDrawer
690                extern btIDebugDraw* debugDrawerPtr;
691                if (curIndex==drawPatch)
692                {
693                        btVector3 aabbMin,aabbMax;
694                        aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
695                        aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
696                        btVector3       color(1,0,0);
697                        debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
698                }
699#endif//VISUALLY_ANALYZE_BVH
700
701                //catch bugs in tree data
702                btAssert (walkIterations < subTreeSize);
703
704                walkIterations++;
705                //PCK: unsigned instead of bool
706                aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
707                isLeafNode = rootNode->isLeafNode();
708               
709                if (isLeafNode && aabbOverlap)
710                {
711                        nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
712                } 
713               
714                //PCK: unsigned instead of bool
715                if ((aabbOverlap != 0) || isLeafNode)
716                {
717                        rootNode++;
718                        curIndex++;
719                } else
720                {
721                        escapeIndex = rootNode->getEscapeIndex();
722                        rootNode += escapeIndex;
723                        curIndex += escapeIndex;
724                }
725        }
726        if (maxIterations < walkIterations)
727                maxIterations = walkIterations;
728
729}
730
731//This traversal can be called from Playstation 3 SPU
732void    btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
733{
734        btAssert(m_useQuantization);
735
736        int i;
737
738
739        for (i=0;i<this->m_SubtreeHeaders.size();i++)
740        {
741                const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
742
743                //PCK: unsigned instead of bool
744                unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
745                if (overlap != 0)
746                {
747                        walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
748                                subtree.m_rootNodeIndex,
749                                subtree.m_rootNodeIndex+subtree.m_subtreeSize);
750                }
751        }
752}
753
754
755void    btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
756{
757        reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0));
758}
759
760
761void    btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
762{
763        //always use stackless
764
765        if (m_useQuantization)
766        {
767                walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
768        }
769        else
770        {
771                walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
772        }
773        /*
774        {
775                //recursive traversal
776                btVector3 qaabbMin = raySource;
777                btVector3 qaabbMax = raySource;
778                qaabbMin.setMin(rayTarget);
779                qaabbMax.setMax(rayTarget);
780                qaabbMin += aabbMin;
781                qaabbMax += aabbMax;
782                reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
783        }
784        */
785
786}
787
788
789void    btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
790{
791        if (m_useQuantization)
792        {
793                        btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
794                        m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
795                        m_quantizedLeafNodes[splitIndex] = tmp;
796        } else
797        {
798                        btOptimizedBvhNode tmp = m_leafNodes[i];
799                        m_leafNodes[i] = m_leafNodes[splitIndex];
800                        m_leafNodes[splitIndex] = tmp;
801        }
802}
803
804void    btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
805{
806        if (m_useQuantization)
807        {
808                m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
809        } else
810        {
811                m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
812        }
813}
814
815//PCK: include
816#include <new>
817
818//PCK: consts
819static const unsigned BVH_ALIGNMENT = 16;
820static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
821
822static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
823
824
825
826unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
827{
828        // I changed this to 0 since the extra padding is not needed or used.
829        return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
830}
831
832unsigned btQuantizedBvh::calculateSerializeBufferSize()
833{
834        unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
835        baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
836        if (m_useQuantization)
837        {
838                return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
839        }
840        return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
841}
842
843bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian)
844{
845        btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
846        m_subtreeHeaderCount = m_SubtreeHeaders.size();
847
848/*      if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
849        {
850                ///check alignedment for buffer?
851                btAssert(0);
852                return false;
853        }
854*/
855
856        btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
857
858        // construct the class so the virtual function table, etc will be set up
859        // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
860        new (targetBvh) btQuantizedBvh;
861
862        if (i_swapEndian)
863        {
864                targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
865
866
867                btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
868                btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
869                btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
870
871                targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
872                targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
873        }
874        else
875        {
876                targetBvh->m_curNodeIndex = m_curNodeIndex;
877                targetBvh->m_bvhAabbMin = m_bvhAabbMin;
878                targetBvh->m_bvhAabbMax = m_bvhAabbMax;
879                targetBvh->m_bvhQuantization = m_bvhQuantization;
880                targetBvh->m_traversalMode = m_traversalMode;
881                targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
882        }
883
884        targetBvh->m_useQuantization = m_useQuantization;
885
886        unsigned char *nodeData = (unsigned char *)targetBvh;
887        nodeData += sizeof(btQuantizedBvh);
888       
889        unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
890        nodeData += sizeToAdd;
891       
892        int nodeCount = m_curNodeIndex;
893
894        if (m_useQuantization)
895        {
896                targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
897
898                if (i_swapEndian)
899                {
900                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
901                        {
902                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
903                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
904                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
905
906                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
907                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
908                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
909
910                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
911                        }
912                }
913                else
914                {
915                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
916                        {
917       
918                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
919                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
920                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
921
922                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
923                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
924                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
925
926                                targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
927
928
929                        }
930                }
931                nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
932
933                // this clears the pointer in the member variable it doesn't really do anything to the data
934                // it does call the destructor on the contained objects, but they are all classes with no destructor defined
935                // so the memory (which is not freed) is left alone
936                targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
937        }
938        else
939        {
940                targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
941
942                if (i_swapEndian)
943                {
944                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
945                        {
946                                btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
947                                btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
948
949                                targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
950                                targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
951                                targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
952                        }
953                }
954                else
955                {
956                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
957                        {
958                                targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
959                                targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
960
961                                targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
962                                targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
963                                targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
964                        }
965                }
966                nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
967
968                // this clears the pointer in the member variable it doesn't really do anything to the data
969                // it does call the destructor on the contained objects, but they are all classes with no destructor defined
970                // so the memory (which is not freed) is left alone
971                targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
972        }
973
974        sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
975        nodeData += sizeToAdd;
976
977        // Now serialize the subtree headers
978        targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
979        if (i_swapEndian)
980        {
981                for (int i = 0; i < m_subtreeHeaderCount; i++)
982                {
983                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
984                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
985                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
986
987                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
988                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
989                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
990
991                        targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
992                        targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
993                }
994        }
995        else
996        {
997                for (int i = 0; i < m_subtreeHeaderCount; i++)
998                {
999                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
1000                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
1001                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
1002
1003                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
1004                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
1005                        targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
1006
1007                        targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
1008                        targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
1009
1010                        // need to clear padding in destination buffer
1011                        targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
1012                        targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
1013                        targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
1014                }
1015        }
1016        nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
1017
1018        // this clears the pointer in the member variable it doesn't really do anything to the data
1019        // it does call the destructor on the contained objects, but they are all classes with no destructor defined
1020        // so the memory (which is not freed) is left alone
1021        targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
1022
1023        // this wipes the virtual function table pointer at the start of the buffer for the class
1024        *((void**)o_alignedDataBuffer) = NULL;
1025
1026        return true;
1027}
1028
1029btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
1030{
1031
1032        if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
1033        {
1034                return NULL;
1035        }
1036        btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
1037
1038        if (i_swapEndian)
1039        {
1040                bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
1041
1042                btUnSwapVector3Endian(bvh->m_bvhAabbMin);
1043                btUnSwapVector3Endian(bvh->m_bvhAabbMax);
1044                btUnSwapVector3Endian(bvh->m_bvhQuantization);
1045
1046                bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
1047                bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
1048        }
1049
1050        unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
1051        btAssert(calculatedBufSize <= i_dataBufferSize);
1052
1053        if (calculatedBufSize > i_dataBufferSize)
1054        {
1055                return NULL;
1056        }
1057
1058        unsigned char *nodeData = (unsigned char *)bvh;
1059        nodeData += sizeof(btQuantizedBvh);
1060       
1061        unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
1062        nodeData += sizeToAdd;
1063       
1064        int nodeCount = bvh->m_curNodeIndex;
1065
1066        // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
1067        // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
1068        new (bvh) btQuantizedBvh(*bvh, false);
1069
1070        if (bvh->m_useQuantization)
1071        {
1072                bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
1073
1074                if (i_swapEndian)
1075                {
1076                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
1077                        {
1078                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
1079                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
1080                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
1081
1082                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
1083                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
1084                                bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
1085
1086                                bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
1087                        }
1088                }
1089                nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
1090        }
1091        else
1092        {
1093                bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
1094
1095                if (i_swapEndian)
1096                {
1097                        for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
1098                        {
1099                                btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
1100                                btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
1101                               
1102                                bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
1103                                bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
1104                                bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
1105                        }
1106                }
1107                nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
1108        }
1109
1110        sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
1111        nodeData += sizeToAdd;
1112
1113        // Now serialize the subtree headers
1114        bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
1115        if (i_swapEndian)
1116        {
1117                for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
1118                {
1119                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
1120                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
1121                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
1122
1123                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
1124                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
1125                        bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
1126
1127                        bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
1128                        bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
1129                }
1130        }
1131
1132        return bvh;
1133}
1134
1135// Constructor that prevents btVector3's default constructor from being called
1136btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
1137m_bvhAabbMin(self.m_bvhAabbMin),
1138m_bvhAabbMax(self.m_bvhAabbMax),
1139m_bvhQuantization(self.m_bvhQuantization)
1140{
1141
1142
1143}
1144
1145
1146
Note: See TracBrowser for help on using the repository browser.