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 normal = info.inputValues.at(1).getInlineValue<QRgb>();
quint8 alpha = qAlpha(color);
if (info.inputValues.at(4).getAttribute()) {
if (!info.isLODLeaf) {
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 },

View file

@ -13,6 +13,8 @@
REGISTER_META_OBJECT(QRgbAttribute)
REGISTER_META_OBJECT(PackedNormalAttribute)
REGISTER_META_OBJECT(SpannerQRgbAttribute)
REGISTER_META_OBJECT(SpannerPackedNormalAttribute)
REGISTER_META_OBJECT(SharedObjectAttribute)
REGISTER_META_OBJECT(SharedObjectSetAttribute)
REGISTER_META_OBJECT(SpannerSetAttribute)
@ -35,7 +37,7 @@ AttributeRegistry::AttributeRegistry() :
_spannerNormalAttribute(registerAttribute(new SpannerPackedNormalAttribute("spannerNormal"))) {
// 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);
}
@ -168,6 +170,10 @@ Attribute::Attribute(const QString& name) :
Attribute::~Attribute() {
}
MetavoxelNode* Attribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const {
return new MetavoxelNode(value);
}
void Attribute::readMetavoxelRoot(MetavoxelData& data, MetavoxelStreamState& 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 {
QRgb firstValue = decodeInline<QRgb>(children[0]);
glm::vec3 total = unpackNormal(firstValue);
glm::vec3 total = unpackNormal(firstValue) * (float)qAlpha(firstValue);
bool allChildrenEqual = true;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
QRgb value = decodeInline<QRgb>(children[i]);
@ -290,46 +296,62 @@ SpannerQRgbAttribute::SpannerQRgbAttribute(const QString& name, QRgb defaultValu
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 {
QRgb firstValue = decodeInline<QRgb>(children[0]);
int totalAlpha = qAlpha(firstValue);
int totalRed = qRed(firstValue) * totalAlpha;
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);
for (int i = 0; i < MERGE_COUNT; i++) {
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
return false;
}
}
if (totalAlpha == 0) {
parent = encodeInline(QRgb());
} else {
parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha,
totalBlue / totalAlpha, totalAlpha / MERGE_COUNT));
}
return allChildrenEqual;
return true;
}
AttributeValue SpannerQRgbAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
SpannerPackedNormalAttribute::SpannerPackedNormalAttribute(const QString& name, QRgb 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 {
QRgb firstValue = decodeInline<QRgb>(children[0]);
glm::vec3 total = unpackNormal(firstValue);
bool allChildrenEqual = true;
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
QRgb value = decodeInline<QRgb>(children[i]);
total += unpackNormal(value) * (float)qAlpha(value);
allChildrenEqual &= (firstValue == value);
for (int i = 0; i < MERGE_COUNT; i++) {
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
return false;
}
}
parent = encodeInline(packNormal(glm::normalize(total)));
return allChildrenEqual;
return true;
}
AttributeValue SpannerPackedNormalAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
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);
}
MetavoxelNode* SharedObjectSetAttribute::createMetavoxelNode(
const AttributeValue& value, const MetavoxelNode* original) const {
return new MetavoxelNode(value, original);
}
bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const {
for (int i = 0; i < MERGE_COUNT; i++) {
if (!decodeInline<SharedObjectSet>(children[i]).isEmpty()) {
@ -395,6 +422,10 @@ bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const {
return true;
}
AttributeValue SharedObjectSetAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
QWidget* SharedObjectSetAttribute::createEditor(QWidget* parent) const {
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 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 writeMetavoxelRoot(const MetavoxelNode& root, MetavoxelStreamState& state);
@ -206,6 +208,9 @@ public:
/// \return whether or not the children and parent values are all equal
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.
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());
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 AttributeValue inherit(const AttributeValue& parentValue) const;
};
/// Packed normals for voxelized spanners.
@ -318,7 +330,14 @@ public:
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 AttributeValue inherit(const AttributeValue& parentValue) const;
};
/// 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 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 AttributeValue inherit(const AttributeValue& parentValue) const;
virtual QWidget* createEditor(QWidget* parent = NULL) const;
private:

View file

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

View file

@ -132,7 +132,7 @@ public:
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);
void setAttributeValue(const AttributeValue& attributeValue);
@ -439,8 +439,9 @@ public:
virtual bool getAttributeValues(MetavoxelInfo& info) const;
/// 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
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.
/// 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>& getVoxelizedAttributes() 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;
signals:

View file

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