diff --git a/interface/src/renderer/MetavoxelSystem.cpp b/interface/src/renderer/MetavoxelSystem.cpp index 76ad824f65..d813ac1653 100644 --- a/interface/src/renderer/MetavoxelSystem.cpp +++ b/interface/src/renderer/MetavoxelSystem.cpp @@ -13,11 +13,13 @@ class DebugVisitor : public MetavoxelVisitor { public: - virtual bool visit(const QVector& attributeValues); + virtual bool visit(const MetavoxelInfo& info); }; -bool DebugVisitor::visit(const QVector& attributeValues) { - qDebug() << decodeInline(attributeValues.at(0).getValue()) << "\n"; +bool DebugVisitor::visit(const MetavoxelInfo& info) { + QRgb color = info.attributeValues.at(0).getInlineValue(); + qDebug("%g %g %g %g %d %d %d %d\n", info.minimum.x, info.minimum.y, info.minimum.z, info.size, + qRed(color), qGreen(color), qBlue(color), qAlpha(color)); return true; } @@ -27,20 +29,12 @@ void MetavoxelSystem::init() { p1 += 1; p1 += 2; - AttributePointer blerp = AttributeRegistry::getInstance()->getAttribute("blerp"); + AttributePointer diffuseColor = AttributeRegistry::getInstance()->getAttribute("diffuseColor"); - void* foo = encodeInline(5.0f); - _data.setAttributeValue(p1, AttributeValue(blerp, &foo)); - - //p1 += 0; - - MetavoxelPath p2; - - AttributeValue value = _data.getAttributeValue(p2, blerp); - - qDebug("fliggedy bloo %g\n", decodeInline(value.getValue())); + void* white = encodeInline(qRgba(0xFF, 0xFF, 0xFF, 0xFF)); + _data.setAttributeValue(p1, AttributeValue(diffuseColor, &white)); DebugVisitor visitor; - _data.visitVoxels(QVector() << blerp, visitor); + _data.visitVoxels(QVector() << diffuseColor, visitor); } diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index dcf5008500..7c2a98049e 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -11,7 +11,7 @@ AttributeRegistry AttributeRegistry::_instance; AttributeRegistry::AttributeRegistry() { - registerAttribute(AttributePointer(new InlineAttribute("blerp"))); + registerAttribute(AttributePointer(new QRgbAttribute("diffuseColor"))); } AttributePointer AttributeRegistry::registerAttribute(AttributePointer attribute) { @@ -75,3 +75,24 @@ Attribute::Attribute(const QString& name) : _name(name) { Attribute::~Attribute() { } +QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) : + InlineAttribute(name, defaultValue) { +} + +void* QRgbAttribute::createAveraged(void* values[]) const { + int totalRed = 0; + int totalGreen = 0; + int totalBlue = 0; + int totalAlpha = 0; + for (int i = 0; i < AVERAGE_COUNT; i++) { + QRgb value = decodeInline(values[i]); + totalRed += qRed(value); + totalGreen += qGreen(value); + totalBlue += qBlue(value); + totalAlpha += qAlpha(value); + } + const int SHIFT_FACTOR = 3; + return encodeInline(qRgba(totalRed / AVERAGE_COUNT, totalGreen / AVERAGE_COUNT, + totalBlue / AVERAGE_COUNT, totalAlpha / AVERAGE_COUNT)); +} + diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index 5ec3f2533b..f8eef1788d 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -9,6 +9,7 @@ #ifndef __interface__AttributeRegistry__ #define __interface__AttributeRegistry__ +#include #include #include #include @@ -43,6 +44,16 @@ private: QHash _attributes; }; +/// Converts a value to a void pointer. +template inline void* encodeInline(T value) { + return *(void**)&value; +} + +/// Extracts a value from a void pointer. +template inline T decodeInline(void* value) { + return *(T*)&value; +} + /// Pairs an attribute value with its type. class AttributeValue { public: @@ -56,6 +67,9 @@ public: AttributePointer getAttribute() const { return _attribute; } void* getValue() const { return _value; } + template void setInlineValue(T value) { _value = encodeInline(value); } + template T getInlineValue() const { return decodeInline(_value); } + void* copy() const; bool isDefault() const; @@ -73,6 +87,8 @@ private: class Attribute { public: + static const int AVERAGE_COUNT = 8; + Attribute(const QString& name); virtual ~Attribute(); @@ -95,14 +111,6 @@ private: QString _name; }; -template inline void* encodeInline(const T& value) { - return *(void**)const_cast(&value); -} - -template inline T decodeInline(void* value) { - return *(T*)&value; -} - /// A simple attribute class that stores its values inline. template class InlineAttribute : public Attribute { public: @@ -128,11 +136,20 @@ private: template inline void* InlineAttribute::createAveraged(void* values[]) const { T total = T(); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < AVERAGE_COUNT; i++) { total += decodeInline(values[i]); } - total /= 8; + total /= AVERAGE_COUNT; return encodeInline(total); } +/// Provides appropriate averaging for RGBA values. +class QRgbAttribute : public InlineAttribute { +public: + + QRgbAttribute(const QString& name, QRgb defaultValue = QRgb()); + + virtual void* createAveraged(void* values[]) const; +}; + #endif /* defined(__interface__AttributeRegistry__) */ diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index e75b51697c..c99364aaa9 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -19,45 +19,58 @@ class Visitation { public: MetavoxelVisitor& visitor; QVector nodes; - QVector attributeValues; + MetavoxelInfo info; void apply(); + +protected: + + bool allNodesLeaves() const; }; +const int X_MAXIMUM_FLAG = 1; +const int Y_MAXIMUM_FLAG = 2; +const int Z_MAXIMUM_FLAG = 4; + void Visitation::apply() { - Visitation nextVisitation = { visitor, QVector(nodes.size()), attributeValues }; - for (int i = 0; i < nodes.size(); i++) { - MetavoxelNode* node = nodes.at(i); - if (node) { - nextVisitation.attributeValues[i] = node->getAttributeValue(attributeValues[i].getAttribute()); - } - } - - if (!visitor.visit(nextVisitation.attributeValues)) { + if (!visitor.visit(info) || allNodesLeaves()) { return; } - + Visitation nextVisitation = { visitor, QVector(nodes.size()), + { glm::vec3(), info.size * 0.5f, QVector(nodes.size()) } }; for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) { - bool anyChildrenPresent = false; for (int j = 0; j < nodes.size(); j++) { MetavoxelNode* node = nodes.at(j); - if ((nextVisitation.nodes[j] = node ? node->getChild(i) : NULL)) { - anyChildrenPresent = true; - } + MetavoxelNode* child = node ? node->getChild(i) : NULL; + nextVisitation.info.attributeValues[j] = ((nextVisitation.nodes[j] = child)) ? + child->getAttributeValue(info.attributeValues[j].getAttribute()) : info.attributeValues[j]; } - if (anyChildrenPresent) { - nextVisitation.apply(); + nextVisitation.info.minimum = info.minimum + glm::vec3( + (i & X_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f, + (i & Y_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f, + (i & Z_MAXIMUM_FLAG) ? nextVisitation.info.size : 0.0f); + nextVisitation.apply(); + } +} + +bool Visitation::allNodesLeaves() const { + foreach (MetavoxelNode* node, nodes) { + if (node != NULL && !node->isLeaf()) { + return false; } } + return true; } void MetavoxelData::visitVoxels(const QVector& attributes, MetavoxelVisitor& visitor) { // start with the root values/defaults + const float TOP_LEVEL_SIZE = 1.0f; Visitation firstVisitation = { visitor, QVector(attributes.size()), - QVector(attributes.size()) }; + { glm::vec3(), TOP_LEVEL_SIZE, QVector(attributes.size()) } }; for (int i = 0; i < attributes.size(); i++) { - firstVisitation.nodes[i] = _roots.value(attributes[i]); - firstVisitation.attributeValues[i] = attributes[i]; + MetavoxelNode* node = _roots.value(attributes[i]); + firstVisitation.nodes[i] = node; + firstVisitation.info.attributeValues[i] = node ? node->getAttributeValue(attributes[i]) : attributes[i]; } firstVisitation.apply(); } diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 11b9db2505..bbdf17c99c 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -14,6 +14,8 @@ #include #include +#include + #include "AttributeRegistry.h" class MetavoxelNode; @@ -94,14 +96,23 @@ private: QBitArray _array; }; +/// Contains information about a metavoxel (explicit or procedural). +class MetavoxelInfo { +public: + + glm::vec3 minimum; ///< the minimum extent of the area covered by the voxel + float size; ///< the size of the voxel in all dimensions + QVector attributeValues; +}; + /// Interface for visitors to metavoxels. class MetavoxelVisitor { public: /// Visits a metavoxel. - /// \param attributeValues the values of the desired attributes + /// \param info the metavoxel ata /// \param if true, continue descending; if false, stop - virtual bool visit(const QVector& attributeValues) = 0; + virtual bool visit(const MetavoxelInfo& info) = 0; }; #endif /* defined(__interface__MetavoxelData__) */