More set/blend bits.

This commit is contained in:
Andrzej Kapolka 2014-04-02 15:48:53 -07:00
parent 40844d2000
commit 3a44a846ed
6 changed files with 96 additions and 19 deletions

View file

@ -144,6 +144,14 @@ void OwnedAttributeValue::mix(const AttributeValue& first, const AttributeValue&
_value = _attribute->mix(first.getValue(), second.getValue(), alpha);
}
void OwnedAttributeValue::blend(const AttributeValue& source, const AttributeValue& dest) {
if (_attribute) {
_attribute->destroy(_value);
}
_attribute = source.getAttribute();
_value = _attribute->blend(source.getValue(), dest.getValue());
}
OwnedAttributeValue& OwnedAttributeValue::operator=(const AttributeValue& other) {
if (_attribute) {
_attribute->destroy(_value);
@ -243,6 +251,19 @@ void* QRgbAttribute::mix(void* first, void* second, float alpha) const {
glm::mix((float)qAlpha(firstValue), (float)qAlpha(secondValue), alpha)));
}
const float EIGHT_BIT_MAXIMUM = 255.0f;
void* QRgbAttribute::blend(void* source, void* dest) const {
QRgb sourceValue = decodeInline<QRgb>(source);
QRgb destValue = decodeInline<QRgb>(dest);
float alpha = qAlpha(sourceValue) / EIGHT_BIT_MAXIMUM;
return encodeInline(qRgba(
glm::mix((float)qRed(destValue), (float)qRed(sourceValue), alpha),
glm::mix((float)qGreen(destValue), (float)qGreen(sourceValue), alpha),
glm::mix((float)qBlue(destValue), (float)qBlue(sourceValue), alpha),
glm::mix((float)qAlpha(destValue), (float)qAlpha(sourceValue), alpha)));
}
void* QRgbAttribute::createFromScript(const QScriptValue& value, QScriptEngine* engine) const {
return encodeInline((QRgb)value.toUInt32());
}
@ -287,6 +308,13 @@ void* PackedNormalAttribute::mix(void* first, void* second, float alpha) const {
return encodeInline(packNormal(glm::normalize(glm::mix(firstNormal, secondNormal, alpha))));
}
void* PackedNormalAttribute::blend(void* source, void* dest) const {
QRgb sourceValue = decodeInline<QRgb>(source);
QRgb destValue = decodeInline<QRgb>(dest);
float alpha = qAlpha(sourceValue) / EIGHT_BIT_MAXIMUM;
return encodeInline(packNormal(glm::normalize(glm::mix(unpackNormal(destValue), unpackNormal(sourceValue), alpha))));
}
const float CHAR_SCALE = 127.0f;
const float INVERSE_CHAR_SCALE = 1.0f / CHAR_SCALE;

View file

@ -158,6 +158,9 @@ public:
/// Sets this attribute to a mix of the first and second provided.
void mix(const AttributeValue& first, const AttributeValue& second, float alpha);
/// Sets this attribute to a blend of the source and destination.
void blend(const AttributeValue& source, const AttributeValue& dest);
/// Destroys the current value, if any, and copies the specified other value.
OwnedAttributeValue& operator=(const AttributeValue& other);
@ -218,6 +221,9 @@ public:
/// Mixes the first and the second, returning a new value with the result.
virtual void* mix(void* first, void* second, float alpha) const = 0;
/// Blends the source with the destination, returning a new value with the result.
virtual void* blend(void* source, void* dest) const = 0;
virtual void* getDefaultValue() const = 0;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const { return create(); }
@ -249,6 +255,8 @@ public:
virtual void* mix(void* first, void* second, float alpha) const { return create(alpha < 0.5f ? first : second); }
virtual void* blend(void* source, void* dest) const { return create(source); }
virtual void* getDefaultValue() const { return encodeInline(_defaultValue); }
protected:
@ -315,6 +323,8 @@ public:
virtual void* mix(void* first, void* second, float alpha) const;
virtual void* blend(void* source, void* dest) const;
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const;
virtual void* createFromVariant(const QVariant& value) const;
@ -333,6 +343,8 @@ public:
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
virtual void* mix(void* first, void* second, float alpha) const;
virtual void* blend(void* source, void* dest) const;
};
/// Packs a normal into an RGB value.

View file

