Working on voxelizing spanners.

This commit is contained in:
Andrzej Kapolka 2014-03-25 20:41:19 -07:00
parent 249e9f0e33
commit 5934a7fbea
8 changed files with 220 additions and 88 deletions

View file

@ -4,22 +4,22 @@
<context>
<name>Application</name>
<message>
<location filename="src/Application.cpp" line="1368"/>
<location filename="src/Application.cpp" line="1380"/>
<source>Export Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="1369"/>
<location filename="src/Application.cpp" line="1381"/>
<source>Sparse Voxel Octree Files (*.svo)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3596"/>
<location filename="src/Application.cpp" line="3597"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3597"/>
<location filename="src/Application.cpp" line="3598"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
@ -113,18 +113,18 @@
<context>
<name>Menu</name>
<message>
<location filename="src/Menu.cpp" line="455"/>
<location filename="src/Menu.cpp" line="457"/>
<source>Open .ini config file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="457"/>
<location filename="src/Menu.cpp" line="469"/>
<location filename="src/Menu.cpp" line="459"/>
<location filename="src/Menu.cpp" line="471"/>
<source>Text files (*.ini)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="467"/>
<location filename="src/Menu.cpp" line="469"/>
<source>Save .ini config file</source>
<translation type="unfinished"></translation>
</message>

View file

@ -168,7 +168,9 @@ void MetavoxelSystem::maybeAttachClient(const SharedNodePointer& node) {
MetavoxelSystem::SimulateVisitor::SimulateVisitor(QVector<Point>& points) :
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<
AttributeRegistry::getInstance()->getNormalAttribute()),
AttributeRegistry::getInstance()->getNormalAttribute() <<
AttributeRegistry::getInstance()->getSpannerColorAttribute() <<
AttributeRegistry::getInstance()->getSpannerNormalAttribute()),
_points(points) {
}
@ -186,11 +188,36 @@ int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) {
QRgb color = info.inputValues.at(0).getInlineValue<QRgb>();
QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>();
quint8 alpha = qAlpha(color);
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 },
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
_points.append(point);
if (info.inputValues.at(4).getAttribute()) {
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 },
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
_points.append(point);
}
} else {
QRgb spannerColor = info.inputValues.at(2).getInlineValue<QRgb>();
QRgb spannerNormal = info.inputValues.at(3).getInlineValue<QRgb>();
quint8 spannerAlpha = qAlpha(spannerColor);
if (spannerAlpha > 0) {
if (alpha > 0) {
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
{ quint8(qRed(spannerColor)), quint8(qGreen(spannerColor)), quint8(qBlue(spannerColor)), spannerAlpha },
{ quint8(qRed(spannerNormal)), quint8(qGreen(spannerNormal)), quint8(qBlue(spannerNormal)) } };
_points.append(point);
} else {
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
{ quint8(qRed(spannerColor)), quint8(qGreen(spannerColor)), quint8(qBlue(spannerColor)), spannerAlpha },
{ quint8(qRed(spannerNormal)), quint8(qGreen(spannerNormal)), quint8(qBlue(spannerNormal)) } };
_points.append(point);
}
} else 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 },
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
_points.append(point);
}
}
return STOP_RECURSION;
}

View file

@ -655,6 +655,5 @@ bool SetSpannerTool::appliesTo(const AttributePointer& attribute) const {
}
QVariant SetSpannerTool::createEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
static_cast<Spanner*>(spanner.data())->setGranularity(_editor->getGridSpacing());
return QVariant::fromValue(SetSpannerEdit(spanner));
}

View file

