Showing the changes to interface/src/VoxelSystem.cpp (1 of 8 files). Show all
Unified · Split
| @@ -99,6 +99,9 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 98 unmodified lines | ||
| 99 | 99 | |
| 100 | 100 | _culledOnce = false; |
| 101 | 101 | _inhideOutOfView = false; |
| 102 | + | |
| 103 | + _lastKnownVoxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE; | |
| 104 | + _lastKnownBoundaryLevelAdjust = 0; | |
| 102 | 105 | } |
| 103 | 106 | |
| 104 | 107 | void VoxelSystem::elementDeleted(OctreeElement* element) { |
| @@ -249,6 +252,9 @@ VoxelSystem::~VoxelSystem() { · 144 unmodified lines | ||
| 249 | 252 | delete _tree; |
| 250 | 253 | } |
| 251 | 254 | |
| 255 | + | |
| 256 | +// This is called by the main application thread on both the initialization of the application and when | |
| 257 | +// the preferences dialog box is called/saved | |
| 252 | 258 | void VoxelSystem::setMaxVoxels(int maxVoxels) { |
| 253 | 259 | if (maxVoxels == _maxVoxels) { |
| 254 | 260 | return; |
| @@ -267,6 +273,8 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) { · 12 unmodified lines | ||
| 267 | 273 | } |
| 268 | 274 | } |
| 269 | 275 | |
| 276 | +// This is called by the main application thread on both the initialization of the application and when | |
| 277 | +// the use voxel shader menu item is chosen | |
| 270 | 278 | void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { |
| 271 | 279 | if (_useVoxelShader == useVoxelShader) { |
| 272 | 280 | return; |
| @@ -330,7 +338,7 @@ void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { · 57 unmodified lines | ||
| 330 | 338 | |
| 331 | 339 | void VoxelSystem::cleanupVoxelMemory() { |
| 332 | 340 | if (_initialized) { |
| 333 | − _bufferWriteLock.lock(); | |
| 341 | + _readArraysLock.lockForWrite(); | |
| 334 | 342 | _initialized = false; // no longer initialized |
| 335 | 343 | if (_useVoxelShader) { |
| 336 | 344 | // these are used when in VoxelShader mode. |
| @@ -368,7 +376,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 31 unmodified lines | ||
| 368 | 376 | delete[] _writeVoxelDirtyArray; |
| 369 | 377 | delete[] _readVoxelDirtyArray; |
| 370 | 378 | _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; |
| 371 | − _bufferWriteLock.unlock(); | |
| 379 | + _readArraysLock.unlock(); | |
| 372 | 380 | } |
| 373 | 381 | } |
| 374 | 382 | |
| @@ -401,7 +409,7 @@ void VoxelSystem::setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndice · 26 unmodified lines | ||
| 401 | 409 | } |
| 402 | 410 | |
| 403 | 411 | void VoxelSystem::initVoxelMemory() { |
| 404 | − _bufferWriteLock.lock(); | |
| 412 | + _readArraysLock.lockForWrite(); | |
| 405 | 413 | |
| 406 | 414 | _memoryUsageRAM = 0; |
| 407 | 415 | _memoryUsageVBO = 0; // our VBO allocations as we know them |
| @@ -516,7 +524,7 @@ void VoxelSystem::initVoxelMemory() { · 108 unmodified lines | ||
| 516 | 524 | |
| 517 | 525 | _initialized = true; |
| 518 | 526 | |
| 519 | − _bufferWriteLock.unlock(); | |
| 527 | + _readArraysLock.unlock(); | |
| 520 | 528 | } |
| 521 | 529 | |
| 522 | 530 | void VoxelSystem::writeToSVOFile(const char* filename, VoxelTreeElement* element) const { |
| @@ -646,7 +654,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 123 unmodified lines | ||
| 646 | 654 | } |
| 647 | 655 | |
| 648 | 656 | _inSetupNewVoxelsForDrawing = true; |
| 649 | − | |
| 657 | + | |
| 650 | 658 | bool didWriteFullVBO = _writeRenderFullVBO; |
| 651 | 659 | if (_tree->isDirty()) { |
| 652 | 660 | static char buffer[64] = { 0 }; |
| @@ -673,7 +681,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 20 unmodified lines | ||
| 673 | 681 | } |
| 674 | 682 | |
| 675 | 683 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it |
| 676 | − _bufferWriteLock.lock(); | |
| 684 | + _readArraysLock.lockForWrite(); | |
| 677 | 685 | |
| 678 | 686 | if (_voxelsUpdated) { |
| 679 | 687 | _voxelsDirty=true; |
| @@ -682,7 +690,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 2 unmodified lines | ||
| 682 | 690 | // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated |
| 683 | 691 | copyWrittenDataToReadArrays(didWriteFullVBO); |
| 684 | 692 | |
| 685 | − _bufferWriteLock.unlock(); | |
| 693 | + _readArraysLock.unlock(); | |
| 686 | 694 | |
| 687 | 695 | quint64 end = usecTimestampNow(); |
| 688 | 696 | int elapsedmsec = (end - start) / 1000; |
| @@ -713,8 +721,8 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 24 unmodified lines | ||
| 713 | 721 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it |
| 714 | 722 | { |
| 715 | 723 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 716 | − "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); | |
| 717 | − _bufferWriteLock.lock(); | |
| 724 | + "setupNewVoxelsForDrawingSingleNode()... _readArraysLock.lockForWrite();" ); | |
| 725 | + _readArraysLock.lockForWrite(); | |
| 718 | 726 | } |
| 719 | 727 | |
| 720 | 728 | _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty |
| @@ -725,7 +733,7 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 4 unmodified lines | ||
| 725 | 733 | // after... |
| 726 | 734 | _voxelsUpdated = 0; |
| 727 | 735 | |
| 728 | − _bufferWriteLock.unlock(); | |
| 736 | + _readArraysLock.unlock(); | |
| 729 | 737 | |
| 730 | 738 | quint64 end = usecTimestampNow(); |
| 731 | 739 | int elapsedmsec = (end - start) / 1000; |
| @@ -733,8 +741,12 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 1 unmodified line | ||
| 733 | 741 | _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; |
| 734 | 742 | } |
| 735 | 743 | |
| 736 | −void VoxelSystem::checkForCulling() { | |
| 744 | +void VoxelSystem::recreateVoxelGeometryInView() { | |
| 745 | + // this is a temporary solution... we need a full implementation that actually does a full redraw into clean VBOs | |
| 746 | + hideOutOfView(true); | |
| 747 | +} | |
| 737 | 748 | |
| 749 | +void VoxelSystem::checkForCulling() { | |
| 738 | 750 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()"); |
| 739 | 751 | quint64 start = usecTimestampNow(); |
| 740 | 752 | |
| @@ -762,7 +774,20 @@ void VoxelSystem::checkForCulling() { · 21 unmodified lines | ||
| 762 | 774 | _hasRecentlyChanged = false; |
| 763 | 775 | } |
| 764 | 776 | |
| 765 | − hideOutOfView(forceFullFrustum); | |
| 777 | + // This would be a good place to do a special processing pass, for example, switching the LOD of the scene | |
| 778 | + bool fullRedraw = (_lastKnownVoxelSizeScale != Menu::getInstance()->getVoxelSizeScale() || | |
| 779 | + _lastKnownBoundaryLevelAdjust != Menu::getInstance()->getBoundaryLevelAdjust()); | |
| 780 | + | |
| 781 | + // track that these values | |
| 782 | + _lastKnownVoxelSizeScale = Menu::getInstance()->getVoxelSizeScale(); | |
| 783 | + _lastKnownBoundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); | |
| 784 | + | |
| 785 | + if (fullRedraw) { | |
| 786 | + // this will remove all old geometry and recreate the correct geometry for all in view voxels | |
| 787 | + recreateVoxelGeometryInView(); | |
| 788 | + } else { | |
| 789 | + hideOutOfView(forceFullFrustum); | |
| 790 | + } | |
| 766 | 791 | |
| 767 | 792 | if (forceFullFrustum) { |
| 768 | 793 | quint64 endViewCulling = usecTimestampNow(); |
| @@ -1197,7 +1222,8 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg · 428 unmodified lines | ||
| 1197 | 1222 | } |
| 1198 | 1223 | } |
| 1199 | 1224 | |
| 1200 | −void VoxelSystem::render(bool texture) { | |
| 1225 | +void VoxelSystem::render() { | |
| 1226 | + bool texture = Menu::getInstance()->isOptionChecked(MenuOption::VoxelTextures); | |
| 1201 | 1227 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 1202 | 1228 | PerformanceWarning warn(showWarnings, "render()"); |
| 1203 | 1229 | |
| @@ -1404,11 +1430,7 @@ void VoxelSystem::killLocalVoxels() { · 200 unmodified lines | ||
| 1404 | 1430 | setupNewVoxelsForDrawing(); |
| 1405 | 1431 | } |
| 1406 | 1432 | |
| 1407 | −void VoxelSystem::redrawInViewVoxels() { | |
| 1408 | − hideOutOfView(true); | |
| 1409 | −} | |
| 1410 | − | |
| 1411 | − | |
| 1433 | +// only called on main thread | |
| 1412 | 1434 | bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void* extraData) { |
| 1413 | 1435 | _nodeCount++; |
| 1414 | 1436 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| @@ -1416,12 +1438,15 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void · 1 unmodified line | ||
| 1416 | 1438 | return true; |
| 1417 | 1439 | } |
| 1418 | 1440 | |
| 1441 | +// only called on main thread, and also always followed by a call to cleanupVoxelMemory() | |
| 1442 | +// you shouldn't be calling this on any other thread or without also cleaning up voxel memory | |
| 1419 | 1443 | void VoxelSystem::clearAllNodesBufferIndex() { |
| 1420 | 1444 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 1421 | 1445 | "VoxelSystem::clearAllNodesBufferIndex()"); |
| 1422 | 1446 | _nodeCount = 0; |
| 1423 | 1447 | _tree->lockForRead(); // we won't change the tree so it's ok to treat this as a read |
| 1424 | 1448 | _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); |
| 1449 | + clearFreeBufferIndexes(); // this should be called too | |
| 1425 | 1450 | _tree->unlock(); |
| 1426 | 1451 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 1427 | 1452 | qDebug("clearing buffer index of %d nodes", _nodeCount); |