diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a90910fe02..82f72bfb4d 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -61,8 +61,8 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) _maxVoxels(maxVoxels), _initialized(false), _showCulledSharedFaces(false), - _usePrimitiveRenderer(false), - _renderer(0) { + _usePrimitiveRenderer(false), + _renderer(0) { _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; _writeRenderFullVBO = true; @@ -215,16 +215,16 @@ void VoxelSystem::freeBufferIndex(glBufferIndex index) { } } if (!inList) { - // make the index available for next node that needs to be drawn - _freeIndexLock.lock(); - _freeIndexes.push_back(index); - _freeIndexLock.unlock(); + // make the index available for next node that needs to be drawn + _freeIndexLock.lock(); + _freeIndexes.push_back(index); + _freeIndexLock.unlock(); - // make the VBO slot "invisible" in case this slot is not used - const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); - const float voxelScale = 0; - const nodeColor BLACK = {0, 0, 0, 0}; - updateArraysDetails(index, startVertex, voxelScale, BLACK); + // make the VBO slot "invisible" in case this slot is not used + const glm::vec3 startVertex(FLT_MAX, FLT_MAX, FLT_MAX); + const float voxelScale = 0; + const nodeColor BLACK = {0, 0, 0, 0}; + updateArraysDetails(index, startVertex, voxelScale, BLACK); } } @@ -254,7 +254,7 @@ VoxelSystem::~VoxelSystem() { cleanupVoxelMemory(); delete _tree; - _renderer = 0; + _renderer = 0; } void VoxelSystem::setMaxVoxels(int maxVoxels) { @@ -263,12 +263,12 @@ void VoxelSystem::setMaxVoxels(int maxVoxels) { } bool wasInitialized = _initialized; if (wasInitialized) { - clearAllNodesBufferIndex(); - cleanupVoxelMemory(); + clearAllNodesBufferIndex(); + cleanupVoxelMemory(); } _maxVoxels = maxVoxels; if (wasInitialized) { - initVoxelMemory(); + initVoxelMemory(); } if (wasInitialized) { forceRedrawEntireTree(); @@ -286,7 +286,7 @@ void VoxelSystem::setUseVoxelShader(bool useVoxelShader) { cleanupVoxelMemory(); } _useVoxelShader = useVoxelShader; - _usePrimitiveRenderer = false; + _usePrimitiveRenderer = false; if (wasInitialized) { initVoxelMemory(); } @@ -373,8 +373,8 @@ void VoxelSystem::cleanupVoxelMemory() { _readColorsArray = NULL; _writeColorsArray = NULL; } - delete _renderer; - _renderer = 0; + delete _renderer; + _renderer = 0; delete[] _writeVoxelDirtyArray; delete[] _readVoxelDirtyArray; _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; @@ -522,7 +522,7 @@ void VoxelSystem::initVoxelMemory() { _shadowMapProgram.release(); } } - _renderer = new PrimitiveRenderer(_maxVoxels); + _renderer = new PrimitiveRenderer(_maxVoxels); _initialized = true; @@ -666,10 +666,10 @@ void VoxelSystem::setupNewVoxelsForDrawing() { _callsToTreesToArrays++; if (_writeRenderFullVBO) { - if (_usePrimitiveRenderer) { - _renderer->release(); - } - clearFreeBufferIndexes(); + if (_usePrimitiveRenderer) { + _renderer->release(); + } + clearFreeBufferIndexes(); } _voxelsUpdated = newTreeToArrays(_tree->getRoot()); _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean @@ -685,24 +685,24 @@ void VoxelSystem::setupNewVoxelsForDrawing() { _voxelsUpdated = 0; } - if (_usePrimitiveRenderer) { - if (_voxelsUpdated) { - _voxelsDirty=true; - } - } - else { - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - _bufferWriteLock.lock(); + if (_usePrimitiveRenderer) { + if (_voxelsUpdated) { + _voxelsDirty=true; + } + } + else { + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + _bufferWriteLock.lock(); - if (_voxelsUpdated) { - _voxelsDirty=true; - } + if (_voxelsUpdated) { + _voxelsDirty=true; + } - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(didWriteFullVBO); + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated + copyWrittenDataToReadArrays(didWriteFullVBO); - _bufferWriteLock.unlock(); - } + _bufferWriteLock.unlock(); + } quint64 end = usecTimestampNow(); int elapsedmsec = (end - start) / 1000; @@ -730,28 +730,28 @@ void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) { return; // bail early, it hasn't been long enough since the last time we ran } - if (_usePrimitiveRenderer) { - _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty - _voxelsUpdated = 0; - } - else { - // lock on the buffer write lock so we can't modify the data when the GPU is reading it - { - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); - _bufferWriteLock.lock(); - } + if (_usePrimitiveRenderer) { + _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty + _voxelsUpdated = 0; + } + else { + // lock on the buffer write lock so we can't modify the data when the GPU is reading it + { + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "setupNewVoxelsForDrawingSingleNode()... _bufferWriteLock.lock();" ); + _bufferWriteLock.lock(); + } - _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty + _voxelsDirty = true; // if we got this far, then we can assume some voxels are dirty - // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated - copyWrittenDataToReadArrays(_writeRenderFullVBO); + // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated + copyWrittenDataToReadArrays(_writeRenderFullVBO); - // after... - _voxelsUpdated = 0; + // after... + _voxelsUpdated = 0; - _bufferWriteLock.unlock(); - } + _bufferWriteLock.unlock(); + } quint64 end = usecTimestampNow(); int elapsedmsec = (end - start) / 1000; _setupNewVoxelsForDrawingLastFinished = end; @@ -972,24 +972,24 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) { return 0; } - if (_usePrimitiveRenderer) { - int primitiveIndex = node->getPrimitiveIndex(); - if (primitiveIndex) { - _renderer->remove(primitiveIndex); - node->setPrimitiveIndex(0); - return 1; - } - } - else { - // if the node is not in the VBOs then we have nothing to do! - if (node->isKnownBufferIndex()) { - // If this node has not yet been written to the array, then add it to the end of the array. - glBufferIndex nodeIndex = node->getBufferIndex(); - node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! - return 1; // updated! - } - } + if (_usePrimitiveRenderer) { + int primitiveIndex = node->getPrimitiveIndex(); + if (primitiveIndex) { + _renderer->remove(primitiveIndex); + node->setPrimitiveIndex(0); + return 1; + } + } + else { + // if the node is not in the VBOs then we have nothing to do! + if (node->isKnownBufferIndex()) { + // If this node has not yet been written to the array, then add it to the end of the array. + glBufferIndex nodeIndex = node->getBufferIndex(); + node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); + freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible! + return 1; // updated! + } + } return 0; // not-updated } @@ -1016,48 +1016,48 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo if (forceDraw || node->isDirty()) { // If we're should render, use our legit location and scale, if (node->getShouldRender()) { - glm::vec3 startVertex = node->getCorner(); - float voxelScale = node->getScale(); - nodeColor const & color = node->getColor(); + glm::vec3 startVertex = node->getCorner(); + float voxelScale = node->getScale(); + nodeColor const & color = node->getColor(); - if (_usePrimitiveRenderer) { - int primitiveIndex = node->getPrimitiveIndex(); - if (primitiveIndex) { - _renderer->remove(primitiveIndex); - node->setPrimitiveIndex(0); - } else { - node->setVoxelSystem(this); - } - inspectForInteriorOcclusionsOperation(node, 0); + if (_usePrimitiveRenderer) { + int primitiveIndex = node->getPrimitiveIndex(); + if (primitiveIndex) { + _renderer->remove(primitiveIndex); + node->setPrimitiveIndex(0); + } else { + node->setVoxelSystem(this); + } + inspectForInteriorOcclusionsOperation(node, 0); unsigned char occlusions; if (_showCulledSharedFaces) { occlusions = ~node->getInteriorOcclusions(); } else { occlusions = node->getInteriorOcclusions(); } - if (occlusions != OctreeElement::HalfSpace::All) { - Cube* cube = new Cube( - startVertex.x, startVertex.y, startVertex.z, voxelScale, - color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], - occlusions); - if (cube) { - primitiveIndex = _renderer->add(cube); - node->setPrimitiveIndex(primitiveIndex); - } - } - } else { - glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; - if (reuseIndex && node->isKnownBufferIndex()) { - nodeIndex = node->getBufferIndex(); - } else { - nodeIndex = getNextBufferIndex(); - node->setBufferIndex(nodeIndex); - node->setVoxelSystem(this); - } - // populate the array with points for the 8 vertices and RGB color for each added vertex - updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); - } - return 1; // updated! + if (occlusions != OctreeElement::HalfSpace::All) { + Cube* cube = new Cube( + startVertex.x, startVertex.y, startVertex.z, voxelScale, + color[RED_INDEX], color[GREEN_INDEX], color[BLUE_INDEX], + occlusions); + if (cube) { + primitiveIndex = _renderer->add(cube); + node->setPrimitiveIndex(primitiveIndex); + } + } + } else { + glBufferIndex nodeIndex = GLBUFFER_INDEX_UNKNOWN; + if (reuseIndex && node->isKnownBufferIndex()) { + nodeIndex = node->getBufferIndex(); + } else { + nodeIndex = getNextBufferIndex(); + node->setBufferIndex(nodeIndex); + node->setVoxelSystem(this); + } + // populate the array with points for the 8 vertices and RGB color for each added vertex + updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); + } + return 1; // updated! } else { // If we shouldn't render, and we're in reuseIndex mode, then free our index, this only operates // on nodes with known index values, so it's safe to call for any node. @@ -1204,17 +1204,17 @@ void VoxelSystem::updateVBOs() { }; // would like to include _callsToTreesToArrays PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), buffer); - if (! _usePrimitiveRenderer) { - if (_voxelsDirty) { - if (_readRenderFullVBO) { - updateFullVBOs(); - } else { - updatePartialVBOs(); - } - _voxelsDirty = false; - _readRenderFullVBO = false; - } - } + if (! _usePrimitiveRenderer) { + if (_voxelsDirty) { + if (_readRenderFullVBO) { + updateFullVBOs(); + } else { + updatePartialVBOs(); + } + _voxelsDirty = false; + _readRenderFullVBO = false; + } + } _callsToTreesToArrays = 0; // clear it } @@ -1341,7 +1341,7 @@ void VoxelSystem::render(bool texture) { glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); } } else - if (!_usePrimitiveRenderer) { + if (!_usePrimitiveRenderer) { PerformanceWarning warn(showWarnings, "render().. TRIANGLES..."); { @@ -1415,12 +1415,12 @@ void VoxelSystem::render(bool texture) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } } - else { - applyScaleAndBindProgram(texture); - _renderer->render(); - removeScaleAndReleaseProgram(texture); + else { + applyScaleAndBindProgram(texture); + _renderer->render(); + removeScaleAndReleaseProgram(texture); - } + } } void VoxelSystem::applyScaleAndBindProgram(bool texture) { @@ -1485,7 +1485,7 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(OctreeElement* element, void _nodeCount++; VoxelTreeElement* voxel = (VoxelTreeElement*)element; voxel->setBufferIndex(GLBUFFER_INDEX_UNKNOWN); - voxel->setPrimitiveIndex(0); + voxel->setPrimitiveIndex(0); return true; } @@ -1503,72 +1503,72 @@ bool VoxelSystem::inspectForInteriorOcclusionsOperation(OctreeElement* element, _nodeCount++; VoxelTreeElement* voxel = (VoxelTreeElement*)element; - // Nothing to do at the leaf level - if (voxel->isLeaf()) { - return false; - } + // Nothing to do at the leaf level + if (voxel->isLeaf()) { + return false; + } - // Bit mask of occluded shared faces indexed by child - unsigned char occludedSharedFace[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + // Bit mask of occluded shared faces indexed by child + unsigned char occludedSharedFace[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - // Traverse all pair combinations of children - for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { + // Traverse all pair combinations of children + for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { - VoxelTreeElement* childA = voxel->getChildAtIndex(i); - if (childA) { + VoxelTreeElement* childA = voxel->getChildAtIndex(i); + if (childA) { - // Get the child A's occluding faces, for a leaf that will be - // all six voxel faces, and for a non leaf, that will be - // all faces which are completely covered by four child octants. - unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); + // Get the child A's occluding faces, for a leaf that will be + // all six voxel faces, and for a non leaf, that will be + // all faces which are completely covered by four child octants. + unsigned char exteriorOcclusionsA = childA->getExteriorOcclusions(); - if (exteriorOcclusionsA == OctreeElement::HalfSpace::None) { - // There is nothing to be done with this child, next... - continue; - } + if (exteriorOcclusionsA == OctreeElement::HalfSpace::None) { + // There is nothing to be done with this child, next... + continue; + } - for (int j = i; --j >= 0; ) { + for (int j = i; --j >= 0; ) { - VoxelTreeElement* childB = voxel->getChildAtIndex(j); - if (childB) { + VoxelTreeElement* childB = voxel->getChildAtIndex(j); + if (childB) { - // Get child B's occluding faces - unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); + // Get child B's occluding faces + unsigned char exteriorOcclusionsB = childB->getExteriorOcclusions(); - if (exteriorOcclusionsB == OctreeElement::HalfSpace::None) { - // There is nothing to be done with this child, next... - continue; - } + if (exteriorOcclusionsB == OctreeElement::HalfSpace::None) { + // There is nothing to be done with this child, next... + continue; + } - // Determine the shared halfspace partition between siblings A and B, - // i.e., near/far, left/right, or top/bottom - unsigned char partition = _sOctantIndexToSharedBitMask[i][j] & - exteriorOcclusionsA & exteriorOcclusionsB; + // Determine the shared halfspace partition between siblings A and B, + // i.e., near/far, left/right, or top/bottom + unsigned char partition = _sOctantIndexToSharedBitMask[i][j] & + exteriorOcclusionsA & exteriorOcclusionsB; - // Determine which face of each sibling is occluded. - // Note the intentionally crossed indicies. It is necessary because - // the _sOctantIndexToBitMask is a partition occupancy mask. For - // example, if the near-left-top (NLT) and near-left-bottom (NLB) child voxels - // exist, the shared partition is top-bottom (TB), and thus the occluded - // shared face of the NLT voxel is its bottom face. - occludedSharedFace[i] |= (partition & _sOctantIndexToBitMask[j]); - occludedSharedFace[j] |= (partition & _sOctantIndexToBitMask[i]); - } - } - // Combine this voxel's interior excluded shared face only to those children which are coincident - // with the excluded face. - occludedSharedFace[i] |= (voxel->getInteriorOcclusions() & _sOctantIndexToBitMask[i]); + // Determine which face of each sibling is occluded. + // Note the intentionally crossed indicies. It is necessary because + // the _sOctantIndexToBitMask is a partition occupancy mask. For + // example, if the near-left-top (NLT) and near-left-bottom (NLB) child voxels + // exist, the shared partition is top-bottom (TB), and thus the occluded + // shared face of the NLT voxel is its bottom face. + occludedSharedFace[i] |= (partition & _sOctantIndexToBitMask[j]); + occludedSharedFace[j] |= (partition & _sOctantIndexToBitMask[i]); + } + } + // Combine this voxel's interior excluded shared face only to those children which are coincident + // with the excluded face. + occludedSharedFace[i] |= (voxel->getInteriorOcclusions() & _sOctantIndexToBitMask[i]); - // Inform the child - childA->setInteriorOcclusions(occludedSharedFace[i]); - if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); + // Inform the child + childA->setInteriorOcclusions(occludedSharedFace[i]); + if (occludedSharedFace[i] != OctreeElement::HalfSpace::None) { + //const glm::vec3& v = voxel->getCorner(); + //float s = voxel->getScale(); - //qDebug("Child %d of voxel at %f %f %f size: %f has %02x occlusions", i, v.x, v.y, v.z, s, occludedSharedFace[i]); - } - } - } + //qDebug("Child %d of voxel at %f %f %f size: %f has %02x occlusions", i, v.x, v.y, v.z, s, occludedSharedFace[i]); + } + } + } return true; } @@ -1576,71 +1576,71 @@ bool VoxelSystem::inspectForExteriorOcclusionsOperation(OctreeElement* element, _nodeCount++; VoxelTreeElement* voxel = (VoxelTreeElement*)element; - // Nothing to do at the leaf level - if (voxel->isLeaf()) { - return false; - } + // Nothing to do at the leaf level + if (voxel->isLeaf()) { + return false; + } - // Count of exterior occluding faces of this voxel element indexed - // by half space partition - unsigned int exteriorOcclusionsCt[6] = { 0, 0, 0, 0, 0, 0 }; + // Count of exterior occluding faces of this voxel element indexed + // by half space partition + unsigned int exteriorOcclusionsCt[6] = { 0, 0, 0, 0, 0, 0 }; - // Traverse all children - for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { + // Traverse all children + for (int i = NUMBER_OF_CHILDREN; --i >= 0; ) { - VoxelTreeElement* child = voxel->getChildAtIndex(i); - if (child) { - // Get the child's occluding faces, for a leaf, that will be - // all six voxel faces, and for a non leaf, that will be - // all faces which are completely covered by four child octants. - unsigned char exteriorOcclusionsOfChild = child->getExteriorOcclusions(); - exteriorOcclusionsOfChild &= _sOctantIndexToBitMask[i]; + VoxelTreeElement* child = voxel->getChildAtIndex(i); + if (child) { + // Get the child's occluding faces, for a leaf, that will be + // all six voxel faces, and for a non leaf, that will be + // all faces which are completely covered by four child octants. + unsigned char exteriorOcclusionsOfChild = child->getExteriorOcclusions(); + exteriorOcclusionsOfChild &= _sOctantIndexToBitMask[i]; - for (int j = 6; --j >= 0; ) { + for (int j = 6; --j >= 0; ) { - // Determine if the halfspace partition indexed by 1 << j is - // present in the exterior occlusions of the child. - unsigned char partition = exteriorOcclusionsOfChild & (1 << j); + // Determine if the halfspace partition indexed by 1 << j is + // present in the exterior occlusions of the child. + unsigned char partition = exteriorOcclusionsOfChild & (1 << j); - if (partition) { - exteriorOcclusionsCt[j]++; - } - } - } - } - { - // Derive the exterior occlusions of the voxel elements from the exclusions - // of its children - unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; - for (int i = 6; --i >= 0; ) { - if (exteriorOcclusionsCt[i] == 4) { + if (partition) { + exteriorOcclusionsCt[j]++; + } + } + } + } + { + // Derive the exterior occlusions of the voxel elements from the exclusions + // of its children + unsigned char exteriorOcclusions = OctreeElement::HalfSpace::None; + for (int i = 6; --i >= 0; ) { + if (exteriorOcclusionsCt[i] == _sNumOctantsPerHemiVoxel) { - // Exactly four octants qualify for full exterior occlusion - exteriorOcclusions |= (1 << i); - } - } + // Exactly four octants qualify for full exterior occlusion + exteriorOcclusions |= (1 << i); + } + } - // Inform the voxel element - voxel->setExteriorOcclusions(exteriorOcclusions); + // Inform the voxel element + voxel->setExteriorOcclusions(exteriorOcclusions); - if (exteriorOcclusions == OctreeElement::HalfSpace::All) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); + if (exteriorOcclusions == OctreeElement::HalfSpace::All) { + //const glm::vec3& v = voxel->getCorner(); + //float s = voxel->getScale(); - //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); + //qDebug("Completely occupied voxel at %f %f %f size: %f", v.x, v.y, v.z, s); - // TODO: All of the exterior faces of this voxel element are - // occluders, which means that this element is completely - // occupied. Hence, the subtree from this node could be - // pruned and replaced by a leaf voxel, if the visible - // properties of the children are the same - } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { - //const glm::vec3& v = voxel->getCorner(); - //float s = voxel->getScale(); + // TODO: All of the exterior faces of this voxel element are + // occluders, which means that this element is completely + // occupied. Hence, the subtree from this node could be + // pruned and replaced by a leaf voxel, if the visible + // properties of the children are the same + } else if (exteriorOcclusions != OctreeElement::HalfSpace::None) { + //const glm::vec3& v = voxel->getCorner(); + //float s = voxel->getScale(); - //qDebug("Partially occupied voxel at %f %f %f size: %f with %02x", v.x, v.y, v.z, s, exteriorOcclusions); - } - } + //qDebug("Partially occupied voxel at %f %f %f size: %f with %02x", v.x, v.y, v.z, s, exteriorOcclusions); + } + } return true; } @@ -1648,55 +1648,55 @@ bool VoxelSystem::clearOcclusionsOperation(OctreeElement* element, void* extraDa _nodeCount++; VoxelTreeElement* voxel = (VoxelTreeElement*)element; - bool rc; - if (voxel->isLeaf()) { + bool rc; + if (voxel->isLeaf()) { - // By definition the the exterior faces of a leaf voxel are - // always occluders. - voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); + // By definition the the exterior faces of a leaf voxel are + // always occluders. + voxel->setExteriorOcclusions(OctreeElement::HalfSpace::All); - // And the sibling occluders - voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); - rc = false; - } else { - voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); - voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); - rc = true; - } + // And the sibling occluders + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); + rc = false; + } else { + voxel->setExteriorOcclusions(OctreeElement::HalfSpace::None); + voxel->setInteriorOcclusions(OctreeElement::HalfSpace::None); + rc = true; + } - return rc; + return rc; } void VoxelSystem::cullSharedFaces() { _nodeCount = 0; if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { - _useVoxelShader = false; - _usePrimitiveRenderer = true; + _useVoxelShader = false; + _usePrimitiveRenderer = true; _renderer->release(); - clearAllNodesBufferIndex(); - lockTree(); - _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); - _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); - unlockTree(); + clearAllNodesBufferIndex(); + lockTree(); + _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); + _tree->recurseTreeWithPostOperation(inspectForExteriorOcclusionsOperation); + unlockTree(); - _nodeCount = 0; - lockTree(); - _tree->recurseTreeWithOperation(inspectForInteriorOcclusionsOperation); - unlockTree(); + _nodeCount = 0; + lockTree(); + _tree->recurseTreeWithOperation(inspectForInteriorOcclusionsOperation); + unlockTree(); qDebug("culling shared faces in %d nodes", _nodeCount); } else { - _usePrimitiveRenderer = false; + _usePrimitiveRenderer = false; _renderer->release(); - clearAllNodesBufferIndex(); - lockTree(); - _tree->recurseTreeWithOperation(clearOcclusionsOperation); - unlockTree(); + clearAllNodesBufferIndex(); + lockTree(); + _tree->recurseTreeWithOperation(clearOcclusionsOperation); + unlockTree(); qDebug("unculling shared faces in %d nodes", _nodeCount); } - _writeRenderFullVBO = true; + _writeRenderFullVBO = true; _tree->setDirtyBit(); setupNewVoxelsForDrawing(); @@ -1705,9 +1705,9 @@ void VoxelSystem::cullSharedFaces() { void VoxelSystem::showCulledSharedFaces() { if (Menu::getInstance()->isOptionChecked(MenuOption::ShowCulledSharedFaces)) { - _showCulledSharedFaces = true; + _showCulledSharedFaces = true; } else { - _showCulledSharedFaces = false; + _showCulledSharedFaces = false; } if (Menu::getInstance()->isOptionChecked(MenuOption::CullSharedFaces)) { cullSharedFaces(); @@ -2337,12 +2337,12 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat // These are both needed to force redraw... voxel->setDirtyBit(); voxel->markWithChangedTime(); - // and this? - { + // and this? + { VoxelSystem* thisVoxelSystem = args->thisVoxelSystem; thisVoxelSystem->_voxelsUpdated += thisVoxelSystem->updateNodeInArrays(voxel, true, true); thisVoxelSystem->setupNewVoxelsForDrawingSingleNode(); - } + } args->nodesShown++; } @@ -2522,8 +2522,8 @@ public: nodesInVBOOverExpectedMax(0), duplicateVBOIndex(0), leafNodes(0), - culledLeafNodes(0), - nodesInPrimitiveRenderer(0) + culledLeafNodes(0), + nodesInPrimitiveRenderer(0) { hasIndexFound = new bool[maxVoxels]; memset(hasIndexFound, false, maxVoxels * sizeof(bool)); @@ -2542,8 +2542,8 @@ public: unsigned long nodesInVBOOverExpectedMax; unsigned long duplicateVBOIndex; unsigned long leafNodes; - unsigned long culledLeafNodes; ///< Number of completely culled nodes because of face sharing - unsigned long nodesInPrimitiveRenderer; + unsigned long culledLeafNodes; ///< Number of completely culled nodes because of face sharing + unsigned long nodesInPrimitiveRenderer; unsigned long expectedMax; @@ -2558,9 +2558,9 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v if (voxel->isLeaf()) { args->leafNodes++; - if (voxel->getInteriorOcclusions() == OctreeElement::HalfSpace::All) { - args->culledLeafNodes++; - } + if (voxel->getInteriorOcclusions() == OctreeElement::HalfSpace::All) { + args->culledLeafNodes++; + } } if (voxel->isColored()) { @@ -2575,16 +2575,16 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v args->dirtyNodes++; } - unsigned long nodeIndex = 0; - if (voxel->isKnownBufferIndex()) { - args->nodesInVBO++; - nodeIndex = voxel->getBufferIndex(); - } + unsigned long nodeIndex = 0; + if (voxel->isKnownBufferIndex()) { + args->nodesInVBO++; + nodeIndex = voxel->getBufferIndex(); + } - if (voxel->getPrimitiveIndex()) { - args->nodesInPrimitiveRenderer++; - nodeIndex = voxel->getPrimitiveIndex(); - } + if (voxel->getPrimitiveIndex()) { + args->nodesInPrimitiveRenderer++; + nodeIndex = voxel->getPrimitiveIndex(); + } if (voxel->isKnownBufferIndex() || (voxel->getPrimitiveIndex() != 0)) { @@ -2593,7 +2593,7 @@ bool VoxelSystem::collectStatsForTreesAndVBOsOperation(OctreeElement* element, v qDebug("node In VBO... [%f,%f,%f] %f ... index=%ld, isDirty=%s, shouldRender=%s, culledFaces=0x%02x \n", voxel->getCorner().x, voxel->getCorner().y, voxel->getCorner().z, voxel->getScale(), nodeIndex, debug::valueOf(voxel->isDirty()), debug::valueOf(voxel->getShouldRender()), - voxel->getInteriorOcclusions()); + voxel->getInteriorOcclusions()); } if (args->hasIndexFound[nodeIndex]) { @@ -2622,14 +2622,14 @@ void VoxelSystem::collectStatsForTreesAndVBOs() { glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; glBufferIndex maxDirty = 0; - if (!_usePrimitiveRenderer) { - for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { - if (_writeVoxelDirtyArray[i]) { - minDirty = std::min(minDirty,i); - maxDirty = std::max(maxDirty,i); - } - } - } + if (!_usePrimitiveRenderer) { + for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { + if (_writeVoxelDirtyArray[i]) { + minDirty = std::min(minDirty,i); + maxDirty = std::max(maxDirty,i); + } + } + } collectStatsForTreesAndVBOsArgs args(_maxVoxels); args.expectedMax = _voxelsInWriteArrays; @@ -3103,98 +3103,98 @@ void VoxelSystem::beginLoadingLocalVoxelCache() { // value corresponds to the voxel's octal code derived in "pointToVoxel" in SharedUtil.cpp, which, BTW, does *not* // correspond to the "ChildIndex" enum value in OctreeElement.h unsigned char VoxelSystem::_sOctantIndexToBitMask[8] = { - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, - OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Near, + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Left | OctreeElement::HalfSpace::Far, + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Near, + OctreeElement::HalfSpace::Top | OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Far, }; // Two dimensional array map indexed by octant row and column. The mask value // indicates the two faces shared by the octants unsigned char VoxelSystem::_sOctantIndexToSharedBitMask[8][8] = { - { // Index 0: Bottom-Left-Near - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 1: Bottom-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Far - 0, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 2: Top-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Far - 0, // Bottom-Right-Near - 0, // Bottom-Right-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 3: Top-Left-Far - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Near - 0, // Top-Left-Far - 0, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Far - }, - { // Index 4: Bottom-Right-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - 0, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Near - 0, // Top-Right-Far - }, - { // Index 5: Bottom-Right-Far - 0, // Bottom-Left-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Far - 0, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Far - }, - { // Index 6: Top-Right-Near - 0, // Bottom-Left-Near - 0, // Bottom-Left-Far - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Near - 0, // Top-Left-Far - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Near - 0, // Bottom-Right-Far - 0, // Top-Right-Near - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Far - }, - { // Index 7: Top-Right-Far - 0, // Bottom-Left-Near - 0, // Bottom-Left-Far - 0, // Top-Left-Near - OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Far - 0, // Bottom-Right-Near - OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Far - OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Near - 0, // Top-Right-Far - }, + { // Index 0: Bottom-Left-Near + 0, // Bottom-Left-Near + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Far + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Near + 0, // Top-Left-Far + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Near + 0, // Bottom-Right-Far + 0, // Top-Right-Near + 0, // Top-Right-Far + }, + { // Index 1: Bottom-Left-Far + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Left-Near + 0, // Bottom-Left-Far + 0, // Top-Left-Near + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Left-Far + 0, // Bottom-Right-Near + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Right-Far + 0, // Top-Right-Near + 0, // Top-Right-Far + }, + { // Index 2: Top-Left-Near + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Near + 0, // Bottom-Left-Far + 0, // Top-Left-Near + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Far + 0, // Bottom-Right-Near + 0, // Bottom-Right-Far + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Near + 0, // Top-Right-Far + }, + { // Index 3: Top-Left-Far + 0, // Bottom-Left-Near + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Left-Far + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Left-Near + 0, // Top-Left-Far + 0, // Bottom-Right-Near + 0, // Bottom-Right-Far + 0, // Top-Right-Near + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Right-Far + }, + { // Index 4: Bottom-Right-Near + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Near + 0, // Bottom-Left-Far + 0, // Top-Left-Near + 0, // Top-Left-Far + 0, // Bottom-Right-Near + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Far + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Near + 0, // Top-Right-Far + }, + { // Index 5: Bottom-Right-Far + 0, // Bottom-Left-Near + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Bottom-Left-Far + 0, // Top-Left-Near + 0, // Top-Left-Far + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Bottom-Right-Near + 0, // Bottom-Right-Far + 0, // Top-Right-Near + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Top-Right-Far + }, + { // Index 6: Top-Right-Near + 0, // Bottom-Left-Near + 0, // Bottom-Left-Far + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Near + 0, // Top-Left-Far + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Near + 0, // Bottom-Right-Far + 0, // Top-Right-Near + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Far + }, + { // Index 7: Top-Right-Far + 0, // Bottom-Left-Near + 0, // Bottom-Left-Far + 0, // Top-Left-Near + OctreeElement::HalfSpace::Right | OctreeElement::HalfSpace::Left, // Top-Left-Far + 0, // Bottom-Right-Near + OctreeElement::HalfSpace::Bottom | OctreeElement::HalfSpace::Top, // Bottom-Right-Far + OctreeElement::HalfSpace::Near | OctreeElement::HalfSpace::Far, // Top-Right-Near + 0, // Top-Right-Far + }, }; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index e9f3a0ca8e..bd0dbdb71f 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -201,7 +201,7 @@ private: static bool inspectForExteriorOcclusionsOperation(OctreeElement* element, void* extraData); static bool inspectForInteriorOcclusionsOperation(OctreeElement* element, void* extraData); static bool clearOcclusionsOperation(OctreeElement* element, void* extraData); - static bool hideOutOfViewOperation(OctreeElement* element, void* extraData); + static bool hideOutOfViewOperation(OctreeElement* element, void* extraData); static bool hideAllSubTreeOperation(OctreeElement* element, void* extraData); static bool showAllSubTreeOperation(OctreeElement* element, void* extraData); static bool showAllLocalVoxelsOperation(OctreeElement* element, void* extraData); @@ -317,11 +317,12 @@ private: void unlockTree(); bool _showCulledSharedFaces; ///< Flag visibility of culled faces - bool _usePrimitiveRenderer; ///< Flag primitive renderer for use - PrimitiveRenderer* _renderer; ///< Voxel renderer + bool _usePrimitiveRenderer; ///< Flag primitive renderer for use + PrimitiveRenderer* _renderer; ///< Voxel renderer - static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask - static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask + static const int _sNumOctantsPerHemiVoxel = 4; + static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask + static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask };