mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
More progress on voxelizing spanners.
This commit is contained in:
parent
176d8f746e
commit
7580951b92
5 changed files with 144 additions and 69 deletions
|
@ -202,7 +202,7 @@ QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) :
|
|||
InlineAttribute<QRgb>(name, defaultValue) {
|
||||
}
|
||||
|
||||
bool QRgbAttribute::merge(void*& parent, void* children[]) const {
|
||||
bool QRgbAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(children[0]);
|
||||
int totalAlpha = qAlpha(firstValue);
|
||||
int totalRed = qRed(firstValue) * totalAlpha;
|
||||
|
@ -261,7 +261,7 @@ PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultVa
|
|||
QRgbAttribute(name, defaultValue) {
|
||||
}
|
||||
|
||||
bool PackedNormalAttribute::merge(void*& parent, void* children[]) const {
|
||||
bool PackedNormalAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(children[0]);
|
||||
glm::vec3 total = unpackNormal(firstValue) * (float)qAlpha(firstValue);
|
||||
bool allChildrenEqual = true;
|
||||
|
@ -270,7 +270,8 @@ bool PackedNormalAttribute::merge(void*& parent, void* children[]) const {
|
|||
total += unpackNormal(value) * (float)qAlpha(value);
|
||||
allChildrenEqual &= (firstValue == value);
|
||||
}
|
||||
parent = encodeInline(packNormal(glm::normalize(total)));
|
||||
float length = glm::length(total);
|
||||
parent = encodeInline(length < EPSILON ? QRgb() : packNormal(total / length));
|
||||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
|
@ -310,13 +311,37 @@ MetavoxelNode* SpannerQRgbAttribute::createMetavoxelNode(
|
|||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool SpannerQRgbAttribute::merge(void*& parent, void* children[]) const {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
bool SpannerQRgbAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
if (postRead) {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
QRgb parentValue = decodeInline<QRgb>(parent);
|
||||
int totalAlpha = qAlpha(parentValue) * Attribute::MERGE_COUNT;
|
||||
int totalRed = qRed(parentValue) * totalAlpha;
|
||||
int totalGreen = qGreen(parentValue) * totalAlpha;
|
||||
int totalBlue = qBlue(parentValue) * totalAlpha;
|
||||
bool allChildrenTransparent = true;
|
||||
for (int i = 0; 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;
|
||||
allChildrenTransparent &= (alpha == 0);
|
||||
}
|
||||
if (totalAlpha == 0) {
|
||||
parent = encodeInline(QRgb());
|
||||
} else {
|
||||
parent = encodeInline(qRgba(totalRed / totalAlpha, totalGreen / totalAlpha,
|
||||
totalBlue / totalAlpha, totalAlpha / MERGE_COUNT));
|
||||
}
|
||||
return allChildrenTransparent;
|
||||
}
|
||||
|
||||
AttributeValue SpannerQRgbAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
|
@ -341,13 +366,27 @@ MetavoxelNode* SpannerPackedNormalAttribute::createMetavoxelNode(
|
|||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool SpannerPackedNormalAttribute::merge(void*& parent, void* children[]) const {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
bool SpannerPackedNormalAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
if (postRead) {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (qAlpha(decodeInline<QRgb>(children[i])) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
QRgb parentValue = decodeInline<QRgb>(parent);
|
||||
glm::vec3 total = unpackNormal(parentValue) * (float)(qAlpha(parentValue) * Attribute::MERGE_COUNT);
|
||||
bool allChildrenTransparent = true;
|
||||
for (int i = 0; i < Attribute::MERGE_COUNT; i++) {
|
||||
QRgb value = decodeInline<QRgb>(children[i]);
|
||||
int alpha = qAlpha(value);
|
||||
total += unpackNormal(value) * (float)alpha;
|
||||
allChildrenTransparent &= (alpha == 0);
|
||||
}
|
||||
float length = glm::length(total);
|
||||
parent = encodeInline(length < EPSILON ? QRgb() : packNormal(total / length));
|
||||
return allChildrenTransparent;
|
||||
}
|
||||
|
||||
AttributeValue SpannerPackedNormalAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
|
@ -373,7 +412,7 @@ void SharedObjectAttribute::write(Bitstream& out, void* value, bool isLeaf) cons
|
|||
}
|
||||
}
|
||||
|
||||
bool SharedObjectAttribute::merge(void*& parent, void* children[]) const {
|
||||
bool SharedObjectAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
SharedObjectPointer firstChild = decodeInline<SharedObjectPointer>(children[0]);
|
||||
for (int i = 1; i < MERGE_COUNT; i++) {
|
||||
if (firstChild != decodeInline<SharedObjectPointer>(children[i])) {
|
||||
|
@ -413,7 +452,7 @@ MetavoxelNode* SharedObjectSetAttribute::createMetavoxelNode(
|
|||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool SharedObjectSetAttribute::merge(void*& parent, void* children[]) const {
|
||||
bool SharedObjectSetAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (!decodeInline<SharedObjectSet>(children[i]).isEmpty()) {
|
||||
return false;
|
||||
|
|
|
@ -115,7 +115,6 @@ 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 getSafeInlineValue() const { return _attribute ? decodeInline<T>(_value) : T(); }
|
||||
|
||||
void* copy() const;
|
||||
|
||||
|
@ -205,8 +204,9 @@ public:
|
|||
virtual bool equal(void* first, void* second) const = 0;
|
||||
|
||||
/// Merges the value of a parent and its children.
|
||||
/// \param postRead whether or not the merge is happening after a read
|
||||
/// \return whether or not the children and parent values are all equal
|
||||
virtual bool merge(void*& parent, void* children[]) const = 0;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) 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; }
|
||||
|
@ -274,7 +274,7 @@ public:
|
|||
|
||||
Q_INVOKABLE QRgbAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
|
||||
|
@ -293,7 +293,7 @@ public:
|
|||
|
||||
Q_INVOKABLE PackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
};
|
||||
|
@ -317,7 +317,7 @@ public:
|
|||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
@ -335,7 +335,7 @@ public:
|
|||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
@ -354,7 +354,7 @@ public:
|
|||
virtual void read(Bitstream& in, void*& value, bool isLeaf) const;
|
||||
virtual void write(Bitstream& out, void* value, bool isLeaf) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual void* createFromVariant(const QVariant& value) const;
|
||||
|
||||
|
@ -382,7 +382,7 @@ public:
|
|||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ void MetavoxelData::guide(MetavoxelVisitor& visitor) {
|
|||
const QVector<AttributePointer>& inputs = visitor.getInputs();
|
||||
const QVector<AttributePointer>& outputs = visitor.getOutputs();
|
||||
MetavoxelVisitation firstVisitation = { NULL, visitor, QVector<MetavoxelNode*>(inputs.size() + 1),
|
||||
QVector<MetavoxelNode*>(outputs.size()), { getMinimum(), _size,
|
||||
QVector<MetavoxelNode*>(outputs.size()), { NULL, getMinimum(), _size,
|
||||
QVector<AttributeValue>(inputs.size() + 1), QVector<OwnedAttributeValue>(outputs.size()) } };
|
||||
for (int i = 0; i < inputs.size(); i++) {
|
||||
MetavoxelNode* node = _roots.value(inputs.at(i));
|
||||
|
@ -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).getSafeInlineValue<SharedObjectSet>();
|
||||
SharedObjectSet set = info.inputValues.at(0).getInlineValue<SharedObjectSet>();
|
||||
F(set, _object);
|
||||
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
|
||||
return STOP_RECURSION;
|
||||
|
@ -523,14 +523,17 @@ AttributeValue MetavoxelNode::getAttributeValue(const AttributePointer& attribut
|
|||
return AttributeValue(attribute, _attributeValue);
|
||||
}
|
||||
|
||||
void MetavoxelNode::mergeChildren(const AttributePointer& attribute) {
|
||||
void MetavoxelNode::mergeChildren(const AttributePointer& attribute, bool postRead) {
|
||||
if (isLeaf()) {
|
||||
return;
|
||||
}
|
||||
void* childValues[CHILD_COUNT];
|
||||
bool allLeaves = true;
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
childValues[i] = _children[i]->_attributeValue;
|
||||
allLeaves &= _children[i]->isLeaf();
|
||||
}
|
||||
if (attribute->merge(_attributeValue, childValues) && allLeaves) {
|
||||
if (attribute->merge(_attributeValue, childValues, postRead) && allLeaves) {
|
||||
clearChildren(attribute);
|
||||
}
|
||||
}
|
||||
|
@ -562,7 +565,7 @@ void MetavoxelNode::read(MetavoxelStreamState& state) {
|
|||
_children[i] = new MetavoxelNode(state.attribute);
|
||||
_children[i]->read(nextState);
|
||||
}
|
||||
mergeChildren(state.attribute);
|
||||
mergeChildren(state.attribute, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +623,7 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta
|
|||
}
|
||||
}
|
||||
}
|
||||
mergeChildren(state.attribute);
|
||||
mergeChildren(state.attribute, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -887,7 +890,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).getSafeInlineValue<SharedObjectSet>()) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->testAndSetVisited()) {
|
||||
if (!visit(spanner)) {
|
||||
|
@ -939,7 +942,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).getSafeInlineValue<SharedObjectSet>()) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->testAndSetVisited()) {
|
||||
SpannerDistance spannerDistance = { spanner };
|
||||
|
@ -989,7 +992,7 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
}
|
||||
MetavoxelVisitation nextVisitation = { &visitation, visitation.visitor,
|
||||
QVector<MetavoxelNode*>(visitation.inputNodes.size()), QVector<MetavoxelNode*>(visitation.outputNodes.size()),
|
||||
{ glm::vec3(), visitation.info.size * 0.5f, QVector<AttributeValue>(visitation.inputNodes.size()),
|
||||
{ &visitation.info, glm::vec3(), visitation.info.size * 0.5f, QVector<AttributeValue>(visitation.inputNodes.size()),
|
||||
QVector<OwnedAttributeValue>(visitation.outputNodes.size()) } };
|
||||
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
|
||||
// the encoded order tells us the child indices for each iteration
|
||||
|
@ -1107,7 +1110,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin
|
|||
QScriptValue infoValue = context->argument(0);
|
||||
QScriptValue minimum = infoValue.property(guide->_minimumHandle);
|
||||
MetavoxelInfo info = {
|
||||
glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()),
|
||||
NULL, glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()),
|
||||
(float)infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues,
|
||||
guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() };
|
||||
|
||||
|
@ -1242,7 +1245,7 @@ const QVector<AttributePointer>& Spanner::getVoxelizedAttributes() const {
|
|||
return emptyVector;
|
||||
}
|
||||
|
||||
bool Spanner::getAttributeValues(MetavoxelInfo& info) const {
|
||||
bool Spanner::getAttributeValues(MetavoxelInfo& info, bool force) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1350,10 +1353,10 @@ const QVector<AttributePointer>& Sphere::getVoxelizedAttributes() const {
|
|||
return attributes;
|
||||
}
|
||||
|
||||
bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
||||
bool Sphere::getAttributeValues(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
|
||||
|
@ -1366,15 +1369,16 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
|||
if (pointsWithin == Box::VERTEX_COUNT) {
|
||||
// entirely contained
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
|
||||
getNormal(info);
|
||||
info.outputValues[1] = getNormal(info, _color.alpha());
|
||||
return false;
|
||||
}
|
||||
if (info.size <= getVoxelizationGranularity()) {
|
||||
if (force || info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
int alpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(qRgba(
|
||||
_color.red(), _color.green(), _color.blue(), _color.alpha() * pointsWithin / Box::VERTEX_COUNT)));
|
||||
getNormal(info);
|
||||
_color.red(), _color.green(), _color.blue(), alpha)));
|
||||
info.outputValues[1] = getNormal(info, alpha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1397,19 +1401,23 @@ bool Sphere::blendAttributeValues(MetavoxelInfo& info, bool force) const {
|
|||
if (pointsWithin == Box::VERTEX_COUNT) {
|
||||
// entirely contained
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
|
||||
info.outputValues[1] = getNormal(info);
|
||||
info.outputValues[1] = getNormal(info, _color.alpha());
|
||||
return false;
|
||||
}
|
||||
if (force || info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
int oldAlpha = qAlpha(info.inputValues.at(0).getInlineValue<QRgb>());
|
||||
const AttributeValue& oldColor = info.outputValues.at(0).getAttribute() ?
|
||||
info.outputValues.at(0) : info.inputValues.at(0);
|
||||
const AttributeValue& oldNormal = info.outputValues.at(1).getAttribute() ?
|
||||
info.outputValues.at(1) : info.inputValues.at(1);
|
||||
int oldAlpha = qAlpha(oldColor.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);
|
||||
int baseAlpha = _color.alpha() * pointsWithin / Box::VERTEX_COUNT;
|
||||
info.outputValues[0].mix(oldColor, AttributeValue(getAttributes().at(0),
|
||||
encodeInline<QRgb>(qRgba(_color.red(), _color.green(), _color.blue(), baseAlpha))), combinedAlpha);
|
||||
info.outputValues[1].mix(oldNormal, getNormal(info, baseAlpha), combinedAlpha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1429,20 +1437,19 @@ void Sphere::updateBounds() {
|
|||
setBounds(Box(getTranslation() - extent, getTranslation() + extent));
|
||||
}
|
||||
|
||||
AttributeValue Sphere::getNormal(MetavoxelInfo& info) const {
|
||||
AttributeValue Sphere::getNormal(MetavoxelInfo& info, int alpha) const {
|
||||
glm::vec3 normal = info.getCenter() - getTranslation();
|
||||
float length = glm::length(normal);
|
||||
QRgb color;
|
||||
if (length > EPSILON) {
|
||||
if (alpha != 0 && length > EPSILON) {
|
||||
const float NORMAL_SCALE = 127.0f;
|
||||
float scale = NORMAL_SCALE / length;
|
||||
const int BYTE_MASK = 0xFF;
|
||||
color = qRgb((int)(normal.x * scale) & BYTE_MASK, (int)(normal.y * scale) & BYTE_MASK,
|
||||
(int)(normal.z * scale) & BYTE_MASK);
|
||||
color = qRgba((int)(normal.x * scale) & BYTE_MASK, (int)(normal.y * scale) & BYTE_MASK,
|
||||
(int)(normal.z * scale) & BYTE_MASK, alpha);
|
||||
|
||||
} else {
|
||||
const QRgb DEFAULT_NORMAL = 0x007F00;
|
||||
color = DEFAULT_NORMAL;
|
||||
color = QRgb();
|
||||
}
|
||||
return AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
AttributeValue getAttributeValue(const AttributePointer& attribute) const;
|
||||
void* getAttributeValue() const { return _attributeValue; }
|
||||
|
||||
void mergeChildren(const AttributePointer& attribute);
|
||||
void mergeChildren(const AttributePointer& attribute, bool postRead = false);
|
||||
|
||||
MetavoxelNode* getChild(int index) const { return _children[index]; }
|
||||
void setChild(int index, MetavoxelNode* child) { _children[index] = child; }
|
||||
|
@ -185,6 +185,7 @@ private:
|
|||
class MetavoxelInfo {
|
||||
public:
|
||||
|
||||
MetavoxelInfo* parentInfo;
|
||||
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> inputValues;
|
||||
|
@ -436,7 +437,7 @@ public:
|
|||
|
||||
/// 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;
|
||||
virtual bool getAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
|
||||
/// Blends the attribute values associated with this spanner into the supplied info.
|
||||
/// \param force if true, blend even if we would normally subdivide
|
||||
|
@ -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 getAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
virtual bool blendAttributeValues(MetavoxelInfo& info, bool force = false) const;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
|
@ -554,7 +555,7 @@ private slots:
|
|||
|
||||
private:
|
||||
|
||||
AttributeValue getNormal(MetavoxelInfo& info) const;
|
||||
AttributeValue getNormal(MetavoxelInfo& info, int alpha) const;
|
||||
|
||||
QColor _color;
|
||||
};
|
||||
|
|
|
@ -104,42 +104,64 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
|
|||
spanner(spanner) {
|
||||
}
|
||||
|
||||
class InsertSpannerEditVisitor : public MetavoxelVisitor {
|
||||
class UpdateSpannerVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
InsertSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
|
||||
UpdateSpannerVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
Spanner* _spanner;
|
||||
float _longestSide;
|
||||
float _voxelizationSize;
|
||||
int _steps;
|
||||
};
|
||||
|
||||
InsertSpannerEditVisitor::InsertSpannerEditVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) :
|
||||
MetavoxelVisitor(attributes, attributes),
|
||||
UpdateSpannerVisitor::UpdateSpannerVisitor(const QVector<AttributePointer>& attributes, Spanner* spanner) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << attributes << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
attributes),
|
||||
_spanner(spanner),
|
||||
_longestSide(qMax(spanner->getBounds().getLongestSide(), spanner->getPlacementGranularity()) * 2.0f /
|
||||
AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()) {
|
||||
_voxelizationSize(qMax(spanner->getBounds().getLongestSide(), spanner->getPlacementGranularity()) * 2.0f /
|
||||
AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()),
|
||||
_steps(roundf(logf(AttributeRegistry::getInstance()->getSpannersAttribute()->getLODThresholdMultiplier()) /
|
||||
logf(2.0f) - 2.0f)) {
|
||||
}
|
||||
|
||||
int InsertSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
||||
int UpdateSpannerVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_spanner->getBounds())) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (info.size > _longestSide) {
|
||||
return DEFAULT_ORDER;
|
||||
MetavoxelInfo* parentInfo = info.parentInfo;
|
||||
for (int i = 0; i < _steps && parentInfo; i++) {
|
||||
parentInfo = parentInfo->parentInfo;
|
||||
}
|
||||
_spanner->blendAttributeValues(info, true);
|
||||
return STOP_RECURSION;
|
||||
if (!parentInfo) {
|
||||
for (int i = 0; i < _outputs.size(); i++) {
|
||||
info.outputValues[i] = AttributeValue(_outputs.at(i));
|
||||
}
|
||||
return (info.size > _voxelizationSize) ? DEFAULT_ORDER : STOP_RECURSION;
|
||||
}
|
||||
SharedObjectSet objects = parentInfo->inputValues.at(_outputs.size()).getInlineValue<SharedObjectSet>();
|
||||
if (objects.isEmpty()) {
|
||||
for (int i = 0; i < _outputs.size(); i++) {
|
||||
info.outputValues[i] = AttributeValue(_outputs.at(i));
|
||||
}
|
||||
return (info.size > _voxelizationSize) ? DEFAULT_ORDER : STOP_RECURSION;
|
||||
}
|
||||
SharedObjectSet::const_iterator it = objects.constBegin();
|
||||
static_cast<const Spanner*>(it->data())->getAttributeValues(info, true);
|
||||
for (it++; it != objects.constEnd(); it++) {
|
||||
static_cast<const Spanner*>(it->data())->blendAttributeValues(info, true);
|
||||
}
|
||||
return (info.size > _voxelizationSize) ? DEFAULT_ORDER : STOP_RECURSION;
|
||||
}
|
||||
|
||||
void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
data.insert(attribute, this->spanner);
|
||||
|
||||
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
|
||||
InsertSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
UpdateSpannerVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
||||
|
@ -154,7 +176,13 @@ void RemoveSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& o
|
|||
qDebug() << "Missing object to remove" << id;
|
||||
return;
|
||||
}
|
||||
// keep a strong reference to the object
|
||||
SharedObjectPointer sharedPointer = object;
|
||||
data.remove(attribute, object);
|
||||
|
||||
Spanner* spanner = static_cast<Spanner*>(object);
|
||||
UpdateSpannerVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
||||
ClearSpannersEdit::ClearSpannersEdit(const AttributePointer& attribute) :
|
||||
|
|
Loading…
Reference in a new issue