History

first cut at local voxel cache

Brad Hefta-Gaub committed 12 years ago

Commit c181d0a1 parent 03794f79 files · +416 −344Browse files

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

Unified · Split

interface/src/VoxelSystem.cpp+230−194
@@ -35,7 +35,6 @@ · 34 unmodified lines
3535
3636 const bool VoxelSystem::DONT_BAIL_EARLY = false;
3737
38−
3938 float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
4039
4140 float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7
@@ -107,16 +106,18 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 65 unmodified lines
107106
108107 _inSetupNewVoxelsForDrawing = false;
109108 _useFastVoxelPipeline = false;
110−
109+
111110 _culledOnce = false;
112111 _inhideOutOfView = false;
113112 _treeIsBusy = false;
113+
114114 }
115115
116116 void VoxelSystem::elementDeleted(OctreeElement* element) {
117117 VoxelTreeElement* voxel = (VoxelTreeElement*)element;
118118 if (voxel->getVoxelSystem() == this) {
119119 if (_voxelsInWriteArrays != 0) {
120+qDebug() << "elementDeleted()... about to call forceRemoveNodeFromArrays()\n";
120121 forceRemoveNodeFromArrays(voxel);
121122 } else {
122123 if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
@@ -148,11 +149,11 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 25 unmodified lines
148149 if (voxel->getShouldRender() != shouldRender) {
149150 voxel->setShouldRender(shouldRender);
150151 }
151−
152+
152153 if (!voxel->isLeaf()) {
153−
154+
154155 // As we check our children, see if any of them went from shouldRender to NOT shouldRender
155− // then we probably dropped LOD and if we don't have color, we want to average our children
156+ // then we probably dropped LOD and if we don't have color, we want to average our children
156157 // for a new color.
157158 int childrenGotHiddenCount = 0;
158159 for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@@ -176,7 +177,7 @@ void VoxelSystem::elementUpdated(OctreeElement* element) { · 17 unmodified lines
176177 _voxelsUpdated++;
177178
178179 voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
179−
180+
180181 setupNewVoxelsForDrawingSingleNode();
181182 }
182183 }
@@ -219,7 +220,7 @@ void VoxelSystem::freeBufferIndex(glBufferIndex index) { · 36 unmodified lines
219220 break;
220221 }
221222 }
222− }
223+ }
223224 if (!inList) {
224225 // make the index available for next node that needs to be drawn
225226 pthread_mutex_lock(&_freeIndexLock);
@@ -308,7 +309,7 @@ void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { · 82 unmodified lines
308309 }
309310
310311 bool wasInitialized = _initialized;
311−
312+
312313 // If we're "turning on" Voxels as points, we need to double check that we're in voxel shader mode.
313314 // Voxels as points uses the VoxelShader memory model, so if we're not in voxel shader mode,
314315 // then set it to voxel shader mode.
@@ -318,7 +319,7 @@ void VoxelSystem::setVoxelsAsPoints(bool voxelsAsPoints) { · 3 unmodified lines
318319 // If enabling this... then do it before checking voxel shader status, that way, if voxel
319320 // shader is already enabled, we just start drawing as points.
320321 _voxelsAsPoints = true;
321−
322+
322323 if (!_useVoxelShader) {
323324 setUseVoxelShader(true);
324325 _voxelShaderModeWhenVoxelsAsPointsEnabled = false;
@@ -354,7 +355,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 29 unmodified lines
354355
355356 delete[] _writeVoxelShaderData;
356357 delete[] _readVoxelShaderData;
357−
358+
358359 _writeVoxelShaderData = _readVoxelShaderData = NULL;
359360
360361 } else {
@@ -368,7 +369,7 @@ void VoxelSystem::cleanupVoxelMemory() { · 7 unmodified lines
368369 glDeleteBuffers(1, &_vboIndicesRight);
369370 glDeleteBuffers(1, &_vboIndicesFront);
370371 glDeleteBuffers(1, &_vboIndicesBack);
371−
372+
372373 delete[] _readVerticesArray;
373374 delete[] _writeVerticesArray;
374375 delete[] _readColorsArray;
@@ -420,12 +421,12 @@ void VoxelSystem::initVoxelMemory() { · 45 unmodified lines
420421
421422 _memoryUsageRAM = 0;
422423 _memoryUsageVBO = 0; // our VBO allocations as we know them
423−
424+
424425 // if _voxelsAsPoints then we must have _useVoxelShader
425426 if (_voxelsAsPoints && !_useVoxelShader) {
426427 _useVoxelShader = true;
427428 }
428−
429+
429430 if (_useVoxelShader) {
430431 GLuint* indicesArray = new GLuint[_maxVoxels];
431432
@@ -445,7 +446,7 @@ void VoxelSystem::initVoxelMemory() { · 13 unmodified lines
445446 glBindBuffer(GL_ARRAY_BUFFER, _vboVoxelsID);
446447 glBufferData(GL_ARRAY_BUFFER, _maxVoxels * sizeof(VoxelShaderVBOData), NULL, GL_DYNAMIC_DRAW);
447448 _memoryUsageVBO += _maxVoxels * sizeof(VoxelShaderVBOData);
448−
449+
449450 // delete the indices and normals arrays that are no longer needed
450451 delete[] indicesArray;
451452
@@ -474,7 +475,7 @@ void VoxelSystem::initVoxelMemory() { · 22 unmodified lines
474475 setupFaceIndices(_vboIndicesRight, identityIndicesRight);
475476 setupFaceIndices(_vboIndicesFront, identityIndicesFront);
476477 setupFaceIndices(_vboIndicesBack, identityIndicesBack);
477−
478+
478479 // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel
479480 int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL;
480481 glGenBuffers(1, &_vboVerticesID);
@@ -519,10 +520,10 @@ void VoxelSystem::initVoxelMemory() { · 38 unmodified lines
519520 _perlinModulateProgram.bind();
520521 _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
521522 _perlinModulateProgram.release();
522−
523+
523524 _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/shadow_map.frag");
524525 _shadowMapProgram.link();
525−
526+
526527 _shadowMapProgram.bind();
527528 _shadowMapProgram.setUniformValue("shadowMap", 0);
528529 _shadowMapProgram.release();
@@ -571,26 +572,26 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 42 unmodified lines
571572 switch(command) {
572573 case PACKET_TYPE_VOXEL_DATA: {
573574 PerformanceWarning warn(showTimingDetails, "VoxelSystem::parseData() PACKET_TYPE_VOXEL_DATA part...",showTimingDetails);
574−
575+
575576 unsigned char* dataAt = sourceBuffer + numBytesPacketHeader;
576577
577578 VOXEL_PACKET_FLAGS flags = (*(VOXEL_PACKET_FLAGS*)(dataAt));
578579 dataAt += sizeof(VOXEL_PACKET_FLAGS);
579580 VOXEL_PACKET_SEQUENCE sequence = (*(VOXEL_PACKET_SEQUENCE*)dataAt);
580581 dataAt += sizeof(VOXEL_PACKET_SEQUENCE);
581−
582+
582583 VOXEL_PACKET_SENT_TIME sentAt = (*(VOXEL_PACKET_SENT_TIME*)dataAt);
583584 dataAt += sizeof(VOXEL_PACKET_SENT_TIME);
584−
585+
585586 bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
586587 bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
587−
588+
588589 VOXEL_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
589590 int flightTime = arrivedAt - sentAt;
590−
591+
591592 VOXEL_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
592593 int dataBytes = numBytes - VOXEL_PACKET_HEADER_SIZE;
593−
594+
594595 int subsection = 1;
595596 while (dataBytes > 0) {
596597 if (packetIsCompressed) {
@@ -605,7 +606,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 8 unmodified lines
605606 } else {
606607 sectionLength = dataBytes;
607608 }
608−
609+
609610 if (sectionLength) {
610611 // ask the VoxelTree to read the bitstream into the tree
611612 ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID());
@@ -616,12 +617,12 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 4 unmodified lines
616617 qDebug("VoxelSystem::parseData() ... Got Packet Section"
617618 " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d"
618619 " subsection:%d sectionLength:%d uncompressed:%d\n",
619− debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
620+ debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
620621 sequence, flightTime, numBytes, dataBytes, subsection, sectionLength, packetData.getUncompressedSize());
621622 }
622623 _tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
623624 unlockTree();
624−
625+
625626 dataBytes -= sectionLength;
626627 dataAt += sectionLength;
627628 }
@@ -635,15 +636,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 7 unmodified lines
635636 } else {
636637 setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
637638 }
638−
639+
639640 Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::VOXELS).updateValue(numBytes);
640−
641+
641642 return numBytes;
642643 }
643644
644645 void VoxelSystem::setupNewVoxelsForDrawing() {
645−
646−
647646 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
648647 "setupNewVoxelsForDrawing()");
649648
@@ -653,7 +652,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 3 unmodified lines
653652
654653 uint64_t start = usecTimestampNow();
655654 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
656−
655+
657656 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
658657 if (!iAmDebugging && sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
659658 return; // bail early, it hasn't been long enough since the last time we ran
@@ -665,7 +664,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 5 unmodified lines
665664 if (_tree->isDirty()) {
666665 static char buffer[64] = { 0 };
667666 if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
668− sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO));
667+ sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", debug::valueOf(_writeRenderFullVBO));
669668 };
670669 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer);
671670 _callsToTreesToArrays++;
@@ -678,17 +677,17 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 6 unmodified lines
678677 if (_writeRenderFullVBO) {
679678 _abandonedVBOSlots = 0; // reset the count of our abandoned slots, why is this here and not earlier????
680679 }
681−
680+
682681 // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
683− // ok again, until/unless we call removeOutOfView()
684− _writeRenderFullVBO = false;
682+ // ok again, until/unless we call removeOutOfView()
683+ _writeRenderFullVBO = false;
685684 } else {
686685 _voxelsUpdated = 0;
687686 }
688−
687+
689688 // lock on the buffer write lock so we can't modify the data when the GPU is reading it
690689 pthread_mutex_lock(&_bufferWriteLock);
691−
690+
692691 if (_voxelsUpdated) {
693692 _voxelsDirty=true;
694693 }
@@ -703,6 +702,11 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 8 unmodified lines
703702 _setupNewVoxelsForDrawingLastFinished = end;
704703 _setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
705704 _inSetupNewVoxelsForDrawing = false;
705+
706+ bool extraDebugging = Application::getInstance()->getLogger()->extraDebugging();
707+ if (extraDebugging) {
708+ qDebug("setupNewVoxelsForDrawing()... _voxelsUpdated=%lu...\n",_voxelsUpdated);
709+ }
706710 }
707711
708712 void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) {
@@ -713,7 +717,7 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 4 unmodified lines
713717 uint64_t sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000;
714718
715719 bool iAmDebugging = false; // if you're debugging set this to true, so you won't get skipped for slow debugging
716− if (allowBailEarly && !iAmDebugging &&
720+ if (allowBailEarly && !iAmDebugging &&
717721 sinceLastTime <= std::max((float) _setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
718722 return; // bail early, it hasn't been long enough since the last time we ran
719723 }
@@ -745,19 +749,17 @@ void VoxelSystem::checkForCulling() { · 25 unmodified lines
745749
746750 PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()");
747751 uint64_t start = usecTimestampNow();
748−
749−
752+
750753 // track how long its been since we were last moving. If we have recently moved then only use delta frustums, if
751754 // it's been a long time since we last moved, then go ahead and do a full frustum cull.
752755 if (isViewChanging()) {
753756 _lastViewIsChanging = start;
754757 }
755758 uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000;
756−
757759 bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS));
758760
759761 // These has changed events will occur before we stop. So we need to remember this for when we finally have stopped
760− // moving long enough to be enoughTime
762+ // moving long enough to be enoughTime
761763 if (hasViewChanged()) {
762764 _hasRecentlyChanged = true;
763765 }
@@ -767,25 +769,25 @@ void VoxelSystem::checkForCulling() { · 3 unmodified lines
767769 bool forceFullFrustum = enoughTime && _hasRecentlyChanged;
768770
769771 // in hide mode, we only track the full frustum culls, because we don't care about the partials.
770− if (forceFullFrustum) {
772+ if (forceFullFrustum) {
771773 _lastViewCulling = start;
772774 _hasRecentlyChanged = false;
773775 }
774−
776+
775777 hideOutOfView(forceFullFrustum);
776778
777− if (forceFullFrustum) {
779+ if (forceFullFrustum) {
778780 uint64_t endViewCulling = usecTimestampNow();
779781 _lastViewCullingElapsed = (endViewCulling - start) / 1000;
780782 }
781−
783+
782784 // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,
783785 // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on
784786 // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary.
785787 cleanupRemovedVoxels();
786788
787789 uint64_t sinceLastAudit = (start - _lastAudit) / 1000;
788−
790+
789791 if (Menu::getInstance()->isOptionChecked(MenuOption::AutomaticallyAuditTree)) {
790792 if (sinceLastAudit >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) {
791793 _lastAudit = start;
@@ -812,7 +814,7 @@ void VoxelSystem::cleanupRemovedVoxels() { · 20 unmodified lines
812814 const float TOO_MANY_ABANDONED_RATIO = 0.5f;
813815 if (!_writeRenderFullVBO && (_abandonedVBOSlots > (_voxelsInWriteArrays * TOO_MANY_ABANDONED_RATIO))) {
814816 if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
815− qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots ["
817+ qDebug() << "cleanupRemovedVoxels().. _abandonedVBOSlots ["
816818 << _abandonedVBOSlots << "] > TOO_MANY_ABANDONED_RATIO \n";
817819 }
818820 _writeRenderFullVBO = true;
@@ -822,10 +824,10 @@ void VoxelSystem::cleanupRemovedVoxels() { · 3 unmodified lines
822824 void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() {
823825 copyWrittenDataSegmentToReadArrays(0, _voxelsInWriteArrays - 1);
824826 _voxelsInReadArrays = _voxelsInWriteArrays;
825−
827+
826828 // clear our dirty flags
827829 memset(_writeVoxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool));
828−
830+
829831 // let the reader know to get the full array
830832 _readRenderFullVBO = true;
831833 }
@@ -851,7 +853,7 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { · 19 unmodified lines
851853 }
852854 }
853855 }
854−
856+
855857 // if we got to the end of the array, and we're in an active dirty segment...
856858 if (inSegment) {
857859 copyWrittenDataSegmentToReadArrays(segmentStart, _voxelsInWriteArrays - 1);
@@ -910,9 +912,9 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) { · 52 unmodified lines
910912 voxel->setShouldRender(shouldRender);
911913 // let children figure out their renderness
912914 if (!voxel->isLeaf()) {
913−
915+
914916 // As we check our children, see if any of them went from shouldRender to NOT shouldRender
915− // then we probably dropped LOD and if we don't have color, we want to average our children
917+ // then we probably dropped LOD and if we don't have color, we want to average our children
916918 // for a new color.
917919 int childrenGotHiddenCount = 0;
918920 for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
@@ -930,17 +932,23 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) { · 11 unmodified lines
930932 voxel->calculateAverageFromChildren();
931933 }
932934 }
933− if (_writeRenderFullVBO) {
934− const bool DONT_REUSE_INDEX = false;
935− const bool FORCE_REDRAW = true;
936− voxelsUpdated += updateNodeInArrays(voxel, DONT_REUSE_INDEX, FORCE_REDRAW);
937− } else {
938− const bool REUSE_INDEX = true;
939− const bool DONT_FORCE_REDRAW = false;
940− voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
935+
936+ // for either voxels that should not render, or those that should render and are in view
937+ // update their geometry in the array.if the voxel "should render" but is not in view, then
938+ // it actually doesn't need to be rendered
939+ if (!shouldRender || voxel->isInView(*_viewFrustum)) {
940+ if (_writeRenderFullVBO) {
941+ const bool DONT_REUSE_INDEX = false;
942+ const bool FORCE_REDRAW = true;
943+ voxelsUpdated += updateNodeInArrays(voxel, DONT_REUSE_INDEX, FORCE_REDRAW);
944+ } else {
945+ const bool REUSE_INDEX = true;
946+ const bool DONT_FORCE_REDRAW = false;
947+ voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
948+ }
941949 }
942950 voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
943−
951+
944952 return voxelsUpdated;
945953 }
946954
@@ -959,7 +967,7 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { · 12 unmodified lines
959967 // If this node has not yet been written to the array, then add it to the end of the array.
960968 glBufferIndex nodeIndex = node->getBufferIndex();
961969 node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
962− freeBufferIndex(nodeIndex); // NOTE: This is make the node invisible!
970+ freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible!
963971 return 1; // updated!
964972 }
965973 return 0; // not-updated
@@ -982,11 +990,11 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 16 unmodified lines
982990 if (!_initialized) {
983991 return 0;
984992 }
985−
993+
986994 // If we've changed any attributes (our renderness, our color, etc), or we've been told to force a redraw
987995 // then update the Arrays...
988996 if (forceDraw || node->isDirty()) {
989− // If we're should render, use our legit location and scale,
997+ // If we're should render, use our legit location and scale,
990998 if (node->getShouldRender()) {
991999 glm::vec3 startVertex = node->getCorner();
9921000 float voxelScale = node->getScale();
@@ -1016,9 +1024,9 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 23 unmodified lines
10161024 void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
10171025 float voxelScale, const nodeColor& color) {
10181026
1019− if (_initialized) {
1027+ if (_initialized && nodeIndex <= _maxVoxels) {
10201028 _writeVoxelDirtyArray[nodeIndex] = true;
1021−
1029+
10221030 if (_useVoxelShader) {
10231031 if (_writeVoxelShaderData) {
10241032 VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
@@ -1071,15 +1079,17 @@ void VoxelSystem::init() { · 46 unmodified lines
10711079 // VBO for the verticesArray
10721080 _initialMemoryUsageGPU = getFreeMemoryGPU();
10731081 initVoxelMemory();
1074−
1082+
10751083 // our own _removedVoxels doesn't need to be notified of voxel deletes
10761084 VoxelTreeElement::removeDeleteHook(&_removedVoxels);
1085+
10771086 }
10781087
10791088 void VoxelSystem::changeTree(VoxelTree* newTree) {
10801089 disconnect(_tree, 0, this, 0);
10811090
10821091 _tree = newTree;
1092+
10831093 _tree->setDirtyBit();
10841094 _tree->getRoot()->setVoxelSystem(this);
10851095
@@ -1102,7 +1112,7 @@ void VoxelSystem::updateFullVBOs() { · 16 unmodified lines
11021112 PerformanceWarning warn(outputWarning,buffer);
11031113 updateVBOSegment(0, _voxelsInReadArrays);
11041114 }
1105−
1115+
11061116 {
11071117 PerformanceWarning warn(outputWarning,"updateFullVBOs() : memset(_readVoxelDirtyArray...)");
11081118 // consider the _readVoxelDirtyArray[] clean!
@@ -1131,7 +1141,7 @@ void VoxelSystem::updatePartialVBOs() { · 22 unmodified lines
11311141 _readVoxelDirtyArray[i] = false; // consider us clean!
11321142 }
11331143 }
1134−
1144+
11351145 // if we got to the end of the array, and we're in an active dirty segment...
11361146 if (inSegment) {
11371147 updateVBOSegment(segmentStart, _voxelsInReadArrays - 1);
@@ -1195,7 +1205,7 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg · 57 unmodified lines
11951205 PerformanceWarning warn(showWarning, "updateVBOSegment() : glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);");
11961206 glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
11971207 }
1198−
1208+
11991209 {
12001210 PerformanceWarning warn(showWarning, "updateVBOSegment() : glBufferSubData() _vboColorsID);");
12011211 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
@@ -1206,14 +1216,14 @@ void VoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferIndex seg · 4 unmodified lines
12061216 void VoxelSystem::render(bool texture) {
12071217 bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
12081218 PerformanceWarning warn(showWarnings, "render()");
1209−
1219+
12101220 // If we got here and we're not initialized then bail!
12111221 if (!_initialized) {
12121222 return;
12131223 }
1214−
1224+
12151225 updateVBOs();
1216−
1226+
12171227 bool dontCallOpenGLDraw = Menu::getInstance()->isOptionChecked(MenuOption::DontCallOpenGLForVoxels);
12181228 // if not don't... then do...
12191229 if (_useVoxelShader) {
@@ -1253,8 +1263,8 @@ void VoxelSystem::render(bool texture) { · 33 unmodified lines
12531263 glEnableVertexAttribArray(attributeLocation);
12541264 glVertexAttribPointer(attributeLocation, 1, GL_FLOAT, false, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(3*sizeof(float)));
12551265 }
1256−
1257−
1266+
1267+
12581268 glEnableClientState(GL_COLOR_ARRAY);
12591269 glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VoxelShaderVBOData), BUFFER_OFFSET(4*sizeof(float)));//The starting point of colors
12601270
@@ -1285,7 +1295,7 @@ void VoxelSystem::render(bool texture) { · 24 unmodified lines
12851295
12861296 {
12871297 PerformanceWarning warn(showWarnings,"render().. setup before glDrawRangeElementsEXT()...");
1288−
1298+
12891299 // tell OpenGL where to find vertex and color information
12901300 glEnableClientState(GL_VERTEX_ARRAY);
12911301 glEnableClientState(GL_COLOR_ARRAY);
@@ -1306,7 +1316,7 @@ void VoxelSystem::render(bool texture) { · 14 unmodified lines
13061316
13071317 if (!dontCallOpenGLDraw) {
13081318 PerformanceWarning warn(showWarnings, "render().. glDrawRangeElementsEXT()...");
1309−
1319+
13101320 glNormal3f(0,1.0f,0);
13111321 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesTop);
13121322 glDrawRangeElementsEXT(GL_TRIANGLES, 0, GLOBAL_NORMALS_VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
@@ -1340,7 +1350,7 @@ void VoxelSystem::render(bool texture) { · 27 unmodified lines
13401350
13411351 {
13421352 PerformanceWarning warn(showWarnings, "render().. cleanup after glDrawRangeElementsEXT()...");
1343−
1353+
13441354 glDisable(GL_CULL_FACE);
13451355
13461356 removeScaleAndReleaseProgram(texture);
@@ -1365,16 +1375,16 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { · 18 unmodified lines
13651375 glEnable(GL_TEXTURE_GEN_T);
13661376 glEnable(GL_TEXTURE_GEN_R);
13671377 glEnable(GL_TEXTURE_2D);
1368−
1378+
13691379 glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]);
13701380 glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]);
13711381 glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]);
1372−
1382+
13731383 } else if (texture) {
13741384 _perlinModulateProgram.bind();
13751385 glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPermutationNormalTextureID());
13761386 }
1377−
1387+
13781388 glPushMatrix();
13791389 glScalef(_treeScale, _treeScale, _treeScale);
13801390 }
@@ -1382,7 +1392,7 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { · 1 unmodified line
13821392 void VoxelSystem::removeScaleAndReleaseProgram(bool texture) {
13831393 // scale back down to 1 so heads aren't massive
13841394 glPopMatrix();
1385−
1395+
13861396 if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) {
13871397 _shadowMapProgram.release();
13881398 glBindTexture(GL_TEXTURE_2D, 0);
@@ -1390,7 +1400,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { · 1 unmodified line
13901400 glDisable(GL_TEXTURE_GEN_T);
13911401 glDisable(GL_TEXTURE_GEN_R);
13921402 glDisable(GL_TEXTURE_2D);
1393−
1403+
13941404 } else if (texture) {
13951405 _perlinModulateProgram.release();
13961406 glBindTexture(GL_TEXTURE_2D, 0);
@@ -1403,7 +1413,7 @@ void VoxelSystem::killLocalVoxels() { · 6 unmodified lines
14031413 lockTree();
14041414 _tree->eraseAllOctreeElements();
14051415 unlockTree();
1406− clearFreeBufferIndexes();
1416+ clearFreeBufferIndexes();
14071417 _voxelsInReadArrays = 0; // do we need to do this?
14081418 setupNewVoxelsForDrawing();
14091419 }
@@ -1422,7 +1432,7 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void · 12 unmodified lines
14221432
14231433 void VoxelSystem::clearAllNodesBufferIndex() {
14241434 _nodeCount = 0;
1425− lockTree();
1435+ lockTree();
14261436 _tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation);
14271437 unlockTree();
14281438 if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
@@ -1584,9 +1594,9 @@ void VoxelSystem::falseColorizeBySource() { · 155 unmodified lines
15841594 const int NUMBER_OF_COLOR_GROUPS = 6;
15851595 const unsigned char MIN_COLOR = 128;
15861596 int voxelServerCount = 0;
1587− groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = {
1588− groupColor(255, 0, 0),
1589− groupColor( 0, 255, 0),
1597+ groupColor groupColors[NUMBER_OF_COLOR_GROUPS] = {
1598+ groupColor(255, 0, 0),
1599+ groupColor( 0, 255, 0),
15901600 groupColor( 0, 0, 255),
15911601 groupColor(255, 0, 255),
15921602 groupColor( 0, 255, 255),
@@ -1614,7 +1624,7 @@ void VoxelSystem::falseColorizeBySource() { · 21 unmodified lines
16141624 voxelServerCount++;
16151625 }
16161626 }
1617−
1627+
16181628 _tree->recurseTreeWithOperation(falseColorizeBySourceOperation, &args);
16191629 qDebug("setting false color by source for %d nodes\n", _nodeCount);
16201630 _tree->setDirtyBit();
@@ -1690,7 +1700,7 @@ public: · 69 unmodified lines
16901700 unsigned long nodesOutside;
16911701 VoxelTreeElement* insideRoot;
16921702 VoxelTreeElement* outsideRoot;
1693−
1703+
16941704 removeOutOfViewArgs(VoxelSystem* voxelSystem, bool widenViewFrustum = true) :
16951705 thisVoxelSystem(voxelSystem),
16961706 thisViewFrustum(*voxelSystem->getViewFrustum()),
@@ -1730,7 +1740,7 @@ bool VoxelSystem::removeOutOfViewOperation(OctreeElement* element, void* extraDa · 33 unmodified lines
17301740 args->dontRecurseBag.remove(voxel);
17311741 return false; // stop recursion
17321742 }
1733−
1743+
17341744 VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;
17351745 args->nodesScanned++;
17361746 // Need to operate on our child nodes, so we can remove them
@@ -1748,7 +1758,7 @@ bool VoxelSystem::removeOutOfViewOperation(OctreeElement* element, void* extraDa · 11 unmodified lines
17481758 } break;
17491759 case ViewFrustum::INSIDE: {
17501760 // if the child node is fully INSIDE the view, then there's no need to recurse it
1751− // because we know all it's children will also be in the view, so we want to
1761+ // because we know all it's children will also be in the view, so we want to
17521762 // tell the caller to NOT recurse this child
17531763 args->nodesInside++;
17541764 args->dontRecurseBag.insert(childNode);
@@ -1779,12 +1789,12 @@ bool VoxelSystem::isViewChanging() { · 24 unmodified lines
17791789
17801790 bool VoxelSystem::hasViewChanged() {
17811791 bool result = false; // assume the best
1782−
1792+
17831793 // If we're still changing, report no change yet.
17841794 if (isViewChanging()) {
17851795 return false;
17861796 }
1787−
1797+
17881798 // If our viewFrustum has changed since our _lastKnownViewFrustum
17891799 if (!_lastStableViewFrustum.isVerySimilar(_viewFrustum)) {
17901800 result = true;
@@ -1803,8 +1813,8 @@ void VoxelSystem::removeOutOfView() { · 12 unmodified lines
18031813 }
18041814 bool showRemoveDebugDetails = false;
18051815 if (showRemoveDebugDetails) {
1806− qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",
1807− args.nodesScanned, args.nodesRemoved, args.nodesInside,
1816+ qDebug("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",
1817+ args.nodesScanned, args.nodesRemoved, args.nodesInside,
18081818 args.nodesIntersect, args.nodesOutside, _removedVoxels.count()
18091819 );
18101820 }
@@ -1816,9 +1826,9 @@ public: · 5 unmodified lines
18161826 VoxelSystem* thisVoxelSystem;
18171827 ViewFrustum thisViewFrustum;
18181828 unsigned long nodesScanned;
1819−
1829+
18201830 showAllLocalVoxelsArgs(VoxelSystem* voxelSystem) :
1821− thisVoxelSystem(voxelSystem),
1831+ thisVoxelSystem(voxelSystem),
18221832 thisViewFrustum(*voxelSystem->getViewFrustum()),
18231833 nodesScanned(0)
18241834 {
@@ -1880,8 +1890,9 @@ public: · 55 unmodified lines
18801890 unsigned long nodesOutsideInside;
18811891 unsigned long nodesInsideOutside;
18821892 unsigned long nodesOutsideOutside;
1883−
1884− hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree,
1893+ unsigned long nodesShown;
1894+
1895+ hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree,
18851896 bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) :
18861897 thisVoxelSystem(voxelSystem),
18871898 tree(tree),
@@ -1898,7 +1909,8 @@ public: · 10 unmodified lines
18981909 nodesIntersectInside(0),
18991910 nodesOutsideInside(0),
19001911 nodesInsideOutside(0),
1901− nodesOutsideOutside(0)
1912+ nodesOutsideOutside(0),
1913+ nodesShown(0)
19021914 {
19031915 // Widen the FOV for trimming
19041916 if (widenViewFrustum) {
@@ -1916,13 +1928,14 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 11 unmodified lines
19161928 if (_inhideOutOfView) {
19171929 return;
19181930 }
1919−
1931+
19201932 _inhideOutOfView = true;
19211933
19221934 bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
19231935 PerformanceWarning warn(showDebugDetails, "hideOutOfView()");
19241936 bool widenFrustum = true;
19251937
1938+
19261939 // When using "delta" view frustums and only hide/show items that are in the difference
19271940 // between the two view frustums. There are some potential problems with this mode.
19281941 //
@@ -1932,7 +1945,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 3 unmodified lines
19321945 //
19331946 // 2) Also, voxels will arrive from the network that are OUTSIDE of the view
19341947 // frustum... these won't get hidden... and so we can't assume they are correctly
1935− // hidden...
1948+ // hidden...
19361949 //
19371950 // Both these problems are solved by intermittently calling this with forceFullFrustum set
19381951 // to true. This will essentially clean up the improperly hidden or shown voxels.
@@ -1947,13 +1960,13 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 8 unmodified lines
19471960 args.lastViewFrustum.printDebugDetails();
19481961 }
19491962 }
1950−
1963+
19511964 if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.isVerySimilar(args.thisViewFrustum)) {
19521965 _inhideOutOfView = false;
19531966 return;
19541967 }
19551968
1956− lockTree();
1969+ lockTree();
19571970 _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args);
19581971 unlockTree();
19591972 _lastCulledViewFrustum = args.thisViewFrustum; // save last stable
@@ -1963,16 +1976,19 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { · 3 unmodified lines
19631976 _tree->setDirtyBit();
19641977 setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
19651978 }
1966−
1967− bool extraDebugDetails = Application::getInstance()->getLogger()->extraDebugging();
1979+
1980+ bool extraDebugDetails = false; // Application::getInstance()->getLogger()->extraDebugging();
19681981 if (extraDebugDetails) {
1969− qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n",
1970− args.nodesScanned, args.nodesRemoved, args.nodesInside,
1982+ qDebug("hideOutOfView() scanned=%ld removed=%ld show=%ld inside=%ld intersect=%ld outside=%ld\n",
1983+ args.nodesScanned, args.nodesRemoved, args.nodesShown, args.nodesInside,
19711984 args.nodesIntersect, args.nodesOutside
19721985 );
1973− qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n",
1986+ qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n",
19741987 args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside
19751988 );
1989+
1990+ qDebug() << "args.thisViewFrustum....\n";
1991+ args.thisViewFrustum.printDebugDetails();
19761992 }
19771993 _inhideOutOfView = false;
19781994 }
@@ -1985,10 +2001,10 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat · 6 unmodified lines
19852001 // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
19862002 // consider that case.
19872003 ViewFrustum::location inLastCulledFrustum;
1988−
2004+
19892005 if (args->culledOnce && args->wantDeltaFrustums) {
19902006 inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
1991−
2007+
19922008 // if this node is fully OUTSIDE our last culled view frustum, then we don't need to recurse further
19932009 if (inLastCulledFrustum == ViewFrustum::OUTSIDE) {
19942010 args->nodesOutsideOutside++;
@@ -2009,7 +2025,7 @@ bool VoxelSystem::hideAllSubTreeOperation(OctreeElement* element, void* extraDat · 14 unmodified lines
20092025 }
20102026
20112027 }
2012−
2028+
20132029 return true;
20142030 }
20152031
@@ -2021,10 +2037,10 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 5 unmodified lines
20212037 // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
20222038 // consider that case.
20232039 ViewFrustum::location inLastCulledFrustum;
2024−
2040+
20252041 if (args->culledOnce && args->wantDeltaFrustums) {
20262042 inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
2027−
2043+
20282044 // if this node is fully inside our last culled view frustum, then we don't need to recurse further
20292045 if (inLastCulledFrustum == ViewFrustum::INSIDE) {
20302046 args->nodesInsideInside++;
@@ -2047,35 +2063,36 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 16 unmodified lines
20472063 // These are both needed to force redraw...
20482064 voxel->setDirtyBit();
20492065 voxel->markWithChangedTime();
2066+ args->nodesShown++;
20502067 }
20512068
20522069 return true; // keep recursing!
20532070 }
20542071
2055−// "hide" voxels in the VBOs that are still in the tree that but not in view.
2072+// "hide" voxels in the VBOs that are still in the tree that but not in view.
20562073 // We don't remove them from the tree, we don't delete them, we do remove them
20572074 // from the VBOs and mark them as such in the tree.
20582075 bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData) {
20592076 VoxelTreeElement* voxel = (VoxelTreeElement*)element;
20602077 hideOutOfViewArgs* args = (hideOutOfViewArgs*)extraData;
20612078
2062− // If we're still recursing the tree using this operator, then we don't know if we're inside or outside...
2079+ // If we're still recursing the tree using this operator, then we don't know if we're inside or outside...
20632080 // so before we move forward we need to determine our frustum location
20642081 ViewFrustum::location inFrustum = voxel->inFrustum(args->thisViewFrustum);
2065−
2082+
20662083 // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine
20672084 // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not
20682085 // consider that case.
20692086 ViewFrustum::location inLastCulledFrustum;
2070−
2087+
20712088 if (args->culledOnce && args->wantDeltaFrustums) {
20722089 inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum);
20732090 }
2074−
2091+
20752092 // ok, now do some processing for this node...
20762093 switch (inFrustum) {
20772094 case ViewFrustum::OUTSIDE: {
2078−
2095+
20792096 // If this node is outside the current view, then we might want to hide it... unless it was previously OUTSIDE,
20802097 // if it was previously outside, then we can safely assume it's already hidden, and we can also safely assume
20812098 // that all of it's children are outside both of our views, in which case we can just stop recursing...
@@ -2084,17 +2101,17 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 2 unmodified lines
20842101 args->nodesOutsideOutside++;
20852102 return false; // stop recursing this branch!
20862103 }
2087−
2104+
20882105 // if this node is fully OUTSIDE the view, but previously intersected and/or was inside the last view, then
2089− // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse
2106+ // we need to hide it. Additionally we know that ALL of it's children are also fully OUTSIDE so we can recurse
20902107 // the children and simply mark them as hidden
20912108 args->tree->recurseNodeWithOperation(voxel, hideAllSubTreeOperation, args );
2092−
2109+
20932110 return false;
2094−
2111+
20952112 } break;
20962113 case ViewFrustum::INSIDE: {
2097−
2114+
20982115 // If this node is INSIDE the current view, then we might want to show it... unless it was previously INSIDE,
20992116 // if it was previously INSIDE, then we can safely assume it's already shown, and we can also safely assume
21002117 // that all of it's children are INSIDE both of our views, in which case we can just stop recursing...
@@ -2103,18 +2120,18 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 2 unmodified lines
21032120 args->nodesInsideInside++;
21042121 return false; // stop recursing this branch!
21052122 }
2106−
2123+
21072124 // if this node is fully INSIDE the view, but previously INTERSECTED and/or was OUTSIDE the last view, then
2108− // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse
2125+ // we need to show it. Additionally we know that ALL of it's children are also fully INSIDE so we can recurse
21092126 // the children and simply mark them as visible (as appropriate based on LOD)
21102127 args->tree->recurseNodeWithOperation(voxel, showAllSubTreeOperation, args);
21112128
2112− return false;
2129+ return false;
21132130 } break;
21142131 case ViewFrustum::INTERSECT: {
21152132 args->nodesScanned++;
21162133
2117− // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE
2134+ // If this node INTERSECTS the current view, then we might want to show it... unless it was previously INSIDE
21182135 // the last known view, in which case it will already be visible, and we know that all it's children are also
21192136 // previously INSIDE and visible. So in this case stop recursing
21202137 if (args->culledOnce && args->wantDeltaFrustums && inLastCulledFrustum == ViewFrustum::INSIDE) {
@@ -2125,21 +2142,22 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 4 unmodified lines
21252142 args->nodesIntersect++;
21262143
21272144 // if the child node INTERSECTs the view, then we want to check to see if it thinks it should render
2128− // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from
2145+ // if it should render but is missing it's VBO index, then we want to flip it on, and we can stop recursing from
21292146 // here because we know will block any children anyway
21302147 if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) {
21312148 voxel->setDirtyBit(); // will this make it draw?
2149+ args->nodesShown++;
21322150 return false;
21332151 }
21342152
21352153 // If it INTERSECTS but shouldn't be displayed, then it's probably a parent and it is at least partially in view.
2136− // So we DO want to recurse the children because some of them may not be in view... nothing specifically to do,
2154+ // So we DO want to recurse the children because some of them may not be in view... nothing specifically to do,
21372155 // just keep iterating the children
2138− return true;
2156+ return true;
21392157
21402158 } break;
21412159 } // switch
2142−
2160+
21432161
21442162 return true; // keep going!
21452163 }
@@ -2147,7 +2165,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData · 1 unmodified line
21472165
21482166 bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
21492167 VoxelDetail& detail, float& distance, BoxFace& face) {
2150− lockTree();
2168+ lockTree();
21512169 OctreeElement* element;
21522170 if (!_tree->findRayIntersection(origin, direction, element, distance, face)) {
21532171 unlockTree();
@@ -2206,7 +2224,7 @@ bool VoxelSystem::falseColorizeRandomEveryOtherOperation(OctreeElement* element, · 52 unmodified lines
22062224 void VoxelSystem::falseColorizeRandomEveryOther() {
22072225 falseColorizeRandomEveryOtherArgs args;
22082226 _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args);
2209− qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",
2227+ qDebug("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",
22102228 args.totalNodes, args.colorableNodes, args.coloredNodes);
22112229 _tree->setDirtyBit();
22122230 setupNewVoxelsForDrawing();
@@ -2214,9 +2232,9 @@ void VoxelSystem::falseColorizeRandomEveryOther() { · 1 unmodified line
22142232
22152233 class collectStatsForTreesAndVBOsArgs {
22162234 public:
2217− collectStatsForTreesAndVBOsArgs(int maxVoxels) :
2218− totalNodes(0),
2219− dirtyNodes(0),
2235+ collectStatsForTreesAndVBOsArgs(int maxVoxels) :
2236+ totalNodes(0),
2237+ dirtyNodes(0),
22202238 shouldRenderNodes(0),
22212239 coloredNodes(0),
22222240 nodesInVBO(0),
@@ -2228,7 +2246,7 @@ public: · 5 unmodified lines
22282246 hasIndexFound = new bool[maxVoxels];
22292247 memset(hasIndexFound, false, maxVoxels * sizeof(bool));
22302248 };
2231−
2249+
22322250 ~collectStatsForTreesAndVBOsArgs() {
22332251 delete[] hasIndexFound;
22342252 }
@@ -2244,13 +2262,13 @@ public: · 9 unmodified lines
22442262 unsigned long leafNodes;
22452263
22462264 unsigned long expectedMax;
2247−
2265+
22482266 bool* hasIndexFound;
22492267 };
22502268
22512269 bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, void* extraData) {
22522270 VoxelTreeElement* voxel = (VoxelTreeElement*)element;
2253−
2271+
22542272 collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData;
22552273 args->totalNodes++;
22562274
@@ -2273,17 +2291,17 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 16 unmodified lines
22732291 if (voxel->isKnownBufferIndex()) {
22742292 args->nodesInVBO++;
22752293 unsigned long nodeIndex = voxel->getBufferIndex();
2276−
2294+
22772295 const bool extraDebugging = false; // enable for extra debugging
22782296 if (extraDebugging) {
2279− qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n",
2280− voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(),
2297+ qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s \n",
2298+ voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(),
22812299 nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender()));
22822300 }
22832301
22842302 if (args->hasIndexFound[nodeIndex]) {
22852303 args->duplicateVBOIndex++;
2286− qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
2304+ qDebug("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,
22872305 debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender()));
22882306 } else {
22892307 args->hasIndexFound[nodeIndex] = true;
@@ -2291,7 +2309,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 1 unmodified line
22912309 if (nodeIndex > args->expectedMax) {
22922310 args->nodesInVBOOverExpectedMax++;
22932311 }
2294−
2312+
22952313 // if it's in VBO but not-shouldRender, track that also...
22962314 if (!voxel->getShouldRender()) {
22972315 args->nodesInVBONotShouldRender++;
@@ -2316,9 +2334,9 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 18 unmodified lines
23162334
23172335 collectStatsForTreesAndVBOsArgs args(_maxVoxels);
23182336 args.expectedMax = _voxelsInWriteArrays;
2319−
2337+
23202338 qDebug("CALCULATING Local Voxel Tree Statistics >>>>>>>>>>>>\n");
2321−
2339+
23222340 _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);
23232341
23242342 qDebug("Local Voxel Tree Statistics:\n total nodes %ld \n leaves %ld \n dirty %ld \n colored %ld \n shouldRender %ld \n",
@@ -2327,7 +2345,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 2 unmodified lines
23272345 qDebug(" _voxelsDirty=%s \n _voxelsInWriteArrays=%ld \n minDirty=%ld \n maxDirty=%ld \n", debug::valueOf(_voxelsDirty),
23282346 _voxelsInWriteArrays, minDirty, maxDirty);
23292347
2330− qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n",
2348+ qDebug(" inVBO %ld \n nodesInVBOOverExpectedMax %ld \n duplicateVBOIndex %ld \n nodesInVBONotShouldRender %ld \n",
23312349 args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex, args.nodesInVBONotShouldRender);
23322350
23332351 glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;
@@ -2340,10 +2358,10 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 6 unmodified lines
23402358 }
23412359 }
23422360
2343− qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
2361+ qDebug(" minInVBO=%ld \n maxInVBO=%ld \n _voxelsInWriteArrays=%ld \n _voxelsInReadArrays=%ld \n",
23442362 minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays);
23452363
2346− qDebug(" _freeIndexes.size()=%ld \n",
2364+ qDebug(" _freeIndexes.size()=%ld \n",
23472365 _freeIndexes.size());
23482366
23492367 qDebug("DONE WITH Local Voxel Tree Statistics >>>>>>>>>>>>\n");
@@ -2354,36 +2372,36 @@ void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) { · 4 unmodified lines
23542372 lockTree();
23552373 _tree->deleteVoxelAt(x, y, z, s);
23562374 unlockTree();
2357−
2375+
23582376 // redraw!
23592377 setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in?
2360−
2378+
23612379 };
23622380
2363−VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const {
2364− return _tree->getVoxelAt(x, y, z, s);
2381+VoxelTreeElement* VoxelSystem::getVoxelAt(float x, float y, float z, float s) const {
2382+ return _tree->getVoxelAt(x, y, z, s);
23652383 };
23662384
2367−void VoxelSystem::createVoxel(float x, float y, float z, float s,
2385+void VoxelSystem::createVoxel(float x, float y, float z, float s,
23682386 unsigned char red, unsigned char green, unsigned char blue, bool destructive) {
2369−
2387+
23702388 //qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s);
23712389 lockTree();
2372− _tree->createVoxel(x, y, z, s, red, green, blue, destructive);
2390+ _tree->createVoxel(x, y, z, s, red, green, blue, destructive);
23732391 unlockTree();
23742392
2375− setupNewVoxelsForDrawing();
2393+ setupNewVoxelsForDrawing();
23762394 };
23772395
2378−void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) {
2379− _tree->createLine(point1, point2, unitSize, color, destructive);
2380− setupNewVoxelsForDrawing();
2396+void VoxelSystem::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color, bool destructive) {
2397+ _tree->createLine(point1, point2, unitSize, color, destructive);
2398+ setupNewVoxelsForDrawing();
23812399 };
23822400
2383−void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid,
2384− creationMode mode, bool destructive, bool debug) {
2385− _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug);
2386− setupNewVoxelsForDrawing();
2401+void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid,
2402+ creationMode mode, bool destructive, bool debug) {
2403+ _tree->createSphere(r, xc, yc, zc, s, solid, mode, destructive, debug);
2404+ setupNewVoxelsForDrawing();
23872405 };
23882406
23892407 void VoxelSystem::copySubTreeIntoNewTree(VoxelTreeElement* startNode, VoxelSystem* destination, bool rebaseToRoot) {
@@ -2431,7 +2449,7 @@ bool VoxelSystem::falseColorizeSubTreeOperation(OctreeElement* element, void* ex · 41 unmodified lines
24312449 voxel->setFalseColor(args->color[0], args->color[1], args->color[2]);
24322450 args->voxelsTouched++;
24332451 }
2434− return true;
2452+ return true;
24352453 }
24362454
24372455 bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* extraData) {
@@ -2459,18 +2477,18 @@ bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* e · 21 unmodified lines
24592477 if (result == OCCLUDED) {
24602478 args->nonLeavesOccluded++;
24612479 delete voxelPolygon;
2462−
2480+
24632481 FalseColorizeSubTreeOperationArgs subArgs;
24642482 subArgs.color[0] = 0;
24652483 subArgs.color[1] = 255;
24662484 subArgs.color[2] = 0;
24672485 subArgs.voxelsTouched = 0;
2468−
2486+
24692487 args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs );
2470−
2488+
24712489 args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1);
24722490 args->totalVoxels += (subArgs.voxelsTouched - 1);
2473−
2491+
24742492 return false;
24752493 }
24762494
@@ -2509,10 +2527,10 @@ bool VoxelSystem::falseColorizeOccludedOperation(OctreeElement* element, void* e · 32 unmodified lines
25092527 void VoxelSystem::falseColorizeOccluded() {
25102528 PerformanceWarning warn(true, "falseColorizeOccluded()",true);
25112529 myCoverageMap.erase();
2512−
2530+
25132531 FalseColorizeOccludedArgs args;
25142532 args.viewFrustum = _viewFrustum;
2515− args.map = &myCoverageMap;
2533+ args.map = &myCoverageMap;
25162534 args.totalVoxels = 0;
25172535 args.coloredVoxels = 0;
25182536 args.occludedVoxels = 0;
@@ -2527,15 +2545,15 @@ void VoxelSystem::falseColorizeOccluded() { · 8 unmodified lines
25272545 OctreeProjectedPolygon::pointInside_calls = 0;
25282546 OctreeProjectedPolygon::occludes_calls = 0;
25292547 OctreeProjectedPolygon::intersects_calls = 0;
2530−
2548+
25312549 glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE);
25322550
25332551 _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedOperation, position, (void*)&args);
25342552
2535− qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
2553+ qDebug("falseColorizeOccluded()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
25362554 position.x, position.y,
2537− args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
2538− args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
2555+ args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
2556+ args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
25392557 args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded,
25402558 OctreeProjectedPolygon::pointInside_calls,
25412559 OctreeProjectedPolygon::occludes_calls,
@@ -2574,18 +2592,18 @@ bool VoxelSystem::falseColorizeOccludedV2Operation(OctreeElement* element, void* · 32 unmodified lines
25742592 if (result == V2_OCCLUDED) {
25752593 args->nonLeavesOccluded++;
25762594 delete voxelPolygon;
2577−
2595+
25782596 FalseColorizeSubTreeOperationArgs subArgs;
25792597 subArgs.color[0] = 0;
25802598 subArgs.color[1] = 255;
25812599 subArgs.color[2] = 0;
25822600 subArgs.voxelsTouched = 0;
2583−
2601+
25842602 args->tree->recurseNodeWithOperation(voxel, falseColorizeSubTreeOperation, &subArgs );
2585−
2603+
25862604 args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1);
25872605 args->totalVoxels += (subArgs.voxelsTouched - 1);
2588−
2606+
25892607 return false;
25902608 }
25912609
@@ -2632,10 +2650,10 @@ void VoxelSystem::falseColorizeOccludedV2() { · 40 unmodified lines
26322650 OctreeProjectedPolygon::pointInside_calls = 0;
26332651 OctreeProjectedPolygon::occludes_calls = 0;
26342652 OctreeProjectedPolygon::intersects_calls = 0;
2635−
2653+
26362654 FalseColorizeOccludedArgs args;
26372655 args.viewFrustum = _viewFrustum;
2638− args.mapV2 = &myCoverageMapV2;
2656+ args.mapV2 = &myCoverageMapV2;
26392657 args.totalVoxels = 0;
26402658 args.coloredVoxels = 0;
26412659 args.occludedVoxels = 0;
@@ -2646,15 +2664,15 @@ void VoxelSystem::falseColorizeOccludedV2() { · 4 unmodified lines
26462664 args.nonLeavesOutOfView = 0;
26472665 args.nonLeavesOccluded = 0;
26482666 args.tree = _tree;
2649−
2667+
26502668 glm::vec3 position = args.viewFrustum->getPosition() * (1.0f/TREE_SCALE);
26512669
26522670 _tree->recurseTreeWithOperationDistanceSorted(falseColorizeOccludedV2Operation, position, (void*)&args);
26532671
2654− qDebug("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
2672+ qDebug("falseColorizeOccludedV2()\n position=(%f,%f)\n total=%ld\n colored=%ld\n occluded=%ld\n notOccluded=%ld\n outOfView=%ld\n subtreeVoxelsSkipped=%ld\n nonLeaves=%ld\n nonLeavesOutOfView=%ld\n nonLeavesOccluded=%ld\n pointInside_calls=%ld\n occludes_calls=%ld\n intersects_calls=%ld\n",
26552673 position.x, position.y,
2656− args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
2657− args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
2674+ args.totalVoxels, args.coloredVoxels, args.occludedVoxels,
2675+ args.notOccludedVoxels, args.outOfView, args.subtreeVoxelsSkipped,
26582676 args.nonLeaves, args.nonLeavesOutOfView, args.nonLeavesOccluded,
26592677 OctreeProjectedPolygon::pointInside_calls,
26602678 OctreeProjectedPolygon::occludes_calls,
@@ -2717,7 +2735,7 @@ unsigned long VoxelSystem::getFreeMemoryGPU() { · 56 unmodified lines
27172735 const GLenum VBO_FREE_MEMORY_ATI = 0x87FB;
27182736 glGetIntegerv(VBO_FREE_MEMORY_ATI, &results[0]);
27192737 GLenum errorATI = glGetError();
2720−
2738+
27212739 if (errorATI == GL_NO_ERROR) {
27222740 _hasMemoryUsageGPU = true;
27232741 freeMemory = results[0];
@@ -2730,19 +2748,19 @@ unsigned long VoxelSystem::getFreeMemoryGPU() { · 6 unmodified lines
27302748 //const GLenum GPU_MEMORY_INFO_EVICTION_COUNT_NVX = 0x904A;
27312749 //const GLenum GPU_MEMORY_INFO_EVICTED_MEMORY_NVX = 0x904B;
27322750 //const GLenum GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048;
2733−
2751+
27342752 const GLenum GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049;
27352753 results[0] = 0;
27362754 glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &results[0]);
2737− freeMemory += results[0];
2755+ freeMemory += results[0];
27382756 GLenum errorNVIDIA = glGetError();
2739−
2757+
27402758 if (errorNVIDIA == GL_NO_ERROR) {
27412759 _hasMemoryUsageGPU = true;
27422760 freeMemory = results[0];
27432761 }
27442762 }
2745−
2763+
27462764 const unsigned long BYTES_PER_KBYTE = 1024;
27472765 return freeMemory * BYTES_PER_KBYTE; // API results in KB, we want it in bytes
27482766 }
@@ -2763,4 +2781,22 @@ void VoxelSystem::unlockTree() { · 14 unmodified lines
27632781 }
27642782
27652783
2784+void VoxelSystem::localVoxelCacheLoaded() {
2785+ qDebug() << "localVoxelCacheLoaded()\n";
2786+
2787+ // Make sure that the application has properly set up the view frustum for our loaded state
2788+ Application::getInstance()->initAvatarAndViewFrustum();
2789+
2790+ _tree->setDirtyBit();
2791+ setupNewVoxelsForDrawing();
2792+ _inhideOutOfView = false; // reenable hideOutOfView behavior
2793+}
2794+
2795+void VoxelSystem::beginLoadingLocalVoxelCache() {
2796+ qDebug() << "beginLoadingLocalVoxelCache()\n";
2797+ _writeRenderFullVBO = true; // this will disable individual node updates
2798+ _inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded
2799+}
2800+
2801+
27662802