From fd12c7a0d7a03ac63435a6a788bb9eba6e78ff21 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 30 Oct 2014 16:52:19 -0700 Subject: [PATCH] One more piece of the resolution puzzle. --- interface/src/MetavoxelSystem.cpp | 187 +++++++++------------ libraries/metavoxels/src/MetavoxelData.cpp | 31 ++-- libraries/metavoxels/src/MetavoxelData.h | 2 + 3 files changed, 104 insertions(+), 116 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index d89725e126..4c0acc553a 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1963,20 +1963,15 @@ private: void addRegion(const Box& unextended, const Box& extended); - int _heightSize; - int _heightDepth; + class DepthInfo { + public: + float minimumColorIncrement; + float minimumMaterialIncrement; + + DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { } + }; - int _inheritedColorSize; - int _inheritedColorDepth; - - int _containedColorSize; - int _containedColorDepth; - - int _inheritedMaterialSize; - int _inheritedMaterialDepth; - - int _containedMaterialSize; - int _containedMaterialDepth; + QVector _depthInfo; QVector _intersections; HeightfieldFetchVisitor _fetchVisitor; @@ -1989,118 +1984,100 @@ HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector() << Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod), regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)), - _heightDepth(-1), - _inheritedColorDepth(-1), - _containedColorDepth(-1), - _inheritedMaterialDepth(-1), - _containedMaterialDepth(-1), _fetchVisitor(lod, _intersections) { } -static int signedLeftShift(int value, int shift) { - return (shift > 0) ? value << shift : value >> (-shift); -} - int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { - HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue(); - int order = DEFAULT_ORDER; - if (height) { - _heightSize = glm::sqrt((float)height->getContents().size()); - _heightDepth = _depth; - order |= ALL_NODES_REST; - } + DepthInfo depthInfo; HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue(); if (color) { - int colorSize = glm::sqrt((float)(color->getContents().size() / DataBlock::COLOR_BYTES)); - if (_heightDepth == -1) { - _inheritedColorSize = colorSize; - _inheritedColorDepth = _depth; - - } else if (_containedColorDepth == -1 || - colorSize > signedLeftShift(_containedColorSize, _containedColorDepth - _depth)) { - _containedColorSize = colorSize; - _containedColorDepth = _depth; - } + int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES); + depthInfo.minimumColorIncrement = info.size / colorSize; } HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue(); if (material) { - int materialSize = glm::sqrt((float)material->getContents().size()); - if (_heightDepth == -1) { - _inheritedMaterialSize = materialSize; - _inheritedMaterialDepth = _depth; - - } else if (_containedMaterialDepth == -1 || - materialSize > signedLeftShift(_containedMaterialSize, _containedMaterialDepth - _depth)) { - _containedMaterialSize = materialSize; - _containedMaterialDepth = _depth; - } + int materialSize = glm::sqrt((float)material->getContents().size()); + depthInfo.minimumMaterialIncrement = info.size / materialSize; + } + if (_depth < _depthInfo.size()) { + _depthInfo[_depth] = depthInfo; + } else { + _depthInfo.append(depthInfo); } if (!info.isLeaf) { - return order; + return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER; } postVisit(info); return STOP_RECURSION; } bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) { - HeightfieldBuffer* buffer = NULL; - if (_depth == _heightDepth) { - int extendedHeightSize = _heightSize + HeightfieldBuffer::HEIGHT_EXTENSION; - int heightContentsSize = extendedHeightSize * extendedHeightSize; - - int extendedColorSize = qMax(_inheritedColorDepth == -1 ? 0 : - signedLeftShift(_inheritedColorSize, _inheritedColorDepth - _depth) + HeightfieldBuffer::SHARED_EDGE, - _containedColorDepth == -1 ? 0 : - signedLeftShift(_containedColorSize, _containedColorDepth - _depth) + HeightfieldBuffer::SHARED_EDGE); - int colorContentsSize = extendedColorSize * extendedColorSize * DataBlock::COLOR_BYTES; - - int extendedMaterialSize = qMax(_inheritedMaterialDepth == -1 ? 0 : - signedLeftShift(_inheritedMaterialSize, _inheritedMaterialDepth - _depth) + HeightfieldBuffer::SHARED_EDGE, - _containedMaterialDepth == -1 ? 0 : - signedLeftShift(_containedMaterialSize, _containedMaterialDepth - _depth) + HeightfieldBuffer::SHARED_EDGE); - int materialContentsSize = extendedMaterialSize * extendedMaterialSize; - - const HeightfieldBuffer* existingBuffer = static_cast( - info.inputValues.at(3).getInlineValue().data()); - Box bounds = info.getBounds(); - if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && - existingBuffer->getColor().size() == colorContentsSize && - existingBuffer->getMaterial().size() == materialContentsSize) { - // we already have a buffer of the correct resolution - addRegion(bounds, existingBuffer->getHeightBounds()); - buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(), - existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials()); - - } else { - // we must create a new buffer and update its borders - buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), - QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0)); - const Box& heightBounds = buffer->getHeightBounds(); - addRegion(bounds, heightBounds); + const DepthInfo& depthInfo = _depthInfo.at(_depth); + if (_depth > 0) { + DepthInfo& parentDepthInfo = _depthInfo[_depth - 1]; + parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement); + parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement, + depthInfo.minimumMaterialIncrement); + } + if (_visitations.at(_depth).isInputLeaf(0)) { + HeightfieldBuffer* buffer = NULL; + HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue(); + if (height) { + int heightSize = glm::sqrt((float)height->getContents().size()); + int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION; + int heightContentsSize = extendedHeightSize * extendedHeightSize; + float minimumColorIncrement = depthInfo.minimumColorIncrement; + float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement; + for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) { + const DepthInfo& ancestorDepthInfo = _depthInfo.at(i); + minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement); + minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement); + } + int colorContentsSize = 0; + if (minimumColorIncrement != FLT_MAX) { + int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE; + colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES; + } + int materialContentsSize = 0; + if (minimumMaterialIncrement != FLT_MAX) { + int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE; + materialContentsSize = materialSize * materialSize; + } + const HeightfieldBuffer* existingBuffer = static_cast( + info.inputValues.at(3).getInlineValue().data()); + Box bounds = info.getBounds(); + if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && + existingBuffer->getColor().size() == colorContentsSize && + existingBuffer->getMaterial().size() == materialContentsSize) { + // we already have a buffer of the correct resolution + addRegion(bounds, existingBuffer->getHeightBounds()); + buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(), + existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials()); - _intersections.clear(); - _intersections.append(Box(heightBounds.minimum, - glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z))); - _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z), - glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z))); - _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z), - heightBounds.maximum)); - _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z), - glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z))); - - _fetchVisitor.init(buffer); - _data->guide(_fetchVisitor); + } else { + // we must create a new buffer and update its borders + buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0), + QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0)); + const Box& heightBounds = buffer->getHeightBounds(); + addRegion(bounds, heightBounds); + + _intersections.clear(); + _intersections.append(Box(heightBounds.minimum, + glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z))); + _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z), + glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z))); + _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z), + heightBounds.maximum)); + _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z), + glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z))); + + _fetchVisitor.init(buffer); + _data->guide(_fetchVisitor); + } } - _heightDepth = _containedColorDepth = _containedMaterialDepth = -1; + BufferDataPointer pointer(buffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); } - if (_depth == _inheritedColorDepth) { - _inheritedColorDepth = -1; - } - if (_depth == _inheritedMaterialDepth) { - _inheritedMaterialDepth = -1; - } - BufferDataPointer pointer(buffer); - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); return true; } diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 2f43f8f4ae..b79903ba8a 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -1509,7 +1509,7 @@ bool MetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { DefaultMetavoxelGuide::DefaultMetavoxelGuide() { } -static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, float lodBase, int encodedOrder) { +static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, int encodedOrder) { MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation(); nextVisitation.info.size = visitation.info.size * 0.5f; for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { @@ -1519,14 +1519,14 @@ static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, float for (int j = 0; j < visitation.inputNodes.size(); j++) { MetavoxelNode* node = visitation.inputNodes.at(j); const AttributeValue& parentValue = visitation.info.inputValues.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= lodBase * + MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? child->getAttributeValue(parentValue.getAttribute()) : parentValue.getAttribute()->inherit(parentValue); } for (int j = 0; j < visitation.outputNodes.size(); j++) { MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= lodBase * + MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * visitation.visitor->getOutputs().at(j)->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; nextVisitation.outputNodes[j] = child; } @@ -1604,9 +1604,10 @@ static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, float bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { // save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute - float lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) * + visitation.info.lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) * visitation.visitor->getLOD().threshold; - visitation.info.isLODLeaf = (visitation.info.size < lodBase * visitation.visitor->getMinimumLODThresholdMultiplier()); + visitation.info.isLODLeaf = (visitation.info.size < visitation.info.lodBase * + visitation.visitor->getMinimumLODThresholdMultiplier()); visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves(); int encodedOrder = visitation.visitor->visit(visitation.info); if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) { @@ -1628,14 +1629,15 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) { return true; } - return (encodedOrder == MetavoxelVisitor::STOP_RECURSION || defaultGuideToChildren(visitation, lodBase, encodedOrder)); + return (encodedOrder == MetavoxelVisitor::STOP_RECURSION || defaultGuideToChildren(visitation, encodedOrder)); } bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { // save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute - float lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) * + visitation.info.lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) * visitation.visitor->getLOD().threshold; - visitation.info.isLODLeaf = (visitation.info.size < lodBase * visitation.visitor->getMinimumLODThresholdMultiplier()); + visitation.info.isLODLeaf = (visitation.info.size < visitation.info.lodBase * + visitation.visitor->getMinimumLODThresholdMultiplier()); visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves(); int encodedOrder = visitation.visitor->visit(visitation.info); if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) { @@ -1658,7 +1660,7 @@ bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { return true; } if (encodedOrder & MetavoxelVisitor::ALL_NODES_REST) { - return defaultGuideToChildren(visitation, lodBase, encodedOrder); + return defaultGuideToChildren(visitation, encodedOrder); } bool onlyVisitDifferent = !(encodedOrder & MetavoxelVisitor::ALL_NODES); MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation(); @@ -1672,7 +1674,8 @@ bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { for (int j = 0; j < visitation.inputNodes.size(); j++) { MetavoxelNode* node = visitation.inputNodes.at(j); const AttributeValue& parentValue = visitation.info.inputValues.at(j); - bool expand = (visitation.info.size >= lodBase * parentValue.getAttribute()->getLODThresholdMultiplier()); + bool expand = (visitation.info.size >= visitation.info.lodBase * + parentValue.getAttribute()->getLODThresholdMultiplier()); MetavoxelNode* child = (node && expand) ? node->getChild(index) : NULL; nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? child->getAttributeValue(parentValue.getAttribute()) : parentValue.getAttribute()->inherit(parentValue); @@ -1686,7 +1689,7 @@ bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) { } for (int j = 0; j < visitation.outputNodes.size(); j++) { MetavoxelNode* node = visitation.outputNodes.at(j); - MetavoxelNode* child = (node && (visitation.info.size >= lodBase * + MetavoxelNode* child = (node && (visitation.info.size >= visitation.info.lodBase * visitation.visitor->getOutputs().at(j)->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; nextVisitation.outputNodes[j] = child; } @@ -1911,6 +1914,12 @@ MetavoxelVisitation::MetavoxelVisitation(MetavoxelVisitation* previous, MetavoxelVisitation::MetavoxelVisitation() { } +bool MetavoxelVisitation::isInputLeaf(int index) const { + MetavoxelNode* node = inputNodes.at(index); + return !node || node->isLeaf() || info.size < info.lodBase * + info.inputValues.at(index).getAttribute()->getLODThresholdMultiplier(); +} + bool MetavoxelVisitation::allInputNodesLeaves() const { foreach (MetavoxelNode* node, inputNodes) { if (node && !node->isLeaf()) { diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 8a240b9d7b..3efb0fc8f2 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -278,6 +278,7 @@ public: float size; ///< the size of the voxel in all dimensions QVector inputValues; QVector outputValues; + float lodBase; bool isLODLeaf; bool isLeaf; @@ -537,6 +538,7 @@ public: MetavoxelVisitation(MetavoxelVisitation* previous, MetavoxelVisitor* visitor, int inputNodesSize, int outputNodesSize); MetavoxelVisitation(); + bool isInputLeaf(int index) const; bool allInputNodesLeaves() const; AttributeValue getInheritedOutputValue(int index) const; };