@ -336,17 +336,41 @@ static glm::vec3 getNextMinimum(const glm::vec3& minimum, float nextSize, int in
(index & Z_MAXIMUM_FLAG) ? nextSize : 0.0f);
}
static void setNode(const AttributePointer& attribute, MetavoxelNode*& node, MetavoxelNode* other) {
if (node) {
node->decrementReferenceCount(attribute);
static void setNode(const AttributeValue& value, MetavoxelNode*& node, MetavoxelNode* other, bool blend) {
if (!blend) {
// if we're not blending, we can just make a shallow copy
if (node) {
node->decrementReferenceCount(value.getAttribute());
}
(node = other)->incrementReferenceCount();
return;
}
(node = other)->incrementReferenceCount();
if (node) {
MetavoxelNode* oldNode = node;
node = new MetavoxelNode(value.getAttribute(), oldNode);
oldNode->decrementReferenceCount(value.getAttribute());
} else {
node = new MetavoxelNode(value);
}
OwnedAttributeValue oldValue = node->getAttributeValue(value.getAttribute());
node->blendAttributeValues(other->getAttributeValue(value.getAttribute()), oldValue);
if (other->isLeaf()) {
node->clearChildren(value.getAttribute());
return;
}
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
MetavoxelNode* child = node->getChild(i);
setNode(oldValue, child, other->getChild(i), true);
node->setChild(i, child);
}
node->mergeChildren(value.getAttribute());
}
static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm::vec3& minimum, float size,
MetavoxelNode* other, const glm::vec3& otherMinimum, float otherSize) {
MetavoxelNode* other, const glm::vec3& otherMinimum, float otherSize, bool blend) {
if (otherSize >= size) {
setNode(value.getAttribute(), node, other);
setNode(value, node, other, blend);
return;
}
if (!node) {
@ -372,21 +396,27 @@ static void setNode(const AttributeValue& value, MetavoxelNode*& node, const glm
}
MetavoxelNode* nextNode = node->getChild(index);
setNode(node->getAttributeValue(value.getAttribute()), nextNode, getNextMinimum(minimum, nextSize, index),
nextSize, other, otherMinimum, otherSize);
nextSize, other, otherMinimum, otherSize, blend);
node->setChild(index, nextNode);
node->mergeChildren(value.getAttribute());
}
void MetavoxelData::set(const glm::vec3& minimum, const MetavoxelData& data) {
void MetavoxelData::set(const glm::vec3& minimum, const MetavoxelData& data, bool blend) {
// expand to fit the entire data
Box bounds = minimum + glm::vec3(data.getSize(), data.getSize(), data.getSize());
while (!getBounds().contains(bounds)) {
expand();
}
// set each attribute separately
// set/mix each attribute separately
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = data._roots.constBegin();
it != data._roots.constEnd(); it++) {
setNode(it.key(), _roots[it.key()], getMinimum(), getSize(), it.value(), minimum, data.getSize());
MetavoxelNode*& root = _roots[it.key()];
setNode(it.key(), root, getMinimum(), getSize(), it.value(), minimum, data.getSize(), blend);
if (root->isLeaf() && root->getAttributeValue(it.key()).isDefault()) {
_roots.remove(it.key());
root->decrementReferenceCount(it.key());
}
}
}
@ -659,7 +689,11 @@ MetavoxelNode::MetavoxelNode(const AttributePointer& attribute, const MetavoxelN
void MetavoxelNode::setAttributeValue(const AttributeValue& attributeValue) {
attributeValue.getAttribute()->destroy(_attributeValue);
_attributeValue = attributeValue.copy();
clearChildren(attributeValue.getAttribute());
}
void MetavoxelNode::blendAttributeValues(const AttributeValue& source, const AttributeValue& dest) {
source.getAttribute()->destroy(_attributeValue);
_attributeValue = source.getAttribute()->blend(source.getValue(), dest.getValue());
}
AttributeValue MetavoxelNode::getAttributeValue(const AttributePointer& attribute) const {

View file

@ -91,7 +91,7 @@ public:
const AttributePointer& attribute, float& distance, const MetavoxelLOD& lod = MetavoxelLOD());
/// Sets part of the data.
void set(const glm::vec3& minimum, const MetavoxelData& data);
void set(const glm::vec3& minimum, const MetavoxelData& data, bool blend = false);
/// Expands the tree, increasing its capacity in all dimensions.
void expand();
@ -158,6 +158,8 @@ public:
void setAttributeValue(const AttributeValue& attributeValue);
void blendAttributeValues(const AttributeValue& source, const AttributeValue& dest);
AttributeValue getAttributeValue(const AttributePointer& attribute) const;
void* getAttributeValue() const { return _attributeValue; }
@ -190,13 +192,13 @@ public:
void destroy(const AttributePointer& attribute);
void clearChildren(const AttributePointer& attribute);
private:
Q_DISABLE_COPY(MetavoxelNode)
friend class MetavoxelVisitation;
void clearChildren(const AttributePointer& attribute);
int _referenceCount;
void* _attributeValue;
MetavoxelNode* _children[CHILD_COUNT];

View file

@ -306,11 +306,12 @@ void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& obje
setIntersectingMasked(spanner->getBounds(), data);
}
SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data) :
SetDataEdit::SetDataEdit(const glm::vec3& minimum, const MetavoxelData& data, bool blend) :
minimum(minimum),
data(data) {
data(data),
blend(blend) {
}
void SetDataEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
data.set(minimum, this->data);
data.set(minimum, this->data, blend);
}

View file

@ -183,10 +183,10 @@ class SetDataEdit : public MetavoxelEdit {
public:
STREAM glm::vec3 minimum;
STREAM MetavoxelData data;
STREAM bool blend;
SetDataEdit(const glm::vec3& minimum = glm::vec3(), const MetavoxelData& data = MetavoxelData());
SetDataEdit(const glm::vec3& minimum = glm::vec3(), const MetavoxelData& data = MetavoxelData(), bool blend = false);
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
};