@ -30,7 +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", qRgb(0, 127, 0)))),
_spannerColorAttribute(registerAttribute(new QRgbAttribute("spannerColor"))),
_spannerNormalAttribute(registerAttribute(new PackedNormalAttribute("spannerNormal", qRgb(0, 127, 0)))) {
// our baseline LOD threshold is for voxels; spanners are a different story
const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 4.0f;
@ -92,6 +94,10 @@ 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));
}
@ -130,6 +136,14 @@ OwnedAttributeValue::~OwnedAttributeValue() {
}
}
void OwnedAttributeValue::mix(const AttributeValue& first, const AttributeValue& second, float alpha) {
if (_attribute) {
_attribute->destroy(_value);
}
_attribute = first.getAttribute();
_value = _attribute->mix(first.getValue(), second.getValue(), alpha);
}
OwnedAttributeValue& OwnedAttributeValue::operator=(const AttributeValue& other) {
if (_attribute) {
_attribute->destroy(_value);
@ -206,6 +220,16 @@ bool QRgbAttribute::merge(void*& parent, void* children[]) const {
return allChildrenEqual;
}
void* QRgbAttribute::mix(void* first, void* second, float alpha) const {
QRgb firstValue = decodeInline<QRgb>(first);
QRgb secondValue = decodeInline<QRgb>(second);
return encodeInline(qRgba(
glm::mix((float)qRed(firstValue), (float)qRed(secondValue), alpha),
glm::mix((float)qGreen(firstValue), (float)qGreen(secondValue), alpha),
glm::mix((float)qBlue(firstValue), (float)qBlue(secondValue), alpha),
glm::mix((float)qAlpha(firstValue), (float)qAlpha(secondValue), alpha)));
}
void* QRgbAttribute::createFromScript(const QScriptValue& value, QScriptEngine* engine) const {
return encodeInline((QRgb)value.toUInt32());
}
@ -232,21 +256,23 @@ PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultVa
bool PackedNormalAttribute::merge(void*& parent, void* children[]) const {
QRgb firstValue = decodeInline<QRgb>(children[0]);
int totalRed = (char)qRed(firstValue);
int totalGreen = (char)qGreen(firstValue);
int totalBlue = (char)qBlue(firstValue);
glm::vec3 total = unpackNormal(firstValue);
bool allChildrenEqual = true;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
QRgb value = decodeInline<QRgb>(children[i]);
totalRed += (char)qRed(value);
totalGreen += (char)qGreen(value);
totalBlue += (char)qBlue(value);
total += unpackNormal(value);
allChildrenEqual &= (firstValue == value);
}
parent = encodeInline(packNormal(glm::normalize(glm::vec3(totalRed, totalGreen, totalBlue))));
parent = encodeInline(packNormal(glm::normalize(total)));
return allChildrenEqual;
}
void* PackedNormalAttribute::mix(void* first, void* second, float alpha) const {
glm::vec3 firstNormal = unpackNormal(decodeInline<QRgb>(first));
glm::vec3 secondNormal = unpackNormal(decodeInline<QRgb>(second));
return encodeInline(packNormal(glm::normalize(glm::mix(firstNormal, secondNormal, alpha))));
}
const float CHAR_SCALE = 127.0f;
const float INVERSE_CHAR_SCALE = 1.0f / CHAR_SCALE;
@ -290,6 +316,10 @@ 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<SharedObjectPointer>()));
}

View file

