| 398 | } |
| 399 | |
| 400 | AvailabilityNode* QuadtreeAvailability::addNode( |
| 401 | const QuadtreeTileID& tileID, |
| 402 | AvailabilityNode* pParentNode) noexcept { |
| 403 | |
| 404 | if (!pParentNode || tileID.level == 0) { |
| 405 | if (this->_pRoot) { |
| 406 | // The root node already exists. |
| 407 | return nullptr; |
| 408 | } else { |
| 409 | // Set the root node. |
| 410 | this->_pRoot = std::make_unique<AvailabilityNode>(); |
| 411 | return this->_pRoot.get(); |
| 412 | } |
| 413 | } |
| 414 | |
| 415 | // We can't insert a new child node if the parent does not have a loaded |
| 416 | // subtree yet. |
| 417 | if (!pParentNode->subtree) { |
| 418 | return nullptr; |
| 419 | } |
| 420 | |
| 421 | // The tile must fall exactly after the parent subtree. |
| 422 | if ((tileID.level % this->_subtreeLevels) != 0) { |
| 423 | return nullptr; |
| 424 | } |
| 425 | |
| 426 | uint32_t subtreeRelativeMask = ~(0xFFFFFFFF << this->_subtreeLevels); |
| 427 | uint32_t mortonIndex = getMortonIndex( |
| 428 | tileID.x & subtreeRelativeMask, |
| 429 | tileID.y & subtreeRelativeMask); |
| 430 | |
| 431 | AvailabilityAccessor subtreeAvailabilityAccessor( |
| 432 | pParentNode->subtree->subtreeAvailability, |
| 433 | *pParentNode->subtree); |
| 434 | |
| 435 | bool subtreeAvailable = false; |
| 436 | uint32_t subtreeIndex = 0; |
| 437 | if (subtreeAvailabilityAccessor.isConstant()) { |
| 438 | subtreeAvailable = subtreeAvailabilityAccessor.getConstant(); |
| 439 | subtreeIndex = mortonIndex; |
| 440 | } else if (subtreeAvailabilityAccessor.isBufferView()) { |
| 441 | uint32_t byteIndex = mortonIndex >> 3; |
| 442 | uint8_t bitIndex = static_cast<uint8_t>(mortonIndex & 7); |
| 443 | uint8_t bitMask = static_cast<uint8_t>(1 << bitIndex); |
| 444 | |
| 445 | std::span<const std::byte> clippedSubtreeAvailability = |
| 446 | subtreeAvailabilityAccessor.getBufferAccessor().subspan(0, byteIndex); |
| 447 | uint8_t availabilityByte = (uint8_t)subtreeAvailabilityAccessor[byteIndex]; |
| 448 | |
| 449 | subtreeAvailable = availabilityByte & bitMask; |
| 450 | |
| 451 | // Calculte the index the child subtree is stored in. |
| 452 | if (subtreeAvailable) { |
| 453 | subtreeIndex = |
| 454 | // TODO: maybe partial sums should be precomputed in the subtree |
| 455 | // availability, instead of iterating through the buffer each time. |
| 456 | AvailabilityUtilities::countOnesInBuffer(clippedSubtreeAvailability) + |
| 457 | AvailabilityUtilities::countOnesInByte( |
nothing calls this directly
no test coverage detected