Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all
Unified · Split
| @@ -111,6 +111,11 @@ void VoxelSystem::voxelDeleted(VoxelNode* node) { · 110 unmodified lines | |||
| 111 | void VoxelSystem::setUseFastVoxelPipeline(bool useFastVoxelPipeline) { | 111 | void VoxelSystem::setUseFastVoxelPipeline(bool useFastVoxelPipeline) { |
| 112 | _useFastVoxelPipeline = useFastVoxelPipeline; | 112 | _useFastVoxelPipeline = useFastVoxelPipeline; |
| 113 | printf("setUseFastVoxelPipeline() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline)); | 113 | printf("setUseFastVoxelPipeline() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline)); |
| 114 | //forceRedrawEntireTree(); | ||
| 115 | if (_voxelsUpdated < 1) { | ||
| 116 | _voxelsUpdated = 1; | ||
| 117 | } | ||
| 118 | setupNewVoxelsForDrawing(); | ||
| 114 | } | 119 | } |
| 115 | 120 | ||
| 116 | void VoxelSystem::voxelUpdated(VoxelNode* node) { | 121 | void VoxelSystem::voxelUpdated(VoxelNode* node) { |
| @@ -131,8 +136,6 @@ void VoxelSystem::voxelUpdated(VoxelNode* node) { · 14 unmodified lines | |||
| 131 | 136 | ||
| 132 | node->setShouldRender(shouldRender); | 137 | node->setShouldRender(shouldRender); |
| 133 | 138 | ||
| 134 | //printf("VoxelSystem::voxelUpdated() shouldRender=%s\n", debug::valueOf(shouldRender)); | ||
| 135 | |||
| 136 | if (!node->isLeaf()) { | 139 | if (!node->isLeaf()) { |
| 137 | 140 | ||
| 138 | // As we check our children, see if any of them went from shouldRender to NOT shouldRender | 141 | // As we check our children, see if any of them went from shouldRender to NOT shouldRender |
| @@ -522,7 +525,6 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 383 unmodified lines | |||
| 522 | break; | 525 | break; |
| 523 | } | 526 | } |
| 524 | 527 | ||
| 525 | //printf("VoxelSystem::parseData() _useFastVoxelPipeline=%s\n", debug::valueOf(_useFastVoxelPipeline)); | ||
| 526 | 528 | ||
| 527 | if (!_useFastVoxelPipeline || _writeRenderFullVBO) { | 529 | if (!_useFastVoxelPipeline || _writeRenderFullVBO) { |
| 528 | setupNewVoxelsForDrawing(); | 530 | setupNewVoxelsForDrawing(); |
| @@ -538,7 +540,6 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 9 unmodified lines | |||
| 538 | void VoxelSystem::setupNewVoxelsForDrawing() { | 540 | void VoxelSystem::setupNewVoxelsForDrawing() { |
| 539 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | 541 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 540 | "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated | 542 | "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated |
| 541 | _inSetupNewVoxelsForDrawing = true; | ||
| 542 | uint64_t start = usecTimestampNow(); | 543 | uint64_t start = usecTimestampNow(); |
| 543 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; | 544 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; |
| 544 | 545 | ||
| @@ -550,25 +551,9 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 5 unmodified lines | |||
| 550 | return; // bail early, it hasn't been long enough since the last time we ran | 551 | return; // bail early, it hasn't been long enough since the last time we ran |
| 551 | } | 552 | } |
| 552 | 553 | ||
| 553 | uint64_t sinceLastViewCulling = (start - _lastViewCulling) / 1000; | 554 | _inSetupNewVoxelsForDrawing = true; |
| 554 | // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view | ||
| 555 | if ((sinceLastViewCulling >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) | ||
| 556 | && !isViewChanging()) { | ||
| 557 | _lastViewCulling = start; | ||
| 558 | |||
| 559 | // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove | ||
| 560 | // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which | ||
| 561 | // can be expensive). | ||
| 562 | removeOutOfView(); | ||
| 563 | |||
| 564 | // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So, | ||
| 565 | // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on | ||
| 566 | // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary. | ||
| 567 | cleanupRemovedVoxels(); | ||
| 568 | 555 | ||
| 569 | uint64_t endViewCulling = usecTimestampNow(); | 556 | checkForCulling(); // check for out of view and deleted voxels... |
| 570 | _lastViewCullingElapsed = (endViewCulling - start) / 1000; | ||
| 571 | } | ||
| 572 | 557 | ||
| 573 | bool didWriteFullVBO = _writeRenderFullVBO; | 558 | bool didWriteFullVBO = _writeRenderFullVBO; |
| 574 | if (_tree->isDirty()) { | 559 | if (_tree->isDirty()) { |
| @@ -616,11 +601,13 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 41 unmodified lines | |||
| 616 | } | 601 | } |
| 617 | 602 | ||
| 618 | void VoxelSystem::setupNewVoxelsForDrawingSingleNode() { | 603 | void VoxelSystem::setupNewVoxelsForDrawingSingleNode() { |
| 604 | |||
| 619 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | 605 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 620 | "setupNewVoxelsForDrawingSingleNode()"); // would like to include _voxelsInArrays, _voxelsUpdated | 606 | "setupNewVoxelsForDrawingSingleNode()"); // would like to include _voxelsInArrays, _voxelsUpdated |
| 607 | |||
| 621 | uint64_t start = usecTimestampNow(); | 608 | uint64_t start = usecTimestampNow(); |
| 622 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; | 609 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; |
| 623 | 610 | ||
| 624 | // clear up the VBOs for any nodes that have been recently deleted. | 611 | // clear up the VBOs for any nodes that have been recently deleted. |
| 625 | clearFreeBufferIndexes(); | 612 | clearFreeBufferIndexes(); |
| 626 | 613 | ||
| @@ -629,10 +616,37 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode() { · 2 unmodified lines | |||
| 629 | return; // bail early, it hasn't been long enough since the last time we ran | 616 | return; // bail early, it hasn't been long enough since the last time we ran |
| 630 | } | 617 | } |
| 631 | 618 | ||
| 619 | |||
| 620 | checkForCulling(); // check for out of view and deleted voxels... | ||
| 621 | |||
| 622 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it | ||
| 623 | pthread_mutex_lock(&_bufferWriteLock); | ||
| 624 | |||
| 625 | _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty | ||
| 626 | |||
| 627 | // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | ||
| 628 | copyWrittenDataToReadArrays(_writeRenderFullVBO); | ||
| 629 | |||
| 630 | // after... | ||
| 631 | _voxelsUpdated = 0; | ||
| 632 | |||
| 633 | pthread_mutex_unlock(&_bufferWriteLock); | ||
| 634 | |||
| 635 | uint64_t end = usecTimestampNow(); | ||
| 636 | int elapsedmsec = (end - start) / 1000; | ||
| 637 | _setupNewVoxelsForDrawingLastFinished = end; | ||
| 638 | _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; | ||
| 639 | } | ||
| 640 | |||
| 641 | void VoxelSystem::checkForCulling() { | ||
| 642 | |||
| 643 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()"); | ||
| 644 | uint64_t start = usecTimestampNow(); | ||
| 632 | uint64_t sinceLastViewCulling = (start - _lastViewCulling) / 1000; | 645 | uint64_t sinceLastViewCulling = (start - _lastViewCulling) / 1000; |
| 633 | // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view | 646 | // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view |
| 634 | if ((sinceLastViewCulling >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) | 647 | if ((sinceLastViewCulling >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) |
| 635 | && !isViewChanging()) { | 648 | && !isViewChanging()) { |
| 649 | |||
| 636 | _lastViewCulling = start; | 650 | _lastViewCulling = start; |
| 637 | 651 | ||
| 638 | // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove | 652 | // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove |
| @@ -648,56 +662,15 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode() { · 9 unmodified lines | |||
| 648 | uint64_t endViewCulling = usecTimestampNow(); | 662 | uint64_t endViewCulling = usecTimestampNow(); |
| 649 | _lastViewCullingElapsed = (endViewCulling - start) / 1000; | 663 | _lastViewCullingElapsed = (endViewCulling - start) / 1000; |
| 650 | } | 664 | } |
| 651 | |||
| 652 | bool didWriteFullVBO = _writeRenderFullVBO; | ||
| 653 | |||
| 654 | if (_tree->isDirty()) { | ||
| 655 | static char buffer[64] = { 0 }; | ||
| 656 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { | ||
| 657 | sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO)); | ||
| 658 | }; | ||
| 659 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); | ||
| 660 | _callsToTreesToArrays++; | ||
| 661 | if (_writeRenderFullVBO) { | ||
| 662 | _voxelsInWriteArrays = 0; // reset our VBO | ||
| 663 | _freeIndexes.clear(); // reset our free indexes | ||
| 664 | _voxelsUpdated = newTreeToArrays(_tree->rootNode); | ||
| 665 | _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean | ||
| 666 | _abandonedVBOSlots = 0; // reset the count of our abandoned slots, why is this here and not earlier???? | ||
| 667 | } | ||
| 668 | |||
| 669 | // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are | ||
| 670 | // ok again, until/unless we call removeOutOfView() | ||
| 671 | _writeRenderFullVBO = false; | ||
| 672 | } else { | ||
| 673 | _voxelsUpdated = 0; | ||
| 674 | } | ||
| 675 | |||
| 676 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it | ||
| 677 | pthread_mutex_lock(&_bufferWriteLock); | ||
| 678 | |||
| 679 | if (_voxelsUpdated) { | ||
| 680 | _voxelsDirty=true; | ||
| 681 | } | ||
| 682 | |||
| 683 | // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | ||
| 684 | copyWrittenDataToReadArrays(didWriteFullVBO); | ||
| 685 | |||
| 686 | // after... | ||
| 687 | _voxelsUpdated = 0; | ||
| 688 | |||
| 689 | pthread_mutex_unlock(&_bufferWriteLock); | ||
| 690 | |||
| 691 | uint64_t end = usecTimestampNow(); | ||
| 692 | int elapsedmsec = (end - start) / 1000; | ||
| 693 | _setupNewVoxelsForDrawingLastFinished = end; | ||
| 694 | _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; | ||
| 695 | } | 665 | } |
| 666 | |||
| 696 | void VoxelSystem::cleanupRemovedVoxels() { | 667 | void VoxelSystem::cleanupRemovedVoxels() { |
| 697 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "cleanupRemovedVoxels()"); | 668 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "cleanupRemovedVoxels()"); |
| 698 | // This handles cleanup of voxels that were culled as part of our regular out of view culling operation | 669 | // This handles cleanup of voxels that were culled as part of our regular out of view culling operation |
| 699 | if (!_removedVoxels.isEmpty()) { | 670 | if (!_removedVoxels.isEmpty()) { |
| 700 | qDebug() << "cleanupRemovedVoxels().. _removedVoxels=" << _removedVoxels.count() << "\n"; | 671 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 672 | qDebug() << "cleanupRemovedVoxels().. _removedVoxels=" << _removedVoxels.count() << "\n"; | ||
| 673 | } | ||
| 701 | while (!_removedVoxels.isEmpty()) { | 674 | while (!_removedVoxels.isEmpty()) { |
| 702 | delete _removedVoxels.extract(); | 675 | delete _removedVoxels.extract(); |
| 703 | } | 676 | } |
| @@ -707,7 +680,10 @@ void VoxelSystem::cleanupRemovedVoxels() { · 3 unmodified lines | |||
| 707 | // are abandonded we want to rerender our full VBOs | 680 | // are abandonded we want to rerender our full VBOs |
| 708 | const float TOO_MANY_ABANDONED_RATIO = 0.5f; | 681 | const float TOO_MANY_ABANDONED_RATIO = 0.5f; |
| 709 | if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) { | 682 | if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) { |
| 710 | qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots ["<< _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO \n"; | 683 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 684 | qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots [" | ||
| 685 | << _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO \n"; | ||
| 686 | } | ||
| 711 | _writeRenderFullVBO = true; | 687 | _writeRenderFullVBO = true; |
| 712 | } | 688 | } |
| 713 | } | 689 | } |
| @@ -1181,7 +1157,7 @@ int VoxelSystem::_nodeCount = 0; · 467 unmodified lines | |||
| 1181 | void VoxelSystem::killLocalVoxels() { | 1157 | void VoxelSystem::killLocalVoxels() { |
| 1182 | _tree->eraseAllVoxels(); | 1158 | _tree->eraseAllVoxels(); |
| 1183 | _voxelsInWriteArrays = _voxelsInReadArrays = 0; // better way to do this?? | 1159 | _voxelsInWriteArrays = _voxelsInReadArrays = 0; // better way to do this?? |
| 1184 | //setupNewVoxelsForDrawing(); | 1160 | setupNewVoxelsForDrawing(); |
| 1185 | } | 1161 | } |
| 1186 | 1162 | ||
| 1187 | 1163 | ||