Finally at the point of actually getting spanners to turn into voxels.

This commit is contained in:
Andrzej Kapolka 2014-03-28 15:19:40 -07:00
parent 78896d6af9
commit 176d8f746e
6 changed files with 153 additions and 55 deletions

View file

@ -188,7 +188,7 @@ int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>(); QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>(); QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
quint8 alpha = qAlpha(color); quint8 alpha = qAlpha(color);
if (info.inputValues.at(4).getAttribute()) { if (!info.isLODLeaf) {
if (alpha > 0) { if (alpha > 0) {
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), 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 }, { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)), alpha },

View file

@ -13,6 +13,8 @@
REGISTER_META_OBJECT(QRgbAttribute) REGISTER_META_OBJECT(QRgbAttribute)
REGISTER_META_OBJECT(PackedNormalAttribute) REGISTER_META_OBJECT(PackedNormalAttribute)
REGISTER_META_OBJECT(SpannerQRgbAttribute)
REGISTER_META_OBJECT(SpannerPackedNormalAttribute)
REGISTER_META_OBJECT(SharedObjectAttribute) REGISTER_META_OBJECT(SharedObjectAttribute)
REGISTER_META_OBJECT(SharedObjectSetAttribute) REGISTER_META_OBJECT(SharedObjectSetAttribute)
REGISTER_META_OBJECT(SpannerSetAttribute) REGISTER_META_OBJECT(SpannerSetAttribute)
@ -35,7 +37,7 @@ AttributeRegistry::AttributeRegistry() :
_spannerNormalAttribute(registerAttribute(new SpannerPackedNormalAttribute("spannerNormal"))) { _spannerNormalAttribute(registerAttribute(new SpannerPackedNormalAttribute("spannerNormal"))) {
// our baseline LOD threshold is for voxels; spanners are a different story // 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); _spannersAttribute->setLODThresholdMultiplier(SPANNER_LOD_THRESHOLD_MULTIPLIER);
} }
@ -168,6 +170,10 @@ Attribute::Attribute(const QString& name) :
Attribute::~Attribute() { Attribute::~Attribute() {
} }
MetavoxelNode* Attribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const {
return new MetavoxelNode(value);
}
void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) { void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state) {
data.createRoot(state.attribute)->read(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 { bool PackedNormalAttribute::merge(void*& parent, void* children[]) const {
QRgb firstValue = decodeInline<QRgb>(children[0]); QRgb firstValue = decodeInline<QRgb>(children[0]);
glm::vec3 total = unpackNormal(firstValue); glm::vec3 total = unpackNormal(firstValue) * (float)qAlpha(firstValue);
bool allChildrenEqual = true; bool allChildrenEqual = true;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) { for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
QRgb value = decodeInline<QRgb>(children[i]); QRgb value = decodeInline<QRgb>(children[i]);
@ -290,46 +296,62 @@ SpannerQRgbAttribute::SpannerQRgbAttribute(const QString& name, QRgb defaultValu
QRgbAttribute(name, defaultValue) { 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 { bool SpannerQRgbAttribute::merge(void*& parent, void* children[]) const {
QRgb firstValue = decodeInline<QRgb>(children[0]); for (int i = 0; i < MERGE_COUNT; i++) {
int totalAlpha = qAlpha(firstValue); if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
int totalRed = qRed(firstValue) * totalAlpha; return false;
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<QRgb>(children[i]);
int alpha = qAlpha(value);
totalRed += qRed(value) * alpha;
totalGreen += qGreen(value) * alpha;
totalBlue += qBlue(value) * alpha;
totalAlpha += alpha;
allChildrenEqual &= (firstValue == value);
} }
if (totalAlpha == 0) { return true;
parent = encodeInline(QRgb());
} else {
parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha,
totalBlue / totalAlpha, totalAlpha / MERGE_COUNT));
}
return allChildrenEqual;
} }
AttributeValue SpannerQRgbAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
SpannerPackedNormalAttribute::SpannerPackedNormalAttribute(const QString& name, QRgb defaultValue) : SpannerPackedNormalAttribute::SpannerPackedNormalAttribute(const QString& name, QRgb defaultValue) :
PackedNormalAttribute(name, 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 { bool SpannerPackedNormalAttribute::merge(void*& parent, void* children[]) const {
QRgb firstValue = decodeInline<QRgb>(children[0]); for (int i = 0; i < MERGE_COUNT; i++) {
glm::vec3 total = unpackNormal(firstValue); if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
bool allChildrenEqual = true; return false;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) { }
QRgb value = decodeInline<QRgb>(children[i]);
total += unpackNormal(value) * (float)qAlpha(value);
allChildrenEqual &= (firstValue == value);
} }
parent = encodeInline(packNormal(glm::normalize(total))); return true;
return allChildrenEqual; }
AttributeValue SpannerPackedNormalAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
} }
SharedObjectAttribute::SharedObjectAttribute(const QString& name, const QMetaObject* metaObject, SharedObjectAttribute::SharedObjectAttribute(const QString& name, const QMetaObject* metaObject,
@ -386,6 +408,11 @@ void SharedObjectSetAttribute::write(Bitstream& out, void* value, bool isLeaf) c
out << decodeInline<SharedObjectSet>(value); out << decodeInline<SharedObjectSet>(value);
} }
MetavoxelNode* SharedObjectSetAttribute::createMetavoxelNode(
const AttributeValue& value, const MetavoxelNode* original) const {
return new MetavoxelNode(value, original);
}
bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const { bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const {
for (int i = 0; i < MERGE_COUNT; i++) { for (int i = 0; i < MERGE_COUNT; i++) {
if (!decodeInline<SharedObjectSet>(children[i]).isEmpty()) { if (!decodeInline<SharedObjectSet>(children[i]).isEmpty()) {
@ -395,6 +422,10 @@ bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const {
return true; return true;
} }
AttributeValue SharedObjectSetAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
QWidget* SharedObjectSetAttribute::createEditor(QWidget* parent) const { QWidget* SharedObjectSetAttribute::createEditor(QWidget* parent) const {
return new SharedObjectEditor(_metaObject, parent); return new SharedObjectEditor(_metaObject, parent);
} }

View file

@ -191,6 +191,8 @@ public:
virtual void readDelta(Bitstream& in, void*& value, void* reference, bool isLeaf) const { read(in, value, isLeaf); } 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 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 readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& state);
virtual void writeMetavoxelRoot(const MetavoxelNode& root, 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 /// \return whether or not the children and parent values are all equal
virtual bool merge(void*& parent, void* children[]) const = 0; 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. /// Mixes the first and the second, returning a new value with the result.
virtual void* mix(void* first, void* second, float alpha) const = 0; 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()); 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 bool merge(void*& parent, void* children[]) const;
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
}; };
/// Packed normals for voxelized spanners. /// Packed normals for voxelized spanners.
@ -318,7 +330,14 @@ public:
Q_INVOKABLE SpannerPackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb()); 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 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). /// 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 read(Bitstream& in, void*& value, bool isLeaf) const;
virtual void write(Bitstream& out, 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 bool merge(void*& parent, void* children[]) const;
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
virtual QWidget* createEditor(QWidget* parent = NULL) const; virtual QWidget* createEditor(QWidget* parent = NULL) const;
private: private:

View file

@ -485,14 +485,26 @@ void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) {
minimum = getNextMinimum(lastMinimum, size, 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(); _attributeValue = attributeValue.copy();
for (int i = 0; i < CHILD_COUNT; i++) { if (copyChildren) {
_children[i] = NULL; 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); _attributeValue = attribute->create(copy->_attributeValue);
for (int i = 0; i < CHILD_COUNT; i++) { for (int i = 0; i < CHILD_COUNT; i++) {
if ((_children[i] = copy->_children[i])) { if ((_children[i] = copy->_children[i])) {
@ -969,7 +981,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
// "set" to same value; disregard // "set" to same value; disregard
value = AttributeValue(); value = AttributeValue();
} else { } else {
node = new MetavoxelNode(value); node = value.getAttribute()->createMetavoxelNode(value, node);
} }
} }
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) { if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
@ -991,7 +1003,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
MetavoxelNode* child = (node && (visitation.info.size >= lodBase * MetavoxelNode* child = (node && (visitation.info.size >= lodBase *
parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL; parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL;
nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ? 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++) { for (int j = 0; j < visitation.outputNodes.size(); j++) {
MetavoxelNode* node = visitation.outputNodes.at(j); MetavoxelNode* node = visitation.outputNodes.at(j);
@ -1019,7 +1031,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
node = new MetavoxelNode(value.getAttribute(), node); node = new MetavoxelNode(value.getAttribute(), node);
} else { } else {
// create leaf with inherited value // 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); MetavoxelNode* node = visitation.outputNodes.at(j);
@ -1028,7 +1040,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
child->decrementReferenceCount(value.getAttribute()); child->decrementReferenceCount(value.getAttribute());
} else { } else {
// it's a leaf; we need to split it up // 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++) { for (int k = 1; k < MetavoxelNode::CHILD_COUNT; k++) {
node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue)); node->setChild((index + k) % MetavoxelNode::CHILD_COUNT, new MetavoxelNode(nodeValue));
} }
@ -1234,7 +1246,7 @@ bool Spanner::getAttributeValues(MetavoxelInfo& info) const {
return false; return false;
} }
bool Spanner::blendAttributeValues(MetavoxelInfo& info) const { bool Spanner::blendAttributeValues(MetavoxelInfo& info, bool force) const {
return false; return false;
} }
@ -1369,10 +1381,10 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
return true; return true;
} }
bool Sphere::blendAttributeValues(MetavoxelInfo& info) const { bool Sphere::blendAttributeValues(MetavoxelInfo& info, bool force) const {
// bounds check // bounds check
Box bounds = info.getBounds(); Box bounds = info.getBounds();
if (!getBounds().intersects(bounds)) { if (!(force || getBounds().intersects(bounds))) {
return false; return false;
} }
// count the points inside the sphere // count the points inside the sphere
@ -1388,7 +1400,7 @@ bool Sphere::blendAttributeValues(MetavoxelInfo& info) const {
info.outputValues[1] = getNormal(info); info.outputValues[1] = getNormal(info);
return false; return false;
} }
if (info.size <= getVoxelizationGranularity()) { if (force || info.size <= getVoxelizationGranularity()) {
// best guess // best guess
if (pointsWithin > 0) { if (pointsWithin > 0) {
int oldAlpha = qAlpha(info.inputValues.at(0).getInlineValue<QRgb>()); int oldAlpha = qAlpha(info.inputValues.at(0).getInlineValue<QRgb>());

View file

@ -132,7 +132,7 @@ public:
static const int CHILD_COUNT = 8; 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); MetavoxelNode(const AttributePointer& attribute, const MetavoxelNode* copy);
void setAttributeValue(const AttributeValue& attributeValue); void setAttributeValue(const AttributeValue& attributeValue);
@ -439,8 +439,9 @@ public:
virtual bool getAttributeValues(MetavoxelInfo& info) const; virtual bool getAttributeValues(MetavoxelInfo& info) const;
/// Blends the attribute values associated with this spanner into the supplied info. /// 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 /// \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. /// 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. /// If we haven't, sets the last visit identifier and returns true.
@ -536,7 +537,7 @@ public:
virtual const QVector<AttributePointer>& getAttributes() const; virtual const QVector<AttributePointer>& getAttributes() const;
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const; virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
virtual bool getAttributeValues(MetavoxelInfo& info) 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; virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
signals: signals:

View file

@ -104,32 +104,42 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
spanner(spanner) { spanner(spanner) {
} }
class SetSpannerEditVisitor : public MetavoxelVisitor { class InsertSpannerEditVisitor : public MetavoxelVisitor {
public: public:
SetSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner); InsertSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
virtual int visit(MetavoxelInfo& info); virtual int visit(MetavoxelInfo& info);
private: private:
Spanner* _spanner; Spanner* _spanner;
float _longestSide;
}; };
SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) : InsertSpannerEditVisitor::InsertSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) :
MetavoxelVisitor(attributes, attributes), 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) { int InsertSpannerEditVisitor::visit(MetavoxelInfo& info) {
return _spanner->blendAttributeValues(info) ? DEFAULT_ORDER : STOP_RECURSION; 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 { void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
data.insert(attribute, this->spanner); data.insert(attribute, this->spanner);
Spanner* spanner = static_cast<Spanner*>(this->spanner.data()); Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
SetSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner); InsertSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
data.guide(visitor); data.guide(visitor);
} }
@ -159,6 +169,27 @@ SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) :
spanner(spanner) { spanner(spanner) {
} }
class SetSpannerEditVisitor : public MetavoxelVisitor {
public:
SetSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
virtual int visit(MetavoxelInfo& info);
private:
Spanner* _spanner;
};
SetSpannerEditVisitor::SetSpannerEditVisitor(const QVector<AttributePointer>& 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 { void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
Spanner* spanner = static_cast<Spanner*>(this->spanner.data()); Spanner* spanner = static_cast<Spanner*>(this->spanner.data());