| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341 |
- /*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 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.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "btQuantizedBvh.h"
- #include "LinearMath/btAabbUtil2.h"
- #include "LinearMath/btIDebugDraw.h"
- #include "LinearMath/btSerializer.h"
- #define RAYAABB2
- btQuantizedBvh::btQuantizedBvh() : m_bulletVersion(BT_BULLET_VERSION),
- m_useQuantization(false),
- //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
- ,
- m_subtreeHeaderCount(0) //PCK: add this line
- {
- m_bvhAabbMin.setValue(-SIMD_INFINITY, -SIMD_INFINITY, -SIMD_INFINITY);
- m_bvhAabbMax.setValue(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
- }
- void btQuantizedBvh::buildInternal()
- {
- ///assumes that caller filled in the m_quantizedLeafNodes
- m_useQuantization = true;
- int numLeafNodes = 0;
- if (m_useQuantization)
- {
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_quantizedLeafNodes.size();
- m_quantizedContiguousNodes.resize(2 * numLeafNodes);
- }
- m_curNodeIndex = 0;
- buildTree(0, numLeafNodes);
- ///if the entire tree is small then subtree size, we need to create a header info for the tree
- if (m_useQuantization && !m_SubtreeHeaders.size())
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
- subtree.m_rootNodeIndex = 0;
- subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
- }
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
- //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
- m_quantizedLeafNodes.clear();
- m_leafNodes.clear();
- }
- ///just for debugging, to visualize the individual patches/subtrees
- #ifdef DEBUG_PATCH_COLORS
- btVector3 color[4] =
- {
- btVector3(1, 0, 0),
- btVector3(0, 1, 0),
- btVector3(0, 0, 1),
- btVector3(0, 1, 1)};
- #endif //DEBUG_PATCH_COLORS
- void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin)
- {
- //enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
- m_bvhAabbMin = bvhAabbMin - clampValue;
- m_bvhAabbMax = bvhAabbMax + clampValue;
- btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
- m_useQuantization = true;
- {
- unsigned short vecIn[3];
- btVector3 v;
- {
- quantize(vecIn, m_bvhAabbMin, false);
- v = unQuantize(vecIn);
- m_bvhAabbMin.setMin(v - clampValue);
- }
- aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
- {
- quantize(vecIn, m_bvhAabbMax, true);
- v = unQuantize(vecIn);
- m_bvhAabbMax.setMax(v + clampValue);
- }
- aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
- }
- }
- btQuantizedBvh::~btQuantizedBvh()
- {
- }
- #ifdef DEBUG_TREE_BUILDING
- int gStackDepth = 0;
- int gMaxStackDepth = 0;
- #endif //DEBUG_TREE_BUILDING
- void btQuantizedBvh::buildTree(int startIndex, int endIndex)
- {
- #ifdef DEBUG_TREE_BUILDING
- gStackDepth++;
- if (gStackDepth > gMaxStackDepth)
- gMaxStackDepth = gStackDepth;
- #endif //DEBUG_TREE_BUILDING
- int splitAxis, splitIndex, i;
- int numIndices = endIndex - startIndex;
- int curIndex = m_curNodeIndex;
- btAssert(numIndices > 0);
- if (numIndices == 1)
- {
- #ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
- #endif //DEBUG_TREE_BUILDING
- assignInternalNodeFromLeafNode(m_curNodeIndex, startIndex);
- m_curNodeIndex++;
- return;
- }
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
- splitAxis = calcSplittingAxis(startIndex, endIndex);
- splitIndex = sortAndCalcSplittingIndex(startIndex, endIndex, splitAxis);
- int internalNodeIndex = m_curNodeIndex;
- //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
- //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
- setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax); //can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
- setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin); //can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
- for (i = startIndex; i < endIndex; i++)
- {
- mergeInternalNodeAabb(m_curNodeIndex, getAabbMin(i), getAabbMax(i));
- }
- m_curNodeIndex++;
- //internalNode->m_escapeIndex;
- int leftChildNodexIndex = m_curNodeIndex;
- //build left child tree
- buildTree(startIndex, splitIndex);
- int rightChildNodexIndex = m_curNodeIndex;
- //build right child tree
- buildTree(splitIndex, endIndex);
- #ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
- #endif //DEBUG_TREE_BUILDING
- int escapeIndex = m_curNodeIndex - curIndex;
- if (m_useQuantization)
- {
- //escapeIndex is the number of nodes of this subtree
- const int sizeQuantizedNode = sizeof(btQuantizedBvhNode);
- const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
- if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
- {
- updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
- }
- }
- else
- {
- }
- setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
- }
- void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
- {
- btAssert(m_useQuantization);
- btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
- int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
- int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
- btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
- int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
- int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
- if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(leftChildNode);
- subtree.m_rootNodeIndex = leftChildNodexIndex;
- subtree.m_subtreeSize = leftSubTreeSize;
- }
- if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(rightChildNode);
- subtree.m_rootNodeIndex = rightChildNodexIndex;
- subtree.m_subtreeSize = rightSubTreeSize;
- }
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
- }
- int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
- {
- int i;
- int splitIndex = startIndex;
- int numIndices = endIndex - startIndex;
- btScalar splitValue;
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
- splitValue = means[splitAxis];
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- if (center[splitAxis] > splitValue)
- {
- //swap
- swapLeafNodes(i, splitIndex);
- splitIndex++;
- }
- }
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
- //this should be safe too:
- int rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
- bool unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
- (void)unbal;
- btAssert(!unbal);
- return splitIndex;
- }
- int btQuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
- {
- int i;
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
- int numIndices = endIndex - startIndex;
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- btVector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
- return variance.maxAxis();
- }
- void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
- {
- //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
- if (m_useQuantization)
- {
- ///quantize query AABB
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, aabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, aabbMax, 1);
- switch (m_traversalMode)
- {
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax, 0, m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
- {
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- break;
- default:
- //unsupported
- btAssert(0);
- }
- }
- else
- {
- walkStacklessTree(nodeCallback, aabbMin, aabbMax);
- }
- }
- void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
- {
- btAssert(!m_useQuantization);
- const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
- while (curIndex < m_curNodeIndex)
- {
- //catch bugs in tree data
- btAssert(walkIterations < m_curNodeIndex);
- walkIterations++;
- aabbOverlap = TestAabbAgainstAabb2(aabbMin, aabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- isLeafNode = rootNode->m_escapeIndex == -1;
- //PCK: unsigned instead of bool
- if (isLeafNode && (aabbOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- }
- /*
- ///this was the original recursive traversal, before we optimized towards stackless traversal
- void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
- {
- bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
- if (aabbOverlap)
- {
- isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
- if (isLeafNode)
- {
- nodeCallback->processNode(rootNode);
- } else
- {
- walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
- walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
- }
- }
- }
- */
- void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
- {
- btAssert(m_useQuantization);
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
- //PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, currentNode->m_quantizedAabbMin, currentNode->m_quantizedAabbMax);
- isLeafNode = currentNode->isLeafNode();
- //PCK: unsigned instead of bool
- if (aabbOverlap != 0)
- {
- if (isLeafNode)
- {
- nodeCallback->processNode(currentNode->getPartId(), currentNode->getTriangleIndex());
- }
- else
- {
- //process left and right children
- const btQuantizedBvhNode* leftChildNode = currentNode + 1;
- walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
- walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- }
- }
- void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
- {
- btAssert(!m_useQuantization);
- const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap = 0;
- unsigned rayBoxOverlap = 0;
- btScalar lambda_max = 1.0;
- /* Quick pruning by quantized box */
- btVector3 rayAabbMin = raySource;
- btVector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
- #ifdef RAYAABB2
- btVector3 rayDir = (rayTarget - raySource);
- rayDir.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
- lambda_max = rayDir.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- btVector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
- #endif
- btVector3 bounds[2];
- while (curIndex < m_curNodeIndex)
- {
- btScalar param = 1.0;
- //catch bugs in tree data
- btAssert(walkIterations < m_curNodeIndex);
- walkIterations++;
- bounds[0] = rootNode->m_aabbMinOrg;
- bounds[1] = rootNode->m_aabbMaxOrg;
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
- aabbOverlap = TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- //perhaps profile if it is worth doing the aabbOverlap test first
- #ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- rayBoxOverlap = aabbOverlap ? btRayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
- #else
- btVector3 normal;
- rayBoxOverlap = btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
- #endif
- isLeafNode = rootNode->m_escapeIndex == -1;
- //PCK: unsigned instead of bool
- if (isLeafNode && (rayBoxOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- }
- void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
- {
- btAssert(m_useQuantization);
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned boxBoxOverlap = 0;
- unsigned rayBoxOverlap = 0;
- btScalar lambda_max = 1.0;
- #ifdef RAYAABB2
- btVector3 rayDirection = (rayTarget - raySource);
- rayDirection.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
- lambda_max = rayDirection.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
- rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
- rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
- unsigned int sign[3] = {rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
- #endif
- /* Quick pruning by quantized box */
- btVector3 rayAabbMin = raySource;
- btVector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, rayAabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, rayAabbMax, 1);
- while (curIndex < endNodeIndex)
- {
- //#define VISUALLY_ANALYZE_BVH 1
- #ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern btIDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- btVector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
- #endif //VISUALLY_ANALYZE_BVH
- //catch bugs in tree data
- btAssert(walkIterations < subTreeSize);
- walkIterations++;
- //PCK: unsigned instead of bool
- // only interested if this is closer than any previous hit
- btScalar param = 1.0;
- rayBoxOverlap = 0;
- boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
- if (boxBoxOverlap)
- {
- btVector3 bounds[2];
- bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
- bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
- btVector3 normal;
- #if 0
- bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
- bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
- if (ra2 != ra)
- {
- printf("functions don't match\n");
- }
- #endif
- #ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- //BT_PROFILE("btRayAabb2");
- rayBoxOverlap = btRayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
- #else
- rayBoxOverlap = true; //btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
- #endif
- }
- if (isLeafNode && rayBoxOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- }
- void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
- {
- btAssert(m_useQuantization);
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
- while (curIndex < endNodeIndex)
- {
- //#define VISUALLY_ANALYZE_BVH 1
- #ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern btIDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- btVector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
- #endif //VISUALLY_ANALYZE_BVH
- //catch bugs in tree data
- btAssert(walkIterations < subTreeSize);
- walkIterations++;
- //PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
- if (isLeafNode && aabbOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- }
- //This traversal can be called from Playstation 3 SPU
- void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
- {
- btAssert(m_useQuantization);
- int i;
- for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
- {
- const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
- //PCK: unsigned instead of bool
- unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax,
- subtree.m_rootNodeIndex,
- subtree.m_rootNodeIndex + subtree.m_subtreeSize);
- }
- }
- }
- void btQuantizedBvh::reportRayOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
- {
- reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0));
- }
- void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const
- {
- //always use stackless
- if (m_useQuantization)
- {
- walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- else
- {
- walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- /*
- {
- //recursive traversal
- btVector3 qaabbMin = raySource;
- btVector3 qaabbMax = raySource;
- qaabbMin.setMin(rayTarget);
- qaabbMax.setMax(rayTarget);
- qaabbMin += aabbMin;
- qaabbMax += aabbMax;
- reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
- }
- */
- }
- void btQuantizedBvh::swapLeafNodes(int i, int splitIndex)
- {
- if (m_useQuantization)
- {
- btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
- m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
- m_quantizedLeafNodes[splitIndex] = tmp;
- }
- else
- {
- btOptimizedBvhNode tmp = m_leafNodes[i];
- m_leafNodes[i] = m_leafNodes[splitIndex];
- m_leafNodes[splitIndex] = tmp;
- }
- }
- void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex)
- {
- if (m_useQuantization)
- {
- m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
- }
- else
- {
- m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
- }
- }
- //PCK: include
- #include <new>
- #if 0
- //PCK: consts
- static const unsigned BVH_ALIGNMENT = 16;
- static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
- static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
- #endif
- unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
- {
- // I changed this to 0 since the extra padding is not needed or used.
- return 0; //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
- }
- unsigned btQuantizedBvh::calculateSerializeBufferSize() const
- {
- unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
- baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
- if (m_useQuantization)
- {
- return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
- }
- return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
- }
- bool btQuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
- {
- btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
- /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- ///check alignedment for buffer?
- btAssert(0);
- return false;
- }
- */
- btQuantizedBvh* targetBvh = (btQuantizedBvh*)o_alignedDataBuffer;
- // construct the class so the virtual function table, etc will be set up
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (targetBvh) btQuantizedBvh;
- if (i_swapEndian)
- {
- targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
- btSwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
- btSwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
- btSwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
- targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
- targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
- }
- else
- {
- targetBvh->m_curNodeIndex = m_curNodeIndex;
- targetBvh->m_bvhAabbMin = m_bvhAabbMin;
- targetBvh->m_bvhAabbMax = m_bvhAabbMax;
- targetBvh->m_bvhQuantization = m_bvhQuantization;
- targetBvh->m_traversalMode = m_traversalMode;
- targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
- }
- targetBvh->m_useQuantization = m_useQuantization;
- unsigned char* nodeData = (unsigned char*)targetBvh;
- nodeData += sizeof(btQuantizedBvh);
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
- int nodeCount = m_curNodeIndex;
- if (m_useQuantization)
- {
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
- }
- }
- nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
- else
- {
- targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
- }
- }
- nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
- // Now serialize the subtree headers
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
- else
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
- // need to clear padding in destination buffer
- targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
- }
- }
- nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
- // this wipes the virtual function table pointer at the start of the buffer for the class
- *((void**)o_alignedDataBuffer) = NULL;
- return true;
- }
- btQuantizedBvh* btQuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
- {
- if (i_alignedDataBuffer == NULL) // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- return NULL;
- }
- btQuantizedBvh* bvh = (btQuantizedBvh*)i_alignedDataBuffer;
- if (i_swapEndian)
- {
- bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
- btUnSwapVector3Endian(bvh->m_bvhAabbMin);
- btUnSwapVector3Endian(bvh->m_bvhAabbMax);
- btUnSwapVector3Endian(bvh->m_bvhQuantization);
- bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
- bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
- }
- unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
- btAssert(calculatedBufSize <= i_dataBufferSize);
- if (calculatedBufSize > i_dataBufferSize)
- {
- return NULL;
- }
- unsigned char* nodeData = (unsigned char*)bvh;
- nodeData += sizeof(btQuantizedBvh);
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
- int nodeCount = bvh->m_curNodeIndex;
- // 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
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (bvh) btQuantizedBvh(*bvh, false);
- if (bvh->m_useQuantization)
- {
- bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
- }
- else
- {
- bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
- bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
- bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
- bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
- }
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
- // Now serialize the subtree headers
- bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
- {
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
- bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
- bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
- return bvh;
- }
- // Constructor that prevents btVector3's default constructor from being called
- btQuantizedBvh::btQuantizedBvh(btQuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
- m_bvhAabbMax(self.m_bvhAabbMax),
- m_bvhQuantization(self.m_bvhQuantization),
- m_bulletVersion(BT_BULLET_VERSION)
- {
- }
- void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
- {
- m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
- m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
- m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
- {
- int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
- if (numElem)
- {
- btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
- {
- int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
- if (numElem)
- {
- btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
- m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
- {
- int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
- }
- void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
- {
- m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
- m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
- m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
- {
- int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
- if (numElem)
- {
- btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
- {
- int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
- if (numElem)
- {
- btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
- m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
- {
- int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
- }
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
- {
- btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
- m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
- m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
- m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
- quantizedData->m_curNodeIndex = m_curNodeIndex;
- quantizedData->m_useQuantization = m_useQuantization;
- quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
- quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*)(m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
- if (quantizedData->m_contiguousNodesPtr)
- {
- int sz = sizeof(btOptimizedBvhNodeData);
- int numElem = m_contiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
- memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
- memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
- memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
- // Fill padding with zeros to appease msan.
- memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
- }
- serializer->finalizeChunk(chunk, "btOptimizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_contiguousNodes[0]);
- }
- quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
- // printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
- quantizedData->m_quantizedContiguousNodesPtr = (btQuantizedBvhNodeData*)(m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
- if (quantizedData->m_quantizedContiguousNodesPtr)
- {
- int sz = sizeof(btQuantizedBvhNodeData);
- int numElem = m_quantizedContiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
- memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
- memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
- memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
- memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
- memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
- memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
- }
- serializer->finalizeChunk(chunk, "btQuantizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_quantizedContiguousNodes[0]);
- }
- quantizedData->m_traversalMode = int(m_traversalMode);
- quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
- quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*)(m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
- if (quantizedData->m_subTreeInfoPtr)
- {
- int sz = sizeof(btBvhSubtreeInfoData);
- int numElem = m_SubtreeHeaders.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
- memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
- memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
- memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
- memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
- memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
- memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
- memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
- }
- serializer->finalizeChunk(chunk, "btBvhSubtreeInfoData", BT_ARRAY_CODE, (void*)&m_SubtreeHeaders[0]);
- }
- return btQuantizedBvhDataName;
- }
|