@ -71,9 +71,15 @@ public:
/// Returns a reference to the standard QRgb "color" attribute.
const AttributePointer& getColorAttribute() const { return _colorAttribute; }
/// Returns a reference to the standard QRgb "normal" attribute.
/// Returns a reference to the standard packed normal "normal" attribute.
const AttributePointer& getNormalAttribute() const { return _normalAttribute; }
/// Returns a reference to the standard QRgb "spannerColor" attribute.
const AttributePointer& getSpannerColorAttribute() const { return _spannerColorAttribute; }
/// Returns a reference to the standard packed normal "spannerNormal" attribute.
const AttributePointer& getSpannerNormalAttribute() const { return _spannerNormalAttribute; }
private:
static QScriptValue getAttribute(QScriptContext* context, QScriptEngine* engine);
@ -83,6 +89,8 @@ private:
AttributePointer _spannersAttribute;
AttributePointer _colorAttribute;
AttributePointer _normalAttribute;
AttributePointer _spannerColorAttribute;
AttributePointer _spannerNormalAttribute;
};
/// Converts a value to a void pointer.
@ -107,13 +115,14 @@ public:
template<class T> void setInlineValue(T value) { _value = encodeInline(value); }
template<class T> T getInlineValue() const { return decodeInline<T>(_value); }
template<class T> T* getPointerValue() const { return static_cast<T*>(_value); }
template<class T> T getSafeInlineValue() const { return _attribute ? decodeInline<T>(_value) : T(); }
void* copy() const;
bool isDefault() const;
AttributeValue split() const;
bool operator==(const AttributeValue& other) const;
bool operator==(void* other) const;
@ -145,6 +154,9 @@ public:
/// Destroys the current value, if any.
~OwnedAttributeValue();
/// Sets this attribute to a mix of the first and second provided.
void mix(const AttributeValue& first, const AttributeValue& second, float alpha);
/// Destroys the current value, if any, and copies the specified other value.
OwnedAttributeValue& operator=(const AttributeValue& other);
@ -196,6 +208,12 @@ 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;
virtual void* getDefaultValue() const = 0;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const { return create(); }
@ -225,6 +243,8 @@ public:
virtual bool equal(void* first, void* second) const { return decodeInline<T>(first) == decodeInline<T>(second); }
virtual void* mix(void* first, void* second, float alpha) const { return create(alpha < 0.5f ? first : second); }
virtual void* getDefaultValue() const { return encodeInline(_defaultValue); }
protected:
@ -245,27 +265,6 @@ template<class T, int bits> inline void InlineAttribute<T, bits>::write(Bitstrea
}
}
/// Provides merging using the =, ==, += and /= operators.
template<class T, int bits = 32> class SimpleInlineAttribute : public InlineAttribute<T, bits> {
public:
SimpleInlineAttribute(const QString& name, T defaultValue = T()) : InlineAttribute<T, bits>(name, defaultValue) { }
virtual bool merge(void*& parent, void* children[]) const;
};
template<class T, int bits> inline bool SimpleInlineAttribute<T, bits>::merge(void*& parent, void* children[]) const {
T& merged = *(T*)&parent;
merged = decodeInline<T>(children[0]);
bool allChildrenEqual = true;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
merged += decodeInline<T>(children[i]);
allChildrenEqual &= (decodeInline<T>(children[0]) == decodeInline<T>(children[i]));
}
merged /= Attribute::MERGE_COUNT;
return allChildrenEqual;
}
/// Provides appropriate averaging for RGBA values.
class QRgbAttribute : public InlineAttribute<QRgb> {
Q_OBJECT
@ -277,6 +276,8 @@ public:
virtual bool merge(void*& parent, void* children[]) const;
virtual void* mix(void* first, void* second, float alpha) const;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const;
virtual void* createFromVariant(const QVariant& value) const;
@ -293,6 +294,8 @@ public:
Q_INVOKABLE PackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
virtual bool merge(void*& parent, void* children[]) const;
virtual void* mix(void* first, void* second, float alpha) const;
};
/// Packs a normal into an RGB value.
@ -343,6 +346,8 @@ public:
virtual bool merge(void*& parent, void* children[]) const;
virtual AttributeValue split(const AttributeValue& parent) const;
virtual QWidget* createEditor(QWidget* parent = NULL) const;
private:

View file

