From 176d8f746e9d19d907b7b257ec7fb760f0d70fd8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 28 Mar 2014 15:19:40 -0700 Subject: [PATCH] Finally at the point of actually getting spanners to turn into voxels. --- interface/src/MetavoxelSystem.cpp | 2 +- .../metavoxels/src/AttributeRegistry.cpp | 95 ++++++++++++------- libraries/metavoxels/src/AttributeRegistry.h | 23 +++++ libraries/metavoxels/src/MetavoxelData.cpp | 36 ++++--- libraries/metavoxels/src/MetavoxelData.h | 7 +- .../metavoxels/src/MetavoxelMessages.cpp | 45 +++++++-- 6 files changed, 153 insertions(+), 55 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index a003f650f5..2da21aae7e 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -188,7 +188,7 @@ int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) { QRgb color = info.inputValues.at(0).getInlineValue(); QRgb normal = info.inputValues.at(1).getInlineValue(); quint8 alpha = qAlpha(color); - if (info.inputValues.at(4).getAttribute()) { + if (!info.isLODLeaf) { if (alpha > 0) { Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)), alpha }, diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index 548a953857..d9abba9950 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -13,6 +13,8 @@ REGISTER_META_OBJECT(QRgbAttribute) REGISTER_META_OBJECT(PackedNormalAttribute) +REGISTER_META_OBJECT(SpannerQRgbAttribute) +REGISTER_META_OBJECT(SpannerPackedNormalAttribute) REGISTER_META_OBJECT(SharedObjectAttribute) REGISTER_META_OBJECT(SharedObjectSetAttribute) REGISTER_META_OBJECT(SpannerSetAttribute) @@ -35,7 +37,7 @@ AttributeRegistry::AttributeRegistry() : _spannerNormalAttribute(registerAttribute(new SpannerPackedNormalAttribute("spannerNormal"))) { // our baseline LOD threshold is for voxels; spanners are a different story - const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 4.0f; + const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 8.0f; _spannersAttribute->setLODThresholdMultiplier(SPANNER_LOD_THRESHOLD_MULTIPLIER); } @@ -168,6 +170,10 @@ Attribute::Attribute(const QString& name) : Attribute::~Attribute() { } +MetavoxelNode* Attribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const { + return new MetavoxelNode(value); +} + void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { data.createRoot(state.attribute)->read(state); } @@ -257,7 +263,7 @@ PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultVa bool PackedNormalAttribute::merge(void*& parent, void* children[]) const { QRgb firstValue = decodeInline(children[0]); - glm::vec3 total = unpackNormal(firstValue); + glm::vec3 total = unpackNormal(firstValue) * (float)qAlpha(firstValue); bool allChildrenEqual = true; for (int i = 1; i < Attribute::MERGE_COUNT; i++) { QRgb value = decodeInline(children[i]); @@ -290,46 +296,62 @@ SpannerQRgbAttribute::SpannerQRgbAttribute(const QString& name, QRgb defaultValu QRgbAttribute(name, defaultValue) { } +void SpannerQRgbAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { + value = getDefaultValue(); + in.read(&value, 32); +} + +void SpannerQRgbAttribute::write(Bitstream& out, void* value, bool isLeaf) const { + out.write(&value, 32); +} + +MetavoxelNode* SpannerQRgbAttribute::createMetavoxelNode( + const AttributeValue& value, const MetavoxelNode* original) const { + return new MetavoxelNode(value, original); +} + bool SpannerQRgbAttribute::merge(void*& parent, void* children[]) const { - QRgb firstValue = decodeInline(children[0]); - 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]); - int alpha = qAlpha(value); - totalRed += qRed(value) * alpha; - totalGreen += qGreen(value) * alpha; - totalBlue += qBlue(value) * alpha; - totalAlpha += alpha; - allChildrenEqual &= (firstValue == value); + for (int i = 0; i < MERGE_COUNT; i++) { + if (qAlpha(decodeInline(children[i])) != 0) { + return false; + } } - if (totalAlpha == 0) { - parent = encodeInline(QRgb()); - } else { - parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha, - totalBlue / totalAlpha, totalAlpha / MERGE_COUNT)); - } - return allChildrenEqual; + return true; } +AttributeValue SpannerQRgbAttribute::inherit(const AttributeValue& parentValue) const { + return AttributeValue(parentValue.getAttribute()); +} + SpannerPackedNormalAttribute::SpannerPackedNormalAttribute(const QString& name, QRgb defaultValue) : PackedNormalAttribute(name, defaultValue) { } +void SpannerPackedNormalAttribute::read(Bitstream& in, void*& value, bool isLeaf) const { + value = getDefaultValue(); + in.read(&value, 32); +} + +void SpannerPackedNormalAttribute::write(Bitstream& out, void* value, bool isLeaf) const { + out.write(&value, 32); +} + +MetavoxelNode* SpannerPackedNormalAttribute::createMetavoxelNode( + const AttributeValue& value, const MetavoxelNode* original) const { + return new MetavoxelNode(value, original); +} + bool SpannerPackedNormalAttribute::merge(void*& parent, void* children[]) const { - QRgb firstValue = decodeInline(children[0]); - glm::vec3 total = unpackNormal(firstValue); - bool allChildrenEqual = true; - for (int i = 1; i < Attribute::MERGE_COUNT; i++) { - QRgb value = decodeInline(children[i]); - total += unpackNormal(value) * (float)qAlpha(value); - allChildrenEqual &= (firstValue == value); + for (int i = 0; i < MERGE_COUNT; i++) { + if (qAlpha(decodeInline(children[i])) != 0) { + return false; + } } - parent = encodeInline(packNormal(glm::normalize(total))); - return allChildrenEqual; + return true; +} + +AttributeValue SpannerPackedNormalAttribute::inherit(const AttributeValue& parentValue) const { + return AttributeValue(parentValue.getAttribute()); } SharedObjectAttribute::SharedObjectAttribute(const QString& name, const QMetaObject* metaObject, @@ -386,6 +408,11 @@ void SharedObjectSetAttribute::write(Bitstream& out, void* value, bool isLeaf) c out << decodeInline(value); } +MetavoxelNode* SharedObjectSetAttribute::createMetavoxelNode( + const AttributeValue& value, const MetavoxelNode* original) const { + return new MetavoxelNode(value, original); +} + bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const { for (int i = 0; i < MERGE_COUNT; i++) { if (!decodeInline(children[i]).isEmpty()) { @@ -395,6 +422,10 @@ bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const { return true; } +AttributeValue SharedObjectSetAttribute::inherit(const AttributeValue& parentValue) const { + return AttributeValue(parentValue.getAttribute()); +} + QWidget* SharedObjectSetAttribute::createEditor(QWidget* parent) const { return new SharedObjectEditor(_metaObject, parent); } diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index ce5984d1af..67388b4cdb 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -191,6 +191,8 @@ public: virtual void readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const { read(in, value, isLeaf); } virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const { write(out, value, isLeaf); } + virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; + virtual void readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state); virtual void writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state); @@ -206,6 +208,9 @@ public: /// \return whether or not the children and parent values are all equal virtual bool merge(void*& parent, void* children[]) const = 0; + /// Given the parent value, returns the value that children should inherit (either the parent value or the default). + virtual AttributeValue inherit(const AttributeValue& parentValue) const { return parentValue; } + /// Mixes the first and the second, returning a new value with the result. virtual void* mix(void* first, void* second, float alpha) const = 0; @@ -307,7 +312,14 @@ public: Q_INVOKABLE SpannerQRgbAttribute(const QString& name = QString(), QRgb defaultValue = QRgb()); + virtual void read(Bitstream& in, void*& value, bool isLeaf) const; + virtual void write(Bitstream& out, void* value, bool isLeaf) const; + + virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; + virtual bool merge(void*& parent, void* children[]) const; + + virtual AttributeValue inherit(const AttributeValue& parentValue) const; }; /// Packed normals for voxelized spanners. @@ -318,7 +330,14 @@ public: Q_INVOKABLE SpannerPackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb()); + virtual void read(Bitstream& in, void*& value, bool isLeaf) const; + virtual void write(Bitstream& out, void* value, bool isLeaf) const; + + virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; + virtual bool merge(void*& parent, void* children[]) const; + + virtual AttributeValue inherit(const AttributeValue& parentValue) const; }; /// An attribute that takes the form of QObjects of a given meta-type (a subclass of SharedObject). @@ -361,8 +380,12 @@ public: virtual void read(Bitstream& in, void*& value, bool isLeaf) const; virtual void write(Bitstream& out, void* value, bool isLeaf) const; + virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const; + virtual bool merge(void*& parent, void* children[]) const; + virtual AttributeValue inherit(const AttributeValue& parentValue) const; + virtual QWidget* createEditor(QWidget* parent = NULL) const; private: diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 0a1f7ba365..ed1de6b4ad 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -485,14 +485,26 @@ void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) { minimum = getNextMinimum(lastMinimum, size, index); } -MetavoxelNode::MetavoxelNode(const AttributeValue& attributeValue) : _referenceCount(1) { +MetavoxelNode::MetavoxelNode(const AttributeValue& attributeValue, const MetavoxelNode* copyChildren) : + _referenceCount(1) { + _attributeValue = attributeValue.copy(); - for (int i = 0; i < CHILD_COUNT; i++) { - _children[i] = NULL; + if (copyChildren) { + for (int i = 0; i < CHILD_COUNT; i++) { + if ((_children[i] = copyChildren->_children[i])) { + _children[i]->incrementReferenceCount(); + } + } + } else { + for (int i = 0; i < CHILD_COUNT; i++) { + _children[i] = NULL; + } } } -MetavoxelNode::MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy) : _referenceCount(1) { +MetavoxelNode::MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy) : + _referenceCount(1) { + _attributeValue = attribute->create(copy->_attributeValue); for (int i = 0; i < CHILD_COUNT; i++) { if ((_children[i] = copy->_children[i])) { @@ -969,7 +981,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { // "set" to same value; disregard value = AttributeValue(); } else { - node = new MetavoxelNode(value); + node = value.getAttribute()->createMetavoxelNode(value, node); } } if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) { @@ -991,7 +1003,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; + child->getAttributeValue(parentValue.getAttribute()) : parentValue.getAttribute()->inherit(parentValue); } for (int j = 0; j < visitation.outputNodes.size(); j++) { MetavoxelNode* node = visitation.outputNodes.at(j); @@ -1019,7 +1031,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { node = new MetavoxelNode(value.getAttribute(), node); } else { // create leaf with inherited value - node = new MetavoxelNode(visitation.getInheritedOutputValue(j)); + node = new MetavoxelNode(value.getAttribute()->inherit(visitation.getInheritedOutputValue(j))); } } MetavoxelNode* node = visitation.outputNodes.at(j); @@ -1028,7 +1040,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) { child->decrementReferenceCount(value.getAttribute()); } else { // it's a leaf; we need to split it up - AttributeValue nodeValue = node->getAttributeValue(value.getAttribute()); + AttributeValue nodeValue = value.getAttribute()->inherit(node->getAttributeValue(value.getAttribute())); for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) { node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue)); } @@ -1234,7 +1246,7 @@ bool Spanner::getAttributeValues(MetavoxelInfo& info) const { return false; } -bool Spanner::blendAttributeValues(MetavoxelInfo& info) const { +bool Spanner::blendAttributeValues(MetavoxelInfo& info, bool force) const { return false; } @@ -1369,10 +1381,10 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const { return true; } -bool Sphere::blendAttributeValues(MetavoxelInfo& info) const { +bool Sphere::blendAttributeValues(MetavoxelInfo& info, bool force) const { // bounds check Box bounds = info.getBounds(); - if (!getBounds().intersects(bounds)) { + if (!(force || getBounds().intersects(bounds))) { return false; } // count the points inside the sphere @@ -1388,7 +1400,7 @@ bool Sphere::blendAttributeValues(MetavoxelInfo& info) const { info.outputValues[1] = getNormal(info); return false; } - if (info.size <= getVoxelizationGranularity()) { + if (force || info.size <= getVoxelizationGranularity()) { // best guess if (pointsWithin > 0) { int oldAlpha = qAlpha(info.inputValues.at(0).getInlineValue()); diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 970d529117..85ff2d0850 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -132,7 +132,7 @@ public: static const int CHILD_COUNT = 8; - MetavoxelNode(const AttributeValue& attributeValue); + MetavoxelNode(const AttributeValue& attributeValue, const MetavoxelNode* copyChildren = NULL); MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy); void setAttributeValue(const AttributeValue& attributeValue); @@ -439,8 +439,9 @@ public: virtual bool getAttributeValues(MetavoxelInfo& info) const; /// Blends the attribute values associated with this spanner into the supplied info. + /// \param force if true, blend even if we would normally subdivide /// \return true to recurse, false to stop - virtual bool blendAttributeValues(MetavoxelInfo& info) const; + virtual bool blendAttributeValues(MetavoxelInfo& info, bool force = false) const; /// Checks whether we've visited this object on the current traversal. If we have, returns false. /// If we haven't, sets the last visit identifier and returns true. @@ -536,7 +537,7 @@ public: virtual const QVector& getAttributes() const; virtual const QVector& getVoxelizedAttributes() const; virtual bool getAttributeValues(MetavoxelInfo& info) const; - virtual bool blendAttributeValues(MetavoxelInfo& info) const; + virtual bool blendAttributeValues(MetavoxelInfo& info, bool force = false) const; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const; signals: diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index b600ef87bf..46924f8af8 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -104,32 +104,42 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh spanner(spanner) { } -class SetSpannerEditVisitor : public MetavoxelVisitor { +class InsertSpannerEditVisitor : public MetavoxelVisitor { public: - SetSpannerEditVisitor(const QVector& attributes, Spanner* spanner); + InsertSpannerEditVisitor(const QVector& attributes, Spanner* spanner); virtual int visit(MetavoxelInfo& info); private: Spanner* _spanner; + float _longestSide; }; -SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector& attributes, Spanner* spanner) : +InsertSpannerEditVisitor::InsertSpannerEditVisitor(const QVector& attributes, Spanner* spanner) : MetavoxelVisitor(attributes, attributes), - _spanner(spanner) { + _spanner(spanner), + _longestSide(qMax(spanner->getBounds().getLongestSide(), spanner->getPlacementGranularity()) * 2.0f / + AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()) { } -int SetSpannerEditVisitor::visit(MetavoxelInfo& info) { - return _spanner->blendAttributeValues(info) ? DEFAULT_ORDER : STOP_RECURSION; +int InsertSpannerEditVisitor::visit(MetavoxelInfo& info) { + if (!info.getBounds().intersects(_spanner->getBounds())) { + return STOP_RECURSION; + } + if (info.size > _longestSide) { + return DEFAULT_ORDER; + } + _spanner->blendAttributeValues(info, true); + return STOP_RECURSION; } void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { data.insert(attribute, this->spanner); Spanner* spanner = static_cast(this->spanner.data()); - SetSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner); + InsertSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner); data.guide(visitor); } @@ -159,6 +169,27 @@ SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) : spanner(spanner) { } +class SetSpannerEditVisitor : public MetavoxelVisitor { +public: + + SetSpannerEditVisitor(const QVector& attributes, Spanner* spanner); + + virtual int visit(MetavoxelInfo& info); + +private: + + Spanner* _spanner; +}; + +SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector& attributes, Spanner* spanner) : + MetavoxelVisitor(attributes, attributes), + _spanner(spanner) { +} + +int SetSpannerEditVisitor::visit(MetavoxelInfo& info) { + return _spanner->blendAttributeValues(info) ? DEFAULT_ORDER : STOP_RECURSION; +} + void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const { Spanner* spanner = static_cast(this->spanner.data());