History

first cut at keeping local voxels

ZappoMan committed 13 years ago

Commit c25b03d1 parent 5e6e15d8 files · +271 −121Browse files

Showing the changes to interface/src/VoxelSystem.cpp (1 of 8 files). Show all

Unified · Split

interface/src/VoxelSystem.cpp+249−114
@@ -109,12 +109,15 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 108 unmodified lines
109 109
110void VoxelSystem::voxelDeleted(VoxelNode* node) {110void VoxelSystem::voxelDeleted(VoxelNode* node) {
111 if (node->isKnownBufferIndex() && (node->getVoxelSystem() == this)) {111 if (node->isKnownBufferIndex() && (node->getVoxelSystem() == this)) {
112 forceRemoveNodeFromArraysAsPartialVBO(node);
113
114 /***
112 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {115 if (!_useFastVoxelPipeline || _inSetupNewVoxelsForDrawing || _writeRenderFullVBO) {
113 freeBufferIndex(node->getBufferIndex());116 freeBufferIndex(node->getBufferIndex());
114 } else {117 } else {
115 forceRemoveNodeFromArraysAsPartialVBO(node);118 forceRemoveNodeFromArraysAsPartialVBO(node);
116 freeBufferIndex(node->getBufferIndex());
117 }119 }
120 ***/
118 }121 }
119}122}
120 123
@@ -160,7 +163,9 @@ void VoxelSystem::voxelUpdated(VoxelNode* node) { · 39 unmodified lines
160 }163 }
161 }164 }
162 165
163 updateNodeInArraysAsPartialVBO(node);166 const bool REUSE_INDEX = true;
167 const bool DONT_FORCE_REDRAW = false;
168 updateNodeInArrays(node, REUSE_INDEX, DONT_FORCE_REDRAW);
164 _voxelsUpdated++;169 _voxelsUpdated++;
165 170
166 node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.171 node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
@@ -185,26 +190,44 @@ glBufferIndex VoxelSystem::getNextBufferIndex() { · 18 unmodified lines
185 return output;190 return output;
186}191}
187 192
188// Doesn't actually clean up the VBOs for the index, but does release responsibility of the index from the VoxelNode, 193// Release responsibility of the buffer/vbo index from the VoxelNode, and makes the index available for some other node to use
189// and makes the index available for some other node to use194// will also "clean up" the index data for the buffer/vbo slot, so that if it's in the middle of the draw range, the triangles
195// will be "invisible"
190void VoxelSystem::freeBufferIndex(glBufferIndex index) {196void VoxelSystem::freeBufferIndex(glBufferIndex index) {
191 _freeIndexes.push_back(index);197 assert(_voxelsInWriteArrays > 0);
198
199 // if the "freed" index was our max index, then just drop the _voxelsInWriteArrays down one...
200 if (index == (_voxelsInWriteArrays - 1)) {
201 _voxelsInWriteArrays--;
202 } else {
203 bool inList = false;
204 // make sure the index isn't already in the free list...
205 for (long i = 0; i < _freeIndexes.size(); i++) {
206 if (_freeIndexes[i] == index) {
207 printf("freeBufferIndex(glBufferIndex index)... index=%ld already in free list!\n", index);
208 inList = true;
209 break;
210 }
211 }
212
213 if (!inList) {
214 // make the index available for next node that needs to be drawn
215 _freeIndexes.push_back(index);
216
217 // make the VBO slot "invisible" in case this slot is not used
218 const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX);
219 const float voxelScale = 0;
220 const nodeColor BLACK = {0, 0, 0, 0};
221 updateArraysDetails(index, startVertex, voxelScale, BLACK);
222 }
223 }
192}224}
193 225
194// This will run through the list of _freeIndexes and reset their VBO array values to be "invisible".226// This will run through the list of _freeIndexes and reset their VBO array values to be "invisible".
195void VoxelSystem::clearFreeBufferIndexes() {227void VoxelSystem::clearFreeBufferIndexes() {
196 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "###### clearFreeBufferIndexes()");228 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "###### clearFreeBufferIndexes()");
197
198 for (int i = 0; i < _freeIndexes.size(); i++) {
199 glBufferIndex nodeIndex = _freeIndexes[i];
200 glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX);
201 float voxelScale = 0;
202 _writeVoxelDirtyArray[nodeIndex] = true;
203 nodeColor color = {0, 0, 0, 0};
204 updateNodeInArrays(nodeIndex, startVertex, voxelScale, color);
205 _abandonedVBOSlots++;
206 }
207 _freeIndexes.clear();229 _freeIndexes.clear();
230 _abandonedVBOSlots = 0;
208}231}
209 232
210VoxelSystem::~VoxelSystem() {233VoxelSystem::~VoxelSystem() {
@@ -589,8 +612,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 378 unmodified lines
589 612
590 613
591 if (!_useFastVoxelPipeline || _writeRenderFullVBO) {614 if (!_useFastVoxelPipeline || _writeRenderFullVBO) {
615//printf("parseData about to call setupNewVoxelsForDrawing();\n");
592 setupNewVoxelsForDrawing();616 setupNewVoxelsForDrawing();
593 } else {617 } else {
618printf("parseData about to call checkForCulling() and setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY)\n");
619 checkForCulling();
594 setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);620 setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
595 }621 }
596 622
@@ -611,7 +637,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 14 unmodified lines
611 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;637 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
612 638
613 // clear up the VBOs for any nodes that have been recently deleted.639 // clear up the VBOs for any nodes that have been recently deleted.
614 clearFreeBufferIndexes();640 //clearFreeBufferIndexes();
615 641
616 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging642 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
617 if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {643 if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
@@ -631,6 +657,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 13 unmodified lines
631 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);657 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);
632 _callsToTreesToArrays++;658 _callsToTreesToArrays++;
633 if (_writeRenderFullVBO) {659 if (_writeRenderFullVBO) {
660 printf("resetting _freeIndexes and _voxelsInWriteArrays\n");
634 _voxelsInWriteArrays = 0; // reset our VBO661 _voxelsInWriteArrays = 0; // reset our VBO
635 _freeIndexes.clear(); // reset our free indexes662 _freeIndexes.clear(); // reset our free indexes
636 }663 }
@@ -676,7 +703,7 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 39 unmodified lines
676 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;703 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
677 704
678 // clear up the VBOs for any nodes that have been recently deleted.705 // clear up the VBOs for any nodes that have been recently deleted.
679 clearFreeBufferIndexes();706 //clearFreeBufferIndexes();
680 707
681 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging708 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
682 if (allowBailEarly && !iAmDebugging && 709 if (allowBailEarly && !iAmDebugging &&
@@ -684,7 +711,7 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 1 unmodified line
684 return; // bail early, it hasn't been long enough since the last time we ran711 return; // bail early, it hasn't been long enough since the last time we ran
685 }712 }
686 713
687 checkForCulling(); // check for out of view and deleted voxels...714 //checkForCulling(); // check for out of view and deleted voxels...
688 715
689 // lock on the buffer write lock so we can't modify the data when the GPU is reading it716 // lock on the buffer write lock so we can't modify the data when the GPU is reading it
690 {717 {
@@ -723,7 +750,12 @@ void VoxelSystem::checkForCulling() { · 32 unmodified lines
723 // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove750 // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove
724 // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which751 // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which
725 // can be expensive).752 // can be expensive).
726 removeOutOfView();753 if (Menu::getInstance()->isOptionChecked(MenuOption::HideOutOfView)) {
754 hideOutOfView();
755 }
756 if (!Menu::getInstance()->isOptionChecked(MenuOption::DontRemoveOutOfView)) {
757 removeOutOfView();
758 }
727 759
728 // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,760 // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,
729 // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on761 // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on
@@ -747,6 +779,7 @@ void VoxelSystem::cleanupRemovedVoxels() { · 17 unmodified lines
747 }779 }
748 _writeRenderFullVBO = true; // if we remove voxels, we must update our full VBOs780 _writeRenderFullVBO = true; // if we remove voxels, we must update our full VBOs
749 }781 }
782
750 // we also might have VBO slots that have been abandoned, if too many of our VBO slots783 // we also might have VBO slots that have been abandoned, if too many of our VBO slots
751 // are abandonded we want to rerender our full VBOs784 // are abandonded we want to rerender our full VBOs
752 const float TOO_MANY_ABANDONED_RATIO = 0.5f;785 const float TOO_MANY_ABANDONED_RATIO = 0.5f;
@@ -830,6 +863,7 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, · 77 unmodified lines
830void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {863void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
831 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),864 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
832 "copyWrittenDataToReadArrays()");865 "copyWrittenDataToReadArrays()");
866
833 if (_voxelsDirty && _voxelsUpdated) {867 if (_voxelsDirty && _voxelsUpdated) {
834 if (fullVBOs) {868 if (fullVBOs) {
835 copyWrittenDataToReadArraysFullVBOs();869 copyWrittenDataToReadArraysFullVBOs();
@@ -869,39 +903,21 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { · 33 unmodified lines
869 }903 }
870 }904 }
871 if (_writeRenderFullVBO) {905 if (_writeRenderFullVBO) {
872 voxelsUpdated += updateNodeInArraysAsFullVBO(node);906 const bool DONT_REUSE_INDEX = false;
907 const bool FORCE_REDRAW = true;
908//printf("newTreeToArrays() about to call updateNodeInArrays(node, DONT_REUSE_INDEX, FORCE_REDRAW);\n");
909 voxelsUpdated += updateNodeInArrays(node, DONT_REUSE_INDEX, FORCE_REDRAW);
873 } else {910 } else {
874 voxelsUpdated += updateNodeInArraysAsPartialVBO(node);911 const bool REUSE_INDEX = true;
912 const bool DONT_FORCE_REDRAW = false;
913//printf("newTreeToArrays() about to call updateNodeInArrays(node, REUSE_INDEX, DONT_FORCE_REDRAW);\n");
914 voxelsUpdated += updateNodeInArrays(node, REUSE_INDEX, DONT_FORCE_REDRAW);
875 }915 }
876 node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.916 node->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
877 917
878 return voxelsUpdated;918 return voxelsUpdated;
879}919}
880 920
881int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) {
882 // If we've run out of room, then just bail...
883 if (_voxelsInWriteArrays >= _maxVoxels) {
884 return 0;
885 }
886
887 if (node->getShouldRender()) {
888 glm::vec3 startVertex = node->getCorner();
889 float voxelScale = node->getScale();
890 glBufferIndex nodeIndex = getNextBufferIndex();
891
892 // populate the array with points for the 8 vertices
893 // and RGB color for each added vertex
894 updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor());
895 node->setBufferIndex(nodeIndex);
896 node->setVoxelSystem(this);
897 return 1; // rendered
898 } else {
899 node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
900 }
901
902 return 0; // not-rendered
903}
904
905// called as response to voxelDeleted() in fast pipeline case. The node921// called as response to voxelDeleted() in fast pipeline case. The node
906// is being deleted, but it's state is such that it thinks it should render922// is being deleted, but it's state is such that it thinks it should render
907// and therefore we can't use the normal render calculations. This method923// and therefore we can't use the normal render calculations. This method
@@ -914,29 +930,22 @@ int VoxelSystem::forceRemoveNodeFromArraysAsPartialVBO(VoxelNode* node) { · 6 unmodified lines
914 930
915 // if the node is not in the VBOs then we have nothing to do!931 // if the node is not in the VBOs then we have nothing to do!
916 if (node->isKnownBufferIndex()) {932 if (node->isKnownBufferIndex()) {
917
918 // if we shouldn't render then set out location to some infinitely distant location,
919 // and our scale as infinitely small
920 glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX);
921 float voxelScale = 0;
922 _abandonedVBOSlots++;
923
924 // If this node has not yet been written to the array, then add it to the end of the array.933 // If this node has not yet been written to the array, then add it to the end of the array.
925 glBufferIndex nodeIndex = node->getBufferIndex();934 glBufferIndex nodeIndex = node->getBufferIndex();
926 935 freeBufferIndex(nodeIndex); // NOTE: This is make the node invisible!
927 _writeVoxelDirtyArray[nodeIndex] = true;936 node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
928
929 // populate the array with points for the 8 vertices
930 // and RGB color for each added vertex
931 const nodeColor BLACK = { 0,0,0};
932 updateNodeInArrays(nodeIndex, startVertex, voxelScale, BLACK);
933
934 return 1; // updated!937 return 1; // updated!
935 }938 }
936 return 0; // not-updated939 return 0; // not-updated
937}940}
938 941
939int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) {942int VoxelSystem::updateNodeInArrays(VoxelNode* node, bool reuseIndex, bool forceDraw) {
943
944/*
945printf("updateNodeInArrays(VoxelNode* node=[%f, %f, %f] %f, bool reuseIndex=%s, bool forceDraw=%s)\n",
946 node->getCorner().x,node->getCorner().y,node->getCorner().z, node->getScale(),
947 debug::valueOf(reuseIndex),debug::valueOf(forceDraw));
948*/
940 // If we've run out of room, then just bail...949 // If we've run out of room, then just bail...
941 if (_voxelsInWriteArrays >= _maxVoxels) {950 if (_voxelsInWriteArrays >= _maxVoxels) {
942 return 0;951 return 0;
@@ -946,64 +955,76 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { · 3 unmodified lines
946 return 0;955 return 0;
947 }956 }
948 957
949 // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays...958 // If we've changed any attributes (our renderness, our color, etc), or we've been told to force a redraw
950 if (node->isDirty()) {959 // then update the Arrays...
951 glm::vec3 startVertex;960 if (forceDraw || node->isDirty()) {
952 float voxelScale = 0;961 /*
962 printf("updateNodeInArrays(VoxelNode* node=[%f, %f, %f] %f, bool reuseIndex=%s, bool forceDraw=%s)\n",
963 node->getCorner().x,node->getCorner().y,node->getCorner().z, node->getScale(),
964 debug::valueOf(reuseIndex),debug::valueOf(forceDraw));
965 */
966 //printf("....(isDirty() [isDirty()=%s] or forceRedraw=%s_...\n",debug::valueOf(node->isDirty()),debug::valueOf(forceDraw));
967
953 // If we're should render, use our legit location and scale, 968 // If we're should render, use our legit location and scale,
954 if (node->getShouldRender()) {969 if (node->getShouldRender()) {
955 startVertex = node->getCorner();970 //printf("....shouldRender()...\n");
956 voxelScale = node->getScale();971 glm::vec3 startVertex = node->getCorner();
957 } else {972 float voxelScale = node->getScale();
958 // if we shouldn't render then set out location to some infinitely distant location, 973
959 // and our scale as infinitely small974 glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN;
960 startVertex[0] = startVertex[1] = startVertex[2] = FLT_MAX;975 if (reuseIndex && node->isKnownBufferIndex()) {
961 voxelScale = 0;976 //printf("....shouldRender() and reuseIndex && node->isKnownBufferIndex() reusing...\n");
962 _abandonedVBOSlots++;977 nodeIndex = node->getBufferIndex();
963 }978 } else {
964 979 //printf("....shouldRender() and NOT(reuseIndex && node->isKnownBufferIndex()) getting new index...\n");
965 // If this node has not yet been written to the array, then add it to the end of the array.980 nodeIndex = getNextBufferIndex();
966 glBufferIndex nodeIndex;981 node->setBufferIndex(nodeIndex);
967 if (node->isKnownBufferIndex()) {982 node->setVoxelSystem(this);
968 nodeIndex = node->getBufferIndex();983 }
984 // populate the array with points for the 8 vertices and RGB color for each added vertex
985 updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor());
986 return 1; // updated!
969 } else {987 } else {
970 nodeIndex = getNextBufferIndex();988 //printf("....NOT shouldRender()...\n");
971 node->setBufferIndex(nodeIndex);989 // If we shouldn't render, but we did have a known index, then we will need to release our index
972 node->setVoxelSystem(this);990 if (reuseIndex && node->isKnownBufferIndex()) {
991 //printf("....NOT shouldRender() and reuseIndex && node->isKnownBufferIndex() freeBufferIndex!...\n");
992 freeBufferIndex(node->getBufferIndex()); // this will make the node invisible
993 return 1; // updated!
994 }
973 }995 }
974 _writeVoxelDirtyArray[nodeIndex] = true;996 } else {
975 997 //printf("....NOT (dirty [isDirty()=%s] or forceRedraw=%s_...\n",debug::valueOf(node->isDirty()),debug::valueOf(forceDraw));
976 // populate the array with points for the 8 vertices
977 // and RGB color for each added vertex
978 updateNodeInArrays(nodeIndex, startVertex, voxelScale, node->getColor());
979
980 return 1; // updated!
981 }998 }
982 return 0; // not-updated999 return 0; // not-updated
983}1000}
984 1001
985void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,1002void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
986 float voxelScale, const nodeColor& color) {1003 float voxelScale, const nodeColor& color) {
1004
1005 if (_initialized) {
1006 _writeVoxelDirtyArray[nodeIndex] = true;
987 1007
988 if (_useVoxelShader) {1008 if (_useVoxelShader) {
989 if (_writeVoxelShaderData) {1009 if (_writeVoxelShaderData) {
990 VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];1010 VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
991 writeVerticesAt->x = startVertex.x * TREE_SCALE;1011 writeVerticesAt->x = startVertex.x * TREE_SCALE;
992 writeVerticesAt->y = startVertex.y * TREE_SCALE;1012 writeVerticesAt->y = startVertex.y * TREE_SCALE;
993 writeVerticesAt->z = startVertex.z * TREE_SCALE;1013 writeVerticesAt->z = startVertex.z * TREE_SCALE;
994 writeVerticesAt->s = voxelScale * TREE_SCALE;1014 writeVerticesAt->s = voxelScale * TREE_SCALE;
995 writeVerticesAt->r = color[RED_INDEX];1015 writeVerticesAt->r = color[RED_INDEX];
996 writeVerticesAt->g = color[GREEN_INDEX];1016 writeVerticesAt->g = color[GREEN_INDEX];
997 writeVerticesAt->b = color[BLUE_INDEX];1017 writeVerticesAt->b = color[BLUE_INDEX];
998 }1018 }
999 } else {1019 } else {
1000 if (_writeVerticesArray && _writeColorsArray) {1020 if (_writeVerticesArray && _writeColorsArray) {
1001 int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;1021 int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;
1002 for (int j = 0; j < vertexPointsPerVoxel; j++ ) {1022 for (int j = 0; j < vertexPointsPerVoxel; j++ ) {
1003 GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel);1023 GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * vertexPointsPerVoxel);
1004 GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel);1024 GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * vertexPointsPerVoxel);
1005 *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale);1025 *(writeVerticesAt+j) = startVertex[j % 3] + (identityVerticesGlobalNormals[j] * voxelScale);
1006 *(writeColorsAt +j) = color[j % 3];1026 *(writeColorsAt +j) = color[j % 3];
1027 }
1007 }1028 }
1008 }1029 }
1009 }1030 }
@@ -1517,7 +1538,7 @@ public: · 507 unmodified lines
1517 unsigned long nodesIntersect;1538 unsigned long nodesIntersect;
1518 unsigned long nodesOutside;1539 unsigned long nodesOutside;
1519 1540
1520 removeOutOfViewArgs(VoxelSystem* voxelSystem) :1541 removeOutOfViewArgs(VoxelSystem* voxelSystem, bool widenViewFrustum = true) :
1521 thisVoxelSystem(voxelSystem),1542 thisVoxelSystem(voxelSystem),
1522 thisViewFrustum(*voxelSystem->getViewFrustum()),1543 thisViewFrustum(*voxelSystem->getViewFrustum()),
1523 dontRecurseBag(),1544 dontRecurseBag(),
@@ -1528,10 +1549,12 @@ public: · 4 unmodified lines
1528 nodesOutside(0)1549 nodesOutside(0)
1529 {1550 {
1530 // Widen the FOV for trimming1551 // Widen the FOV for trimming
1531 float originalFOV = thisViewFrustum.getFieldOfView();1552 if (widenViewFrustum) {
1532 float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;1553 float originalFOV = thisViewFrustum.getFieldOfView();
1533 thisViewFrustum.setFieldOfView(wideFOV);1554 float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
1534 thisViewFrustum.calculate();1555 thisViewFrustum.setFieldOfView(wideFOV);
1556 thisViewFrustum.calculate();
1557 }
1535 }1558 }
1536};1559};
1537 1560
@@ -1587,6 +1610,80 @@ bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) { · 49 unmodified lines
1587 return true; // keep going!1610 return true; // keep going!
1588}1611}
1589 1612
1613// "hide" voxels in the VBOs that are still in the tree that but not in view.
1614// We don't remove them from the tree, we don't delete them, we do remove them
1615// from the VBOs and mark them as such in the tree.
1616bool VoxelSystem::hideOutOfViewOperation(VoxelNode* node, void* extraData) {
1617 removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData;
1618
1619 // If our node was previously added to the don't recurse bag, then return false to
1620 // stop the further recursion. This means that the whole node and it's children are
1621 // known to be in view, so don't recurse them
1622 if (args->dontRecurseBag.contains(node)) {
1623 args->dontRecurseBag.remove(node);
1624 return false; // stop recursion
1625 }
1626
1627 VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;
1628 args->nodesScanned++;
1629 // Need to operate on our child nodes, so we can remove them
1630 for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
1631 VoxelNode* childNode = node->getChildAtIndex(i);
1632 if (childNode) {
1633 ViewFrustum::location inFrustum = childNode->inFrustum(args->thisViewFrustum);
1634 switch (inFrustum) {
1635 case ViewFrustum::OUTSIDE: {
1636 args->nodesOutside++;
1637 if (childNode->isKnownBufferIndex()) {
1638 args->nodesRemoved++;
1639 thisVoxelSystem->forceRemoveNodeFromArraysAsPartialVBO(childNode);
1640 thisVoxelSystem->_voxelsUpdated++;
1641 thisVoxelSystem->setupNewVoxelsForDrawingSingleNode();
1642 }
1643 // how to handle recursion???? we probably want to continue
1644 } break;
1645 case ViewFrustum::INSIDE: {
1646
1647 // if the child node is fully INSIDE the view, then there's no need to recurse it
1648 // because we know all it's children will also be in the view, so we want to
1649 // tell the caller to NOT recurse this child
1650 args->nodesInside++;
1651
1652 if (childNode->getShouldRender() && !childNode->isKnownBufferIndex()) {
1653 /*
1654 printf("in view, isKnownIndex()=%s isDirty()=%s shouldRender()=%s\n",
1655 debug::valueOf(childNode->isKnownBufferIndex()),
1656 debug::valueOf(childNode->isDirty()),
1657 debug::valueOf(childNode->getShouldRender()));
1658 */
1659 childNode->setDirtyBit(); // will this make it draw?
1660 }
1661 //args->dontRecurseBag.insert(childNode);
1662 } break;
1663 case ViewFrustum::INTERSECT: {
1664 // if the child node INTERSECTs the view, then we don't want to remove it because
1665 // it is at least partially in view. But we DO want to recurse the children because
1666 // some of them may not be in view... nothing specifically to do, just keep iterating
1667 // the children
1668 args->nodesIntersect++;
1669
1670 if (childNode->getShouldRender() && !childNode->isKnownBufferIndex()) {
1671 /*
1672 printf("intersect view, isKnownIndex()=%s isDirty()=%s shouldRender()=%s\n",
1673 debug::valueOf(childNode->isKnownBufferIndex()),
1674 debug::valueOf(childNode->isDirty()),
1675 debug::valueOf(childNode->getShouldRender()));
1676 */
1677 childNode->setDirtyBit(); // will this make it draw?
1678 }
1679
1680 } break;
1681 }
1682 }
1683 }
1684 return true; // keep going!
1685}
1686
1590 1687
1591bool VoxelSystem::isViewChanging() {1688bool VoxelSystem::isViewChanging() {
1592 bool result = false; // assume the best1689 bool result = false; // assume the best
@@ -1632,6 +1729,29 @@ void VoxelSystem::removeOutOfView() { · 39 unmodified lines
1632 }1729 }
1633}1730}
1634 1731
1732void VoxelSystem::hideOutOfView() {
1733 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "hideOutOfView()",true);
1734 removeOutOfViewArgs args(this, true); // widen to match server!
1735 _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args);
1736
1737 if (args.nodesRemoved) {
1738 _tree->setDirtyBit();
1739 setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
1740 }
1741
1742
1743 bool showRemoveDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
1744 if (showRemoveDebugDetails) {
1745 qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n",
1746 args.nodesScanned, args.nodesRemoved, args.nodesInside,
1747 args.nodesIntersect, args.nodesOutside
1748 );
1749 }
1750
1751 collectStatsForTreesAndVBOs();
1752}
1753
1754
1635bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,1755bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
1636 VoxelDetail& detail, float& distance, BoxFace& face) {1756 VoxelDetail& detail, float& distance, BoxFace& face) {
1637 pthread_mutex_lock(&_treeLock); 1757 pthread_mutex_lock(&_treeLock);
@@ -1751,6 +1871,14 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* ex · 113 unmodified lines
1751 if (node->isKnownBufferIndex()) {1871 if (node->isKnownBufferIndex()) {
1752 args->nodesInVBO++;1872 args->nodesInVBO++;
1753 unsigned long nodeIndex = node->getBufferIndex();1873 unsigned long nodeIndex = node->getBufferIndex();
1874
1875 const bool extraDebugging = false; // enable for extra debugging
1876 if (extraDebugging) {
1877 qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n",
1878 node->getCorner().x, node->getCorner().y, node->getCorner().z, node->getScale(),
1879 nodeIndex, debug::valueOf(node->isDirty()), debug::valueOf(node->getShouldRender()));
1880 }
1881
1754 if (args->hasIndexFound[nodeIndex]) {1882 if (args->hasIndexFound[nodeIndex]) {
1755 args->duplicateVBOIndex++;1883 args->duplicateVBOIndex++;
1756 qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, 1884 qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
@@ -1786,6 +1914,9 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 29 unmodified lines
1786 1914
1787 collectStatsForTreesAndVBOsArgs args;1915 collectStatsForTreesAndVBOsArgs args;
1788 args.expectedMax = _voxelsInWriteArrays;1916 args.expectedMax = _voxelsInWriteArrays;
1917
1918 qDebug("CALCULATING Local Voxel Tree Statistics >>>>>>>>>>>>\n");
1919
1789 _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);1920 _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
1790 1921
1791 qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",1922 qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",
@@ -1810,6 +1941,10 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 18 unmodified lines
1810 qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n", 1941 qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
1811 minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays);1942 minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays);
1812 1943
1944 qDebug(" _freeIndexes.size()=%ld \n",
1945 _freeIndexes.size());
1946
1947 qDebug("DONE WITH Local Voxel Tree Statistics >>>>>>>>>>>>\n");
1813}1948}
1814 1949
1815 1950