Showing the changes to interface/src/VoxelSystem.cpp (1 of 140 files). Show all
Unified · Split
| @@ -18,8 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <NodeList.h> |
| 19 | 19 | |
| 20 | 20 | #include "Application.h" |
| 21 | −#include "CoverageMap.h" | |
| 22 | −#include "CoverageMapV2.h" | |
| 23 | 21 | #include "InterfaceConfig.h" |
| 24 | 22 | #include "Menu.h" |
| 25 | 23 | #include "renderer/ProgramObject.h" |
| @@ -84,9 +82,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) · 58 unmodified lines | ||
| 84 | 82 | |
| 85 | 83 | _viewFrustum = Application::getInstance()->getViewFrustum(); |
| 86 | 84 | |
| 87 | − connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); | |
| 88 | − connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); | |
| 89 | − | |
| 90 | 85 | _useVoxelShader = false; |
| 91 | 86 | _voxelsAsPoints = false; |
| 92 | 87 | _voxelShaderModeWhenVoxelsAsPointsEnabled = false; |
| @@ -206,31 +201,16 @@ void VoxelSystem::freeBufferIndex(glBufferIndex index) { · 113 unmodified lines | ||
| 206 | 201 | qDebug() << "freeBufferIndex() called when _voxelsInWriteArrays == 0!"; |
| 207 | 202 | } |
| 208 | 203 | |
| 209 | − // if the "freed" index was our max index, then just drop the _voxelsInWriteArrays down one... | |
| 210 | − bool inList = false; | |
| 211 | − | |
| 212 | − // make sure the index isn't already in the free list..., this is a debugging measure only done if you've enabled audits | |
| 213 | − if (Menu::getInstance()->isOptionChecked(MenuOption::AutomaticallyAuditTree)) { | |
| 214 | − for (unsigned long i = 0; i < _freeIndexes.size(); i++) { | |
| 215 | − if (_freeIndexes[i] == index) { | |
| 216 | − printf("freeBufferIndex(glBufferIndex index)... index=%ld already in free list!", index); | |
| 217 | − inList = true; | |
| 218 | − break; | |
| 219 | − } | |
| 220 | − } | |
| 221 | − } | |
| 222 | − if (!inList) { | |
| 223 | − // make the index available for next node that needs to be drawn | |
| 224 | − _freeIndexLock.lock(); | |
| 225 | − _freeIndexes.push_back(index); | |
| 226 | − _freeIndexLock.unlock(); | |
| 204 | + // make the index available for next node that needs to be drawn | |
| 205 | + _freeIndexLock.lock(); | |
| 206 | + _freeIndexes.push_back(index); | |
| 207 | + _freeIndexLock.unlock(); | |
| 227 | 208 | |
| 228 | − // make the VBO slot "invisible" in case this slot is not used | |
| 229 | − const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); | |
| 230 | − const float voxelScale = 0; | |
| 231 | − const nodeColor BLACK = {0, 0, 0, 0}; | |
| 232 | − updateArraysDetails(index, startVertex, voxelScale, BLACK); | |
| 233 | − } | |
| 209 | + // make the VBO slot "invisible" in case this slot is not used | |
| 210 | + const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); | |
| 211 | + const float voxelScale = 0; | |
| 212 | + const nodeColor BLACK = {0, 0, 0, 0}; | |
| 213 | + updateArraysDetails(index, startVertex, voxelScale, BLACK); | |
| 234 | 214 | } |
| 235 | 215 | |
| 236 | 216 | // This will run through the list of _freeIndexes and reset their VBO array values to be "invisible". |
| @@ -541,34 +521,6 @@ void VoxelSystem::initVoxelMemory() { · 304 unmodified lines | ||
| 541 | 521 | _readArraysLock.unlock(); |
| 542 | 522 | } |
| 543 | 523 | |
| 544 | −void VoxelSystem::writeToSVOFile(const char* filename, VoxelTreeElement* element) const { | |
| 545 | − _tree->writeToSVOFile(filename, element); | |
| 546 | −} | |
| 547 | − | |
| 548 | −bool VoxelSystem::readFromSVOFile(const char* filename) { | |
| 549 | − bool result = _tree->readFromSVOFile(filename); | |
| 550 | − if (result) { | |
| 551 | − setupNewVoxelsForDrawing(); | |
| 552 | − } | |
| 553 | − return result; | |
| 554 | −} | |
| 555 | − | |
| 556 | −bool VoxelSystem::readFromSquareARGB32Pixels(const char *filename) { | |
| 557 | − bool result = _tree->readFromSquareARGB32Pixels(filename); | |
| 558 | − if (result) { | |
| 559 | − setupNewVoxelsForDrawing(); | |
| 560 | − } | |
| 561 | − return result; | |
| 562 | −} | |
| 563 | − | |
| 564 | −bool VoxelSystem::readFromSchematicFile(const char* filename) { | |
| 565 | − bool result = _tree->readFromSchematicFile(filename); | |
| 566 | − if (result) { | |
| 567 | − setupNewVoxelsForDrawing(); | |
| 568 | − } | |
| 569 | − return result; | |
| 570 | −} | |
| 571 | − | |
| 572 | 524 | int VoxelSystem::parseData(const QByteArray& packet) { |
| 573 | 525 | bool showTimingDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 574 | 526 | PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData()",showTimingDetails); |
| @@ -618,7 +570,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { · 43 unmodified lines | ||
| 618 | 570 | // ask the VoxelTree to read the bitstream into the tree |
| 619 | 571 | ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID()); |
| 620 | 572 | _tree->lockForWrite(); |
| 621 | − VoxelPacketData packetData(packetIsCompressed); | |
| 573 | + OctreePacketData packetData(packetIsCompressed); | |
| 622 | 574 | packetData.loadFinalizedContent(dataAt, sectionLength); |
| 623 | 575 | if (Application::getInstance()->getLogger()->extraDebugging()) { |
| 624 | 576 | qDebug("VoxelSystem::parseData() ... Got Packet Section" |
| @@ -692,8 +644,6 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 67 unmodified lines | ||
| 692 | 644 | _abandonedVBOSlots = 0; // reset the count of our abandoned slots, why is this here and not earlier???? |
| 693 | 645 | } |
| 694 | 646 | |
| 695 | − // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are | |
| 696 | − // ok again, until/unless we call removeOutOfView() | |
| 697 | 647 | _writeRenderFullVBO = false; |
| 698 | 648 | } else { |
| 699 | 649 | _voxelsUpdated = 0; |
| @@ -886,15 +836,6 @@ void VoxelSystem::checkForCulling() { · 186 unmodified lines | ||
| 886 | 836 | // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on |
| 887 | 837 | // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary. |
| 888 | 838 | cleanupRemovedVoxels(); |
| 889 | − | |
| 890 | − quint64 sinceLastAudit = (start - _lastAudit) / 1000; | |
| 891 | − | |
| 892 | − if (Menu::getInstance()->isOptionChecked(MenuOption::AutomaticallyAuditTree)) { | |
| 893 | − if (sinceLastAudit >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) { | |
| 894 | − _lastAudit = start; | |
| 895 | − collectStatsForTreesAndVBOs(); | |
| 896 | − } | |
| 897 | − } | |
| 898 | 839 | } |
| 899 | 840 | |
| 900 | 841 | void VoxelSystem::cleanupRemovedVoxels() { |
| @@ -1241,9 +1182,6 @@ void VoxelSystem::changeTree(VoxelTree* newTree) { · 340 unmodified lines | ||
| 1241 | 1182 | _tree->setDirtyBit(); |
| 1242 | 1183 | _tree->getRoot()->setVoxelSystem(this); |
| 1243 | 1184 | |
| 1244 | − connect(_tree, SIGNAL(importSize(float,float,float)), SIGNAL(importSize(float,float,float))); | |
| 1245 | − connect(_tree, SIGNAL(importProgress(int)), SIGNAL(importProgress(int))); | |
| 1246 | − | |
| 1247 | 1185 | setupNewVoxelsForDrawing(); |
| 1248 | 1186 | } |
| 1249 | 1187 | |
| @@ -1830,329 +1768,6 @@ void VoxelSystem::forceRedrawEntireTree() { · 580 unmodified lines | ||
| 1830 | 1768 | setupNewVoxelsForDrawing(); |
| 1831 | 1769 | } |
| 1832 | 1770 | |
| 1833 | −bool VoxelSystem::randomColorOperation(OctreeElement* element, void* extraData) { | |
| 1834 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1835 | − _nodeCount++; | |
| 1836 | − if (voxel->isColored()) { | |
| 1837 | − nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 }; | |
| 1838 | − voxel->setColor(newColor); | |
| 1839 | − } | |
| 1840 | − return true; | |
| 1841 | −} | |
| 1842 | − | |
| 1843 | −void VoxelSystem::randomizeVoxelColors() { | |
| 1844 | − _nodeCount = 0; | |
| 1845 | − _tree->recurseTreeWithOperation(randomColorOperation); | |
| 1846 | − qDebug("setting randomized true color for %d nodes", _nodeCount); | |
| 1847 | − _tree->setDirtyBit(); | |
| 1848 | − setupNewVoxelsForDrawing(); | |
| 1849 | −} | |
| 1850 | − | |
| 1851 | −bool VoxelSystem::falseColorizeRandomOperation(OctreeElement* element, void* extraData) { | |
| 1852 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1853 | − _nodeCount++; | |
| 1854 | − // always false colorize | |
| 1855 | − voxel->setFalseColor(255, randomColorValue(150), randomColorValue(150)); | |
| 1856 | − return true; // keep going! | |
| 1857 | −} | |
| 1858 | − | |
| 1859 | −void VoxelSystem::falseColorizeRandom() { | |
| 1860 | − _nodeCount = 0; | |
| 1861 | − _tree->recurseTreeWithOperation(falseColorizeRandomOperation); | |
| 1862 | − qDebug("setting randomized false color for %d nodes", _nodeCount); | |
| 1863 | − _tree->setDirtyBit(); | |
| 1864 | − setupNewVoxelsForDrawing(); | |
| 1865 | −} | |
| 1866 | − | |
| 1867 | −bool VoxelSystem::trueColorizeOperation(OctreeElement* element, void* extraData) { | |
| 1868 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1869 | − _nodeCount++; | |
| 1870 | − voxel->setFalseColored(false); | |
| 1871 | − return true; | |
| 1872 | −} | |
| 1873 | − | |
| 1874 | −void VoxelSystem::trueColorize() { | |
| 1875 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 1876 | − "trueColorize()",true); | |
| 1877 | − _nodeCount = 0; | |
| 1878 | − _tree->recurseTreeWithOperation(trueColorizeOperation); | |
| 1879 | − qDebug("setting true color for %d nodes", _nodeCount); | |
| 1880 | − _tree->setDirtyBit(); | |
| 1881 | − setupNewVoxelsForDrawing(); | |
| 1882 | −} | |
| 1883 | − | |
| 1884 | −// Will false colorize voxels that are not in view | |
| 1885 | −bool VoxelSystem::falseColorizeInViewOperation(OctreeElement* element, void* extraData) { | |
| 1886 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1887 | − const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; | |
| 1888 | − _nodeCount++; | |
| 1889 | − if (voxel->isColored()) { | |
| 1890 | − if (!voxel->isInView(*viewFrustum)) { | |
| 1891 | − // Out of view voxels are colored RED | |
| 1892 | − voxel->setFalseColor(255, 0, 0); | |
| 1893 | − } | |
| 1894 | − } | |
| 1895 | − return true; // keep going! | |
| 1896 | −} | |
| 1897 | − | |
| 1898 | −void VoxelSystem::falseColorizeInView() { | |
| 1899 | − _nodeCount = 0; | |
| 1900 | − _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)_viewFrustum); | |
| 1901 | − qDebug("setting in view false color for %d nodes", _nodeCount); | |
| 1902 | − _tree->setDirtyBit(); | |
| 1903 | − setupNewVoxelsForDrawing(); | |
| 1904 | −} | |
| 1905 | − | |
| 1906 | −class VoxelAndPoint { | |
| 1907 | −public: | |
| 1908 | − VoxelTreeElement* voxel; | |
| 1909 | − glm::vec3 point; | |
| 1910 | −}; | |
| 1911 | − | |
| 1912 | −// Find the smallest colored voxel enclosing a point (if there is one) | |
| 1913 | −bool VoxelSystem::getVoxelEnclosingOperation(OctreeElement* element, void* extraData) { | |
| 1914 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1915 | − VoxelAndPoint* args = (VoxelAndPoint*) extraData; | |
| 1916 | − AABox voxelBox = voxel->getAABox(); | |
| 1917 | − if (voxelBox.contains(args->point)) { | |
| 1918 | − if (voxel->isColored() && voxel->isLeaf()) { | |
| 1919 | − // we've reached a solid leaf containing the point, return the node. | |
| 1920 | − args->voxel = voxel; | |
| 1921 | − return false; | |
| 1922 | − } | |
| 1923 | − } else { | |
| 1924 | − // The point is not inside this voxel, so stop recursing. | |
| 1925 | − return false; | |
| 1926 | − } | |
| 1927 | − return true; // keep looking | |
| 1928 | −} | |
| 1929 | − | |
| 1930 | −VoxelTreeElement* VoxelSystem::getVoxelEnclosing(const glm::vec3& point) { | |
| 1931 | − VoxelAndPoint voxelAndPoint; | |
| 1932 | − voxelAndPoint.point = point; | |
| 1933 | − voxelAndPoint.voxel = NULL; | |
| 1934 | − _tree->recurseTreeWithOperation(getVoxelEnclosingOperation, (void*) &voxelAndPoint); | |
| 1935 | − return voxelAndPoint.voxel; | |
| 1936 | −} | |
| 1937 | − | |
| 1938 | − | |
| 1939 | −// helper classes and args for falseColorizeBySource | |
| 1940 | −class groupColor { | |
| 1941 | −public: | |
| 1942 | − unsigned char red, green, blue; | |
| 1943 | − groupColor(unsigned char red, unsigned char green, unsigned char blue) : | |
| 1944 | − red(red), green(green), blue(blue) { } | |
| 1945 | − | |
| 1946 | − groupColor() : | |
| 1947 | − red(0), green(0), blue(0) { } | |
| 1948 | −}; | |
| 1949 | − | |
| 1950 | −class colorizeBySourceArgs { | |
| 1951 | −public: | |
| 1952 | − std::map<uint16_t, groupColor> colors; | |
| 1953 | −}; | |
| 1954 | − | |
| 1955 | −// Will false colorize voxels that are not in view | |
| 1956 | −bool VoxelSystem::falseColorizeBySourceOperation(OctreeElement* element, void* extraData) { | |
| 1957 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 1958 | − colorizeBySourceArgs* args = (colorizeBySourceArgs*)extraData; | |
| 1959 | − _nodeCount++; | |
| 1960 | − if (voxel->isColored()) { | |
| 1961 | − // pick a color based on the source - we want each source to be obviously different | |
| 1962 | − uint16_t nodeIDKey = voxel->getSourceUUIDKey(); | |
| 1963 | − voxel->setFalseColor(args->colors[nodeIDKey].red, args->colors[nodeIDKey].green, args->colors[nodeIDKey].blue); | |
| 1964 | − } | |
| 1965 | − return true; // keep going! | |
| 1966 | −} | |
| 1967 | − | |
| 1968 | −void VoxelSystem::falseColorizeBySource() { | |
| 1969 | − _nodeCount = 0; | |
| 1970 | − colorizeBySourceArgs args; | |
| 1971 | − const int NUMBER_OF_COLOR_GROUPS = 6; | |
| 1972 | − const unsigned char MIN_COLOR = 128; | |
| 1973 | − int voxelServerCount = 0; | |
| 1974 | − groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = { | |
| 1975 | − groupColor(255, 0, 0), | |
| 1976 | − groupColor( 0, 255, 0), | |
| 1977 | − groupColor( 0, 0, 255), | |
| 1978 | − groupColor(255, 0, 255), | |
| 1979 | − groupColor( 0, 255, 255), | |
| 1980 | − groupColor(255, 255, 255) | |
| 1981 | − }; | |
| 1982 | − | |
| 1983 | − // create a bunch of colors we'll use during colorization | |
| 1984 | − | |
| 1985 | − foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { | |
| 1986 | − if (node->getType() == NodeType::VoxelServer) { | |
| 1987 | − uint16_t nodeID = VoxelTreeElement::getSourceNodeUUIDKey(node->getUUID()); | |
| 1988 | − int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS; | |
| 1989 | − args.colors[nodeID] = groupColors[groupColor]; | |
| 1990 | − | |
| 1991 | − if (groupColors[groupColor].red > 0) { | |
| 1992 | − groupColors[groupColor].red = ((groupColors[groupColor].red - MIN_COLOR)/2) + MIN_COLOR; | |
| 1993 | − } | |
| 1994 | − if (groupColors[groupColor].green > 0) { | |
| 1995 | − groupColors[groupColor].green = ((groupColors[groupColor].green - MIN_COLOR)/2) + MIN_COLOR; | |
| 1996 | − } | |
| 1997 | − if (groupColors[groupColor].blue > 0) { | |
| 1998 | − groupColors[groupColor].blue = ((groupColors[groupColor].blue - MIN_COLOR)/2) + MIN_COLOR; | |
| 1999 | − } | |
| 2000 | − | |
| 2001 | − voxelServerCount++; | |
| 2002 | − } | |
| 2003 | − } | |
| 2004 | − | |
| 2005 | − _tree->recurseTreeWithOperation(falseColorizeBySourceOperation, &args); | |
| 2006 | − qDebug("setting false color by source for %d nodes", _nodeCount); | |
| 2007 | − _tree->setDirtyBit(); | |
| 2008 | − setupNewVoxelsForDrawing(); | |
| 2009 | −} | |
| 2010 | − | |
| 2011 | −// Will false colorize voxels based on distance from view | |
| 2012 | −bool VoxelSystem::falseColorizeDistanceFromViewOperation(OctreeElement* element, void* extraData) { | |
| 2013 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2014 | − ViewFrustum* viewFrustum = (ViewFrustum*) extraData; | |
| 2015 | − if (voxel->isColored()) { | |
| 2016 | − float distance = voxel->distanceToCamera(*viewFrustum); | |
| 2017 | − _nodeCount++; | |
| 2018 | − float distanceRatio = (_minDistance == _maxDistance) ? 1 : (distance - _minDistance) / (_maxDistance - _minDistance); | |
| 2019 | − | |
| 2020 | − // We want to colorize this in 16 bug chunks of color | |
| 2021 | − const unsigned char maxColor = 255; | |
| 2022 | − const unsigned char colorBands = 16; | |
| 2023 | − const unsigned char gradientOver = 128; | |
| 2024 | − unsigned char colorBand = (colorBands * distanceRatio); | |
| 2025 | − voxel->setFalseColor((colorBand * (gradientOver / colorBands)) + (maxColor - gradientOver), 0, 0); | |
| 2026 | − } | |
| 2027 | − return true; // keep going! | |
| 2028 | −} | |
| 2029 | − | |
| 2030 | −float VoxelSystem::_maxDistance = 0.0; | |
| 2031 | −float VoxelSystem::_minDistance = FLT_MAX; | |
| 2032 | − | |
| 2033 | −// Helper function will get the distance from view range, would be nice if you could just keep track | |
| 2034 | −// of this as voxels are created and/or colored... seems like some transform math could do that so | |
| 2035 | −// we wouldn't need to do two passes of the tree | |
| 2036 | −bool VoxelSystem::getDistanceFromViewRangeOperation(OctreeElement* element, void* extraData) { | |
| 2037 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2038 | − ViewFrustum* viewFrustum = (ViewFrustum*) extraData; | |
| 2039 | − // only do this for truly colored voxels... | |
| 2040 | − if (voxel->isColored()) { | |
| 2041 | − float distance = voxel->distanceToCamera(*viewFrustum); | |
| 2042 | − // calculate the range of distances | |
| 2043 | − if (distance > _maxDistance) { | |
| 2044 | − _maxDistance = distance; | |
| 2045 | − } | |
| 2046 | − if (distance < _minDistance) { | |
| 2047 | − _minDistance = distance; | |
| 2048 | − } | |
| 2049 | − _nodeCount++; | |
| 2050 | − } | |
| 2051 | − return true; // keep going! | |
| 2052 | −} | |
| 2053 | − | |
| 2054 | −void VoxelSystem::falseColorizeDistanceFromView() { | |
| 2055 | − _nodeCount = 0; | |
| 2056 | − _maxDistance = 0.0; | |
| 2057 | − _minDistance = FLT_MAX; | |
| 2058 | − _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation, (void*) _viewFrustum); | |
| 2059 | − qDebug("determining distance range for %d nodes", _nodeCount); | |
| 2060 | − _nodeCount = 0; | |
| 2061 | − _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation, (void*) _viewFrustum); | |
| 2062 | − qDebug("setting in distance false color for %d nodes", _nodeCount); | |
| 2063 | − _tree->setDirtyBit(); | |
| 2064 | − setupNewVoxelsForDrawing(); | |
| 2065 | −} | |
| 2066 | − | |
| 2067 | −// combines the removeOutOfView args into a single class | |
| 2068 | −class removeOutOfViewArgs { | |
| 2069 | −public: | |
| 2070 | − VoxelSystem* thisVoxelSystem; | |
| 2071 | − ViewFrustum thisViewFrustum; | |
| 2072 | − OctreeElementBag dontRecurseBag; | |
| 2073 | − unsigned long nodesScanned; | |
| 2074 | − unsigned long nodesRemoved; | |
| 2075 | − unsigned long nodesInside; | |
| 2076 | − unsigned long nodesIntersect; | |
| 2077 | − unsigned long nodesOutside; | |
| 2078 | − VoxelTreeElement* insideRoot; | |
| 2079 | − VoxelTreeElement* outsideRoot; | |
| 2080 | − | |
| 2081 | − removeOutOfViewArgs(VoxelSystem* voxelSystem, bool widenViewFrustum = true) : | |
| 2082 | − thisVoxelSystem(voxelSystem), | |
| 2083 | − thisViewFrustum(*voxelSystem->getViewFrustum()), | |
| 2084 | − dontRecurseBag(), | |
| 2085 | − nodesScanned(0), | |
| 2086 | − nodesRemoved(0), | |
| 2087 | − nodesInside(0), | |
| 2088 | − nodesIntersect(0), | |
| 2089 | − nodesOutside(0), | |
| 2090 | − insideRoot(NULL), | |
| 2091 | − outsideRoot(NULL) | |
| 2092 | − { | |
| 2093 | − // Widen the FOV for trimming | |
| 2094 | − if (widenViewFrustum) { | |
| 2095 | − float originalFOV = thisViewFrustum.getFieldOfView(); | |
| 2096 | − float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND; | |
| 2097 | − thisViewFrustum.setFieldOfView(wideFOV); | |
| 2098 | − thisViewFrustum.calculate(); | |
| 2099 | − } | |
| 2100 | − } | |
| 2101 | −}; | |
| 2102 | − | |
| 2103 | −void VoxelSystem::cancelImport() { | |
| 2104 | − _tree->cancelImport(); | |
| 2105 | −} | |
| 2106 | − | |
| 2107 | −// "Remove" voxels from the tree that are not in view. We don't actually delete them, | |
| 2108 | −// we remove them from the tree and place them into a holding area for later deletion | |
| 2109 | −bool VoxelSystem::removeOutOfViewOperation(OctreeElement* element, void* extraData) { | |
| 2110 | − VoxelTreeElement* voxel = (VoxelTreeElement*) element; | |
| 2111 | − removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData; | |
| 2112 | − | |
| 2113 | − // If our node was previously added to the don't recurse bag, then return false to | |
| 2114 | − // stop the further recursion. This means that the whole node and it's children are | |
| 2115 | − // known to be in view, so don't recurse them | |
| 2116 | − if (args->dontRecurseBag.contains(voxel)) { | |
| 2117 | − args->dontRecurseBag.remove(voxel); | |
| 2118 | − return false; // stop recursion | |
| 2119 | − } | |
| 2120 | − | |
| 2121 | − VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; | |
| 2122 | − args->nodesScanned++; | |
| 2123 | − // Need to operate on our child nodes, so we can remove them | |
| 2124 | − for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { | |
| 2125 | − VoxelTreeElement* childNode = voxel->getChildAtIndex(i); | |
| 2126 | − if (childNode) { | |
| 2127 | − ViewFrustum::location inFrustum = childNode->inFrustum(args->thisViewFrustum); | |
| 2128 | − switch (inFrustum) { | |
| 2129 | − case ViewFrustum::OUTSIDE: { | |
| 2130 | − args->nodesOutside++; | |
| 2131 | − args->nodesRemoved++; | |
| 2132 | − voxel->removeChildAtIndex(i); | |
| 2133 | − thisVoxelSystem->_removedVoxels.insert(childNode); | |
| 2134 | − // by removing the child, it will not get recursed! | |
| 2135 | − } break; | |
| 2136 | − case ViewFrustum::INSIDE: { | |
| 2137 | − // if the child node is fully INSIDE the view, then there's no need to recurse it | |
| 2138 | − // because we know all it's children will also be in the view, so we want to | |
| 2139 | − // tell the caller to NOT recurse this child | |
| 2140 | − args->nodesInside++; | |
| 2141 | − args->dontRecurseBag.insert(childNode); | |
| 2142 | − } break; | |
| 2143 | − case ViewFrustum::INTERSECT: { | |
| 2144 | − // if the child node INTERSECTs the view, then we don't want to remove it because | |
| 2145 | − // it is at least partially in view. But we DO want to recurse the children because | |
| 2146 | − // some of them may not be in view... nothing specifically to do, just keep iterating | |
| 2147 | − // the children | |
| 2148 | − args->nodesIntersect++; | |
| 2149 | − } break; | |
| 2150 | − } | |
| 2151 | − } | |
| 2152 | − } | |
| 2153 | − return true; // keep going! | |
| 2154 | −} | |
| 2155 | − | |
| 2156 | 1771 | bool VoxelSystem::isViewChanging() { |
| 2157 | 1772 | bool result = false; // assume the best |
| 2158 | 1773 | |
| @@ -2180,74 +1795,6 @@ bool VoxelSystem::hasViewChanged() { · 21 unmodified lines | ||
| 2180 | 1795 | return result; |
| 2181 | 1796 | } |
| 2182 | 1797 | |
| 2183 | −void VoxelSystem::removeOutOfView() { | |
| 2184 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "removeOutOfView()"); | |
| 2185 | − removeOutOfViewArgs args(this); | |
| 2186 | − _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); | |
| 2187 | − | |
| 2188 | − if (args.nodesRemoved) { | |
| 2189 | − _tree->setDirtyBit(); | |
| 2190 | − } | |
| 2191 | − bool showRemoveDebugDetails = false; | |
| 2192 | − if (showRemoveDebugDetails) { | |
| 2193 | − qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d", | |
| 2194 | − args.nodesScanned, args.nodesRemoved, args.nodesInside, | |
| 2195 | − args.nodesIntersect, args.nodesOutside, _removedVoxels.count() | |
| 2196 | − ); | |
| 2197 | − } | |
| 2198 | −} | |
| 2199 | − | |
| 2200 | −// combines the removeOutOfView args into a single class | |
| 2201 | −class showAllLocalVoxelsArgs { | |
| 2202 | −public: | |
| 2203 | − VoxelSystem* thisVoxelSystem; | |
| 2204 | − ViewFrustum thisViewFrustum; | |
| 2205 | − unsigned long nodesScanned; | |
| 2206 | − | |
| 2207 | − showAllLocalVoxelsArgs(VoxelSystem* voxelSystem) : | |
| 2208 | − thisVoxelSystem(voxelSystem), | |
| 2209 | − thisViewFrustum(*voxelSystem->getViewFrustum()), | |
| 2210 | − nodesScanned(0) | |
| 2211 | − { | |
| 2212 | − } | |
| 2213 | −}; | |
| 2214 | − | |
| 2215 | −void VoxelSystem::showAllLocalVoxels() { | |
| 2216 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "showAllLocalVoxels()"); | |
| 2217 | − showAllLocalVoxelsArgs args(this); | |
| 2218 | − _tree->recurseTreeWithOperation(showAllLocalVoxelsOperation,(void*)&args); | |
| 2219 | − | |
| 2220 | − bool showRemoveDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); | |
| 2221 | − if (showRemoveDebugDetails) { | |
| 2222 | − qDebug("showAllLocalVoxels() scanned=%ld",args.nodesScanned ); | |
| 2223 | − } | |
| 2224 | −} | |
| 2225 | − | |
| 2226 | −bool VoxelSystem::showAllLocalVoxelsOperation(OctreeElement* element, void* extraData) { | |
| 2227 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2228 | − showAllLocalVoxelsArgs* args = (showAllLocalVoxelsArgs*)extraData; | |
| 2229 | − | |
| 2230 | − args->nodesScanned++; | |
| 2231 | − | |
| 2232 | − float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();; | |
| 2233 | − int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust(); | |
| 2234 | − bool shouldRender = voxel->calculateShouldRender(&args->thisViewFrustum, voxelSizeScale, boundaryLevelAdjust); | |
| 2235 | − voxel->setShouldRender(shouldRender); | |
| 2236 | − | |
| 2237 | − if (shouldRender) { | |
| 2238 | − bool falseColorize = false; | |
| 2239 | − if (falseColorize) { | |
| 2240 | − voxel->setFalseColor(0,0,255); // false colorize | |
| 2241 | − } | |
| 2242 | − // These are both needed to force redraw... | |
| 2243 | − voxel->setDirtyBit(); | |
| 2244 | − voxel->markWithChangedTime(); | |
| 2245 | − } | |
| 2246 | − | |
| 2247 | − return true; // keep recursing! | |
| 2248 | −} | |
| 2249 | − | |
| 2250 | − | |
| 2251 | 1798 | // combines the removeOutOfView args into a single class |
| 2252 | 1799 | class hideOutOfViewArgs { |
| 2253 | 1800 | public: |
| @@ -2396,15 +1943,9 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat · 142 unmodified lines | ||
| 2396 | 1943 | args->nodesOutside++; |
| 2397 | 1944 | if (voxel->isKnownBufferIndex()) { |
| 2398 | 1945 | args->nodesRemoved++; |
| 2399 | − bool falseColorize = false; | |
| 2400 | − if (falseColorize) { | |
| 2401 | − voxel->setFalseColor(255,0,0); // false colorize | |
| 2402 | − } else { | |
| 2403 | − VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; | |
| 2404 | − thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->forceRemoveNodeFromArrays(voxel); | |
| 2405 | − thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); | |
| 2406 | − } | |
| 2407 | − | |
| 1946 | + VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; | |
| 1947 | + thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->forceRemoveNodeFromArrays(voxel); | |
| 1948 | + thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); | |
| 2408 | 1949 | } |
| 2409 | 1950 | |
| 2410 | 1951 | return true; |
| @@ -2437,20 +1978,9 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 26 unmodified lines | ||
| 2437 | 1978 | voxel->setShouldRender(shouldRender); |
| 2438 | 1979 | |
| 2439 | 1980 | if (shouldRender && !voxel->isKnownBufferIndex()) { |
| 2440 | − bool falseColorize = false; | |
| 2441 | − if (falseColorize) { | |
| 2442 | − voxel->setFalseColor(0,0,255); // false colorize | |
| 2443 | − } | |
| 2444 | 1981 | // These are both needed to force redraw... |
| 2445 | 1982 | voxel->setDirtyBit(); |
| 2446 | 1983 | voxel->markWithChangedTime(); |
| 2447 | − // and this? | |
| 2448 | −// no, not needed, because markWithChangedTime notifies hooks, which calls elementUpdated, which calls updateNodeInArrays | |
| 2449 | −// { | |
| 2450 | −// VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; | |
| 2451 | −// thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->updateNodeInArrays(voxel, true, true); | |
| 2452 | −// thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); | |
| 2453 | −// } | |
| 2454 | 1984 | args->nodesShown++; |
| 2455 | 1985 | } |
| 2456 | 1986 | |
| @@ -2552,567 +2082,6 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 95 unmodified lines | ||
| 2552 | 2082 | } |
| 2553 | 2083 | |
| 2554 | 2084 | |
| 2555 | −bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, | |
| 2556 | − VoxelDetail& detail, float& distance, BoxFace& face) { | |
| 2557 | − | |
| 2558 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 2559 | − "VoxelSystem::findRayIntersection()"); | |
| 2560 | − bool result = false; // assume no intersection | |
| 2561 | − if (_tree->tryLockForRead()) { | |
| 2562 | − OctreeElement* element; | |
| 2563 | − result = _tree->findRayIntersection(origin, direction, element, distance, face); | |
| 2564 | − if (result) { | |
| 2565 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2566 | − detail.x = voxel->getCorner().x; | |
| 2567 | − detail.y = voxel->getCorner().y; | |
| 2568 | − detail.z = voxel->getCorner().z; | |
| 2569 | − detail.s = voxel->getScale(); | |
| 2570 | − detail.red = voxel->getColor()[0]; | |
| 2571 | − detail.green = voxel->getColor()[1]; | |
| 2572 | − detail.blue = voxel->getColor()[2]; | |
| 2573 | − } | |
| 2574 | − _tree->unlock(); | |
| 2575 | − } | |
| 2576 | − return result; | |
| 2577 | −} | |
| 2578 | − | |
| 2579 | −bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) { | |
| 2580 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 2581 | − "VoxelSystem::findSpherePenetration()"); | |
| 2582 | − bool result = false; // assume no penetration | |
| 2583 | − if (_tree->tryLockForRead()) { | |
| 2584 | − result = _tree->findSpherePenetration(center, radius, penetration); | |
| 2585 | − _tree->unlock(); | |
| 2586 | − } | |
| 2587 | − return result; | |
| 2588 | −} | |
| 2589 | − | |
| 2590 | −bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) { | |
| 2591 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 2592 | − "VoxelSystem::findCapsulePenetration()"); | |
| 2593 | − bool result = false; // assume no penetration | |
| 2594 | − if (_tree->tryLockForRead()) { | |
| 2595 | − result = _tree->findCapsulePenetration(start, end, radius, penetration); | |
| 2596 | − _tree->unlock(); | |
| 2597 | − } | |
| 2598 | − return result; | |
| 2599 | −} | |
| 2600 | − | |
| 2601 | −class falseColorizeRandomEveryOtherArgs { | |
| 2602 | −public: | |
| 2603 | − falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {}; | |
| 2604 | − unsigned long totalNodes; | |
| 2605 | − unsigned long colorableNodes; | |
| 2606 | − unsigned long coloredNodes; | |
| 2607 | − bool colorThis; | |
| 2608 | −}; | |
| 2609 | − | |
| 2610 | −bool VoxelSystem::falseColorizeRandomEveryOtherOperation(OctreeElement* element, void* extraData) { | |
| 2611 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2612 | − falseColorizeRandomEveryOtherArgs* args = (falseColorizeRandomEveryOtherArgs*)extraData; | |
| 2613 | − args->totalNodes++; | |
| 2614 | − if (voxel->isColored()) { | |
| 2615 | − args->colorableNodes++; | |
| 2616 | − if (args->colorThis) { | |
| 2617 | − args->coloredNodes++; | |
| 2618 | − voxel->setFalseColor(255, randomColorValue(150), randomColorValue(150)); | |
| 2619 | − } | |
| 2620 | − args->colorThis = !args->colorThis; | |
| 2621 | − } | |
| 2622 | − return true; // keep going! | |
| 2623 | −} | |
| 2624 | − | |
| 2625 | −void VoxelSystem::falseColorizeRandomEveryOther() { | |
| 2626 | − falseColorizeRandomEveryOtherArgs args; | |
| 2627 | − _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args); | |
| 2628 | − qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld", | |
| 2629 | − args.totalNodes, args.colorableNodes, args.coloredNodes); | |
| 2630 | − _tree->setDirtyBit(); | |
| 2631 | − setupNewVoxelsForDrawing(); | |
| 2632 | −} | |
| 2633 | − | |
| 2634 | −class collectStatsForTreesAndVBOsArgs { | |
| 2635 | −public: | |
| 2636 | − collectStatsForTreesAndVBOsArgs(int maxVoxels) : | |
| 2637 | − totalNodes(0), | |
| 2638 | − dirtyNodes(0), | |
| 2639 | − shouldRenderNodes(0), | |
| 2640 | − coloredNodes(0), | |
| 2641 | − nodesInVBO(0), | |
| 2642 | − nodesInVBONotShouldRender(0), | |
| 2643 | − nodesInVBOOverExpectedMax(0), | |
| 2644 | − duplicateVBOIndex(0), | |
| 2645 | − leafNodes(0), | |
| 2646 | − culledLeafNodes(0), | |
| 2647 | − nodesInPrimitiveRenderer(0) | |
| 2648 | − { | |
| 2649 | − hasIndexFound = new bool[maxVoxels]; | |
| 2650 | − memset(hasIndexFound, false, maxVoxels * sizeof(bool)); | |
| 2651 | − }; | |
| 2652 | − | |
| 2653 | − ~collectStatsForTreesAndVBOsArgs() { | |
| 2654 | − delete[] hasIndexFound; | |
| 2655 | − } | |
| 2656 | − | |
| 2657 | − unsigned long totalNodes; | |
| 2658 | − unsigned long dirtyNodes; | |
| 2659 | − unsigned long shouldRenderNodes; | |
| 2660 | − unsigned long coloredNodes; | |
| 2661 | − unsigned long nodesInVBO; | |
| 2662 | − unsigned long nodesInVBONotShouldRender; | |
| 2663 | − unsigned long nodesInVBOOverExpectedMax; | |
| 2664 | − unsigned long duplicateVBOIndex; | |
| 2665 | − unsigned long leafNodes; | |
| 2666 | − unsigned long culledLeafNodes; ///< Number of completely culled nodes because of face sharing | |
| 2667 | − unsigned long nodesInPrimitiveRenderer; | |
| 2668 | − | |
| 2669 | − unsigned long expectedMax; | |
| 2670 | − | |
| 2671 | − bool* hasIndexFound; | |
| 2672 | −}; | |
| 2673 | − | |
| 2674 | −bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, void* extraData) { | |
| 2675 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2676 | − | |
| 2677 | − collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData; | |
| 2678 | − args->totalNodes++; | |
| 2679 | − | |
| 2680 | − if (voxel->isLeaf()) { | |
| 2681 | − args->leafNodes++; | |
| 2682 | − if (voxel->getInteriorOcclusions() == OctreeElement::HalfSpace::All) { | |
| 2683 | − args->culledLeafNodes++; | |
| 2684 | − } | |
| 2685 | − } | |
| 2686 | − | |
| 2687 | − if (voxel->isColored()) { | |
| 2688 | − args->coloredNodes++; | |
| 2689 | − } | |
| 2690 | − | |
| 2691 | − if (voxel->getShouldRender()) { | |
| 2692 | − args->shouldRenderNodes++; | |
| 2693 | − } | |
| 2694 | − | |
| 2695 | − if (voxel->isDirty()) { | |
| 2696 | − args->dirtyNodes++; | |
| 2697 | − } | |
| 2698 | − | |
| 2699 | − unsigned long nodeIndex = 0; | |
| 2700 | − if (voxel->getBufferIndex()) { | |
| 2701 | − args->nodesInPrimitiveRenderer++; | |
| 2702 | − nodeIndex = voxel->getBufferIndex(); | |
| 2703 | − | |
| 2704 | − const bool extraDebugging = false; // enable for extra debugging | |
| 2705 | − if (extraDebugging) { | |
| 2706 | − qDebug("node In Renderer... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s, culledFaces=0x%02x \n", | |
| 2707 | − voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), | |
| 2708 | − nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender()), | |
| 2709 | − voxel->getInteriorOcclusions()); | |
| 2710 | − } | |
| 2711 | − } | |
| 2712 | − | |
| 2713 | − if (voxel->isKnownBufferIndex()) { | |
| 2714 | − args->nodesInVBO++; | |
| 2715 | − nodeIndex = voxel->getBufferIndex(); | |
| 2716 | − | |
| 2717 | − const bool extraDebugging = false; // enable for extra debugging | |
| 2718 | − if (extraDebugging) { | |
| 2719 | − qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n", | |
| 2720 | − voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), | |
| 2721 | − nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender())); | |
| 2722 | − } | |
| 2723 | − | |
| 2724 | − if (args->hasIndexFound[nodeIndex]) { | |
| 2725 | − args->duplicateVBOIndex++; | |
| 2726 | − qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s", nodeIndex, | |
| 2727 | − debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender())); | |
| 2728 | − } else { | |
| 2729 | − args->hasIndexFound[nodeIndex] = true; | |
| 2730 | − } | |
| 2731 | − if (nodeIndex > args->expectedMax) { | |
| 2732 | − args->nodesInVBOOverExpectedMax++; | |
| 2733 | − } | |
| 2734 | − | |
| 2735 | − // if it's in VBO but not-shouldRender, track that also... | |
| 2736 | − if (!voxel->getShouldRender()) { | |
| 2737 | − args->nodesInVBONotShouldRender++; | |
| 2738 | − } | |
| 2739 | − } | |
| 2740 | − | |
| 2741 | − return true; // keep going! | |
| 2742 | −} | |
| 2743 | − | |
| 2744 | −void VoxelSystem::collectStatsForTreesAndVBOs() { | |
| 2745 | − PerformanceWarning warn(true, "collectStatsForTreesAndVBOs()", true); | |
| 2746 | − | |
| 2747 | − glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; | |
| 2748 | − glBufferIndex maxDirty = 0; | |
| 2749 | − | |
| 2750 | − if (!_usePrimitiveRenderer) { | |
| 2751 | − for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { | |
| 2752 | − if (_writeVoxelDirtyArray[i]) { | |
| 2753 | − minDirty = std::min(minDirty,i); | |
| 2754 | − maxDirty = std::max(maxDirty,i); | |
| 2755 | − } | |
| 2756 | − } | |
| 2757 | − } | |
| 2758 | − | |
| 2759 | − collectStatsForTreesAndVBOsArgs args(_maxVoxels); | |
| 2760 | − args.expectedMax = _voxelsInWriteArrays; | |
| 2761 | − | |
| 2762 | − qDebug("CALCULATING Local Voxel Tree Statistics >>>>>>>>>>>>"); | |
| 2763 | − | |
| 2764 | − _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args); | |
| 2765 | − | |
| 2766 | − qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n", | |
| 2767 | − args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes); | |
| 2768 | − | |
| 2769 | − if (!_usePrimitiveRenderer) { | |
| 2770 | − qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld", debug::valueOf(_voxelsDirty), | |
| 2771 | − _voxelsInWriteArrays, minDirty, maxDirty); | |
| 2772 | − | |
| 2773 | − qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld", | |
| 2774 | − args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender); | |
| 2775 | − | |
| 2776 | − qDebug(" memory usage %ld \n gpu memory usage %ld \n", _memoryUsageRAM, _memoryUsageVBO); | |
| 2777 | − | |
| 2778 | − glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; | |
| 2779 | − glBufferIndex maxInVBO = 0; | |
| 2780 | − | |
| 2781 | − for (glBufferIndex i = 0; i < _maxVoxels; i++) { | |
| 2782 | − if (args.hasIndexFound[i]) { | |
| 2783 | − minInVBO = std::min(minInVBO,i); | |
| 2784 | − maxInVBO = std::max(maxInVBO,i); | |
| 2785 | − } | |
| 2786 | − } | |
| 2787 | − | |
| 2788 | − qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld", | |
| 2789 | − minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); | |
| 2790 | − | |
| 2791 | − qDebug(" _freeIndexes.size()=%ld", | |
| 2792 | − _freeIndexes.size()); | |
| 2793 | − } else { | |
| 2794 | − qDebug(" PrimitiveRenderer nodes %ld \n completely culled nodes %ld \n", | |
| 2795 | − args.nodesInPrimitiveRenderer, args.culledLeafNodes); | |
| 2796 | − | |
| 2797 | − qDebug(" memory usage %ld \n gpu memory usage %ld \n", | |
| 2798 | − _renderer->getMemoryUsage(), _renderer->getMemoryUsageGPU()); | |
| 2799 | − } | |
| 2800 | − qDebug("DONE WITH Local Voxel Tree Statistics >>>>>>>>>>>>"); | |
| 2801 | −} | |
| 2802 | − | |
| 2803 | − | |
| 2804 | −void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { | |
| 2805 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 2806 | − "VoxelSystem::deleteVoxelAt()"); | |
| 2807 | − _tree->lockForWrite(); | |
| 2808 | − _tree->deleteVoxelAt(x, y, z, s); | |
| 2809 | − _tree->unlock(); | |
| 2810 | − | |
| 2811 | − // redraw! | |
| 2812 | − setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in? | |
| 2813 | −}; | |
| 2814 | − | |
| 2815 | −VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const { | |
| 2816 | − return _tree->getVoxelAt(x, y, z, s); | |
| 2817 | −}; | |
| 2818 | − | |
| 2819 | −void VoxelSystem::createVoxel(float x, float y, float z, float s, | |
| 2820 | − unsigned char red, unsigned char green, unsigned char blue, bool destructive) { | |
| 2821 | − | |
| 2822 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 2823 | − "VoxelSystem::createVoxel()"); | |
| 2824 | − | |
| 2825 | − _tree->lockForWrite(); | |
| 2826 | − _tree->createVoxel(x, y, z, s, red, green, blue, destructive); | |
| 2827 | − _tree->unlock(); | |
| 2828 | − | |
| 2829 | − setupNewVoxelsForDrawing(); | |
| 2830 | −}; | |
| 2831 | − | |
| 2832 | −void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) { | |
| 2833 | − _tree->createLine(point1, point2, unitSize, color, destructive); | |
| 2834 | − setupNewVoxelsForDrawing(); | |
| 2835 | −}; | |
| 2836 | − | |
| 2837 | −void VoxelSystem::copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelSystem* destination, bool rebaseToRoot) { | |
| 2838 | − _tree->copySubTreeIntoNewTree(startNode, destination->_tree, rebaseToRoot); | |
| 2839 | − destination->setupNewVoxelsForDrawing(); | |
| 2840 | −} | |
| 2841 | − | |
| 2842 | −void VoxelSystem::copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelTree* destination, bool rebaseToRoot) { | |
| 2843 | − _tree->copySubTreeIntoNewTree(startNode, destination, rebaseToRoot); | |
| 2844 | −} | |
| 2845 | − | |
| 2846 | −void VoxelSystem::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelTreeElement* destinationNode) { | |
| 2847 | − _tree->copyFromTreeIntoSubTree(sourceTree, destinationNode); | |
| 2848 | −} | |
| 2849 | − | |
| 2850 | −void VoxelSystem::recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData) { | |
| 2851 | − _tree->recurseTreeWithOperation(operation, extraData); | |
| 2852 | −} | |
| 2853 | − | |
| 2854 | −struct FalseColorizeOccludedArgs { | |
| 2855 | − ViewFrustum* viewFrustum; | |
| 2856 | − CoverageMap* map; | |
| 2857 | − CoverageMapV2* mapV2; | |
| 2858 | − VoxelTree* tree; | |
| 2859 | − long totalVoxels; | |
| 2860 | − long coloredVoxels; | |
| 2861 | − long occludedVoxels; | |
| 2862 | − long notOccludedVoxels; | |
| 2863 | − long outOfView; | |
| 2864 | − long subtreeVoxelsSkipped; | |
| 2865 | − long nonLeaves; | |
| 2866 | − long nonLeavesOutOfView; | |
| 2867 | − long nonLeavesOccluded; | |
| 2868 | −}; | |
| 2869 | − | |
| 2870 | −struct FalseColorizeSubTreeOperationArgs { | |
| 2871 | − unsigned char color[NUMBER_OF_COLORS]; | |
| 2872 | − long voxelsTouched; | |
| 2873 | −}; | |
| 2874 | − | |
| 2875 | −bool VoxelSystem::falseColorizeSubTreeOperation(OctreeElement* element, void* extraData) { | |
| 2876 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2877 | − if (voxel->getShouldRender()) { | |
| 2878 | − FalseColorizeSubTreeOperationArgs* args = (FalseColorizeSubTreeOperationArgs*) extraData; | |
| 2879 | − voxel->setFalseColor(args->color[0], args->color[1], args->color[2]); | |
| 2880 | − args->voxelsTouched++; | |
| 2881 | − } | |
| 2882 | − return true; | |
| 2883 | −} | |
| 2884 | − | |
| 2885 | −bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* extraData) { | |
| 2886 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 2887 | − | |
| 2888 | − FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; | |
| 2889 | − args->totalVoxels++; | |
| 2890 | − | |
| 2891 | − // If we are a parent, let's see if we're completely occluded. | |
| 2892 | − if (!voxel->isLeaf()) { | |
| 2893 | − args->nonLeaves++; | |
| 2894 | − | |
| 2895 | − AABox voxelBox = voxel->getAABox(); | |
| 2896 | − voxelBox.scale(TREE_SCALE); | |
| 2897 | − OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); | |
| 2898 | − | |
| 2899 | − // If we're not all in view, then ignore it, and just return. But keep searching... | |
| 2900 | − if (!voxelPolygon->getAllInView()) { | |
| 2901 | − args->nonLeavesOutOfView++; | |
| 2902 | − delete voxelPolygon; | |
| 2903 | − return true; | |
| 2904 | − } | |
| 2905 | − | |
| 2906 | − CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, false); | |
| 2907 | − if (result == OCCLUDED) { | |
| 2908 | − args->nonLeavesOccluded++; | |
| 2909 | − delete voxelPolygon; | |
| 2910 | − | |
| 2911 | − FalseColorizeSubTreeOperationArgs subArgs; | |
| 2912 | − subArgs.color[0] = 0; | |
| 2913 | − subArgs.color[1] = 255; | |
| 2914 | − subArgs.color[2] = 0; | |
| 2915 | − subArgs.voxelsTouched = 0; | |
| 2916 | − | |
| 2917 | − args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs ); | |
| 2918 | − | |
| 2919 | − args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); | |
| 2920 | − args->totalVoxels += (subArgs.voxelsTouched - 1); | |
| 2921 | − | |
| 2922 | − return false; | |
| 2923 | − } | |
| 2924 | − | |
| 2925 | − delete voxelPolygon; | |
| 2926 | − return true; // keep looking... | |
| 2927 | − } | |
| 2928 | − | |
| 2929 | − if (voxel->isLeaf() && voxel->isColored() && voxel->getShouldRender()) { | |
| 2930 | − args->coloredVoxels++; | |
| 2931 | − | |
| 2932 | − AABox voxelBox = voxel->getAABox(); | |
| 2933 | − voxelBox.scale(TREE_SCALE); | |
| 2934 | − OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); | |
| 2935 | − | |
| 2936 | − // If we're not all in view, then ignore it, and just return. But keep searching... | |
| 2937 | − if (!voxelPolygon->getAllInView()) { | |
| 2938 | − args->outOfView++; | |
| 2939 | − delete voxelPolygon; | |
| 2940 | − return true; | |
| 2941 | − } | |
| 2942 | − | |
| 2943 | − CoverageMapStorageResult result = args->map->checkMap(voxelPolygon, true); | |
| 2944 | − if (result == OCCLUDED) { | |
| 2945 | − voxel->setFalseColor(255, 0, 0); | |
| 2946 | − args->occludedVoxels++; | |
| 2947 | − } else if (result == STORED) { | |
| 2948 | − args->notOccludedVoxels++; | |
| 2949 | − //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); | |
| 2950 | − } else if (result == DOESNT_FIT) { | |
| 2951 | − //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); | |
| 2952 | − } | |
| 2953 | − } | |
| 2954 | − return true; // keep going! | |
| 2955 | −} | |
| 2956 | − | |
| 2957 | −void VoxelSystem::falseColorizeOccluded() { | |
| 2958 | − PerformanceWarning warn(true, "falseColorizeOccluded()",true); | |
| 2959 | − myCoverageMap.erase(); | |
| 2960 | − | |
| 2961 | − FalseColorizeOccludedArgs args; | |
| 2962 | − args.viewFrustum = _viewFrustum; | |
| 2963 | − args.map = &myCoverageMap; | |
| 2964 | − args.totalVoxels = 0; | |
| 2965 | − args.coloredVoxels = 0; | |
| 2966 | − args.occludedVoxels = 0; | |
| 2967 | − args.notOccludedVoxels = 0; | |
| 2968 | − args.outOfView = 0; | |
| 2969 | − args.subtreeVoxelsSkipped = 0; | |
| 2970 | − args.nonLeaves = 0; | |
| 2971 | − args.nonLeavesOutOfView = 0; | |
| 2972 | − args.nonLeavesOccluded = 0; | |
| 2973 | − args.tree = _tree; | |
| 2974 | − | |
| 2975 | − OctreeProjectedPolygon::pointInside_calls = 0; | |
| 2976 | − OctreeProjectedPolygon::occludes_calls = 0; | |
| 2977 | − OctreeProjectedPolygon::intersects_calls = 0; | |
| 2978 | − | |
| 2979 | − glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); | |
| 2980 | − | |
| 2981 | − _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args); | |
| 2982 | − | |
| 2983 | − 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", | |
| 2984 | − position.x, position.y, | |
| 2985 | − args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 2986 | − args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 2987 | − args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, | |
| 2988 | − OctreeProjectedPolygon::pointInside_calls, | |
| 2989 | − OctreeProjectedPolygon::occludes_calls, | |
| 2990 | − OctreeProjectedPolygon::intersects_calls | |
| 2991 | − ); | |
| 2992 | − | |
| 2993 | − | |
| 2994 | − //myCoverageMap.erase(); | |
| 2995 | − | |
| 2996 | − _tree->setDirtyBit(); | |
| 2997 | − setupNewVoxelsForDrawing(); | |
| 2998 | −} | |
| 2999 | − | |
| 3000 | −bool VoxelSystem::falseColorizeOccludedV2Operation(OctreeElement* element, void* extraData) { | |
| 3001 | − VoxelTreeElement* voxel = (VoxelTreeElement*)element; | |
| 3002 | − | |
| 3003 | − FalseColorizeOccludedArgs* args = (FalseColorizeOccludedArgs*) extraData; | |
| 3004 | − args->totalVoxels++; | |
| 3005 | − | |
| 3006 | − // If we are a parent, let's see if we're completely occluded. | |
| 3007 | − if (!voxel->isLeaf()) { | |
| 3008 | − args->nonLeaves++; | |
| 3009 | − | |
| 3010 | − AABox voxelBox = voxel->getAABox(); | |
| 3011 | − voxelBox.scale(TREE_SCALE); | |
| 3012 | − OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); | |
| 3013 | − | |
| 3014 | − // If we're not all in view, then ignore it, and just return. But keep searching... | |
| 3015 | − if (!voxelPolygon->getAllInView()) { | |
| 3016 | − args->nonLeavesOutOfView++; | |
| 3017 | − delete voxelPolygon; | |
| 3018 | − return true; | |
| 3019 | − } | |
| 3020 | − | |
| 3021 | − CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, false); | |
| 3022 | − if (result == V2_OCCLUDED) { | |
| 3023 | − args->nonLeavesOccluded++; | |
| 3024 | − delete voxelPolygon; | |
| 3025 | − | |
| 3026 | − FalseColorizeSubTreeOperationArgs subArgs; | |
| 3027 | − subArgs.color[0] = 0; | |
| 3028 | − subArgs.color[1] = 255; | |
| 3029 | − subArgs.color[2] = 0; | |
| 3030 | − subArgs.voxelsTouched = 0; | |
| 3031 | − | |
| 3032 | − args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs ); | |
| 3033 | − | |
| 3034 | − args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); | |
| 3035 | − args->totalVoxels += (subArgs.voxelsTouched - 1); | |
| 3036 | − | |
| 3037 | − return false; | |
| 3038 | − } | |
| 3039 | − | |
| 3040 | − delete voxelPolygon; | |
| 3041 | − return true; // keep looking... | |
| 3042 | − } | |
| 3043 | − | |
| 3044 | − if (voxel->isLeaf() && voxel->isColored() && voxel->getShouldRender()) { | |
| 3045 | − args->coloredVoxels++; | |
| 3046 | − | |
| 3047 | − AABox voxelBox = voxel->getAABox(); | |
| 3048 | − voxelBox.scale(TREE_SCALE); | |
| 3049 | − OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(args->viewFrustum->getProjectedPolygon(voxelBox)); | |
| 3050 | − | |
| 3051 | − // If we're not all in view, then ignore it, and just return. But keep searching... | |
| 3052 | − if (!voxelPolygon->getAllInView()) { | |
| 3053 | − args->outOfView++; | |
| 3054 | − delete voxelPolygon; | |
| 3055 | − return true; | |
| 3056 | − } | |
| 3057 | − | |
| 3058 | − CoverageMapV2StorageResult result = args->mapV2->checkMap(voxelPolygon, true); | |
| 3059 | − if (result == V2_OCCLUDED) { | |
| 3060 | − voxel->setFalseColor(255, 0, 0); | |
| 3061 | − args->occludedVoxels++; | |
| 3062 | − } else if (result == V2_STORED) { | |
| 3063 | − args->notOccludedVoxels++; | |
| 3064 | − //qDebug("***** falseColorizeOccludedOperation() NODE is STORED *****\n"); | |
| 3065 | − } else if (result == V2_DOESNT_FIT) { | |
| 3066 | − //qDebug("***** falseColorizeOccludedOperation() NODE DOESNT_FIT???? *****\n"); | |
| 3067 | − } | |
| 3068 | − delete voxelPolygon; // V2 maps don't store polygons, so we're always in charge of freeing | |
| 3069 | − } | |
| 3070 | − return true; // keep going! | |
| 3071 | −} | |
| 3072 | − | |
| 3073 | − | |
| 3074 | −void VoxelSystem::falseColorizeOccludedV2() { | |
| 3075 | − PerformanceWarning warn(true, "falseColorizeOccludedV2()",true); | |
| 3076 | − myCoverageMapV2.erase(); | |
| 3077 | − | |
| 3078 | − CoverageMapV2::wantDebugging = true; | |
| 3079 | − | |
| 3080 | − OctreeProjectedPolygon::pointInside_calls = 0; | |
| 3081 | − OctreeProjectedPolygon::occludes_calls = 0; | |
| 3082 | − OctreeProjectedPolygon::intersects_calls = 0; | |
| 3083 | − | |
| 3084 | − FalseColorizeOccludedArgs args; | |
| 3085 | − args.viewFrustum = _viewFrustum; | |
| 3086 | − args.mapV2 = &myCoverageMapV2; | |
| 3087 | − args.totalVoxels = 0; | |
| 3088 | − args.coloredVoxels = 0; | |
| 3089 | − args.occludedVoxels = 0; | |
| 3090 | − args.notOccludedVoxels = 0; | |
| 3091 | − args.outOfView = 0; | |
| 3092 | − args.subtreeVoxelsSkipped = 0; | |
| 3093 | − args.nonLeaves = 0; | |
| 3094 | − args.nonLeavesOutOfView = 0; | |
| 3095 | − args.nonLeavesOccluded = 0; | |
| 3096 | − args.tree = _tree; | |
| 3097 | − | |
| 3098 | − glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE); | |
| 3099 | − | |
| 3100 | − _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedV2Operation, position, (void*)&args); | |
| 3101 | − | |
| 3102 | − 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", | |
| 3103 | − position.x, position.y, | |
| 3104 | − args.totalVoxels, args.coloredVoxels, args.occludedVoxels, | |
| 3105 | − args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped, | |
| 3106 | − args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded, | |
| 3107 | − OctreeProjectedPolygon::pointInside_calls, | |
| 3108 | − OctreeProjectedPolygon::occludes_calls, | |
| 3109 | − OctreeProjectedPolygon::intersects_calls | |
| 3110 | − ); | |
| 3111 | − //myCoverageMapV2.erase(); | |
| 3112 | − _tree->setDirtyBit(); | |
| 3113 | − setupNewVoxelsForDrawing(); | |
| 3114 | −} | |
| 3115 | − | |
| 3116 | 2085 | void VoxelSystem::nodeAdded(SharedNodePointer node) { |
| 3117 | 2086 | if (node->getType() == NodeType::VoxelServer) { |
| 3118 | 2087 | qDebug("VoxelSystem... voxel server %s added...", node->getUUID().toString().toLocal8Bit().constData()); |