Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all
Unified · Split
| @@ -61,8 +61,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) · 60 unmodified lines | ||
| 61 | 61 | _maxVoxels(maxVoxels), |
| 62 | 62 | _initialized(false), |
| 63 | 63 | _showCulledSharedFaces(false), |
| 64 | − _usePrimitiveRenderer(false), | |
| 65 | − _renderer(0) { | |
| 64 | + _usePrimitiveRenderer(false), | |
| 65 | + _renderer(0) { | |
| 66 | 66 | |
| 67 | 67 | _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; |
| 68 | 68 | _writeRenderFullVBO = true; |
| @@ -215,16 +215,16 @@ void VoxelSystem::freeBufferIndex(glBufferIndex index) { · 146 unmodified lines | ||
| 215 | 215 | } |
| 216 | 216 | } |
| 217 | 217 | if (!inList) { |
| 218 | − // make the index available for next node that needs to be drawn | |
| 219 | − _freeIndexLock.lock(); | |
| 220 | − _freeIndexes.push_back(index); | |
| 221 | − _freeIndexLock.unlock(); | |
| 218 | + // make the index available for next node that needs to be drawn | |
| 219 | + _freeIndexLock.lock(); | |
| 220 | + _freeIndexes.push_back(index); | |
| 221 | + _freeIndexLock.unlock(); | |
| 222 | 222 | |
| 223 | − // make the VBO slot "invisible" in case this slot is not used | |
| 224 | − const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); | |
| 225 | − const float voxelScale = 0; | |
| 226 | − const nodeColor BLACK = {0, 0, 0, 0}; | |
| 227 | − updateArraysDetails(index, startVertex, voxelScale, BLACK); | |
| 223 | + // make the VBO slot "invisible" in case this slot is not used | |
| 224 | + const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); | |
| 225 | + const float voxelScale = 0; | |
| 226 | + const nodeColor BLACK = {0, 0, 0, 0}; | |
| 227 | + updateArraysDetails(index, startVertex, voxelScale, BLACK); | |
| 228 | 228 | } |
| 229 | 229 | } |
| 230 | 230 | |
| @@ -254,7 +254,7 @@ VoxelSystem::~VoxelSystem() { · 23 unmodified lines | ||
| 254 | 254 | cleanupVoxelMemory(); |
| 255 | 255 | delete _tree; |
| 256 | 256 | |
| 257 | − _renderer = 0; | |
| 257 | + _renderer = 0; | |
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 | void VoxelSystem::setMaxVoxels(int maxVoxels) { |
| @@ -263,12 +263,12 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) { · 2 unmodified lines | ||
| 263 | 263 | } |
| 264 | 264 | bool wasInitialized = _initialized; |
| 265 | 265 | if (wasInitialized) { |
| 266 | − clearAllNodesBufferIndex(); | |
| 267 | − cleanupVoxelMemory(); | |
| 266 | + clearAllNodesBufferIndex(); | |
| 267 | + cleanupVoxelMemory(); | |
| 268 | 268 | } |
| 269 | 269 | _maxVoxels = maxVoxels; |
| 270 | 270 | if (wasInitialized) { |
| 271 | − initVoxelMemory(); | |
| 271 | + initVoxelMemory(); | |
| 272 | 272 | } |
| 273 | 273 | if (wasInitialized) { |
| 274 | 274 | forceRedrawEntireTree(); |
| @@ -286,7 +286,7 @@ void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { · 11 unmodified lines | ||
| 286 | 286 | cleanupVoxelMemory(); |
| 287 | 287 | } |
| 288 | 288 | _useVoxelShader = useVoxelShader; |
| 289 | − _usePrimitiveRenderer = false; | |
| 289 | + _usePrimitiveRenderer = false; | |
| 290 | 290 | if (wasInitialized) { |
| 291 | 291 | initVoxelMemory(); |
| 292 | 292 | } |
| @@ -373,8 +373,8 @@ void VoxelSystem::cleanupVoxelMemory() { · 80 unmodified lines | ||
| 373 | 373 | _readColorsArray = NULL; |
| 374 | 374 | _writeColorsArray = NULL; |
| 375 | 375 | } |
| 376 | − delete _renderer; | |
| 377 | − _renderer = 0; | |
| 376 | + delete _renderer; | |
| 377 | + _renderer = 0; | |
| 378 | 378 | delete[] _writeVoxelDirtyArray; |
| 379 | 379 | delete[] _readVoxelDirtyArray; |
| 380 | 380 | _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; |
| @@ -522,7 +522,7 @@ void VoxelSystem::initVoxelMemory() { · 141 unmodified lines | ||
| 522 | 522 | _shadowMapProgram.release(); |
| 523 | 523 | } |
| 524 | 524 | } |
| 525 | − _renderer = new PrimitiveRenderer(_maxVoxels); | |
| 525 | + _renderer = new PrimitiveRenderer(_maxVoxels); | |
| 526 | 526 | |
| 527 | 527 | _initialized = true; |
| 528 | 528 | |
| @@ -666,10 +666,10 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 137 unmodified lines | ||
| 666 | 666 | _callsToTreesToArrays++; |
| 667 | 667 | |
| 668 | 668 | if (_writeRenderFullVBO) { |
| 669 | − if (_usePrimitiveRenderer) { | |
| 670 | − _renderer->release(); | |
| 671 | − } | |
| 672 | − clearFreeBufferIndexes(); | |
| 669 | + if (_usePrimitiveRenderer) { | |
| 670 | + _renderer->release(); | |
| 671 | + } | |
| 672 | + clearFreeBufferIndexes(); | |
| 673 | 673 | } |
| 674 | 674 | _voxelsUpdated = newTreeToArrays(_tree->getRoot()); |
| 675 | 675 | _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean |
| @@ -685,24 +685,24 @@ void VoxelSystem::setupNewVoxelsForDrawing() { · 9 unmodified lines | ||
| 685 | 685 | _voxelsUpdated = 0; |
| 686 | 686 | } |
| 687 | 687 | |
| 688 | − if (_usePrimitiveRenderer) { | |
| 689 | − if (_voxelsUpdated) { | |
| 690 | − _voxelsDirty=true; | |
| 691 | − } | |
| 692 | − } | |
| 693 | − else { | |
| 694 | − // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 695 | − _bufferWriteLock.lock(); | |
| 688 | + if (_usePrimitiveRenderer) { | |
| 689 | + if (_voxelsUpdated) { | |
| 690 | + _voxelsDirty=true; | |
| 691 | + } | |
| 692 | + } | |
| 693 | + else { | |
| 694 | + // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 695 | + _bufferWriteLock.lock(); | |
| 696 | 696 | |
| 697 | − if (_voxelsUpdated) { | |
| 698 | − _voxelsDirty=true; | |
| 699 | − } | |
| 697 | + if (_voxelsUpdated) { | |
| 698 | + _voxelsDirty=true; | |
| 699 | + } | |
| 700 | 700 | |
| 701 | − // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | |
| 702 | − copyWrittenDataToReadArrays(didWriteFullVBO); | |
| 701 | + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | |
| 702 | + copyWrittenDataToReadArrays(didWriteFullVBO); | |
| 703 | 703 | |
| 704 | − _bufferWriteLock.unlock(); | |
| 705 | − } | |
| 704 | + _bufferWriteLock.unlock(); | |
| 705 | + } | |
| 706 | 706 | |
| 707 | 707 | quint64 end = usecTimestampNow(); |
| 708 | 708 | int elapsedmsec = (end - start) / 1000; |
| @@ -730,28 +730,28 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { · 21 unmodified lines | ||
| 730 | 730 | return; // bail early, it hasn't been long enough since the last time we ran |
| 731 | 731 | } |
| 732 | 732 | |
| 733 | − if (_usePrimitiveRenderer) { | |
| 734 | − _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty | |
| 735 | − _voxelsUpdated = 0; | |
| 736 | − } | |
| 737 | − else { | |
| 738 | − // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 739 | − { | |
| 740 | − PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 741 | − "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); | |
| 742 | − _bufferWriteLock.lock(); | |
| 743 | − } | |
| 733 | + if (_usePrimitiveRenderer) { | |
| 734 | + _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty | |
| 735 | + _voxelsUpdated = 0; | |
| 736 | + } | |
| 737 | + else { | |
| 738 | + // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 739 | + { | |
| 740 | + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | |
| 741 | + "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); | |
| 742 | + _bufferWriteLock.lock(); | |
| 743 | + } | |
| 744 | 744 | |
| 745 | − _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty | |
| 745 | + _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty | |
| 746 | 746 | |
| 747 | − // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | |
| 748 | − copyWrittenDataToReadArrays(_writeRenderFullVBO); | |
| 747 | + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated | |
| 748 | + copyWrittenDataToReadArrays(_writeRenderFullVBO); | |
| 749 | 749 | |
| 750 | − // after... | |
| 751 | − _voxelsUpdated = 0; | |
| 750 | + // after... | |
| 751 | + _voxelsUpdated = 0; | |
| 752 | 752 | |
| 753 | − _bufferWriteLock.unlock(); | |
| 754 | − } | |
| 753 | + _bufferWriteLock.unlock(); | |
| 754 | + } | |
| 755 | 755 | quint64 end = usecTimestampNow(); |
| 756 | 756 | int elapsedmsec = (end - start) / 1000; |
| 757 | 757 | _setupNewVoxelsForDrawingLastFinished = end; |
| @@ -972,24 +972,24 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { · 214 unmodified lines | ||
| 972 | 972 | return 0; |
| 973 | 973 | } |
| 974 | 974 | |
| 975 | − if (_usePrimitiveRenderer) { | |
| 976 | − int primitiveIndex = node->getPrimitiveIndex(); | |
| 977 | − if (primitiveIndex) { | |
| 978 | − _renderer->remove(primitiveIndex); | |
| 979 | − node->setPrimitiveIndex(0); | |
| 980 | − return 1; | |
| 981 | − } | |
| 982 | − } | |
| 983 | − else { | |
| 984 | − // if the node is not in the VBOs then we have nothing to do! | |
| 985 | − if (node->isKnownBufferIndex()) { | |
| 986 | − // If this node has not yet been written to the array, then add it to the end of the array. | |
| 987 | − glBufferIndex nodeIndex = node->getBufferIndex(); | |
| 988 | − node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); | |
| 989 | − freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! | |
| 990 | − return 1; // updated! | |
| 991 | − } | |
| 992 | − } | |
| 975 | + if (_usePrimitiveRenderer) { | |
| 976 | + int primitiveIndex = node->getPrimitiveIndex(); | |
| 977 | + if (primitiveIndex) { | |
| 978 | + _renderer->remove(primitiveIndex); | |
| 979 | + node->setPrimitiveIndex(0); | |
| 980 | + return 1; | |
| 981 | + } | |
| 982 | + } | |
| 983 | + else { | |
| 984 | + // if the node is not in the VBOs then we have nothing to do! | |
| 985 | + if (node->isKnownBufferIndex()) { | |
| 986 | + // If this node has not yet been written to the array, then add it to the end of the array. | |
| 987 | + glBufferIndex nodeIndex = node->getBufferIndex(); | |
| 988 | + node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); | |
| 989 | + freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! | |
| 990 | + return 1; // updated! | |
| 991 | + } | |
| 992 | + } | |
| 993 | 993 | return 0; // not-updated |
| 994 | 994 | } |
| 995 | 995 | |
| @@ -1016,48 +1016,48 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo · 20 unmodified lines | ||
| 1016 | 1016 | if (forceDraw || node->isDirty()) { |
| 1017 | 1017 | // If we're should render, use our legit location and scale, |
| 1018 | 1018 | if (node->getShouldRender()) { |
| 1019 | − glm::vec3 startVertex = node->getCorner(); | |
| 1020 | − float voxelScale = node->getScale(); | |
| 1021 | − nodeColor const & color = node->getColor(); | |
| 1022 | − | |
| 1023 | − if (_usePrimitiveRenderer) { | |
| 1024 | − int primitiveIndex = node->getPrimitiveIndex(); | |
| 1025 | − if (primitiveIndex) { | |
| 1026 | − _renderer->remove(primitiveIndex); | |
| 1027 | − node->setPrimitiveIndex(0); | |
| 1028 | − } else { | |
| 1029 | − node->setVoxelSystem(this); | |
| 1030 | − } | |
| 1031 | − inspectForInteriorOcclusionsOperation(node, 0); | |
| 1019 | + glm::vec3 startVertex = node->getCorner(); | |
| 1020 | + float voxelScale = node->getScale(); | |
| 1021 | + nodeColor const & color = node->getColor(); | |
| 1022 | + | |
| 1023 | + if (_usePrimitiveRenderer) { | |
| 1024 | + int primitiveIndex = node->getPrimitiveIndex(); | |
| 1025 | + if (primitiveIndex) { | |
| 1026 | + _renderer->remove(primitiveIndex); | |
| 1027 | + node->setPrimitiveIndex(0); | |
| 1028 | + } else { | |
| 1029 | + node->setVoxelSystem(this); | |
| 1030 | + } | |
| 1031 | + inspectForInteriorOcclusionsOperation(node, 0); | |
| 1032 | 1032 | unsigned char occlusions; |
| 1033 | 1033 | if (_showCulledSharedFaces) { |
| 1034 | 1034 | occlusions = ~node->getInteriorOcclusions(); |
| 1035 | 1035 | } else { |
| 1036 | 1036 | occlusions = node->getInteriorOcclusions(); |
| 1037 | 1037 | } |
| 1038 | − if (occlusions != OctreeElement::HalfSpace::All) { | |
| 1039 | − Cube* cube = new Cube( | |
| 1040 | − startVertex.x, startVertex.y, startVertex.z, voxelScale, | |
| 1041 | − color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], | |
| 1042 | − occlusions); | |
| 1043 | − if (cube) { | |
| 1044 | − primitiveIndex = _renderer->add(cube); | |
| 1045 | − node->setPrimitiveIndex(primitiveIndex); | |
| 1046 | − } | |
| 1047 | − } | |
| 1048 | − } else { | |
| 1049 | − glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; | |
| 1050 | − if (reuseIndex && node->isKnownBufferIndex()) { | |
| 1051 | − nodeIndex = node->getBufferIndex(); | |
| 1052 | − } else { | |
| 1053 | − nodeIndex = getNextBufferIndex(); | |
| 1054 | − node->setBufferIndex(nodeIndex); | |
| 1055 | − node->setVoxelSystem(this); | |
| 1056 | − } | |
| 1057 | − // populate the array with points for the 8 vertices and RGB color for each added vertex | |
| 1058 | − updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); | |
| 1059 | − } | |
| 1060 | − return 1; // updated! | |
| 1038 | + if (occlusions != OctreeElement::HalfSpace::All) { | |
| 1039 | + Cube* cube = new Cube( | |
| 1040 | + startVertex.x, startVertex.y, startVertex.z, voxelScale, | |
| 1041 | + color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], | |
| 1042 | + occlusions); | |
| 1043 | + if (cube) { | |
| 1044 | + primitiveIndex = _renderer->add(cube); | |
| 1045 | + node->setPrimitiveIndex(primitiveIndex); | |
| 1046 | + } | |
| 1047 | + } | |
| 1048 | + } else { | |
| 1049 | + glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; | |
| 1050 | + if (reuseIndex && node->isKnownBufferIndex()) { | |
| 1051 | + nodeIndex = node->getBufferIndex(); | |
| 1052 | + } else { | |
| 1053 | + nodeIndex = getNextBufferIndex(); | |
| 1054 | + node->setBufferIndex(nodeIndex); | |
| 1055 | + node->setVoxelSystem(this); | |
| 1056 | + } | |
| 1057 | + // populate the array with points for the 8 vertices and RGB color for each added vertex | |
| 1058 | + updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); | |
| 1059 | + } | |
| 1060 | + return 1; // updated! | |
| 1061 | 1061 | } else { |
| 1062 | 1062 | // If we shouldn't render, and we're in reuseIndex mode, then free our index, this only operates |
| 1063 | 1063 | // on nodes with known index values, so it's safe to call for any node. |
| @@ -1204,17 +1204,17 @@ void VoxelSystem::updateVBOs() { · 140 unmodified lines | ||
| 1204 | 1204 | }; |
| 1205 | 1205 | // would like to include _callsToTreesToArrays |
| 1206 | 1206 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); |
| 1207 | − if (! _usePrimitiveRenderer) { | |
| 1208 | − if (_voxelsDirty) { | |
| 1209 | − if (_readRenderFullVBO) { | |
| 1210 | − updateFullVBOs(); | |
| 1211 | − } else { | |
| 1212 | − updatePartialVBOs(); | |
| 1213 | − } | |
| 1214 | − _voxelsDirty = false; | |
| 1215 | − _readRenderFullVBO = false; | |
| 1216 | − } | |
| 1217 | − } | |
| 1207 | + if (! _usePrimitiveRenderer) { | |
| 1208 | + if (_voxelsDirty) { | |
| 1209 | + if (_readRenderFullVBO) { | |
| 1210 | + updateFullVBOs(); | |
| 1211 | + } else { | |
| 1212 | + updatePartialVBOs(); | |
| 1213 | + } | |
| 1214 | + _voxelsDirty = false; | |
| 1215 | + _readRenderFullVBO = false; | |
| 1216 | + } | |
| 1217 | + } | |
| 1218 | 1218 | _callsToTreesToArrays = 0; // clear it |
| 1219 | 1219 | } |
| 1220 | 1220 | |
| @@ -1341,7 +1341,7 @@ void VoxelSystem::render(bool texture) { · 120 unmodified lines | ||
| 1341 | 1341 | glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); |
| 1342 | 1342 | } |
| 1343 | 1343 | } else |
| 1344 | − if (!_usePrimitiveRenderer) { | |
| 1344 | + if (!_usePrimitiveRenderer) { | |
| 1345 | 1345 | PerformanceWarning warn(showWarnings, "render().. TRIANGLES..."); |
| 1346 | 1346 | |
| 1347 | 1347 | { |
| @@ -1415,12 +1415,12 @@ void VoxelSystem::render(bool texture) { · 67 unmodified lines | ||
| 1415 | 1415 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
| 1416 | 1416 | } |
| 1417 | 1417 | } |
| 1418 | − else { | |
| 1419 | − applyScaleAndBindProgram(texture); | |
| 1420 | − _renderer->render(); | |
| 1421 | − removeScaleAndReleaseProgram(texture); | |
| 1418 | + else { | |
| 1419 | + applyScaleAndBindProgram(texture); | |
| 1420 | + _renderer->render(); | |
| 1421 | + removeScaleAndReleaseProgram(texture); | |
| 1422 | 1422 | |
| 1423 | − } | |
| 1423 | + } | |
| 1424 | 1424 | } |
| 1425 | 1425 | |
| 1426 | 1426 | void VoxelSystem::applyScaleAndBindProgram(bool texture) { |
| @@ -1485,7 +1485,7 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void · 58 unmodified lines | ||
| 1485 | 1485 | _nodeCount++; |
| 1486 | 1486 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 1487 | 1487 | voxel->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); |
| 1488 | − voxel->setPrimitiveIndex(0); | |
| 1488 | + voxel->setPrimitiveIndex(0); | |
| 1489 | 1489 | return true; |
| 1490 | 1490 | } |
| 1491 | 1491 | |
| @@ -1503,72 +1503,72 @@ bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, · 11 unmodified lines | ||
| 1503 | 1503 | _nodeCount++; |
| 1504 | 1504 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 1505 | 1505 | |
| 1506 | − // Nothing to do at the leaf level | |
| 1507 | − if (voxel->isLeaf()) { | |
| 1508 | − return false; | |
| 1509 | − } | |
| 1510 | − | |
| 1511 | − // Bit mask of occluded shared faces indexed by child | |
| 1512 | − unsigned char occludedSharedFace[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| 1513 | − | |
| 1514 | − // Traverse all pair combinations of children | |
| 1515 | − for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { | |
| 1516 | − | |
| 1517 | − VoxelTreeElement* childA = voxel->getChildAtIndex(i); | |
| 1518 | − if (childA) { | |
| 1519 | − | |
| 1520 | − // Get the child A's occluding faces, for a leaf that will be | |
| 1521 | − // all six voxel faces, and for a non leaf, that will be | |
| 1522 | − // all faces which are completely covered by four child octants. | |
| 1523 | − unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); | |
| 1524 | − | |
| 1525 | − if (exteriorOcclusionsA == OctreeElement::HalfSpace::None) { | |
| 1526 | − // There is nothing to be done with this child, next... | |
| 1527 | − continue; | |
| 1528 | − } | |
| 1529 | − | |
| 1530 | − for (int j = i; --j >= 0; ) { | |
| 1531 | − | |
| 1532 | − VoxelTreeElement* childB = voxel->getChildAtIndex(j); | |
| 1533 | − if (childB) { | |
| 1534 | − | |
| 1535 | − // Get child B's occluding faces | |
| 1536 | − unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); | |
| 1537 | − | |
| 1538 | − if (exteriorOcclusionsB == OctreeElement::HalfSpace::None) { | |
| 1539 | − // There is nothing to be done with this child, next... | |
| 1540 | − continue; | |
| 1541 | − } | |
| 1542 | − | |
| 1543 | − // Determine the shared halfspace partition between siblings A and B, | |
| 1544 | − // i.e., near/far, left/right, or top/bottom | |
| 1545 | − unsigned char partition = _sOctantIndexToSharedBitMask[i][j] & | |
| 1546 | − exteriorOcclusionsA & exteriorOcclusionsB; | |
| 1547 | − | |
| 1548 | − // Determine which face of each sibling is occluded. | |
| 1549 | − // Note the intentionally crossed indicies. It is necessary because | |
| 1550 | − // the _sOctantIndexToBitMask is a partition occupancy mask. For | |
| 1551 | − // example, if the near-left-top (NLT) and near-left-bottom (NLB) child voxels | |
| 1552 | − // exist, the shared partition is top-bottom (TB), and thus the occluded | |
| 1553 | − // shared face of the NLT voxel is its bottom face. | |
| 1554 | − occludedSharedFace[i] |= (partition & _sOctantIndexToBitMask[j]); | |
| 1555 | − occludedSharedFace[j] |= (partition & _sOctantIndexToBitMask[i]); | |
| 1556 | − } | |
| 1557 | − } | |
| 1558 | − // Combine this voxel's interior excluded shared face only to those children which are coincident | |
| 1559 | − // with the excluded face. | |
| 1560 | − occludedSharedFace[i] |= (voxel->getInteriorOcclusions() & _sOctantIndexToBitMask[i]); | |
| 1561 | − | |
| 1562 | − // Inform the child | |
| 1563 | − childA->setInteriorOcclusions(occludedSharedFace[i]); | |
| 1564 | − if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { | |
| 1565 | − //const glm::vec3& v = voxel->getCorner(); | |
| 1566 | − //float s = voxel->getScale(); | |
| 1567 | − | |
| 1568 | − //qDebug("Child %d of voxel at %f %f %f size: %f has %02x occlusions", i, v.x, v.y, v.z, s, occludedSharedFace[i]); | |
| 1569 | − } | |
| 1570 | − } | |
| 1571 | − } | |
| 1506 | + // Nothing to do at the leaf level | |
| 1507 | + if (voxel->isLeaf()) { | |
| 1508 | + return false; | |
| 1509 | + } | |
| 1510 | + | |
| 1511 | + // Bit mask of occluded shared faces indexed by child | |
| 1512 | + unsigned char occludedSharedFace[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| 1513 | + | |
| 1514 | + // Traverse all pair combinations of children | |
| 1515 | + for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { | |
| 1516 | + | |
| 1517 | + VoxelTreeElement* childA = voxel->getChildAtIndex(i); | |
| 1518 | + if (childA) { | |
| 1519 | + | |
| 1520 | + // Get the child A's occluding faces, for a leaf that will be | |
| 1521 | + // all six voxel faces, and for a non leaf, that will be | |
| 1522 | + // all faces which are completely covered by four child octants. | |
| 1523 | + unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); | |
| 1524 | + | |
| 1525 | + if (exteriorOcclusionsA == OctreeElement::HalfSpace::None) { | |
| 1526 | + // There is nothing to be done with this child, next... | |
| 1527 | + continue; | |
| 1528 | + } | |
| 1529 | + | |
| 1530 | + for (int j = i; --j >= 0; ) { | |
| 1531 | + | |
| 1532 | + VoxelTreeElement* childB = voxel->getChildAtIndex(j); | |
| 1533 | + if (childB) { | |
| 1534 | + | |
| 1535 | + // Get child B's occluding faces | |
| 1536 | + unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); | |
| 1537 | + | |
| 1538 | + if (exteriorOcclusionsB == OctreeElement::HalfSpace::None) { | |
| 1539 | + // There is nothing to be done with this child, next... | |
| 1540 | + continue; | |
| 1541 | + } | |
| 1542 | + | |
| 1543 | + // Determine the shared halfspace partition between siblings A and B, | |
| 1544 | + // i.e., near/far, left/right, or top/bottom | |
| 1545 | + unsigned char partition = _sOctantIndexToSharedBitMask[i][j] & | |
| 1546 | + exteriorOcclusionsA & exteriorOcclusionsB; | |
| 1547 | + | |
| 1548 | + // Determine which face of each sibling is occluded. | |
| 1549 | + // Note the intentionally crossed indicies. It is necessary because | |
| 1550 | + // the _sOctantIndexToBitMask is a partition occupancy mask. For | |
| 1551 | + // example, if the near-left-top (NLT) and near-left-bottom (NLB) child voxels | |
| 1552 | + // exist, the shared partition is top-bottom (TB), and thus the occluded | |
| 1553 | + // shared face of the NLT voxel is its bottom face. | |
| 1554 | + occludedSharedFace[i] |= (partition & _sOctantIndexToBitMask[j]); | |
| 1555 | + occludedSharedFace[j] |= (partition & _sOctantIndexToBitMask[i]); | |
| 1556 | + } | |
| 1557 | + } | |
| 1558 | + // Combine this voxel's interior excluded shared face only to those children which are coincident | |
| 1559 | + // with the excluded face. | |
| 1560 | + occludedSharedFace[i] |= (voxel->getInteriorOcclusions() & _sOctantIndexToBitMask[i]); | |
| 1561 | + | |
| 1562 | + // Inform the child | |
| 1563 | + childA->setInteriorOcclusions(occludedSharedFace[i]); | |
| 1564 | + if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { | |
| 1565 | + //const glm::vec3& v = voxel->getCorner(); | |
| 1566 | + //float s = voxel->getScale(); | |
| 1567 | + | |
| 1568 | + //qDebug("Child %d of voxel at %f %f %f size: %f has %02x occlusions", i, v.x, v.y, v.z, s, occludedSharedFace[i]); | |
| 1569 | + } | |
| 1570 | + } | |
| 1571 | + } | |
| 1572 | 1572 | return true; |
| 1573 | 1573 | } |
| 1574 | 1574 | |
| @@ -1576,71 +1576,71 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element, · 1 unmodified line | ||
| 1576 | 1576 | _nodeCount++; |
| 1577 | 1577 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 1578 | 1578 | |
| 1579 | − // Nothing to do at the leaf level | |
| 1580 | − if (voxel->isLeaf()) { | |
| 1581 | − return false; | |
| 1582 | − } | |
| 1583 | − | |
| 1584 | − // Count of exterior occluding faces of this voxel element indexed | |
| 1585 | − // by half space partition | |
| 1586 | − unsigned int exteriorOcclusionsCt[6] = { 0, 0, 0, 0, 0, 0 }; | |
| 1587 | − | |
| 1588 | − // Traverse all children | |
| 1589 | − for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { | |
| 1590 | − | |
| 1591 | − VoxelTreeElement* child = voxel->getChildAtIndex(i); | |
| 1592 | − if (child) { | |
| 1593 | − // Get the child's occluding faces, for a leaf, that will be | |
| 1594 | − // all six voxel faces, and for a non leaf, that will be | |
| 1595 | − // all faces which are completely covered by four child octants. | |
| 1596 | − unsigned char exteriorOcclusionsOfChild = child->getExteriorOcclusions(); | |
| 1597 | − exteriorOcclusionsOfChild &= _sOctantIndexToBitMask[i]; | |
| 1598 | − | |
| 1599 | − for (int j = 6; --j >= 0; ) { | |
| 1600 | − | |
| 1601 | − // Determine if the halfspace partition indexed by 1 << j is | |
| 1602 | − // present in the exterior occlusions of the child. | |
| 1603 | − unsigned char partition = exteriorOcclusionsOfChild & (1 << j); | |
| 1604 | − | |
| 1605 | − if (partition) { | |
| 1606 | − exteriorOcclusionsCt[j]++; | |
| 1607 | − } | |
| 1608 | − } | |
| 1609 | − } | |
| 1610 | − } | |
| 1611 | − { | |
| 1612 | − // Derive the exterior occlusions of the voxel elements from the exclusions | |
| 1613 | − // of its children | |
| 1614 | − unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; | |
| 1615 | − for (int i = 6; --i >= 0; ) { | |
| 1616 | − if (exteriorOcclusionsCt[i] == 4) { | |
| 1617 | − | |
| 1618 | − // Exactly four octants qualify for full exterior occlusion | |
| 1619 | − exteriorOcclusions |= (1 << i); | |
| 1620 | − } | |
| 1621 | − } | |
| 1622 | − | |
| 1623 | − // Inform the voxel element | |
| 1624 | − voxel->setExteriorOcclusions(exteriorOcclusions); | |
| 1625 | − | |
| 1626 | − if (exteriorOcclusions == OctreeElement::HalfSpace::All) { | |
| 1627 | − //const glm::vec3& v = voxel->getCorner(); | |
| 1628 | − //float s = voxel->getScale(); | |
| 1629 | − | |
| 1630 | − //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); | |
| 1631 | − | |
| 1632 | − // TODO: All of the exterior faces of this voxel element are | |
| 1633 | − // occluders, which means that this element is completely | |
| 1634 | − // occupied. Hence, the subtree from this node could be | |
| 1635 | − // pruned and replaced by a leaf voxel, if the visible | |
| 1636 | − // properties of the children are the same | |
| 1637 | − } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { | |
| 1638 | − //const glm::vec3& v = voxel->getCorner(); | |
| 1639 | − //float s = voxel->getScale(); | |
| 1640 | − | |
| 1641 | − //qDebug("Partially occupied voxel at %f %f %f size: %f with %02x", v.x, v.y, v.z, s, exteriorOcclusions); | |
| 1642 | − } | |
| 1643 | − } | |
| 1579 | + // Nothing to do at the leaf level | |
| 1580 | + if (voxel->isLeaf()) { | |
| 1581 | + return false; | |
| 1582 | + } | |
| 1583 | + | |
| 1584 | + // Count of exterior occluding faces of this voxel element indexed | |
| 1585 | + // by half space partition | |
| 1586 | + unsigned int exteriorOcclusionsCt[6] = { 0, 0, 0, 0, 0, 0 }; | |
| 1587 | + | |
| 1588 | + // Traverse all children | |
| 1589 | + for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { | |
| 1590 | + | |
| 1591 | + VoxelTreeElement* child = voxel->getChildAtIndex(i); | |
| 1592 | + if (child) { | |
| 1593 | + // Get the child's occluding faces, for a leaf, that will be | |
| 1594 | + // all six voxel faces, and for a non leaf, that will be | |
| 1595 | + // all faces which are completely covered by four child octants. | |
| 1596 | + unsigned char exteriorOcclusionsOfChild = child->getExteriorOcclusions(); | |
| 1597 | + exteriorOcclusionsOfChild &= _sOctantIndexToBitMask[i]; | |
| 1598 | + | |
| 1599 | + for (int j = 6; --j >= 0; ) { | |
| 1600 | + | |
| 1601 | + // Determine if the halfspace partition indexed by 1 << j is | |
| 1602 | + // present in the exterior occlusions of the child. | |
| 1603 | + unsigned char partition = exteriorOcclusionsOfChild & (1 << j); | |
| 1604 | + | |
| 1605 | + if (partition) { | |
| 1606 | + exteriorOcclusionsCt[j]++; | |
| 1607 | + } | |
| 1608 | + } | |
| 1609 | + } | |
| 1610 | + } | |
| 1611 | + { | |
| 1612 | + // Derive the exterior occlusions of the voxel elements from the exclusions | |
| 1613 | + // of its children | |
| 1614 | + unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; | |
| 1615 | + for (int i = 6; --i >= 0; ) { | |
| 1616 | + if (exteriorOcclusionsCt[i] == _sNumOctantsPerHemiVoxel) { | |
| 1617 | + | |
| 1618 | + // Exactly four octants qualify for full exterior occlusion | |
| 1619 | + exteriorOcclusions |= (1 << i); | |
| 1620 | + } | |
| 1621 | + } | |
| 1622 | + | |
| 1623 | + // Inform the voxel element | |
| 1624 | + voxel->setExteriorOcclusions(exteriorOcclusions); | |
| 1625 | + | |
| 1626 | + if (exteriorOcclusions == OctreeElement::HalfSpace::All) { | |
| 1627 | + //const glm::vec3& v = voxel->getCorner(); | |
| 1628 | + //float s = voxel->getScale(); | |
| 1629 | + | |
| 1630 | + //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); | |
| 1631 | + | |
| 1632 | + // TODO: All of the exterior faces of this voxel element are | |
| 1633 | + // occluders, which means that this element is completely | |
| 1634 | + // occupied. Hence, the subtree from this node could be | |
| 1635 | + // pruned and replaced by a leaf voxel, if the visible | |
| 1636 | + // properties of the children are the same | |
| 1637 | + } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { | |
| 1638 | + //const glm::vec3& v = voxel->getCorner(); | |
| 1639 | + //float s = voxel->getScale(); | |
| 1640 | + | |
| 1641 | + //qDebug("Partially occupied voxel at %f %f %f size: %f with %02x", v.x, v.y, v.z, s, exteriorOcclusions); | |
| 1642 | + } | |
| 1643 | + } | |
| 1644 | 1644 | return true; |
| 1645 | 1645 | } |
| 1646 | 1646 | |
| @@ -1648,55 +1648,55 @@ bool VoxelSystem::clearOcclusionsOperation(OctreeElement* element, void* extraDa · 1 unmodified line | ||
| 1648 | 1648 | _nodeCount++; |
| 1649 | 1649 | VoxelTreeElement* voxel = (VoxelTreeElement*)element; |
| 1650 | 1650 | |
| 1651 | − bool rc; | |
| 1652 | − if (voxel->isLeaf()) { | |
| 1651 | + bool rc; | |
| 1652 | + if (voxel->isLeaf()) { | |
| 1653 | 1653 | |
| 1654 | − // By definition the the exterior faces of a leaf voxel are | |
| 1655 | − // always occluders. | |
| 1656 | − voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); | |
| 1654 | + // By definition the the exterior faces of a leaf voxel are | |
| 1655 | + // always occluders. | |
| 1656 | + voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); | |
| 1657 | 1657 | |
| 1658 | − // And the sibling occluders | |
| 1659 | − voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1660 | − rc = false; | |
| 1661 | − } else { | |
| 1662 | − voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1663 | − voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1664 | − rc = true; | |
| 1665 | − } | |
| 1658 | + // And the sibling occluders | |
| 1659 | + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1660 | + rc = false; | |
| 1661 | + } else { | |
| 1662 | + voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1663 | + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); | |
| 1664 | + rc = true; | |
| 1665 | + } | |
| 1666 | 1666 | |
| 1667 | − return rc; | |
| 1667 | + return rc; | |
| 1668 | 1668 | } |
| 1669 | 1669 | |
| 1670 | 1670 | void VoxelSystem::cullSharedFaces() { |
| 1671 | 1671 | _nodeCount = 0; |
| 1672 | 1672 | |
| 1673 | 1673 | if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { |
| 1674 | − _useVoxelShader = false; | |
| 1675 | − _usePrimitiveRenderer = true; | |
| 1674 | + _useVoxelShader = false; | |
| 1675 | + _usePrimitiveRenderer = true; | |
| 1676 | 1676 | _renderer->release(); |
| 1677 | − clearAllNodesBufferIndex(); | |
| 1678 | − lockTree(); | |
| 1679 | − _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); | |
| 1680 | − _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); | |
| 1681 | − unlockTree(); | |
| 1682 | − | |
| 1683 | − _nodeCount = 0; | |
| 1684 | − lockTree(); | |
| 1685 | − _tree->recurseTreeWithOperation(inspectForInteriorOcclusionsOperation); | |
| 1686 | − unlockTree(); | |
| 1677 | + clearAllNodesBufferIndex(); | |
| 1678 | + lockTree(); | |
| 1679 | + _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); | |
| 1680 | + _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); | |
| 1681 | + unlockTree(); | |
| 1682 | + | |
| 1683 | + _nodeCount = 0; | |
| 1684 | + lockTree(); | |
| 1685 | + _tree->recurseTreeWithOperation(inspectForInteriorOcclusionsOperation); | |
| 1686 | + unlockTree(); | |
| 1687 | 1687 | qDebug("culling shared faces in %d nodes", _nodeCount); |
| 1688 | 1688 | } else { |
| 1689 | − _usePrimitiveRenderer = false; | |
| 1689 | + _usePrimitiveRenderer = false; | |
| 1690 | 1690 | _renderer->release(); |
| 1691 | − clearAllNodesBufferIndex(); | |
| 1692 | − lockTree(); | |
| 1693 | − _tree->recurseTreeWithOperation(clearOcclusionsOperation); | |
| 1694 | − unlockTree(); | |
| 1691 | + clearAllNodesBufferIndex(); | |
| 1692 | + lockTree(); | |
| 1693 | + _tree->recurseTreeWithOperation(clearOcclusionsOperation); | |
| 1694 | + unlockTree(); | |
| 1695 | 1695 | |
| 1696 | 1696 | |
| 1697 | 1697 | qDebug("unculling shared faces in %d nodes", _nodeCount); |
| 1698 | 1698 | } |
| 1699 | − _writeRenderFullVBO = true; | |
| 1699 | + _writeRenderFullVBO = true; | |
| 1700 | 1700 | _tree->setDirtyBit(); |
| 1701 | 1701 | setupNewVoxelsForDrawing(); |
| 1702 | 1702 | |
| @@ -1705,9 +1705,9 @@ void VoxelSystem::cullSharedFaces() { · 2 unmodified lines | ||
| 1705 | 1705 | void VoxelSystem::showCulledSharedFaces() { |
| 1706 | 1706 | |
| 1707 | 1707 | if (Menu::getInstance()->isOptionChecked(MenuOption::ShowCulledSharedFaces)) { |
| 1708 | − _showCulledSharedFaces = true; | |
| 1708 | + _showCulledSharedFaces = true; | |
| 1709 | 1709 | } else { |
| 1710 | − _showCulledSharedFaces = false; | |
| 1710 | + _showCulledSharedFaces = false; | |
| 1711 | 1711 | } |
| 1712 | 1712 | if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { |
| 1713 | 1713 | cullSharedFaces(); |
| @@ -2337,12 +2337,12 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat · 623 unmodified lines | ||
| 2337 | 2337 | // These are both needed to force redraw... |
| 2338 | 2338 | voxel->setDirtyBit(); |
| 2339 | 2339 | voxel->markWithChangedTime(); |
| 2340 | − // and this? | |
| 2341 | − { | |
| 2340 | + // and this? | |
| 2341 | + { | |
| 2342 | 2342 | VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; |
| 2343 | 2343 | thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->updateNodeInArrays(voxel, true, true); |
| 2344 | 2344 | thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); |
| 2345 | − } | |
| 2345 | + } | |
| 2346 | 2346 | args->nodesShown++; |
| 2347 | 2347 | } |
| 2348 | 2348 | |
| @@ -2522,8 +2522,8 @@ public: · 173 unmodified lines | ||
| 2522 | 2522 | nodesInVBOOverExpectedMax(0), |
| 2523 | 2523 | duplicateVBOIndex(0), |
| 2524 | 2524 | leafNodes(0), |
| 2525 | − culledLeafNodes(0), | |
| 2526 | − nodesInPrimitiveRenderer(0) | |
| 2525 | + culledLeafNodes(0), | |
| 2526 | + nodesInPrimitiveRenderer(0) | |
| 2527 | 2527 | { |
| 2528 | 2528 | hasIndexFound = new bool[maxVoxels]; |
| 2529 | 2529 | memset(hasIndexFound, false, maxVoxels * sizeof(bool)); |
| @@ -2542,8 +2542,8 @@ public: · 12 unmodified lines | ||
| 2542 | 2542 | unsigned long nodesInVBOOverExpectedMax; |
| 2543 | 2543 | unsigned long duplicateVBOIndex; |
| 2544 | 2544 | unsigned long leafNodes; |
| 2545 | − unsigned long culledLeafNodes; ///< Number of completely culled nodes because of face sharing | |
| 2546 | − unsigned long nodesInPrimitiveRenderer; | |
| 2545 | + unsigned long culledLeafNodes; ///< Number of completely culled nodes because of face sharing | |
| 2546 | + unsigned long nodesInPrimitiveRenderer; | |
| 2547 | 2547 | |
| 2548 | 2548 | unsigned long expectedMax; |
| 2549 | 2549 | |
| @@ -2558,9 +2558,9 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 8 unmodified lines | ||
| 2558 | 2558 | |
| 2559 | 2559 | if (voxel->isLeaf()) { |
| 2560 | 2560 | args->leafNodes++; |
| 2561 | − if (voxel->getInteriorOcclusions() == OctreeElement::HalfSpace::All) { | |
| 2562 | − args->culledLeafNodes++; | |
| 2563 | − } | |
| 2561 | + if (voxel->getInteriorOcclusions() == OctreeElement::HalfSpace::All) { | |
| 2562 | + args->culledLeafNodes++; | |
| 2563 | + } | |
| 2564 | 2564 | } |
| 2565 | 2565 | |
| 2566 | 2566 | if (voxel->isColored()) { |
| @@ -2575,16 +2575,16 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 8 unmodified lines | ||
| 2575 | 2575 | args->dirtyNodes++; |
| 2576 | 2576 | } |
| 2577 | 2577 | |
| 2578 | − unsigned long nodeIndex = 0; | |
| 2579 | − if (voxel->isKnownBufferIndex()) { | |
| 2580 | − args->nodesInVBO++; | |
| 2581 | − nodeIndex = voxel->getBufferIndex(); | |
| 2582 | − } | |
| 2578 | + unsigned long nodeIndex = 0; | |
| 2579 | + if (voxel->isKnownBufferIndex()) { | |
| 2580 | + args->nodesInVBO++; | |
| 2581 | + nodeIndex = voxel->getBufferIndex(); | |
| 2582 | + } | |
| 2583 | 2583 | |
| 2584 | − if (voxel->getPrimitiveIndex()) { | |
| 2585 | − args->nodesInPrimitiveRenderer++; | |
| 2586 | − nodeIndex = voxel->getPrimitiveIndex(); | |
| 2587 | − } | |
| 2584 | + if (voxel->getPrimitiveIndex()) { | |
| 2585 | + args->nodesInPrimitiveRenderer++; | |
| 2586 | + nodeIndex = voxel->getPrimitiveIndex(); | |
| 2587 | + } | |
| 2588 | 2588 | |
| 2589 | 2589 | if (voxel->isKnownBufferIndex() || (voxel->getPrimitiveIndex() != 0)) { |
| 2590 | 2590 | |
| @@ -2593,7 +2593,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v · 2 unmodified lines | ||
| 2593 | 2593 | qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s, culledFaces=0x%02x \n", |
| 2594 | 2594 | voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), |
| 2595 | 2595 | nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender()), |
| 2596 | − voxel->getInteriorOcclusions()); | |
| 2596 | + voxel->getInteriorOcclusions()); | |
| 2597 | 2597 | } |
| 2598 | 2598 | |
| 2599 | 2599 | if (args->hasIndexFound[nodeIndex]) { |
| @@ -2622,14 +2622,14 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { · 22 unmodified lines | ||
| 2622 | 2622 | glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; |
| 2623 | 2623 | glBufferIndex maxDirty = 0; |
| 2624 | 2624 | |
| 2625 | − if (!_usePrimitiveRenderer) { | |
| 2626 | − for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { | |
| 2627 | − if (_writeVoxelDirtyArray[i]) { | |
| 2628 | − minDirty = std::min(minDirty,i); | |
| 2629 | − maxDirty = std::max(maxDirty,i); | |
| 2630 | − } | |
| 2631 | − } | |
| 2632 | − } | |
| 2625 | + if (!_usePrimitiveRenderer) { | |
| 2626 | + for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { | |
| 2627 | + if (_writeVoxelDirtyArray[i]) { | |
| 2628 | + minDirty = std::min(minDirty,i); | |
| 2629 | + maxDirty = std::max(maxDirty,i); | |
| 2630 | + } | |
| 2631 | + } | |
| 2632 | + } | |
| 2633 | 2633 | |
| 2634 | 2634 | collectStatsForTreesAndVBOsArgs args(_maxVoxels); |
| 2635 | 2635 | args.expectedMax = _voxelsInWriteArrays; |
| @@ -3103,98 +3103,98 @@ void VoxelSystem::beginLoadingLocalVoxelCache() { · 467 unmodified lines | ||
| 3103 | 3103 | // value corresponds to the voxel's octal code derived in "pointToVoxel" in SharedUtil.cpp, which, BTW, does *not* |
| 3104 | 3104 | // correspond to the "ChildIndex" enum value in OctreeElement.h |
| 3105 | 3105 | unsigned char VoxelSystem::_sOctantIndexToBitMask[8] = { |
| 3106 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, | |
| 3107 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, | |
| 3108 | − OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, | |
| 3109 | − OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, | |
| 3110 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, | |
| 3111 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, | |
| 3112 | − OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, | |
| 3113 | − OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, | |
| 3106 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, | |
| 3107 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, | |
| 3108 | + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, | |
| 3109 | + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, | |
| 3110 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, | |
| 3111 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, | |
| 3112 | + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, | |
| 3113 | + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, | |
| 3114 | 3114 | }; |
| 3115 | 3115 | |
| 3116 | 3116 | // Two dimensional array map indexed by octant row and column. The mask value |
| 3117 | 3117 | // indicates the two faces shared by the octants |
| 3118 | 3118 | unsigned char VoxelSystem::_sOctantIndexToSharedBitMask[8][8] = { |
| 3119 | − { // Index 0: Bottom-Left-Near | |
| 3120 | − 0, // Bottom-Left-Near | |
| 3121 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Far | |
| 3122 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Near | |
| 3123 | − 0, // Top-Left-Far | |
| 3124 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Near | |
| 3125 | − 0, // Bottom-Right-Far | |
| 3126 | − 0, // Top-Right-Near | |
| 3127 | − 0, // Top-Right-Far | |
| 3128 | − }, | |
| 3129 | − { // Index 1: Bottom-Left-Far | |
| 3130 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Near | |
| 3131 | − 0, // Bottom-Left-Far | |
| 3132 | − 0, // Top-Left-Near | |
| 3133 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Far | |
| 3134 | − 0, // Bottom-Right-Near | |
| 3135 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Far | |
| 3136 | − 0, // Top-Right-Near | |
| 3137 | − 0, // Top-Right-Far | |
| 3138 | − }, | |
| 3139 | − { // Index 2: Top-Left-Near | |
| 3140 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Near | |
| 3141 | − 0, // Bottom-Left-Far | |
| 3142 | − 0, // Top-Left-Near | |
| 3143 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Far | |
| 3144 | − 0, // Bottom-Right-Near | |
| 3145 | − 0, // Bottom-Right-Far | |
| 3146 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Near | |
| 3147 | − 0, // Top-Right-Far | |
| 3148 | − }, | |
| 3149 | − { // Index 3: Top-Left-Far | |
| 3150 | − 0, // Bottom-Left-Near | |
| 3151 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Far | |
| 3152 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Near | |
| 3153 | − 0, // Top-Left-Far | |
| 3154 | − 0, // Bottom-Right-Near | |
| 3155 | − 0, // Bottom-Right-Far | |
| 3156 | − 0, // Top-Right-Near | |
| 3157 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Far | |
| 3158 | − }, | |
| 3159 | − { // Index 4: Bottom-Right-Near | |
| 3160 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Near | |
| 3161 | − 0, // Bottom-Left-Far | |
| 3162 | − 0, // Top-Left-Near | |
| 3163 | − 0, // Top-Left-Far | |
| 3164 | − 0, // Bottom-Right-Near | |
| 3165 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Far | |
| 3166 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Near | |
| 3167 | − 0, // Top-Right-Far | |
| 3168 | − }, | |
| 3169 | − { // Index 5: Bottom-Right-Far | |
| 3170 | − 0, // Bottom-Left-Near | |
| 3171 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Far | |
| 3172 | − 0, // Top-Left-Near | |
| 3173 | − 0, // Top-Left-Far | |
| 3174 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Near | |
| 3175 | − 0, // Bottom-Right-Far | |
| 3176 | − 0, // Top-Right-Near | |
| 3177 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Far | |
| 3178 | − }, | |
| 3179 | − { // Index 6: Top-Right-Near | |
| 3180 | − 0, // Bottom-Left-Near | |
| 3181 | − 0, // Bottom-Left-Far | |
| 3182 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Near | |
| 3183 | − 0, // Top-Left-Far | |
| 3184 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Near | |
| 3185 | − 0, // Bottom-Right-Far | |
| 3186 | − 0, // Top-Right-Near | |
| 3187 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Far | |
| 3188 | − }, | |
| 3189 | − { // Index 7: Top-Right-Far | |
| 3190 | − 0, // Bottom-Left-Near | |
| 3191 | − 0, // Bottom-Left-Far | |
| 3192 | − 0, // Top-Left-Near | |
| 3193 | − OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Far | |
| 3194 | − 0, // Bottom-Right-Near | |
| 3195 | − OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Far | |
| 3196 | − OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Near | |
| 3197 | − 0, // Top-Right-Far | |
| 3198 | − }, | |
| 3119 | + { // Index 0: Bottom-Left-Near | |
| 3120 | + 0, // Bottom-Left-Near | |
| 3121 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Far | |
| 3122 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Near | |
| 3123 | + 0, // Top-Left-Far | |
| 3124 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Near | |
| 3125 | + 0, // Bottom-Right-Far | |
| 3126 | + 0, // Top-Right-Near | |
| 3127 | + 0, // Top-Right-Far | |
| 3128 | + }, | |
| 3129 | + { // Index 1: Bottom-Left-Far | |
| 3130 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Near | |
| 3131 | + 0, // Bottom-Left-Far | |
| 3132 | + 0, // Top-Left-Near | |
| 3133 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Far | |
| 3134 | + 0, // Bottom-Right-Near | |
| 3135 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Far | |
| 3136 | + 0, // Top-Right-Near | |
| 3137 | + 0, // Top-Right-Far | |
| 3138 | + }, | |
| 3139 | + { // Index 2: Top-Left-Near | |
| 3140 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Near | |
| 3141 | + 0, // Bottom-Left-Far | |
| 3142 | + 0, // Top-Left-Near | |
| 3143 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Far | |
| 3144 | + 0, // Bottom-Right-Near | |
| 3145 | + 0, // Bottom-Right-Far | |
| 3146 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Near | |
| 3147 | + 0, // Top-Right-Far | |
| 3148 | + }, | |
| 3149 | + { // Index 3: Top-Left-Far | |
| 3150 | + 0, // Bottom-Left-Near | |
| 3151 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Far | |
| 3152 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Near | |
| 3153 | + 0, // Top-Left-Far | |
| 3154 | + 0, // Bottom-Right-Near | |
| 3155 | + 0, // Bottom-Right-Far | |
| 3156 | + 0, // Top-Right-Near | |
| 3157 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Far | |
| 3158 | + }, | |
| 3159 | + { // Index 4: Bottom-Right-Near | |
| 3160 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Near | |
| 3161 | + 0, // Bottom-Left-Far | |
| 3162 | + 0, // Top-Left-Near | |
| 3163 | + 0, // Top-Left-Far | |
| 3164 | + 0, // Bottom-Right-Near | |
| 3165 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Far | |
| 3166 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Near | |
| 3167 | + 0, // Top-Right-Far | |
| 3168 | + }, | |
| 3169 | + { // Index 5: Bottom-Right-Far | |
| 3170 | + 0, // Bottom-Left-Near | |
| 3171 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Far | |
| 3172 | + 0, // Top-Left-Near | |
| 3173 | + 0, // Top-Left-Far | |
| 3174 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Near | |
| 3175 | + 0, // Bottom-Right-Far | |
| 3176 | + 0, // Top-Right-Near | |
| 3177 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Far | |
| 3178 | + }, | |
| 3179 | + { // Index 6: Top-Right-Near | |
| 3180 | + 0, // Bottom-Left-Near | |
| 3181 | + 0, // Bottom-Left-Far | |
| 3182 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Near | |
| 3183 | + 0, // Top-Left-Far | |
| 3184 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Near | |
| 3185 | + 0, // Bottom-Right-Far | |
| 3186 | + 0, // Top-Right-Near | |
| 3187 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Far | |
| 3188 | + }, | |
| 3189 | + { // Index 7: Top-Right-Far | |
| 3190 | + 0, // Bottom-Left-Near | |
| 3191 | + 0, // Bottom-Left-Far | |
| 3192 | + 0, // Top-Left-Near | |
| 3193 | + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Far | |
| 3194 | + 0, // Bottom-Right-Near | |
| 3195 | + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Far | |
| 3196 | + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Near | |
| 3197 | + 0, // Top-Right-Far | |
| 3198 | + }, | |
| 3199 | 3199 | }; |
| 3200 | 3200 | |