Better merging for normals.

This commit is contained in:
Andrzej Kapolka 2014-03-10 13:00:58 -07:00
parent 3b63424abd
commit 7fc55e5596
2 changed files with 52 additions and 1 deletions

View file

@ -12,6 +12,7 @@
#include "MetavoxelData.h"
REGISTER_META_OBJECT(QRgbAttribute)
REGISTER_META_OBJECT(PackedNormalAttribute)
REGISTER_META_OBJECT(SharedObjectAttribute)
REGISTER_META_OBJECT(SharedObjectSetAttribute)
REGISTER_META_OBJECT(SpannerSetAttribute)
@ -26,7 +27,7 @@ AttributeRegistry::AttributeRegistry() :
SharedObjectPointer(new DefaultMetavoxelGuide())))),
_spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))),
_colorAttribute(registerAttribute(new QRgbAttribute("color"))),
_normalAttribute(registerAttribute(new QRgbAttribute("normal", qRgb(0, 127, 0)))) {
_normalAttribute(registerAttribute(new PackedNormalAttribute("normal", qRgb(0, 127, 0)))) {
}
static QScriptValue qDebugFunction(QScriptContext* context, QScriptEngine* engine) {
@ -217,6 +218,39 @@ QWidget* QRgbAttribute::createEditor(QWidget* parent) const {
return editor;
}
PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultValue) :
QRgbAttribute(name, defaultValue) {
}
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);
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);
allChildrenEqual &= (firstValue == value);
}
parent = encodeInline(packNormal(glm::normalize(glm::vec3(totalRed, totalGreen, totalBlue))));
return allChildrenEqual;
}
const float CHAR_SCALE = 127.0f;
const float INVERSE_CHAR_SCALE = 1.0f / CHAR_SCALE;
QRgb packNormal(const glm::vec3& normal) {
return qRgb((char)(normal.x * CHAR_SCALE), (char)(normal.y * CHAR_SCALE), (char)(normal.z * CHAR_SCALE));
}
glm::vec3 unpackNormal(QRgb value) {
return glm::vec3((char)qRed(value) * INVERSE_CHAR_SCALE, (char)qGreen(value) * INVERSE_CHAR_SCALE,
(char)qBlue(value) * INVERSE_CHAR_SCALE);
}
SharedObjectAttribute::SharedObjectAttribute(const QString& name, const QMetaObject* metaObject,
const SharedObjectPointer& defaultValue) :
InlineAttribute<SharedObjectPointer>(name, defaultValue),

View file

@ -272,6 +272,23 @@ public:
virtual QWidget* createEditor(QWidget* parent = NULL) const;
};
/// Provides appropriate averaging for packed normals.
class PackedNormalAttribute : public QRgbAttribute {
Q_OBJECT
public:
Q_INVOKABLE PackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
virtual bool merge(void*& parent, void* children[]) const;
};
/// Packs a normal into an RGB value.
QRgb packNormal(const glm::vec3& normal);
/// Unpacks a normal from an RGB value.
glm::vec3 unpackNormal(QRgb value);
/// An attribute that takes the form of QObjects of a given meta-type (a subclass of SharedObject).
class SharedObjectAttribute : public InlineAttribute<SharedObjectPointer> {
Q_OBJECT