From fd5f378e1c81491c46e748beb214a6cb64d1ae08 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 28 Mar 2014 11:16:55 -0700 Subject: [PATCH] Better color/normal merging. --- .../metavoxels/src/AttributeRegistry.cpp | 39 +++++++++---------- libraries/metavoxels/src/AttributeRegistry.h | 7 ---- libraries/metavoxels/src/MetavoxelData.cpp | 6 +-- libraries/metavoxels/src/MetavoxelData.h | 1 + 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index c61a8e7560..c41420d7c6 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -30,9 +30,9 @@ AttributeRegistry::AttributeRegistry() : SharedObjectPointer(new DefaultMetavoxelGuide())))), _spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))), _colorAttribute(registerAttribute(new QRgbAttribute("color"))), - _normalAttribute(registerAttribute(new PackedNormalAttribute("normal", qRgb(0, 127, 0)))), + _normalAttribute(registerAttribute(new PackedNormalAttribute("normal"))), _spannerColorAttribute(registerAttribute(new QRgbAttribute("spannerColor"))), - _spannerNormalAttribute(registerAttribute(new PackedNormalAttribute("spannerNormal", qRgb(0, 127, 0)))) { + _spannerNormalAttribute(registerAttribute(new PackedNormalAttribute("spannerNormal"))) { // our baseline LOD threshold is for voxels; spanners are a different story const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 4.0f; @@ -94,10 +94,6 @@ bool AttributeValue::isDefault() const { return !_attribute || _attribute->equal(_value, _attribute->getDefaultValue()); } -AttributeValue AttributeValue::split() const { - return _attribute ? _attribute->split(*this) : AttributeValue(); -} - bool AttributeValue::operator==(const AttributeValue& other) const { return _attribute == other._attribute && (!_attribute || _attribute->equal(_value, other._value)); } @@ -199,24 +195,29 @@ void Attribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelSt QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) : InlineAttribute(name, defaultValue) { } - + bool QRgbAttribute::merge(void*& parent, void* children[]) const { QRgb firstValue = decodeInline(children[0]); - int totalRed = qRed(firstValue); - int totalGreen = qGreen(firstValue); - int totalBlue = qBlue(firstValue); int totalAlpha = qAlpha(firstValue); + int totalRed = qRed(firstValue) * totalAlpha; + int totalGreen = qGreen(firstValue) * totalAlpha; + int totalBlue = qBlue(firstValue) * totalAlpha; bool allChildrenEqual = true; for (int i = 1; i < Attribute::MERGE_COUNT; i++) { QRgb value = decodeInline(children[i]); - totalRed += qRed(value); - totalGreen += qGreen(value); - totalBlue += qBlue(value); - totalAlpha += qAlpha(value); + int alpha = qAlpha(value); + totalRed += qRed(value) * alpha; + totalGreen += qGreen(value) * alpha; + totalBlue += qBlue(value) * alpha; + totalAlpha += alpha; allChildrenEqual &= (firstValue == value); } - parent = encodeInline(qRgba(totalRed / MERGE_COUNT, totalGreen / MERGE_COUNT, - totalBlue / MERGE_COUNT, totalAlpha / MERGE_COUNT)); + if (totalAlpha == 0) { + parent = encodeInline(QRgb()); + } else { + parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha, + totalBlue / totalAlpha, totalAlpha / MERGE_COUNT)); + } return allChildrenEqual; } @@ -260,7 +261,7 @@ bool PackedNormalAttribute::merge(void*& parent, void* children[]) const { bool allChildrenEqual = true; for (int i = 1; i < Attribute::MERGE_COUNT; i++) { QRgb value = decodeInline(children[i]); - total += unpackNormal(value); + total += unpackNormal(value) * (float)qAlpha(value); allChildrenEqual &= (firstValue == value); } parent = encodeInline(packNormal(glm::normalize(total))); @@ -316,10 +317,6 @@ bool SharedObjectAttribute::merge(void*& parent, void* children[]) const { return true; } -AttributeValue SharedObjectSetAttribute::split(const AttributeValue& parent) const { - return AttributeValue(); -} - void* SharedObjectAttribute::createFromVariant(const QVariant& value) const { return create(encodeInline(value.value())); } diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index e0a1c0b3f0..c7d5c057ac 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -121,8 +121,6 @@ public: bool isDefault() const; - AttributeValue split() const; - bool operator==(const AttributeValue& other) const; bool operator==(void* other) const; @@ -208,9 +206,6 @@ public: /// \return whether or not the children and parent values are all equal virtual bool merge(void*& parent, void* children[]) const = 0; - /// Returns the attribute value to pass to children below leaves (either the parent, or the default, or a null value). - virtual AttributeValue split(const AttributeValue& parent) const { return parent; } - /// Mixes the first and the second, returning a new value with the result. virtual void* mix(void* first, void* second, float alpha) const = 0; @@ -346,8 +341,6 @@ public: virtual bool merge(void*& parent, void* children[]) const; - virtual AttributeValue split(const AttributeValue& parent) const; - virtual QWidget* createEditor(QWidget* parent = NULL) const; private: diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index c561cbae09..9f46781363 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -953,8 +953,8 @@ 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.visitor.getLOD().threshold; - visitation.info.isLeaf = (visitation.info.size < lodBase * visitation.visitor.getMinimumLODThresholdMultiplier()) || - visitation.allInputNodesLeaves(); + visitation.info.isLODLeaf = (visitation.info.size < lodBase * visitation.visitor.getMinimumLODThresholdMultiplier()); + visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves(); int encodedOrder = visitation.visitor.visit(visitation.info); if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) { return false; @@ -991,7 +991,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { MetavoxelNode* child = (node && (visitation.info.size >= lodBase * parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? - child->getAttributeValue(parentValue.getAttribute()) : parentValue.split(); + child->getAttributeValue(parentValue.getAttribute()) : parentValue; } for (int j = 0; j < visitation.outputNodes.size(); j++) { MetavoxelNode* node = visitation.outputNodes.at(j); diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 3e7c6f1b15..970d529117 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -189,6 +189,7 @@ public: float size; ///< the size of the voxel in all dimensions QVector inputValues; QVector outputValues; + bool isLODLeaf; bool isLeaf; Box getBounds() const { return Box(minimum, minimum + glm::vec3(size, size, size)); }