Showing the changes to interface/src/VoxelSystem.cpp (1 of 9 files). Show all
Unified · Split
| @@ -35,7 +35,6 @@ · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | const bool VoxelSystem::DONT_BAIL_EARLY = false; |
| 37 | 37 | |
| 38 | − | |
| 39 | 38 | float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 }; |
| 40 | 39 | |
| 41 | 40 | float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7 |
| @@ -107,16 +106,18 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 65 unmodified lines | ||
| 107 | 106 | |
| 108 | 107 | _inSetupNewVoxelsForDrawing = false; |
| 109 | 108 | _useFastVoxelPipeline = false; |
| 110 | − | |
| 109 | + | |
| 111 | 110 | _culledOnce = false; |
| 112 | 111 | _inhideOutOfView = false; |
| 113 | 112 | _treeIsBusy = false; |
| 113 | + | |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | 116 | void VoxelSystem::elementDeleted(OctreeElement* element) { |
| 117 | 117 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 118 | 118 | if (voxel->getVoxelSystem() == this) { |
| 119 | 119 | if (_voxelsInWriteArrays != 0) { |
| 120 | +qDebug() << "elementDeleted()... about to call forceRemoveNodeFromArrays()\n"; | |
| 120 | 121 | forceRemoveNodeFromArrays(voxel); |
| 121 | 122 | } else { |
| 122 | 123 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| @@ -148,11 +149,11 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 25 unmodified lines | ||
| 148 | 149 | if (voxel->getShouldRender() != shouldRender) { |
| 149 | 150 | voxel->setShouldRender(shouldRender); |
| 150 | 151 | } |
| 151 | − | |
| 152 | + | |
| 152 | 153 | if (!voxel->isLeaf()) { |
| 153 | − | |
| 154 | + | |
| 154 | 155 | // As we check our children, see if any of them went from shouldRender to NOT shouldRender |
| 155 | − // then we probably dropped LOD and if we don't have color, we want to average our children | |
| 156 | + // then we probably dropped LOD and if we don't have color, we want to average our children | |
| 156 | 157 | // for a new color. |
| 157 | 158 | int childrenGotHiddenCount = 0; |
| 158 | 159 | for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { |
| @@ -176,7 +177,7 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 17 unmodified lines | ||
| 176 | 177 | _voxelsUpdated++; |
| 177 | 178 | |
| 178 | 179 | voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things. |
| 179 | − | |
| 180 | + | |
| 180 | 181 | setupNewVoxelsForDrawingSingleNode(); |
| 181 | 182 | } |
| 182 | 183 | } |
| @@ -219,7 +220,7 @@ void VoxelSystem::freeBufferIndex(glBufferIndex index) { · 36 unmodified lines | ||
| 219 | 220 | break; |
| 220 | 221 | } |
| 221 | 222 | } |
| 222 | − } | |
| 223 | + } | |
| 223 | 224 | if (!inList) { |
| 224 | 225 | // make the index available for next node that needs to be drawn |
| 225 | 226 | pthread_mutex_lock(&_freeIndexLock); |
| @@ -308,7 +309,7 @@ void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { · 82 unmodified lines | ||
| 308 | 309 | } |
| 309 | 310 | |
| 310 | 311 | bool wasInitialized = _initialized; |
| 311 | − | |
| 312 | + | |
| 312 | 313 | // If we're "turning on" Voxels as points, we need to double check that we're in voxel shader mode. |
| 313 | 314 | // Voxels as points uses the VoxelShader memory model, so if we're not in voxel shader mode, |
| 314 | 315 | // then set it to voxel shader mode. |
| @@ -318,7 +319,7 @@ void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { · 3 unmodified lines | ||
| 318 | 319 | // If enabling this... then do it before checking voxel shader status, that way, if voxel |
| 319 | 320 | // shader is already enabled, we just start drawing as points. |
| 320 | 321 | _voxelsAsPoints = true; |
| 321 | − | |
| 322 | + | |
| 322 | 323 | if (!_useVoxelShader) { |
| 323 | 324 | setUseVoxelShader(true); |
| 324 | 325 | _voxelShaderModeWhenVoxelsAsPointsEnabled = false; |
| @@ -354,7 +355,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 29 unmodified lines | ||
| 354 | 355 | |
| 355 | 356 | delete[] _writeVoxelShaderData; |
| 356 | 357 | delete[] _readVoxelShaderData; |
| 357 | − | |
| 358 | + | |
| 358 | 359 | _writeVoxelShaderData = _readVoxelShaderData = NULL; |
| 359 | 360 | |
| 360 | 361 | } else { |
| @@ -368,7 +369,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 7 unmodified lines | ||
| 368 | 369 | glDeleteBuffers(1, &_vboIndicesRight); |
| 369 | 370 | glDeleteBuffers(1, &_vboIndicesFront); |
| 370 | 371 | glDeleteBuffers(1, &_vboIndicesBack); |
| 371 | − | |
| 372 | + | |
| 372 | 373 | delete[] _readVerticesArray; |
| 373 | 374 | delete[] _writeVerticesArray; |
| 374 | 375 | delete[] _readColorsArray; |
| @@ -420,12 +421,12 @@ void VoxelSystem::initVoxelMemory() { · 45 unmodified lines | ||
| 420 | 421 | |
| 421 | 422 | _memoryUsageRAM = 0; |
| 422 | 423 | _memoryUsageVBO = 0; // our VBO allocations as we know them |
| 423 | − | |
| 424 | + | |
| 424 | 425 | // if _voxelsAsPoints then we must have _useVoxelShader |
| 425 | 426 | if (_voxelsAsPoints && !_useVoxelShader) { |
| 426 | 427 | _useVoxelShader = true; |
| 427 | 428 | } |
| 428 | − | |
| 429 | + | |
| 429 | 430 | if (_useVoxelShader) { |
| 430 | 431 | GLuint* indicesArray = new GLuint[_maxVoxels]; |
| 431 | 432 | |
| @@ -445,7 +446,7 @@ void VoxelSystem::initVoxelMemory() { · 13 unmodified lines | ||
| 445 | 446 | glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID); |
| 446 | 447 | glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW); |
| 447 | 448 | _memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData); |
| 448 | − | |
| 449 | + | |
| 449 | 450 | // delete the indices and normals arrays that are no longer needed |
| 450 | 451 | delete[] indicesArray; |
| 451 | 452 | |
| @@ -474,7 +475,7 @@ void VoxelSystem::initVoxelMemory() { · 22 unmodified lines | ||
| 474 | 475 | setupFaceIndices(_vboIndicesRight, identityIndicesRight); |
| 475 | 476 | setupFaceIndices(_vboIndicesFront, identityIndicesFront); |
| 476 | 477 | setupFaceIndices(_vboIndicesBack, identityIndicesBack); |
| 477 | − | |
| 478 | + | |
| 478 | 479 | // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel |
| 479 | 480 | int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; |
| 480 | 481 | glGenBuffers(1, &_vboVerticesID); |
| @@ -519,10 +520,10 @@ void VoxelSystem::initVoxelMemory() { · 38 unmodified lines | ||
| 519 | 520 | _perlinModulateProgram.bind(); |
| 520 | 521 | _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); |
| 521 | 522 | _perlinModulateProgram.release(); |
| 522 | − | |
| 523 | + | |
| 523 | 524 | _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/shadow_map.frag"); |
| 524 | 525 | _shadowMapProgram.link(); |
| 525 | − | |
| 526 | + | |
| 526 | 527 | _shadowMapProgram.bind(); |
| 527 | 528 | _shadowMapProgram.setUniformValue("shadowMap", 0); |
| 528 | 529 | _shadowMapProgram.release(); |
| @@ -571,26 +572,26 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 42 unmodified lines | ||
| 571 | 572 | switch(command) { |
| 572 | 573 | case PACKET_TYPE_VOXEL_DATA: { |
| 573 | 574 | PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData() PACKET_TYPE_VOXEL_DATA part...",showTimingDetails); |
| 574 | − | |
| 575 | + | |
| 575 | 576 | unsigned char* dataAt = sourceBuffer + numBytesPacketHeader; |
| 576 | 577 | |
| 577 | 578 | VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt)); |
| 578 | 579 | dataAt += sizeof(VOXEL_PACKET_FLAGS); |
| 579 | 580 | VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt); |
| 580 | 581 | dataAt += sizeof(VOXEL_PACKET_SEQUENCE); |
| 581 | − | |
| 582 | + | |
| 582 | 583 | VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt); |
| 583 | 584 | dataAt += sizeof(VOXEL_PACKET_SENT_TIME); |
| 584 | − | |
| 585 | + | |
| 585 | 586 | bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT); |
| 586 | 587 | bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT); |
| 587 | − | |
| 588 | + | |
| 588 | 589 | VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); |
| 589 | 590 | int flightTime = arrivedAt - sentAt; |
| 590 | − | |
| 591 | + | |
| 591 | 592 | VOXEL_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; |
| 592 | 593 | int dataBytes = numBytes - VOXEL_PACKET_HEADER_SIZE; |
| 593 | − | |
| 594 | + | |
| 594 | 595 | int subsection = 1; |
| 595 | 596 | while (dataBytes > 0) { |
| 596 | 597 | if (packetIsCompressed) { |
| @@ -605,7 +606,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 8 unmodified lines | ||
| 605 | 606 | } else { |
| 606 | 607 | sectionLength = dataBytes; |
| 607 | 608 | } |
| 608 | − | |
| 609 | + | |
| 609 | 610 | if (sectionLength) { |
| 610 | 611 | // ask the VoxelTree to read the bitstream into the tree |
| 611 | 612 | ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID()); |
| @@ -616,12 +617,12 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 4 unmodified lines | ||
| 616 | 617 | qDebug("VoxelSystem::parseData() ... Got Packet Section" |
| 617 | 618 | " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" |
| 618 | 619 | " subsection:%d sectionLength:%d uncompressed:%d\n", |
| 619 | − debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), | |
| 620 | + debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), | |
| 620 | 621 | sequence, flightTime, numBytes, dataBytes, subsection, sectionLength, packetData.getUncompressedSize()); |
| 621 | 622 | } |
| 622 | 623 | _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); |
| 623 | 624 | unlockTree(); |
| 624 | − | |
| 625 | + | |
| 625 | 626 | dataBytes -= sectionLength; |
| 626 | 627 | dataAt += sectionLength; |
| 627 | 628 | } |
| @@ -635,15 +636,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 7 unmodified lines | ||
| 635 | 636 | } else { |
| 636 | 637 | setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY); |
| 637 | 638 | } |
| 638 | − | |
| 639 | + | |
| 639 | 640 | Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::VOXELS).updateValue(numBytes); |
| 640 | − | |
| 641 | + | |
| 641 | 642 | return numBytes; |
| 642 | 643 | } |
| 643 | 644 | |
| 644 | 645 | void VoxelSystem::setupNewVoxelsForDrawing() { |
| 645 | − | |
| 646 | − | |
| 647 | 646 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 648 | 647 | "setupNewVoxelsForDrawing()"); |
| 649 | 648 | |
| @@ -653,7 +652,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 3 unmodified lines | ||
| 653 | 652 | |
| 654 | 653 | uint64_t start = usecTimestampNow(); |
| 655 | 654 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; |
| 656 | − | |
| 655 | + | |
| 657 | 656 | bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging |
| 658 | 657 | if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) { |
| 659 | 658 | return; // bail early, it hasn't been long enough since the last time we ran |
| @@ -665,7 +664,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 5 unmodified lines | ||
| 665 | 664 | if (_tree->isDirty()) { |
| 666 | 665 | static char buffer[64] = { 0 }; |
| 667 | 666 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 668 | − sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO)); | |
| 667 | + sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO)); | |
| 669 | 668 | }; |
| 670 | 669 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); |
| 671 | 670 | _callsToTreesToArrays++; |
| @@ -678,17 +677,17 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 6 unmodified lines | ||
| 678 | 677 | if (_writeRenderFullVBO) { |
| 679 | 678 | _abandonedVBOSlots = 0; // reset the count of our abandoned slots, why is this here and not earlier???? |
| 680 | 679 | } |
| 681 | − | |
| 680 | + | |
| 682 | 681 | // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are |
| 683 | − // ok again, until/unless we call removeOutOfView() | |
| 684 | − _writeRenderFullVBO = false; | |
| 682 | + // ok again, until/unless we call removeOutOfView() | |
| 683 | + _writeRenderFullVBO = false; | |
| 685 | 684 | } else { |
| 686 | 685 | _voxelsUpdated = 0; |
| 687 | 686 | } |
| 688 | − | |
| 687 | + | |
| 689 | 688 | // lock on the buffer write lock so we can't modify the data when the GPU is reading it |
| 690 | 689 | pthread_mutex_lock(&_bufferWriteLock); |
| 691 | − | |
| 690 | + | |
| 692 | 691 | if (_voxelsUpdated) { |
| 693 | 692 | _voxelsDirty=true; |
| 694 | 693 | } |
| @@ -703,6 +702,11 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 8 unmodified lines | ||
| 703 | 702 | _setupNewVoxelsForDrawingLastFinished = end; |
| 704 | 703 | _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; |
| 705 | 704 | _inSetupNewVoxelsForDrawing = false; |
| 705 | + | |
| 706 | + bool extraDebugging = Application::getInstance()->getLogger()->extraDebugging(); | |
| 707 | + if (extraDebugging) { | |
| 708 | + qDebug("setupNewVoxelsForDrawing()... _voxelsUpdated=%lu...\n",_voxelsUpdated); | |
| 709 | + } | |
| 706 | 710 | } |
| 707 | 711 | |
| 708 | 712 | void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { |
| @@ -713,7 +717,7 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 4 unmodified lines | ||
| 713 | 717 | uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000; |
| 714 | 718 | |
| 715 | 719 | bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging |
| 716 | − if (allowBailEarly && !iAmDebugging && | |
| 720 | + if (allowBailEarly && !iAmDebugging && | |
| 717 | 721 | sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) { |
| 718 | 722 | return; // bail early, it hasn't been long enough since the last time we ran |
| 719 | 723 | } |
| @@ -745,19 +749,17 @@ void VoxelSystem::checkForCulling() { · 25 unmodified lines | ||
| 745 | 749 | |
| 746 | 750 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()"); |
| 747 | 751 | uint64_t start = usecTimestampNow(); |
| 748 | − | |
| 749 | − | |
| 752 | + | |
| 750 | 753 | // track how long its been since we were last moving. If we have recently moved then only use delta frustums, if |
| 751 | 754 | // it's been a long time since we last moved, then go ahead and do a full frustum cull. |
| 752 | 755 | if (isViewChanging()) { |
| 753 | 756 | _lastViewIsChanging = start; |
| 754 | 757 | } |
| 755 | 758 | uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000; |
| 756 | − | |
| 757 | 759 | bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)); |
| 758 | 760 | |
| 759 | 761 | // These has changed events will occur before we stop. So we need to remember this for when we finally have stopped |
| 760 | − // moving long enough to be enoughTime | |
| 762 | + // moving long enough to be enoughTime | |
| 761 | 763 | if (hasViewChanged()) { |
| 762 | 764 | _hasRecentlyChanged = true; |
| 763 | 765 | } |
| @@ -767,25 +769,25 @@ void VoxelSystem::checkForCulling() { · 3 unmodified lines | ||
| 767 | 769 | bool forceFullFrustum = enoughTime && _hasRecentlyChanged; |
| 768 | 770 | |
| 769 | 771 | // in hide mode, we only track the full frustum culls, because we don't care about the partials. |
| 770 | − if (forceFullFrustum) { | |
| 772 | + if (forceFullFrustum) { | |
| 771 | 773 | _lastViewCulling = start; |
| 772 | 774 | _hasRecentlyChanged = false; |
| 773 | 775 | } |
| 774 | − | |
| 776 | + | |
| 775 | 777 | hideOutOfView(forceFullFrustum); |
| 776 | 778 | |
| 777 | − if (forceFullFrustum) { | |
| 779 | + if (forceFullFrustum) { | |
| 778 | 780 | uint64_t endViewCulling = usecTimestampNow(); |
| 779 | 781 | _lastViewCullingElapsed = (endViewCulling - start) / 1000; |
| 780 | 782 | } |
| 781 | − | |
| 783 | + | |
| 782 | 784 | // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So, |
| 783 | 785 | // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on |
| 784 | 786 | // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary. |
| 785 | 787 | cleanupRemovedVoxels(); |
| 786 | 788 | |
| 787 | 789 | uint64_t sinceLastAudit = (start - _lastAudit) / 1000; |
| 788 | − | |
| 790 | + | |
| 789 | 791 | if (Menu::getInstance()->isOptionChecked(MenuOption::AutomaticallyAuditTree)) { |
| 790 | 792 | if (sinceLastAudit >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) { |
| 791 | 793 | _lastAudit = start; |
| @@ -812,7 +814,7 @@ void VoxelSystem::cleanupRemovedVoxels() { · 20 unmodified lines | ||
| 812 | 814 | const float TOO_MANY_ABANDONED_RATIO = 0.5f; |
| 813 | 815 | if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) { |
| 814 | 816 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 815 | − qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots [" | |
| 817 | + qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots [" | |
| 816 | 818 | << _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO \n"; |
| 817 | 819 | } |
| 818 | 820 | _writeRenderFullVBO = true; |
| @@ -822,10 +824,10 @@ void VoxelSystem::cleanupRemovedVoxels() { · 3 unmodified lines | ||
| 822 | 824 | void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() { |
| 823 | 825 | copyWrittenDataSegmentToReadArrays(0, _voxelsInWriteArrays - 1); |
| 824 | 826 | _voxelsInReadArrays = _voxelsInWriteArrays; |
| 825 | − | |
| 827 | + | |
| 826 | 828 | // clear our dirty flags |
| 827 | 829 | memset(_writeVoxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool)); |
| 828 | − | |
| 830 | + | |
| 829 | 831 | // let the reader know to get the full array |
| 830 | 832 | _readRenderFullVBO = true; |
| 831 | 833 | } |
| @@ -851,7 +853,7 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { · 19 unmodified lines | ||
| 851 | 853 | } |
| 852 | 854 | } |
| 853 | 855 | } |
| 854 | − | |
| 856 | + | |
| 855 | 857 | // if we got to the end of the array, and we're in an active dirty segment... |
| 856 | 858 | if (inSegment) { |
| 857 | 859 | copyWrittenDataSegmentToReadArrays(segmentStart, _voxelsInWriteArrays - 1); |
| @@ -910,9 +912,9 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) { · 52 unmodified lines | ||
| 910 | 912 | voxel->setShouldRender(shouldRender); |
| 911 | 913 | // let children figure out their renderness |
| 912 | 914 | if (!voxel->isLeaf()) { |
| 913 | − | |
| 915 | + | |
| 914 | 916 | // As we check our children, see if any of them went from shouldRender to NOT shouldRender |
| 915 | − // then we probably dropped LOD and if we don't have color, we want to average our children | |
| 917 | + // then we probably dropped LOD and if we don't have color, we want to average our children | |
| 916 | 918 | // for a new color. |
| 917 | 919 | int childrenGotHiddenCount = 0; |
| 918 | 920 | for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { |
| @@ -930,17 +932,23 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) { · 11 unmodified lines | ||
| 930 | 932 | voxel->calculateAverageFromChildren(); |
| 931 | 933 | } |
| 932 | 934 | } |
| 933 | − if (_writeRenderFullVBO) { | |
| 934 | − const bool DONT_REUSE_INDEX = false; | |
| 935 | − const bool FORCE_REDRAW = true; | |
| 936 | − voxelsUpdated += updateNodeInArrays(voxel, DONT_REUSE_INDEX, FORCE_REDRAW); | |
| 937 | − } else { | |
| 938 | − const bool REUSE_INDEX = true; | |
| 939 | − const bool DONT_FORCE_REDRAW = false; | |
| 940 | − voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW); | |
| 935 | + | |
| 936 | + // for either voxels that should not render, or those that should render and are in view | |
| 937 | + // update their geometry in the array.if the voxel "should render" but is not in view, then | |
| 938 | + // it actually doesn't need to be rendered | |
| 939 | + if (!shouldRender || voxel->isInView(*_viewFrustum)) { | |
| 940 | + if (_writeRenderFullVBO) { | |
| 941 | + const bool DONT_REUSE_INDEX = false; | |
| 942 | + const bool FORCE_REDRAW = true; | |
| 943 | + voxelsUpdated += updateNodeInArrays(voxel, DONT_REUSE_INDEX, FORCE_REDRAW); | |
| 944 | + } else { | |
| 945 | + const bool REUSE_INDEX = true; | |
| 946 | + const bool DONT_FORCE_REDRAW = false; | |
| 947 | + voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW); | |
| 948 | + } | |
| 941 | 949 | } |
| 942 | 950 | voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things. |
| 943 | − | |
| 951 | + | |
| 944 | 952 | return voxelsUpdated; |
| 945 | 953 | } |
| 946 | 954 | |
| @@ -959,7 +967,7 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { · 12 unmodified lines | ||
| 959 | 967 | // If this node has not yet been written to the array, then add it to the end of the array. |
| 960 | 968 | glBufferIndex nodeIndex = node->getBufferIndex(); |
| 961 | 969 | node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); |
| 962 | − freeBufferIndex(nodeIndex); // NOTE: This is make the node invisible! | |
| 970 | + freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! | |
| 963 | 971 | return 1; // updated! |
| 964 | 972 | } |
| 965 | 973 | return 0; // not-updated |
| @@ -982,11 +990,11 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 16 unmodified lines | ||
| 982 | 990 | if (!_initialized) { |
| 983 | 991 | return 0; |
| 984 | 992 | } |
| 985 | − | |
| 993 | + | |
| 986 | 994 | // If we've changed any attributes (our renderness, our color, etc), or we've been told to force a redraw |
| 987 | 995 | // then update the Arrays... |
| 988 | 996 | if (forceDraw || node->isDirty()) { |
| 989 | − // If we're should render, use our legit location and scale, | |
| 997 | + // If we're should render, use our legit location and scale, | |
| 990 | 998 | if (node->getShouldRender()) { |
| 991 | 999 | glm::vec3 startVertex = node->getCorner(); |
| 992 | 1000 | float voxelScale = node->getScale(); |
| @@ -1016,9 +1024,9 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 23 unmodified lines | ||
| 1016 | 1024 | void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, |
| 1017 | 1025 | float voxelScale, const nodeColor& color) { |
| 1018 | 1026 | |
| 1019 | − if (_initialized) { | |
| 1027 | + if (_initialized && nodeIndex <= _maxVoxels) { | |
| 1020 | 1028 | _writeVoxelDirtyArray[nodeIndex] = true; |
| 1021 | − | |
| 1029 | + | |
| 1022 | 1030 | if (_useVoxelShader) { |
| 1023 | 1031 | if (_writeVoxelShaderData) { |
| 1024 | 1032 | VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; |
| @@ -1071,15 +1079,17 @@ void VoxelSystem::init() { · 46 unmodified lines | ||
| 1071 | 1079 | // VBO for the verticesArray |
| 1072 | 1080 | _initialMemoryUsageGPU = getFreeMemoryGPU(); |
| 1073 | 1081 | initVoxelMemory(); |
| 1074 | − | |
| 1082 | + | |
| 1075 | 1083 | // our own _removedVoxels doesn't need to be notified of voxel deletes |
| 1076 | 1084 | VoxelTreeElement::removeDeleteHook(&_removedVoxels); |
| 1085 | + | |
| 1077 | 1086 | } |
| 1078 | 1087 | |
| 1079 | 1088 | void VoxelSystem::changeTree(VoxelTree* newTree) { |
| 1080 | 1089 | disconnect(_tree, 0, this, 0); |
| 1081 | 1090 | |
| 1082 | 1091 | _tree = newTree; |
| 1092 | + | |
| 1083 | 1093 | _tree->setDirtyBit(); |
| 1084 | 1094 | _tree->getRoot()->setVoxelSystem(this); |
| 1085 | 1095 | |
| @@ -1102,7 +1112,7 @@ void VoxelSystem::updateFullVBOs() { · 16 unmodified lines | ||
| 1102 | 1112 | PerformanceWarning warn(outputWarning,buffer); |
| 1103 | 1113 | updateVBOSegment(0, _voxelsInReadArrays); |
| 1104 | 1114 | } |
| 1105 | − | |
| 1115 | + | |
| 1106 | 1116 | { |
| 1107 | 1117 | PerformanceWarning warn(outputWarning,"updateFullVBOs() : memset(_readVoxelDirtyArray...)"); |
| 1108 | 1118 | // consider the _readVoxelDirtyArray[] clean! |
| @@ -1131,7 +1141,7 @@ void VoxelSystem::updatePartialVBOs() { · 22 unmodified lines | ||
| 1131 | 1141 | _readVoxelDirtyArray[i] = false; // consider us clean! |
| 1132 | 1142 | } |
| 1133 | 1143 | } |
| 1134 | − | |
| 1144 | + | |
| 1135 | 1145 | // if we got to the end of the array, and we're in an active dirty segment... |
| 1136 | 1146 | if (inSegment) { |
| 1137 | 1147 | updateVBOSegment(segmentStart, _voxelsInReadArrays - 1); |
| @@ -1195,7 +1205,7 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg · 57 unmodified lines | ||
| 1195 | 1205 | PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);"); |
| 1196 | 1206 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); |
| 1197 | 1207 | } |
| 1198 | − | |
| 1208 | + | |
| 1199 | 1209 | { |
| 1200 | 1210 | PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboColorsID);"); |
| 1201 | 1211 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); |
| @@ -1206,14 +1216,14 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg · 4 unmodified lines | ||
| 1206 | 1216 | void VoxelSystem::render(bool texture) { |
| 1207 | 1217 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 1208 | 1218 | PerformanceWarning warn(showWarnings, "render()"); |
| 1209 | − | |
| 1219 | + | |
| 1210 | 1220 | // If we got here and we're not initialized then bail! |
| 1211 | 1221 | if (!_initialized) { |
| 1212 | 1222 | return; |
| 1213 | 1223 | } |
| 1214 | − | |
| 1224 | + | |
| 1215 | 1225 | updateVBOs(); |
| 1216 | − | |
| 1226 | + | |
| 1217 | 1227 | bool dontCallOpenGLDraw = Menu::getInstance()->isOptionChecked(MenuOption::DontCallOpenGLForVoxels); |
| 1218 | 1228 | // if not don't... then do... |
| 1219 | 1229 | if (_useVoxelShader) { |
| @@ -1253,8 +1263,8 @@ void VoxelSystem::render(bool texture) { · 33 unmodified lines | ||
| 1253 | 1263 | glEnableVertexAttribArray(attributeLocation); |
| 1254 | 1264 | glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float))); |
| 1255 | 1265 | } |
| 1256 | − | |
| 1257 | − | |
| 1266 | + | |
| 1267 | + | |
| 1258 | 1268 | glEnableClientState(GL_COLOR_ARRAY); |
| 1259 | 1269 | glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors |
| 1260 | 1270 | |
| @@ -1285,7 +1295,7 @@ void VoxelSystem::render(bool texture) { · 24 unmodified lines | ||
| 1285 | 1295 | |
| 1286 | 1296 | { |
| 1287 | 1297 | PerformanceWarning warn(showWarnings,"render().. setup before glDrawRangeElementsEXT()..."); |
| 1288 | − | |
| 1298 | + | |
| 1289 | 1299 | // tell OpenGL where to find vertex and color information |
| 1290 | 1300 | glEnableClientState(GL_VERTEX_ARRAY); |
| 1291 | 1301 | glEnableClientState(GL_COLOR_ARRAY); |
| @@ -1306,7 +1316,7 @@ void VoxelSystem::render(bool texture) { · 14 unmodified lines | ||
| 1306 | 1316 | |
| 1307 | 1317 | if (!dontCallOpenGLDraw) { |
| 1308 | 1318 | PerformanceWarning warn(showWarnings, "render().. glDrawRangeElementsEXT()..."); |
| 1309 | − | |
| 1319 | + | |
| 1310 | 1320 | glNormal3f(0,1.0f,0); |
| 1311 | 1321 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesTop); |
| 1312 | 1322 | glDrawRangeElementsEXT(GL_TRIANGLES, 0, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _voxelsInReadArrays - 1, |
| @@ -1340,7 +1350,7 @@ void VoxelSystem::render(bool texture) { · 27 unmodified lines | ||
| 1340 | 1350 | |
| 1341 | 1351 | { |
| 1342 | 1352 | PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()..."); |
| 1343 | − | |
| 1353 | + | |
| 1344 | 1354 | glDisable(GL_CULL_FACE); |
| 1345 | 1355 | |
| 1346 | 1356 | removeScaleAndReleaseProgram(texture); |
| @@ -1365,16 +1375,16 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { · 18 unmodified lines | ||
| 1365 | 1375 | glEnable(GL_TEXTURE_GEN_T); |
| 1366 | 1376 | glEnable(GL_TEXTURE_GEN_R); |
| 1367 | 1377 | glEnable(GL_TEXTURE_2D); |
| 1368 | − | |
| 1378 | + | |
| 1369 | 1379 | glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); |
| 1370 | 1380 | glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); |
| 1371 | 1381 | glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]); |
| 1372 | − | |
| 1382 | + | |
| 1373 | 1383 | } else if (texture) { |
| 1374 | 1384 | _perlinModulateProgram.bind(); |
| 1375 | 1385 | glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID()); |
| 1376 | 1386 | } |
| 1377 | − | |
| 1387 | + | |
| 1378 | 1388 | glPushMatrix(); |
| 1379 | 1389 | glScalef(_treeScale, _treeScale, _treeScale); |
| 1380 | 1390 | } |
| @@ -1382,7 +1392,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { · 1 unmodified line | ||
| 1382 | 1392 | void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { |
| 1383 | 1393 | // scale back down to 1 so heads aren't massive |
| 1384 | 1394 | glPopMatrix(); |
| 1385 | − | |
| 1395 | + | |
| 1386 | 1396 | if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { |
| 1387 | 1397 | _shadowMapProgram.release(); |
| 1388 | 1398 | glBindTexture(GL_TEXTURE_2D, 0); |
| @@ -1390,7 +1400,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { · 1 unmodified line | ||
| 1390 | 1400 | glDisable(GL_TEXTURE_GEN_T); |
| 1391 | 1401 | glDisable(GL_TEXTURE_GEN_R); |
| 1392 | 1402 | glDisable(GL_TEXTURE_2D); |
| 1393 | − | |
| 1403 | + | |
| 1394 | 1404 | } else if (texture) { |
| 1395 | 1405 | _perlinModulateProgram.release(); |
| 1396 | 1406 | glBindTexture(GL_TEXTURE_2D, 0); |
| @@ -1403,7 +1413,7 @@ void VoxelSystem::killLocalVoxels() { · 6 unmodified lines | ||
| 1403 | 1413 | lockTree(); |
| 1404 | 1414 | _tree->eraseAllOctreeElements(); |
| 1405 | 1415 | unlockTree(); |
| 1406 | − clearFreeBufferIndexes(); | |
| 1416 | + clearFreeBufferIndexes(); | |
| 1407 | 1417 | _voxelsInReadArrays = 0; // do we need to do this? |
| 1408 | 1418 | setupNewVoxelsForDrawing(); |
| 1409 | 1419 | } |
| @@ -1422,7 +1432,7 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void · 12 unmodified lines | ||
| 1422 | 1432 | |
| 1423 | 1433 | void VoxelSystem::clearAllNodesBufferIndex() { |
| 1424 | 1434 | _nodeCount = 0; |
| 1425 | − lockTree(); | |
| 1435 | + lockTree(); | |
| 1426 | 1436 | _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation); |
| 1427 | 1437 | unlockTree(); |
| 1428 | 1438 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| @@ -1584,9 +1594,9 @@ void VoxelSystem::falseColorizeBySource() { · 155 unmodified lines | ||
| 1584 | 1594 | const int NUMBER_OF_COLOR_GROUPS = 6; |
| 1585 | 1595 | const unsigned char MIN_COLOR = 128; |
| 1586 | 1596 | int voxelServerCount = 0; |
| 1587 | − groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = { | |
| 1588 | − groupColor(255, 0, 0), | |
| 1589 | − groupColor( 0, 255, 0), | |
| 1597 | + groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = { | |
| 1598 | + groupColor(255, 0, 0), | |
| 1599 | + groupColor( 0, 255, 0), | |
| 1590 | 1600 | groupColor( 0, 0, 255), |
| 1591 | 1601 | groupColor(255, 0, 255), |
| 1592 | 1602 | groupColor( 0, 255, 255), |
| @@ -1614,7 +1624,7 @@ void VoxelSystem::falseColorizeBySource() { · 21 unmodified lines | ||
| 1614 | 1624 | voxelServerCount++; |
| 1615 | 1625 | } |
| 1616 | 1626 | } |
| 1617 | − | |
| 1627 | + | |
| 1618 | 1628 | _tree->recurseTreeWithOperation(falseColorizeBySourceOperation, &args); |
| 1619 | 1629 | qDebug("setting false color by source for %d nodes\n", _nodeCount); |
| 1620 | 1630 | _tree->setDirtyBit(); |
| @@ -1690,7 +1700,7 @@ public: · 69 unmodified lines | ||
| 1690 | 1700 | unsigned long nodesOutside; |
| 1691 | 1701 | VoxelTreeElement* insideRoot; |
| 1692 | 1702 | VoxelTreeElement* outsideRoot; |
| 1693 | − | |
| 1703 | + | |
| 1694 | 1704 | removeOutOfViewArgs(VoxelSystem* voxelSystem, bool widenViewFrustum = true) : |
| 1695 | 1705 | thisVoxelSystem(voxelSystem), |
| 1696 | 1706 | thisViewFrustum(*voxelSystem->getViewFrustum()), |
| @@ -1730,7 +1740,7 @@ bool VoxelSystem::removeOutOfViewOperation(OctreeElement* element, void* extraDa · 33 unmodified lines | ||
| 1730 | 1740 | args->dontRecurseBag.remove(voxel); |
| 1731 | 1741 | return false; // stop recursion |
| 1732 | 1742 | } |
| 1733 | − | |
| 1743 | + | |
| 1734 | 1744 | VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; |
| 1735 | 1745 | args->nodesScanned++; |
| 1736 | 1746 | // Need to operate on our child nodes, so we can remove them |
| @@ -1748,7 +1758,7 @@ bool VoxelSystem::removeOutOfViewOperation(OctreeElement* element, void* extraDa · 11 unmodified lines | ||
| 1748 | 1758 | } break; |
| 1749 | 1759 | case ViewFrustum::INSIDE: { |
| 1750 | 1760 | // if the child node is fully INSIDE the view, then there's no need to recurse it |
| 1751 | − // because we know all it's children will also be in the view, so we want to | |
| 1761 | + // because we know all it's children will also be in the view, so we want to | |
| 1752 | 1762 | // tell the caller to NOT recurse this child |
| 1753 | 1763 | args->nodesInside++; |
| 1754 | 1764 | args->dontRecurseBag.insert(childNode); |
| @@ -1779,12 +1789,12 @@ bool VoxelSystem::isViewChanging() { · 24 unmodified lines | ||
| 1779 | 1789 | |
| 1780 | 1790 | bool VoxelSystem::hasViewChanged() { |
| 1781 | 1791 | bool result = false; // assume the best |
| 1782 | − | |
| 1792 | + | |
| 1783 | 1793 | // If we're still changing, report no change yet. |
| 1784 | 1794 | if (isViewChanging()) { |
| 1785 | 1795 | return false; |
| 1786 | 1796 | } |
| 1787 | − | |
| 1797 | + | |
| 1788 | 1798 | // If our viewFrustum has changed since our _lastKnownViewFrustum |
| 1789 | 1799 | if (!_lastStableViewFrustum.isVerySimilar(_viewFrustum)) { |
| 1790 | 1800 | result = true; |
| @@ -1803,8 +1813,8 @@ void VoxelSystem::removeOutOfView() { · 12 unmodified lines | ||
| 1803 | 1813 | } |
| 1804 | 1814 | bool showRemoveDebugDetails = false; |
| 1805 | 1815 | if (showRemoveDebugDetails) { |
| 1806 | − qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", | |
| 1807 | − args.nodesScanned, args.nodesRemoved, args.nodesInside, | |
| 1816 | + qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", | |
| 1817 | + args.nodesScanned, args.nodesRemoved, args.nodesInside, | |
| 1808 | 1818 | args.nodesIntersect, args.nodesOutside, _removedVoxels.count() |
| 1809 | 1819 | ); |
| 1810 | 1820 | } |
| @@ -1816,9 +1826,9 @@ public: · 5 unmodified lines | ||
| 1816 | 1826 | VoxelSystem* thisVoxelSystem; |
| 1817 | 1827 | ViewFrustum thisViewFrustum; |
| 1818 | 1828 | unsigned long nodesScanned; |
| 1819 | − | |
| 1829 | + | |
| 1820 | 1830 | showAllLocalVoxelsArgs(VoxelSystem* voxelSystem) : |
| 1821 | − thisVoxelSystem(voxelSystem), | |
| 1831 | + thisVoxelSystem(voxelSystem), | |
| 1822 | 1832 | thisViewFrustum(*voxelSystem->getViewFrustum()), |
| 1823 | 1833 | nodesScanned(0) |
| 1824 | 1834 | { |
| @@ -1880,8 +1890,9 @@ public: · 55 unmodified lines | ||
| 1880 | 1890 | unsigned long nodesOutsideInside; |
| 1881 | 1891 | unsigned long nodesInsideOutside; |
| 1882 | 1892 | unsigned long nodesOutsideOutside; |
| 1883 | − | |
| 1884 | − hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree, | |
| 1893 | + unsigned long nodesShown; | |
| 1894 | + | |
| 1895 | + hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree, | |
| 1885 | 1896 | bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) : |
| 1886 | 1897 | thisVoxelSystem(voxelSystem), |
| 1887 | 1898 | tree(tree), |
| @@ -1898,7 +1909,8 @@ public: · 10 unmodified lines | ||
| 1898 | 1909 | nodesIntersectInside(0), |
| 1899 | 1910 | nodesOutsideInside(0), |
| 1900 | 1911 | nodesInsideOutside(0), |
| 1901 | − nodesOutsideOutside(0) | |
| 1912 | + nodesOutsideOutside(0), | |
| 1913 | + nodesShown(0) | |
| 1902 | 1914 | { |
| 1903 | 1915 | // Widen the FOV for trimming |
| 1904 | 1916 | if (widenViewFrustum) { |
| @@ -1916,13 +1928,14 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 11 unmodified lines | ||
| 1916 | 1928 | if (_inhideOutOfView) { |
| 1917 | 1929 | return; |
| 1918 | 1930 | } |
| 1919 | − | |
| 1931 | + | |
| 1920 | 1932 | _inhideOutOfView = true; |
| 1921 | 1933 | |
| 1922 | 1934 | bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 1923 | 1935 | PerformanceWarning warn(showDebugDetails, "hideOutOfView()"); |
| 1924 | 1936 | bool widenFrustum = true; |
| 1925 | 1937 | |
| 1938 | + | |
| 1926 | 1939 | // When using "delta" view frustums and only hide/show items that are in the difference |
| 1927 | 1940 | // between the two view frustums. There are some potential problems with this mode. |
| 1928 | 1941 | // |
| @@ -1932,7 +1945,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 3 unmodified lines | ||
| 1932 | 1945 | // |
| 1933 | 1946 | // 2) Also, voxels will arrive from the network that are OUTSIDE of the view |
| 1934 | 1947 | // frustum... these won't get hidden... and so we can't assume they are correctly |
| 1935 | − // hidden... | |
| 1948 | + // hidden... | |
| 1936 | 1949 | // |
| 1937 | 1950 | // Both these problems are solved by intermittently calling this with forceFullFrustum set |
| 1938 | 1951 | // to true. This will essentially clean up the improperly hidden or shown voxels. |
| @@ -1947,13 +1960,13 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 8 unmodified lines | ||
| 1947 | 1960 | args.lastViewFrustum.printDebugDetails(); |
| 1948 | 1961 | } |
| 1949 | 1962 | } |
| 1950 | − | |
| 1963 | + | |
| 1951 | 1964 | if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) { |
| 1952 | 1965 | _inhideOutOfView = false; |
| 1953 | 1966 | return; |
| 1954 | 1967 | } |
| 1955 | 1968 | |
| 1956 | − lockTree(); | |
| 1969 | + lockTree(); | |
| 1957 | 1970 | _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); |
| 1958 | 1971 | unlockTree(); |
| 1959 | 1972 | _lastCulledViewFrustum = args.thisViewFrustum; // save last stable |
| @@ -1963,16 +1976,19 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 3 unmodified lines | ||
| 1963 | 1976 | _tree->setDirtyBit(); |
| 1964 | 1977 | setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY); |
| 1965 | 1978 | } |
| 1966 | − | |
| 1967 | − bool extraDebugDetails = Application::getInstance()->getLogger()->extraDebugging(); | |
| 1979 | + | |
| 1980 | + bool extraDebugDetails = false; // Application::getInstance()->getLogger()->extraDebugging(); | |
| 1968 | 1981 | if (extraDebugDetails) { |
| 1969 | − qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n", | |
| 1970 | − args.nodesScanned, args.nodesRemoved, args.nodesInside, | |
| 1982 | + qDebug("hideOutOfView() scanned=%ld removed=%ld show=%ld inside=%ld intersect=%ld outside=%ld\n", | |
| 1983 | + args.nodesScanned, args.nodesRemoved, args.nodesShown, args.nodesInside, | |
| 1971 | 1984 | args.nodesIntersect, args.nodesOutside |
| 1972 | 1985 | ); |
| 1973 | − qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n", | |
| 1986 | + qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n", | |
| 1974 | 1987 | args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside |
| 1975 | 1988 | ); |
| 1989 | + | |
| 1990 | + qDebug() << "args.thisViewFrustum....\n"; | |
| 1991 | + args.thisViewFrustum.printDebugDetails(); | |
| 1976 | 1992 | } |
| 1977 | 1993 | _inhideOutOfView = false; |
| 1978 | 1994 | } |
| @@ -1985,10 +2001,10 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat · 6 unmodified lines | ||
| 1985 | 2001 | // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not |
| 1986 | 2002 | // consider that case. |
| 1987 | 2003 | ViewFrustum::location inLastCulledFrustum; |
| 1988 | − | |
| 2004 | + | |
| 1989 | 2005 | if (args->culledOnce && args->wantDeltaFrustums) { |
| 1990 | 2006 | inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); |
| 1991 | − | |
| 2007 | + | |
| 1992 | 2008 | // if this node is fully OUTSIDE our last culled view frustum, then we don't need to recurse further |
| 1993 | 2009 | if (inLastCulledFrustum == ViewFrustum::OUTSIDE) { |
| 1994 | 2010 | args->nodesOutsideOutside++; |
| @@ -2009,7 +2025,7 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat · 14 unmodified lines | ||
| 2009 | 2025 | } |
| 2010 | 2026 | |
| 2011 | 2027 | } |
| 2012 | − | |
| 2028 | + | |
| 2013 | 2029 | return true; |
| 2014 | 2030 | } |
| 2015 | 2031 | |
| @@ -2021,10 +2037,10 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 5 unmodified lines | ||
| 2021 | 2037 | // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not |
| 2022 | 2038 | // consider that case. |
| 2023 | 2039 | ViewFrustum::location inLastCulledFrustum; |
| 2024 | − | |
| 2040 | + | |
| 2025 | 2041 | if (args->culledOnce && args->wantDeltaFrustums) { |
| 2026 | 2042 | inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); |
| 2027 | − | |
| 2043 | + | |
| 2028 | 2044 | // if this node is fully inside our last culled view frustum, then we don't need to recurse further |
| 2029 | 2045 | if (inLastCulledFrustum == ViewFrustum::INSIDE) { |
| 2030 | 2046 | args->nodesInsideInside++; |
| @@ -2047,35 +2063,36 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 16 unmodified lines | ||
| 2047 | 2063 | // These are both needed to force redraw... |
| 2048 | 2064 | voxel->setDirtyBit(); |
| 2049 | 2065 | voxel->markWithChangedTime(); |
| 2066 | + args->nodesShown++; | |
| 2050 | 2067 | } |
| 2051 | 2068 | |
| 2052 | 2069 | return true; // keep recursing! |
| 2053 | 2070 | } |
| 2054 | 2071 | |
| 2055 | −// "hide" voxels in the VBOs that are still in the tree that but not in view. | |
| 2072 | +// "hide" voxels in the VBOs that are still in the tree that but not in view. | |
| 2056 | 2073 | // We don't remove them from the tree, we don't delete them, we do remove them |
| 2057 | 2074 | // from the VBOs and mark them as such in the tree. |
| 2058 | 2075 | bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData) { |
| 2059 | 2076 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 2060 | 2077 | hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData; |
| 2061 | 2078 | |
| 2062 | − // If we're still recursing the tree using this operator, then we don't know if we're inside or outside... | |
| 2079 | + // If we're still recursing the tree using this operator, then we don't know if we're inside or outside... | |
| 2063 | 2080 | // so before we move forward we need to determine our frustum location |
| 2064 | 2081 | ViewFrustum::location inFrustum = voxel->inFrustum(args->thisViewFrustum); |
| 2065 | − | |
| 2082 | + | |
| 2066 | 2083 | // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine |
| 2067 | 2084 | // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not |
| 2068 | 2085 | // consider that case. |
| 2069 | 2086 | ViewFrustum::location inLastCulledFrustum; |
| 2070 | − | |
| 2087 | + | |
| 2071 | 2088 | if (args->culledOnce && args->wantDeltaFrustums) { |
| 2072 | 2089 | inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); |
| 2073 | 2090 | } |
| 2074 | − | |
| 2091 | + | |
| 2075 | 2092 | // ok, now do some processing for this node... |
| 2076 | 2093 | switch (inFrustum) { |
| 2077 | 2094 | case ViewFrustum::OUTSIDE: { |
| 2078 | − | |
| 2095 | + | |
| 2079 | 2096 | // If this node is outside the current view, then we might want to hide it... unless it was previously OUTSIDE, |
| 2080 | 2097 | // if it was previously outside, then we can safely assume it's already hidden, and we can also safely assume |
| 2081 | 2098 | // that all of it's children are outside both of our views, in which case we can just stop recursing... |
| @@ -2084,17 +2101,17 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 2 unmodified lines | ||
| 2084 | 2101 | args->nodesOutsideOutside++; |
| 2085 | 2102 | return false; // stop recursing this branch! |
| 2086 | 2103 | } |
| 2087 | − | |
| 2104 | + | |
| 2088 | 2105 | // if this node is fully OUTSIDE the view, but previously intersected and/or was inside the last view, then |
| 2089 | − // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse | |
| 2106 | + // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse | |
| 2090 | 2107 | // the children and simply mark them as hidden |
| 2091 | 2108 | args->tree->recurseNodeWithOperation(voxel, hideAllSubTreeOperation, args ); |
| 2092 | − | |
| 2109 | + | |
| 2093 | 2110 | return false; |
| 2094 | − | |
| 2111 | + | |
| 2095 | 2112 | } break; |
| 2096 | 2113 | case ViewFrustum::INSIDE: { |
| 2097 | − | |
| 2114 | + | |
| 2098 | 2115 | // If this node is INSIDE the current view, then we might want to show it... unless it was previously INSIDE, |
| 2099 | 2116 | // if it was previously INSIDE, then we can safely assume it's already shown, and we can also safely assume |
| 2100 | 2117 | // that all of it's children are INSIDE both of our views, in which case we can just stop recursing... |
| @@ -2103,18 +2120,18 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 2 unmodified lines | ||
| 2103 | 2120 | args->nodesInsideInside++; |
| 2104 | 2121 | return false; // stop recursing this branch! |
| 2105 | 2122 | } |
| 2106 | − | |
| 2123 | + | |
| 2107 | 2124 | // if this node is fully INSIDE the view, but previously INTERSECTED and/or was OUTSIDE the last view, then |
| 2108 | − // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse | |
| 2125 | + // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse | |
| 2109 | 2126 | // the children and simply mark them as visible (as appropriate based on LOD) |
| 2110 | 2127 | args->tree->recurseNodeWithOperation(voxel, showAllSubTreeOperation, args); |
| 2111 | 2128 | |
| 2112 | − return false; | |
| 2129 | + return false; | |
| 2113 | 2130 | } break; |
| 2114 | 2131 | case ViewFrustum::INTERSECT: { |
| 2115 | 2132 | args->nodesScanned++; |
| 2116 | 2133 | |
| 2117 | − // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE | |
| 2134 | + // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE | |
| 2118 | 2135 | // the last known view, in which case it will already be visible, and we know that all it's children are also |
| 2119 | 2136 | // previously INSIDE and visible. So in this case stop recursing |
| 2120 | 2137 | if (args->culledOnce && args->wantDeltaFrustums && inLastCulledFrustum == ViewFrustum::INSIDE) { |
| @@ -2125,21 +2142,22 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 4 unmodified lines | ||
| 2125 | 2142 | args->nodesIntersect++; |
| 2126 | 2143 | |
| 2127 | 2144 | // if the child node INTERSECTs the view, then we want to check to see if it thinks it should render |
| 2128 | − // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from | |
| 2145 | + // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from | |
| 2129 | 2146 | // here because we know will block any children anyway |
| 2130 | 2147 | if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) { |
| 2131 | 2148 | voxel->setDirtyBit(); // will this make it draw? |
| 2149 | + args->nodesShown++; | |
| 2132 | 2150 | return false; |
| 2133 | 2151 | } |
| 2134 | 2152 | |
| 2135 | 2153 | // If it INTERSECTS but shouldn't be displayed, then it's probably a parent and it is at least partially in view. |
| 2136 | − // So we DO want to recurse the children because some of them may not be in view... nothing specifically to do, | |
| 2154 | + // So we DO want to recurse the children because some of them may not be in view... nothing specifically to do, | |
| 2137 | 2155 | // just keep iterating the children |
| 2138 | − return true; | |
| 2156 | + return true; | |
| 2139 | 2157 | |
| 2140 | 2158 | } break; |
| 2141 | 2159 | } // switch |
| 2142 | − | |
| 2160 | + | |
| 2143 | 2161 | |
| 2144 | 2162 | return true; // keep going! |
| 2145 | 2163 | } |
| @@ -2147,7 +2165,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 1 unmodified line | ||
| 2147 | 2165 | |
| 2148 | 2166 | bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, |
| 2149 | 2167 | VoxelDetail& detail, float& distance, BoxFace& face) { |
| 2150 | − lockTree(); | |
| 2168 | + lockTree(); | |
| 2151 | 2169 | OctreeElement* element; |
| 2152 | 2170 | if (!_tree->findRayIntersection(origin, direction, element, distance, face)) { |
| 2153 | 2171 | unlockTree(); |
| @@ -2206,7 +2224,7 @@ bool VoxelSystem::falseColorizeRandomEveryOtherOperation(OctreeElement* element, · 52 unmodified lines | ||
| 2206 | 2224 | void VoxelSystem::falseColorizeRandomEveryOther() { |
| 2207 | 2225 | falseColorizeRandomEveryOtherArgs args; |
| 2208 | 2226 | _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args); |
| 2209 | − qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n", | |
| 2227 | + qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n", | |
| 2210 | 2228 | args.totalNodes, args.colorableNodes, args.coloredNodes); |
| 2211 | 2229 | _tree->setDirtyBit(); |
| 2212 | 2230 | setupNewVoxelsForDrawing(); |
| @@ -2214,9 +2232,9 @@ void VoxelSystem::falseColorizeRandomEveryOther() { · 1 unmodified line | ||
| 2214 | 2232 | |
| 2215 | 2233 | class collectStatsForTreesAndVBOsArgs { |
| 2216 | 2234 | public: |
| 2217 | − collectStatsForTreesAndVBOsArgs(int maxVoxels) : | |
| 2218 | − totalNodes(0), | |
| 2219 | − dirtyNodes(0), | |
| 2235 | + collectStatsForTreesAndVBOsArgs(int maxVoxels) : | |
| 2236 | + totalNodes(0), | |
| 2237 | + dirtyNodes(0), | |
| 2220 | 2238 | shouldRenderNodes(0), |
| 2221 | 2239 | coloredNodes(0), |
| 2222 | 2240 | nodesInVBO(0), |
| @@ -2228,7 +2246,7 @@ public: · 5 unmodified lines | ||
| 2228 | 2246 | hasIndexFound = new bool[maxVoxels]; |
| 2229 | 2247 | memset(hasIndexFound, false, maxVoxels * sizeof(bool)); |
| 2230 | 2248 | }; |
| 2231 | − | |
| 2249 | + | |
| 2232 | 2250 | ~collectStatsForTreesAndVBOsArgs() { |
| 2233 | 2251 | delete[] hasIndexFound; |
| 2234 | 2252 | } |
| @@ -2244,13 +2262,13 @@ public: · 9 unmodified lines | ||
| 2244 | 2262 | unsigned long leafNodes; |
| 2245 | 2263 | |
| 2246 | 2264 | unsigned long expectedMax; |
| 2247 | − | |
| 2265 | + | |
| 2248 | 2266 | bool* hasIndexFound; |
| 2249 | 2267 | }; |
| 2250 | 2268 | |
| 2251 | 2269 | bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, void* extraData) { |
| 2252 | 2270 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 2253 | − | |
| 2271 | + | |
| 2254 | 2272 | collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData; |
| 2255 | 2273 | args->totalNodes++; |
| 2256 | 2274 | |
| @@ -2273,17 +2291,17 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 16 unmodified lines | ||
| 2273 | 2291 | if (voxel->isKnownBufferIndex()) { |
| 2274 | 2292 | args->nodesInVBO++; |
| 2275 | 2293 | unsigned long nodeIndex = voxel->getBufferIndex(); |
| 2276 | − | |
| 2294 | + | |
| 2277 | 2295 | const bool extraDebugging = false; // enable for extra debugging |
| 2278 | 2296 | if (extraDebugging) { |
| 2279 | − qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n", | |
| 2280 | − voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), | |
| 2297 | + qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n", | |
| 2298 | + voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), | |
| 2281 | 2299 | nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender())); |
| 2282 | 2300 | } |
| 2283 | 2301 | |
| 2284 | 2302 | if (args->hasIndexFound[nodeIndex]) { |
| 2285 | 2303 | args->duplicateVBOIndex++; |
| 2286 | − qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, | |
| 2304 | + qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, | |
| 2287 | 2305 | debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender())); |
| 2288 | 2306 | } else { |
| 2289 | 2307 | args->hasIndexFound[nodeIndex] = true; |
| @@ -2291,7 +2309,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 1 unmodified line | ||
| 2291 | 2309 | if (nodeIndex > args->expectedMax) { |
| 2292 | 2310 | args->nodesInVBOOverExpectedMax++; |
| 2293 | 2311 | } |
| 2294 | − | |
| 2312 | + | |
| 2295 | 2313 | // if it's in VBO but not-shouldRender, track that also... |
| 2296 | 2314 | if (!voxel->getShouldRender()) { |
| 2297 | 2315 | args->nodesInVBONotShouldRender++; |
| @@ -2316,9 +2334,9 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 18 unmodified lines | ||
| 2316 | 2334 | |
| 2317 | 2335 | collectStatsForTreesAndVBOsArgs args(_maxVoxels); |
| 2318 | 2336 | args.expectedMax = _voxelsInWriteArrays; |
| 2319 | − | |
| 2337 | + | |
| 2320 | 2338 | qDebug("CALCULATING Local Voxel Tree Statistics >>>>>>>>>>>>\n"); |
| 2321 | − | |
| 2339 | + | |
| 2322 | 2340 | _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args); |
| 2323 | 2341 | |
| 2324 | 2342 | qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n", |
| @@ -2327,7 +2345,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 2 unmodified lines | ||
| 2327 | 2345 | qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty), |
| 2328 | 2346 | _voxelsInWriteArrays, minDirty, maxDirty); |
| 2329 | 2347 | |
| 2330 | − qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n", | |
| 2348 | + qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n", | |
| 2331 | 2349 | args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); |
| 2332 | 2350 | |
| 2333 | 2351 | glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; |
| @@ -2340,10 +2358,10 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 6 unmodified lines | ||
| 2340 | 2358 | } |
| 2341 | 2359 | } |
| 2342 | 2360 | |
| 2343 | − qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n", | |
| 2361 | + qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n", | |
| 2344 | 2362 | minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); |
| 2345 | 2363 | |
| 2346 | − qDebug(" _freeIndexes.size()=%ld \n", | |
| 2364 | + qDebug(" _freeIndexes.size()=%ld \n", | |
| 2347 | 2365 | _freeIndexes.size()); |
| 2348 | 2366 | |
| 2349 | 2367 | qDebug("DONE WITH Local Voxel Tree Statistics >>>>>>>>>>>>\n"); |
| @@ -2354,36 +2372,36 @@ void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { · 4 unmodified lines | ||
| 2354 | 2372 | lockTree(); |
| 2355 | 2373 | _tree->deleteVoxelAt(x, y, z, s); |
| 2356 | 2374 | unlockTree(); |
| 2357 | − | |
| 2375 | + | |
| 2358 | 2376 | // redraw! |
| 2359 | 2377 | setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? |
| 2360 | − | |
| 2378 | + | |
| 2361 | 2379 | }; |
| 2362 | 2380 | |
| 2363 | −VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { | |
| 2364 | − return _tree->getVoxelAt(x, y, z, s); | |
| 2381 | +VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { | |
| 2382 | + return _tree->getVoxelAt(x, y, z, s); | |
| 2365 | 2383 | }; |
| 2366 | 2384 | |
| 2367 | −void VoxelSystem::createVoxel(float x, float y, float z, float s, | |
| 2385 | +void VoxelSystem::createVoxel(float x, float y, float z, float s, | |
| 2368 | 2386 | unsigned char red, unsigned char green, unsigned char blue, bool destructive) { |
| 2369 | − | |
| 2387 | + | |
| 2370 | 2388 | //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s); |
| 2371 | 2389 | lockTree(); |
| 2372 | − _tree->createVoxel(x, y, z, s, red, green, blue, destructive); | |
| 2390 | + _tree->createVoxel(x, y, z, s, red, green, blue, destructive); | |
| 2373 | 2391 | unlockTree(); |
| 2374 | 2392 | |
| 2375 | − setupNewVoxelsForDrawing(); | |
| 2393 | + setupNewVoxelsForDrawing(); | |
| 2376 | 2394 | }; |
| 2377 | 2395 | |
| 2378 | −void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) { | |
| 2379 | − _tree->createLine(point1, point2, unitSize, color, destructive); | |
| 2380 | − setupNewVoxelsForDrawing(); | |
| 2396 | +void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) { | |
| 2397 | + _tree->createLine(point1, point2, unitSize, color, destructive); | |
| 2398 | + setupNewVoxelsForDrawing(); | |
| 2381 | 2399 | }; |
| 2382 | 2400 | |
| 2383 | −void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, | |
| 2384 | − creationMode mode, bool destructive, bool debug) { | |
| 2385 | − _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug); | |
| 2386 | − setupNewVoxelsForDrawing(); | |
| 2401 | +void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, | |
| 2402 | + creationMode mode, bool destructive, bool debug) { | |
| 2403 | + _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug); | |
| 2404 | + setupNewVoxelsForDrawing(); | |
| 2387 | 2405 | }; |
| 2388 | 2406 | |
| 2389 | 2407 | void VoxelSystem::copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelSystem* destination, bool rebaseToRoot) { |
| @@ -2431,7 +2449,7 @@ bool VoxelSystem::falseColorizeSubTreeOperation(OctreeElement* element, void* ex · 41 unmodified lines | ||
| 2431 | 2449 | voxel->setFalseColor(args->color[0], args->color[1], args->color[2]); |
| 2432 | 2450 | args->voxelsTouched++; |
| 2433 | 2451 | } |
| 2434 | − return true; | |
| 2452 | + return true; | |
| 2435 | 2453 | } |
| 2436 | 2454 | |
| 2437 | 2455 | bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* extraData) { |
| @@ -2459,18 +2477,18 @@ bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* e · 21 unmodified lines | ||
| 2459 | 2477 | if (result == OCCLUDED) { |
| 2460 | 2478 | args->nonLeavesOccluded++; |
| 2461 | 2479 | delete voxelPolygon; |
| 2462 | − | |
| 2480 | + | |
| 2463 | 2481 | FalseColorizeSubTreeOperationArgs subArgs; |
| 2464 | 2482 | subArgs.color[0] = 0; |
| 2465 | 2483 | subArgs.color[1] = 255; |
| 2466 | 2484 | subArgs.color[2] = 0; |
| 2467 | 2485 | subArgs.voxelsTouched = 0; |
| 2468 | − | |
| 2486 | + | |
| 2469 | 2487 | args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs ); |
| 2470 | − | |
| 2488 | + | |
| 2471 | 2489 | args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); |
| 2472 | 2490 | args->totalVoxels += (subArgs.voxelsTouched - 1); |
| 2473 | − | |
| 2491 | + | |
| 2474 | 2492 | return false; |
| 2475 | 2493 | } |
| 2476 | 2494 | |
| @@ -2509,10 +2527,10 @@ bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* e · 32 unmodified lines | ||
| 2509 | 2527 | void VoxelSystem::falseColorizeOccluded() { |
| 2510 | 2528 | PerformanceWarning warn(true, "falseColorizeOccluded()",true); |
| 2511 | 2529 | myCoverageMap.erase(); |
| 2512 | − | |
| 2530 | + | |
| 2513 | 2531 | FalseColorizeOccludedArgs args; |
| 2514 | 2532 | args.viewFrustum = _viewFrustum; |
| 2515 | − args.map = &myCoverageMap; | |
| 2533 | + args.map = &myCoverageMap; | |
| 2516 | 2534 | args.totalVoxels = 0; |
| 2517 | 2535 | args.coloredVoxels = 0; |
| 2518 | 2536 | args.occludedVoxels = 0; |
| @@ -2527,15 +2545,15 @@ void VoxelSystem::falseColorizeOccluded() { · 8 unmodified lines | ||
| 2527 | 2545 | OctreeProjectedPolygon::pointInside_calls = 0; |
| 2528 | 2546 | OctreeProjectedPolygon::occludes_calls = 0; |
| 2529 | 2547 | OctreeProjectedPolygon::intersects_calls = 0; |
| 2530 | − | |
| 2548 | + | |
| 2531 | 2549 | glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); |
| 2532 | 2550 | |
| 2533 | 2551 | _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args); |
| 2534 | 2552 | |
| 2535 | − qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", | |
| 2553 | + qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", | |
| 2536 | 2554 | position.x, position.y, |
| 2537 | − args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 2538 | − args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 2555 | + args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 2556 | + args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 2539 | 2557 | args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, |
| 2540 | 2558 | OctreeProjectedPolygon::pointInside_calls, |
| 2541 | 2559 | OctreeProjectedPolygon::occludes_calls, |
| @@ -2574,18 +2592,18 @@ bool VoxelSystem::falseColorizeOccludedV2Operation(OctreeElement* element, void* · 32 unmodified lines | ||
| 2574 | 2592 | if (result == V2_OCCLUDED) { |
| 2575 | 2593 | args->nonLeavesOccluded++; |
| 2576 | 2594 | delete voxelPolygon; |
| 2577 | − | |
| 2595 | + | |
| 2578 | 2596 | FalseColorizeSubTreeOperationArgs subArgs; |
| 2579 | 2597 | subArgs.color[0] = 0; |
| 2580 | 2598 | subArgs.color[1] = 255; |
| 2581 | 2599 | subArgs.color[2] = 0; |
| 2582 | 2600 | subArgs.voxelsTouched = 0; |
| 2583 | − | |
| 2601 | + | |
| 2584 | 2602 | args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs ); |
| 2585 | − | |
| 2603 | + | |
| 2586 | 2604 | args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); |
| 2587 | 2605 | args->totalVoxels += (subArgs.voxelsTouched - 1); |
| 2588 | − | |
| 2606 | + | |
| 2589 | 2607 | return false; |
| 2590 | 2608 | } |
| 2591 | 2609 | |
| @@ -2632,10 +2650,10 @@ void VoxelSystem::falseColorizeOccludedV2() { · 40 unmodified lines | ||
| 2632 | 2650 | OctreeProjectedPolygon::pointInside_calls = 0; |
| 2633 | 2651 | OctreeProjectedPolygon::occludes_calls = 0; |
| 2634 | 2652 | OctreeProjectedPolygon::intersects_calls = 0; |
| 2635 | − | |
| 2653 | + | |
| 2636 | 2654 | FalseColorizeOccludedArgs args; |
| 2637 | 2655 | args.viewFrustum = _viewFrustum; |
| 2638 | − args.mapV2 = &myCoverageMapV2; | |
| 2656 | + args.mapV2 = &myCoverageMapV2; | |
| 2639 | 2657 | args.totalVoxels = 0; |
| 2640 | 2658 | args.coloredVoxels = 0; |
| 2641 | 2659 | args.occludedVoxels = 0; |
| @@ -2646,15 +2664,15 @@ void VoxelSystem::falseColorizeOccludedV2() { · 4 unmodified lines | ||
| 2646 | 2664 | args.nonLeavesOutOfView = 0; |
| 2647 | 2665 | args.nonLeavesOccluded = 0; |
| 2648 | 2666 | args.tree = _tree; |
| 2649 | − | |
| 2667 | + | |
| 2650 | 2668 | glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); |
| 2651 | 2669 | |
| 2652 | 2670 | _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedV2Operation, position, (void*)&args); |
| 2653 | 2671 | |
| 2654 | − qDebug("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", | |
| 2672 | + qDebug("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n", | |
| 2655 | 2673 | position.x, position.y, |
| 2656 | − args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 2657 | − args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 2674 | + args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 2675 | + args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 2658 | 2676 | args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, |
| 2659 | 2677 | OctreeProjectedPolygon::pointInside_calls, |
| 2660 | 2678 | OctreeProjectedPolygon::occludes_calls, |
| @@ -2717,7 +2735,7 @@ unsigned long VoxelSystem::getFreeMemoryGPU() { · 56 unmodified lines | ||
| 2717 | 2735 | const GLenum VBO_FREE_MEMORY_ATI = 0x87FB; |
| 2718 | 2736 | glGetIntegerv(VBO_FREE_MEMORY_ATI, &results[0]); |
| 2719 | 2737 | GLenum errorATI = glGetError(); |
| 2720 | − | |
| 2738 | + | |
| 2721 | 2739 | if (errorATI == GL_NO_ERROR) { |
| 2722 | 2740 | _hasMemoryUsageGPU = true; |
| 2723 | 2741 | freeMemory = results[0]; |
| @@ -2730,19 +2748,19 @@ unsigned long VoxelSystem::getFreeMemoryGPU() { · 6 unmodified lines | ||
| 2730 | 2748 | //const GLenum GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A; |
| 2731 | 2749 | //const GLenum GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B; |
| 2732 | 2750 | //const GLenum GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048; |
| 2733 | − | |
| 2751 | + | |
| 2734 | 2752 | const GLenum GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049; |
| 2735 | 2753 | results[0] = 0; |
| 2736 | 2754 | glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &results[0]); |
| 2737 | − freeMemory += results[0]; | |
| 2755 | + freeMemory += results[0]; | |
| 2738 | 2756 | GLenum errorNVIDIA = glGetError(); |
| 2739 | − | |
| 2757 | + | |
| 2740 | 2758 | if (errorNVIDIA == GL_NO_ERROR) { |
| 2741 | 2759 | _hasMemoryUsageGPU = true; |
| 2742 | 2760 | freeMemory = results[0]; |
| 2743 | 2761 | } |
| 2744 | 2762 | } |
| 2745 | − | |
| 2763 | + | |
| 2746 | 2764 | const unsigned long BYTES_PER_KBYTE = 1024; |
| 2747 | 2765 | return freeMemory * BYTES_PER_KBYTE; // API results in KB, we want it in bytes |
| 2748 | 2766 | } |
| @@ -2763,4 +2781,22 @@ void VoxelSystem::unlockTree() { · 14 unmodified lines | ||
| 2763 | 2781 | } |
| 2764 | 2782 | |
| 2765 | 2783 | |
| 2784 | +void VoxelSystem::localVoxelCacheLoaded() { | |
| 2785 | + qDebug() << "localVoxelCacheLoaded()\n"; | |
| 2786 | + | |
| 2787 | + // Make sure that the application has properly set up the view frustum for our loaded state | |
| 2788 | + Application::getInstance()->initAvatarAndViewFrustum(); | |
| 2789 | + | |
| 2790 | + _tree->setDirtyBit(); | |
| 2791 | + setupNewVoxelsForDrawing(); | |
| 2792 | + _inhideOutOfView = false; // reenable hideOutOfView behavior | |
| 2793 | +} | |
| 2794 | + | |
| 2795 | +void VoxelSystem::beginLoadingLocalVoxelCache() { | |
| 2796 | + qDebug() << "beginLoadingLocalVoxelCache()\n"; | |
| 2797 | + _writeRenderFullVBO = true; // this will disable individual node updates | |
| 2798 | + _inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded | |
| 2799 | +} | |
| 2800 | + | |
| 2801 | + | |
| 2766 | 2802 | |