@ -169,7 +169,7 @@ template<SpannerUpdateFunction F> int SpannerUpdateVisitor<F>::visit(MetavoxelIn
if (info.size > _longestSide) {
return DEFAULT_ORDER;
}
SharedObjectSet set = info.inputValues.at(0).getInlineValue<SharedObjectSet>();
SharedObjectSet set = info.inputValues.at(0).getSafeInlineValue<SharedObjectSet>();
F(set, _object);
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
return STOP_RECURSION;
@ -177,7 +177,7 @@ template<SpannerUpdateFunction F> int SpannerUpdateVisitor<F>::visit(MetavoxelIn
void MetavoxelData::insert(const AttributePointer& attribute, const SharedObjectPointer& object) {
Spanner* spanner = static_cast<Spanner*>(object.data());
insert(attribute, spanner->getBounds(), spanner->getGranularity(), object);
insert(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
}
void MetavoxelData::insert(const AttributePointer& attribute, const Box& bounds,
@ -192,7 +192,7 @@ void MetavoxelData::insert(const AttributePointer& attribute, const Box& bounds,
void MetavoxelData::remove(const AttributePointer& attribute, const SharedObjectPointer& object) {
Spanner* spanner = static_cast<Spanner*>(object.data());
remove(attribute, spanner->getBounds(), spanner->getGranularity(), object);
remove(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
}
void MetavoxelData::remove(const AttributePointer& attribute, const Box& bounds,
@ -203,7 +203,7 @@ void MetavoxelData::remove(const AttributePointer& attribute, const Box& bounds,
void MetavoxelData::toggle(const AttributePointer& attribute, const SharedObjectPointer& object) {
Spanner* spanner = static_cast<Spanner*>(object.data());
toggle(attribute, spanner->getBounds(), spanner->getGranularity(), object);
toggle(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
}
void MetavoxelData::toggle(const AttributePointer& attribute, const Box& bounds,
@ -875,7 +875,7 @@ void SpannerVisitor::prepare() {
int SpannerVisitor::visit(MetavoxelInfo& info) {
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getSafeInlineValue<SharedObjectSet>()) {
Spanner* spanner = static_cast<Spanner*>(object.data());
if (spanner->testAndSetVisited()) {
if (!visit(spanner)) {
@ -927,7 +927,7 @@ bool operator<(const SpannerDistance& first, const SpannerDistance& second) {
int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {
QVarLengthArray<SpannerDistance, 4> spannerDistances;
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getSafeInlineValue<SharedObjectSet>()) {
Spanner* spanner = static_cast<Spanner*>(object.data());
if (spanner->testAndSetVisited()) {
SpannerDistance spannerDistance = { spanner };
@ -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;
child->getAttributeValue(parentValue.getAttribute()) : parentValue.split();
}
for (int j = 0; j < visitation.outputNodes.size(); j++) {
MetavoxelNode* node = visitation.outputNodes.at(j);
@ -1202,11 +1202,13 @@ AttributeValue MetavoxelVisitation::getInheritedOutputValue(int index) const {
return AttributeValue(visitor.getOutputs().at(index));
}
const float DEFAULT_GRANULARITY = 0.01f;
const float DEFAULT_PLACEMENT_GRANULARITY = 0.01f;
const float DEFAULT_VOXELIZATION_GRANULARITY = powf(2.0f, -3.0f);
Spanner::Spanner() :
_renderer(NULL),
_granularity(DEFAULT_GRANULARITY),
_placementGranularity(DEFAULT_PLACEMENT_GRANULARITY),
_voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY),
_lastVisit(0) {
}
@ -1223,10 +1225,19 @@ const QVector<AttributePointer>& Spanner::getAttributes() const {
return emptyVector;
}
const QVector<AttributePointer>& Spanner::getVoxelizedAttributes() const {
static QVector<AttributePointer> emptyVector;
return emptyVector;
}
bool Spanner::getAttributeValues(MetavoxelInfo& info) const {
return false;
}
bool Spanner::blendAttributeValues(MetavoxelInfo& info) const {
return false;
}
bool Spanner::testAndSetVisited() {
if (_lastVisit == _visit) {
return false;
@ -1320,6 +1331,13 @@ const QVector<AttributePointer>& Sphere::getAttributes() const {
return attributes;
}
const QVector<AttributePointer>& Sphere::getVoxelizedAttributes() const {
static QVector<AttributePointer> attributes = QVector<AttributePointer>() <<
AttributeRegistry::getInstance()->getSpannerColorAttribute() <<
AttributeRegistry::getInstance()->getSpannerNormalAttribute();
return attributes;
}
bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
// bounds check
Box bounds = info.getBounds();
@ -1339,7 +1357,7 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
getNormal(info);
return false;
}
if (info.size <= getGranularity()) {
if (info.size <= getVoxelizationGranularity()) {
// best guess
if (pointsWithin > 0) {
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(qRgba(
@ -1351,6 +1369,41 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
return true;
}
bool Sphere::blendAttributeValues(MetavoxelInfo& info) const {
// bounds check
Box bounds = info.getBounds();
if (!getBounds().intersects(bounds)) {
return false;
}
// count the points inside the sphere
int pointsWithin = 0;
for (int i = 0; i < Box::VERTEX_COUNT; i++) {
if (glm::distance(bounds.getVertex(i), getTranslation()) <= getScale()) {
pointsWithin++;
}
}
if (pointsWithin == Box::VERTEX_COUNT) {
// entirely contained
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
info.outputValues[1] = getNormal(info);
return false;
}
if (info.size <= getVoxelizationGranularity()) {
// best guess
if (pointsWithin > 0) {
int oldAlpha = qAlpha(info.inputValues.at(0).getInlineValue<QRgb>());
int newAlpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
float combinedAlpha = (float)newAlpha / (oldAlpha + newAlpha);
info.outputValues[0].mix(info.inputValues.at(0), AttributeValue(getAttributes().at(0),
encodeInline<QRgb>(qRgba(_color.red(), _color.green(), _color.blue(),
_color.alpha() * pointsWithin / Box::VERTEX_COUNT))), combinedAlpha);
info.outputValues[1].mix(info.inputValues.at(1), getNormal(info), combinedAlpha);
}
return false;
}
return true;
}
bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
return findRaySphereIntersection(origin, direction, getTranslation(), getScale(), distance);
}
@ -1364,7 +1417,7 @@ void Sphere::updateBounds() {
setBounds(Box(getTranslation() - extent, getTranslation() + extent));
}
void Sphere::getNormal(MetavoxelInfo& info) const {
AttributeValue Sphere::getNormal(MetavoxelInfo& info) const {
glm::vec3 normal = info.getCenter() - getTranslation();
float length = glm::length(normal);
QRgb color;
@ -1379,7 +1432,7 @@ void Sphere::getNormal(MetavoxelInfo& info) const {
const QRgb DEFAULT_NORMAL = 0x007F00;
color = DEFAULT_NORMAL;
}
info.outputValues[1] = AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
return AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
}
StaticModel::StaticModel() {

View file

@ -408,8 +408,9 @@ public:
class Spanner : public SharedObject {
Q_OBJECT
Q_PROPERTY(Box bounds MEMBER _bounds WRITE setBounds NOTIFY boundsChanged DESIGNABLE false)
Q_PROPERTY(float granularity MEMBER _granularity DESIGNABLE false)
Q_PROPERTY(float placementGranularity MEMBER _placementGranularity DESIGNABLE false)
Q_PROPERTY(float voxelizationGranularity MEMBER _voxelizationGranularity DESIGNABLE false)
public:
/// Increments the value of the global visit counter.
@ -420,16 +421,26 @@ public:
void setBounds(const Box& bounds);
const Box& getBounds() const { return _bounds; }
void setGranularity(float granularity) { _granularity = granularity; }
float getGranularity() const { return _granularity; }
void setPlacementGranularity(float granularity) { _placementGranularity = granularity; }
float getPlacementGranularity() const { return _placementGranularity; }
void setVoxelizationGranularity(float granularity) { _voxelizationGranularity = granularity; }
float getVoxelizationGranularity() const { return _voxelizationGranularity; }
/// Returns a reference to the list of attributes associated with this spanner.
virtual const QVector<AttributePointer>& getAttributes() const;
/// Returns a reference to the list of corresponding attributes that we voxelize the spanner into.
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
/// Sets the attribute values associated with this spanner in the supplied info.
/// \return true to recurse, false to stop
virtual bool getAttributeValues(MetavoxelInfo& info) const;
/// Blends the attribute values associated with this spanner into the supplied info.
/// \return true to recurse, false to stop
virtual bool blendAttributeValues(MetavoxelInfo& info) 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.
bool testAndSetVisited();
@ -455,7 +466,8 @@ protected:
private:
Box _bounds;
float _granularity;
float _placementGranularity;
float _voxelizationGranularity;
int _lastVisit; ///< the identifier of the last visit
static int _visit; ///< the global visit counter
@ -521,7 +533,9 @@ public:
const QColor& getColor() const { return _color; }
virtual const QVector<AttributePointer>& getAttributes() const;
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
virtual bool getAttributeValues(MetavoxelInfo& info) const;
virtual bool blendAttributeValues(MetavoxelInfo& info) const;
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
signals:
@ -538,7 +552,7 @@ private slots:
private:
void getNormal(MetavoxelInfo& info) const;
AttributeValue getNormal(MetavoxelInfo& info) const;
QColor _color;
};

View file

@ -104,8 +104,33 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
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 InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
data.insert(attribute, spanner);
data.insert(attribute, this->spanner);
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
SetSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
data.guide(visitor);
}
RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id) :
@ -130,27 +155,6 @@ void ClearSpannersEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& o
data.clear(attribute);
}
class SetSpannerEditVisitor : public MetavoxelVisitor {
public:
SetSpannerEditVisitor(Spanner* spanner);
virtual int visit(MetavoxelInfo& info);
private:
Spanner* _spanner;
};
SetSpannerEditVisitor::SetSpannerEditVisitor(Spanner* spanner) :
MetavoxelVisitor(spanner->getAttributes(), spanner->getAttributes()),
_spanner(spanner) {
}
int SetSpannerEditVisitor::visit(MetavoxelInfo& info) {
return _spanner->getAttributeValues(info) ? DEFAULT_ORDER : STOP_RECURSION;
}
SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) :
spanner(spanner) {
}
@ -163,6 +167,6 @@ void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& obje
data.expand();
}
SetSpannerEditVisitor visitor(spanner);
SetSpannerEditVisitor visitor(spanner->getAttributes(), spanner);
data.guide(visitor);
}