More progress on generic attributes; color attributes.

This commit is contained in:
Andrzej Kapolka 2013-12-11 16:13:36 -08:00
parent 79a2e409a8
commit dce9599201
5 changed files with 104 additions and 48 deletions

View file

@ -13,11 +13,13 @@
class DebugVisitor : public MetavoxelVisitor {
public:
virtual bool visit(const QVector<AttributeValue>& attributeValues);
virtual bool visit(const MetavoxelInfo& info);
};
bool DebugVisitor::visit(const QVector<AttributeValue>& attributeValues) {
qDebug() << decodeInline<float>(attributeValues.at(0).getValue()) << "\n";
bool DebugVisitor::visit(const MetavoxelInfo& info) {
QRgb color = info.attributeValues.at(0).getInlineValue<QRgb>();
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<float>(value.getValue()));
void* white = encodeInline(qRgba(0xFF, 0xFF, 0xFF, 0xFF));
_data.setAttributeValue(p1, AttributeValue(diffuseColor, &white));
DebugVisitor visitor;
_data.visitVoxels(QVector<AttributePointer>() << blerp, visitor);
_data.visitVoxels(QVector<AttributePointer>() << diffuseColor, visitor);
}

View file

@ -11,7 +11,7 @@
AttributeRegistry AttributeRegistry::_instance;
AttributeRegistry::AttributeRegistry() {
registerAttribute(AttributePointer(new InlineAttribute<float, 32>("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<QRgb, 32>(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<QRgb>(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));
}

View file

@ -9,6 +9,7 @@
#ifndef __interface__AttributeRegistry__
#define __interface__AttributeRegistry__
#include <QColor>
#include <QHash>
#include <QSharedPointer>
#include <QString>
@ -43,6 +44,16 @@ private:
QHash<QString, AttributePointer> _attributes;
};
/// Converts a value to a void pointer.
template<class T> inline void* encodeInline(T value) {
return *(void**)&value;
}
/// Extracts a value from a void pointer.
template<class T> 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<class T> void setInlineValue(T value) { _value = encodeInline(value); }
template<class T> T getInlineValue() const { return decodeInline<T>(_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<class T> inline void* encodeInline(const T& value) {
return *(void**)const_cast<T*>(&value);
}
template<class T> inline T decodeInline(void* value) {
return *(T*)&value;
}
/// A simple attribute class that stores its values inline.
template<class T, int bits> class InlineAttribute : public Attribute {
public:
@ -128,11 +136,20 @@ private:
template<class T, int bits> inline void* InlineAttribute<T, bits>::createAveraged(void* values[]) const {
T total = T();
for (int i = 0; i < 8; i++) {
for (int i = 0; i < AVERAGE_COUNT; i++) {
total += decodeInline<T>(values[i]);
}
total /= 8;
total /= AVERAGE_COUNT;
return encodeInline(total);
}
/// Provides appropriate averaging for RGBA values.
class QRgbAttribute : public InlineAttribute<QRgb, 32> {
public:
QRgbAttribute(const QString& name, QRgb defaultValue = QRgb());
virtual void* createAveraged(void* values[]) const;
};
#endif /* defined(__interface__AttributeRegistry__) */

View file

@ -19,45 +19,58 @@ class Visitation {
public:
MetavoxelVisitor& visitor;
QVector<MetavoxelNode*> nodes;
QVector<AttributeValue> 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<MetavoxelNode*>(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<MetavoxelNode*>(nodes.size()),
{ glm::vec3(), info.size * 0.5f, QVector<AttributeValue>(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<AttributePointer>& attributes, MetavoxelVisitor& visitor) {
// start with the root values/defaults
const float TOP_LEVEL_SIZE = 1.0f;
Visitation firstVisitation = { visitor, QVector<MetavoxelNode*>(attributes.size()),
QVector<AttributeValue>(attributes.size()) };
{ glm::vec3(), TOP_LEVEL_SIZE, QVector<AttributeValue>(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();
}

View file

@ -14,6 +14,8 @@
#include <QScopedPointer>
#include <QVector>
#include <glm/glm.hpp>
#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<AttributeValue> 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<AttributeValue>& attributeValues) = 0;
virtual bool visit(const MetavoxelInfo& info) = 0;
};
#endif /* defined(__interface__MetavoxelData__) */