Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all
Unified · Split
| @@ -60,6 +60,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 59 unmodified lines | ||
| 60 | 60 | _treeScale(treeScale), |
| 61 | 61 | _maxVoxels(maxVoxels), |
| 62 | 62 | _initialized(false), |
| 63 | + _showCulledSharedFaces(false), | |
| 63 | 64 | _usePrimitiveRenderer(false), |
| 64 | 65 | _renderer(0) { |
| 65 | 66 | |
| @@ -350,8 +351,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 284 unmodified lines | ||
| 350 | 351 | |
| 351 | 352 | _writeVoxelShaderData = _readVoxelShaderData = NULL; |
| 352 | 353 | |
| 353 | − } else | |
| 354 | − if (! _usePrimitiveRenderer) { | |
| 354 | + } else { | |
| 355 | 355 | // Destroy glBuffers |
| 356 | 356 | glDeleteBuffers(1, &_vboVerticesID); |
| 357 | 357 | glDeleteBuffers(1, &_vboColorsID); |
| @@ -373,10 +373,8 @@ void VoxelSystem::cleanupVoxelMemory() { · 15 unmodified lines | ||
| 373 | 373 | _readColorsArray = NULL; |
| 374 | 374 | _writeColorsArray = NULL; |
| 375 | 375 | } |
| 376 | − else { | |
| 377 | − delete _renderer; | |
| 378 | − _renderer = 0; | |
| 379 | − } | |
| 376 | + delete _renderer; | |
| 377 | + _renderer = 0; | |
| 380 | 378 | delete[] _writeVoxelDirtyArray; |
| 381 | 379 | delete[] _readVoxelDirtyArray; |
| 382 | 380 | _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; |
| @@ -461,8 +459,7 @@ void VoxelSystem::initVoxelMemory() { · 78 unmodified lines | ||
| 461 | 459 | |
| 462 | 460 | _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; |
| 463 | 461 | _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); |
| 464 | − } else | |
| 465 | − if (! _usePrimitiveRenderer) { | |
| 462 | + } else { | |
| 466 | 463 | |
| 467 | 464 | // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead |
| 468 | 465 | // rendering the voxel faces in 6 passes that use a global call to glNormal3f() |
| @@ -525,27 +522,7 @@ void VoxelSystem::initVoxelMemory() { · 56 unmodified lines | ||
| 525 | 522 | _shadowMapProgram.release(); |
| 526 | 523 | } |
| 527 | 524 | } |
| 528 | − else { | |
| 529 | − _renderer = new PrimitiveRenderer(_maxVoxels); | |
| 530 | − // create our simple fragment shader if we're the first system to init | |
| 531 | − if (!_perlinModulateProgram.isLinked()) { | |
| 532 | − switchToResourcesParentIfRequired(); | |
| 533 | − _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/perlin_modulate.vert"); | |
| 534 | − _perlinModulateProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/perlin_modulate.frag"); | |
| 535 | − _perlinModulateProgram.link(); | |
| 536 | − | |
| 537 | − _perlinModulateProgram.bind(); | |
| 538 | − _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); | |
| 539 | − _perlinModulateProgram.release(); | |
| 540 | − | |
| 541 | − _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/shadow_map.frag"); | |
| 542 | − _shadowMapProgram.link(); | |
| 543 | − | |
| 544 | − _shadowMapProgram.bind(); | |
| 545 | − _shadowMapProgram.setUniformValue("shadowMap", 0); | |
| 546 | − _shadowMapProgram.release(); | |
| 547 | − } | |
| 548 | − } | |
| 525 | + _renderer = new PrimitiveRenderer(_maxVoxels); | |
| 549 | 526 | |
| 550 | 527 | _initialized = true; |
| 551 | 528 | |
| @@ -690,12 +667,9 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 138 unmodified lines | ||
| 690 | 667 | |
| 691 | 668 | if (_writeRenderFullVBO) { |
| 692 | 669 | if (_usePrimitiveRenderer) { |
| 693 | − delete _renderer; | |
| 694 | − _renderer = new PrimitiveRenderer(_maxVoxels); | |
| 695 | − } | |
| 696 | − else { | |
| 697 | − clearFreeBufferIndexes(); | |
| 670 | + _renderer->release(); | |
| 698 | 671 | } |
| 672 | + clearFreeBufferIndexes(); | |
| 699 | 673 | } |
| 700 | 674 | _voxelsUpdated = newTreeToArrays(_tree->getRoot()); |
| 701 | 675 | _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean |
| @@ -851,7 +825,8 @@ void VoxelSystem::cleanupRemovedVoxels() { · 149 unmodified lines | ||
| 851 | 825 | // we also might have VBO slots that have been abandoned, if too many of our VBO slots |
| 852 | 826 | // are abandonded we want to rerender our full VBOs |
| 853 | 827 | const float TOO_MANY_ABANDONED_RATIO = 0.5f; |
| 854 | − if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) { | |
| 828 | + if (!_usePrimitiveRenderer && !_writeRenderFullVBO && | |
| 829 | + (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) { | |
| 855 | 830 | if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) { |
| 856 | 831 | qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots [" |
| 857 | 832 | << _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO"; |
| @@ -1054,12 +1029,17 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 196 unmodified lines | ||
| 1054 | 1029 | node->setVoxelSystem(this); |
| 1055 | 1030 | } |
| 1056 | 1031 | inspectForInteriorOcclusionsOperation(node, 0); |
| 1057 | − | |
| 1058 | − if (node->getInteriorOcclusions() != OctreeElement::HalfSpace::All) { | |
| 1032 | + unsigned char occlusions; | |
| 1033 | + if (_showCulledSharedFaces) { | |
| 1034 | + occlusions = ~node->getInteriorOcclusions(); | |
| 1035 | + } else { | |
| 1036 | + occlusions = node->getInteriorOcclusions(); | |
| 1037 | + } | |
| 1038 | + if (occlusions != OctreeElement::HalfSpace::All) { | |
| 1059 | 1039 | Cube* cube = new Cube( |
| 1060 | 1040 | startVertex.x, startVertex.y, startVertex.z, voxelScale, |
| 1061 | 1041 | color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], |
| 1062 | − node->getInteriorOcclusions()); | |
| 1042 | + occlusions); | |
| 1063 | 1043 | if (cube) { |
| 1064 | 1044 | primitiveIndex = _renderer->add(cube); |
| 1065 | 1045 | node->setPrimitiveIndex(primitiveIndex); |
| @@ -1491,6 +1471,7 @@ void VoxelSystem::killLocalVoxels() { · 425 unmodified lines | ||
| 1491 | 1471 | _tree->eraseAllOctreeElements(); |
| 1492 | 1472 | unlockTree(); |
| 1493 | 1473 | clearFreeBufferIndexes(); |
| 1474 | + _renderer->release(); | |
| 1494 | 1475 | _voxelsInReadArrays = 0; // do we need to do this? |
| 1495 | 1476 | setupNewVoxelsForDrawing(); |
| 1496 | 1477 | } |
| @@ -1541,7 +1522,7 @@ bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, · 44 unmodified lines | ||
| 1541 | 1522 | // all faces which are completely covered by four child octants. |
| 1542 | 1523 | unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); |
| 1543 | 1524 | |
| 1544 | − if (exteriorOcclusionsA == 0) { | |
| 1525 | + if (exteriorOcclusionsA == OctreeElement::HalfSpace::None) { | |
| 1545 | 1526 | // There is nothing to be done with this child, next... |
| 1546 | 1527 | continue; |
| 1547 | 1528 | } |
| @@ -1554,7 +1535,7 @@ bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, · 6 unmodified lines | ||
| 1554 | 1535 | // Get child B's occluding faces |
| 1555 | 1536 | unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); |
| 1556 | 1537 | |
| 1557 | − if (exteriorOcclusionsB == 0) { | |
| 1538 | + if (exteriorOcclusionsB == OctreeElement::HalfSpace::None) { | |
| 1558 | 1539 | // There is nothing to be done with this child, next... |
| 1559 | 1540 | continue; |
| 1560 | 1541 | } |
| @@ -1580,7 +1561,7 @@ bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, · 19 unmodified lines | ||
| 1580 | 1561 | |
| 1581 | 1562 | // Inform the child |
| 1582 | 1563 | childA->setInteriorOcclusions(occludedSharedFace[i]); |
| 1583 | − if (occludedSharedFace[i]) { | |
| 1564 | + if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { | |
| 1584 | 1565 | //const glm::vec3& v = voxel->getCorner(); |
| 1585 | 1566 | //float s = voxel->getScale(); |
| 1586 | 1567 | |
| @@ -1630,7 +1611,7 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element, · 43 unmodified lines | ||
| 1630 | 1611 | { |
| 1631 | 1612 | // Derive the exterior occlusions of the voxel elements from the exclusions |
| 1632 | 1613 | // of its children |
| 1633 | − unsigned char exteriorOcclusions = 0; | |
| 1614 | + unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; | |
| 1634 | 1615 | for (int i = 6; --i >= 0; ) { |
| 1635 | 1616 | if (exteriorOcclusionsCt[i] == 4) { |
| 1636 | 1617 | |
| @@ -1653,7 +1634,7 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element, · 16 unmodified lines | ||
| 1653 | 1634 | // occupied. Hence, the subtree from this node could be |
| 1654 | 1635 | // pruned and replaced by a leaf voxel, if the visible |
| 1655 | 1636 | // properties of the children are the same |
| 1656 | − } else if (exteriorOcclusions) { | |
| 1637 | + } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { | |
| 1657 | 1638 | //const glm::vec3& v = voxel->getCorner(); |
| 1658 | 1639 | //float s = voxel->getScale(); |
| 1659 | 1640 | |
| @@ -1675,11 +1656,11 @@ bool VoxelSystem::clearOcclusionsOperation(OctreeElement* element, void* extraDa · 15 unmodified lines | ||
| 1675 | 1656 | voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); |
| 1676 | 1657 | |
| 1677 | 1658 | // And the sibling occluders |
| 1678 | − voxel->setInteriorOcclusions(0); | |
| 1659 | + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1679 | 1660 | rc = false; |
| 1680 | 1661 | } else { |
| 1681 | − voxel->setExteriorOcclusions(0); | |
| 1682 | − voxel->setInteriorOcclusions(0); | |
| 1662 | + voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1663 | + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1683 | 1664 | rc = true; |
| 1684 | 1665 | } |
| 1685 | 1666 | |
| @@ -1690,10 +1671,9 @@ void VoxelSystem::cullSharedFaces() { · 4 unmodified lines | ||
| 1690 | 1671 | _nodeCount = 0; |
| 1691 | 1672 | |
| 1692 | 1673 | if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { |
| 1693 | − cleanupVoxelMemory(); | |
| 1694 | 1674 | _useVoxelShader = false; |
| 1695 | 1675 | _usePrimitiveRenderer = true; |
| 1696 | − initVoxelMemory(); | |
| 1676 | + _renderer->release(); | |
| 1697 | 1677 | clearAllNodesBufferIndex(); |
| 1698 | 1678 | lockTree(); |
| 1699 | 1679 | _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); |
| @@ -1706,9 +1686,8 @@ void VoxelSystem::cullSharedFaces() { · 6 unmodified lines | ||
| 1706 | 1686 | unlockTree(); |
| 1707 | 1687 | qDebug("culling shared faces in %d nodes", _nodeCount); |
| 1708 | 1688 | } else { |
| 1709 | − cleanupVoxelMemory(); | |
| 1710 | 1689 | _usePrimitiveRenderer = false; |
| 1711 | − initVoxelMemory(); | |
| 1690 | + _renderer->release(); | |
| 1712 | 1691 | clearAllNodesBufferIndex(); |
| 1713 | 1692 | lockTree(); |
| 1714 | 1693 | _tree->recurseTreeWithOperation(clearOcclusionsOperation); |
| @@ -1723,6 +1702,18 @@ void VoxelSystem::cullSharedFaces() { · 8 unmodified lines | ||
| 1723 | 1702 | |
| 1724 | 1703 | } |
| 1725 | 1704 | |
| 1705 | +void VoxelSystem::showCulledSharedFaces() { | |
| 1706 | + | |
| 1707 | + if (Menu::getInstance()->isOptionChecked(MenuOption::ShowCulledSharedFaces)) { | |
| 1708 | + _showCulledSharedFaces = true; | |
| 1709 | + } else { | |
| 1710 | + _showCulledSharedFaces = false; | |
| 1711 | + } | |
| 1712 | + if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { | |
| 1713 | + cullSharedFaces(); | |
| 1714 | + } | |
| 1715 | +} | |
| 1716 | + | |
| 1726 | 1717 | bool VoxelSystem::forceRedrawEntireTreeOperation(OctreeElement* element, void* extraData) { |
| 1727 | 1718 | _nodeCount++; |
| 1728 | 1719 | element->setDirtyBit(); |
| @@ -2650,31 +2641,37 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 921 unmodified lines | ||
| 2650 | 2641 | qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n", |
| 2651 | 2642 | args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes); |
| 2652 | 2643 | |
| 2653 | − qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld", debug::valueOf(_voxelsDirty), | |
| 2654 | − _voxelsInWriteArrays, minDirty, maxDirty); | |
| 2644 | + if (!_usePrimitiveRenderer) { | |
| 2645 | + qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld", debug::valueOf(_voxelsDirty), | |
| 2646 | + _voxelsInWriteArrays, minDirty, maxDirty); | |
| 2655 | 2647 | |
| 2656 | − qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld", | |
| 2657 | − args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); | |
| 2648 | + qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld", | |
| 2649 | + args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); | |
| 2658 | 2650 | |
| 2659 | − qDebug(" inPrimitiveRenderer %ld \n completely culled %ld \n", | |
| 2660 | − args.nodesInPrimitiveRenderer, args.culledLeafNodes); | |
| 2651 | + qDebug(" memory usage %ld \n gpu memory usage %ld \n", _memoryUsageRAM, _memoryUsageVBO); | |
| 2661 | 2652 | |
| 2662 | − glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; | |
| 2663 | − glBufferIndex maxInVBO = 0; | |
| 2653 | + glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; | |
| 2654 | + glBufferIndex maxInVBO = 0; | |
| 2664 | 2655 | |
| 2665 | − for (glBufferIndex i = 0; i < _maxVoxels; i++) { | |
| 2666 | − if (args.hasIndexFound[i]) { | |
| 2667 | − minInVBO = std::min(minInVBO,i); | |
| 2668 | − maxInVBO = std::max(maxInVBO,i); | |
| 2656 | + for (glBufferIndex i = 0; i < _maxVoxels; i++) { | |
| 2657 | + if (args.hasIndexFound[i]) { | |
| 2658 | + minInVBO = std::min(minInVBO,i); | |
| 2659 | + maxInVBO = std::max(maxInVBO,i); | |
| 2660 | + } | |
| 2669 | 2661 | } |
| 2670 | − } | |
| 2671 | 2662 | |
| 2672 | − qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld", | |
| 2673 | − minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); | |
| 2663 | + qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld", | |
| 2664 | + minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); | |
| 2674 | 2665 | |
| 2675 | − qDebug(" _freeIndexes.size()=%ld", | |
| 2676 | − _freeIndexes.size()); | |
| 2666 | + qDebug(" _freeIndexes.size()=%ld", | |
| 2667 | + _freeIndexes.size()); | |
| 2668 | + } else { | |
| 2669 | + qDebug(" PrimitiveRenderer nodes %ld \n completely culled nodes %ld \n", | |
| 2670 | + args.nodesInPrimitiveRenderer, args.culledLeafNodes); | |
| 2677 | 2671 | |
| 2672 | + qDebug(" memory usage %ld \n gpu memory usage %ld \n", | |
| 2673 | + _renderer->getMemoryUsage(), _renderer->getMemoryUsageGPU()); | |
| 2674 | + } | |
| 2678 | 2675 | qDebug("DONE WITH Local Voxel Tree Statistics >>>>>>>>>>>>"); |
| 2679 | 2676 | } |
| 2680 | 2677 | |