mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 11:07:50 +02:00
Working on voxelizing spanners.
This commit is contained in:
parent
249e9f0e33
commit
5934a7fbea
8 changed files with 220 additions and 88 deletions
|
@ -4,22 +4,22 @@
|
|||
<context>
|
||||
<name>Application</name>
|
||||
<message>
|
||||
<location filename="src/Application.cpp" line="1368"/>
|
||||
<location filename="src/Application.cpp" line="1380"/>
|
||||
<source>Export Voxels</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/Application.cpp" line="1369"/>
|
||||
<location filename="src/Application.cpp" line="1381"/>
|
||||
<source>Sparse Voxel Octree Files (*.svo)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/Application.cpp" line="3596"/>
|
||||
<location filename="src/Application.cpp" line="3597"/>
|
||||
<source>Open Script</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/Application.cpp" line="3597"/>
|
||||
<location filename="src/Application.cpp" line="3598"/>
|
||||
<source>JavaScript Files (*.js)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -113,18 +113,18 @@
|
|||
<context>
|
||||
<name>Menu</name>
|
||||
<message>
|
||||
<location filename="src/Menu.cpp" line="455"/>
|
||||
<location filename="src/Menu.cpp" line="457"/>
|
||||
<source>Open .ini config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/Menu.cpp" line="457"/>
|
||||
<location filename="src/Menu.cpp" line="469"/>
|
||||
<location filename="src/Menu.cpp" line="459"/>
|
||||
<location filename="src/Menu.cpp" line="471"/>
|
||||
<source>Text files (*.ini)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="src/Menu.cpp" line="467"/>
|
||||
<location filename="src/Menu.cpp" line="469"/>
|
||||
<source>Save .ini config file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
|
@ -168,7 +168,9 @@ void MetavoxelSystem::maybeAttachClient(const SharedNodePointer& node) {
|
|||
MetavoxelSystem::SimulateVisitor::SimulateVisitor(QVector<Point>& points) :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getNormalAttribute()),
|
||||
AttributeRegistry::getInstance()->getNormalAttribute() <<
|
||||
AttributeRegistry::getInstance()->getSpannerColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getSpannerNormalAttribute()),
|
||||
_points(points) {
|
||||
}
|
||||
|
||||
|
@ -186,11 +188,36 @@ 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 (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 },
|
||||
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
|
||||
_points.append(point);
|
||||
if (info.inputValues.at(4).getAttribute()) {
|
||||
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 },
|
||||
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
|
||||
_points.append(point);
|
||||
}
|
||||
} else {
|
||||
QRgb spannerColor = info.inputValues.at(2).getInlineValue<QRgb>();
|
||||
QRgb spannerNormal = info.inputValues.at(3).getInlineValue<QRgb>();
|
||||
quint8 spannerAlpha = qAlpha(spannerColor);
|
||||
if (spannerAlpha > 0) {
|
||||
if (alpha > 0) {
|
||||
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
|
||||
{ quint8(qRed(spannerColor)), quint8(qGreen(spannerColor)), quint8(qBlue(spannerColor)), spannerAlpha },
|
||||
{ quint8(qRed(spannerNormal)), quint8(qGreen(spannerNormal)), quint8(qBlue(spannerNormal)) } };
|
||||
_points.append(point);
|
||||
|
||||
} else {
|
||||
Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size),
|
||||
{ quint8(qRed(spannerColor)), quint8(qGreen(spannerColor)), quint8(qBlue(spannerColor)), spannerAlpha },
|
||||
{ quint8(qRed(spannerNormal)), quint8(qGreen(spannerNormal)), quint8(qBlue(spannerNormal)) } };
|
||||
_points.append(point);
|
||||
}
|
||||
} else 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 },
|
||||
{ quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } };
|
||||
_points.append(point);
|
||||
}
|
||||
}
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
|
|
@ -655,6 +655,5 @@ bool SetSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
|||
}
|
||||
|
||||
QVariant SetSpannerTool::createEdit(const AttributePointer& attribute, const SharedObjectPointer& spanner) {
|
||||
static_cast<Spanner*>(spanner.data())->setGranularity(_editor->getGridSpacing());
|
||||
return QVariant::fromValue(SetSpannerEdit(spanner));
|
||||
}
|
||||
|
|
|
@ -30,7 +30,9 @@ AttributeRegistry::AttributeRegistry() :
|
|||
SharedObjectPointer(new DefaultMetavoxelGuide())))),
|
||||
_spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))),
|
||||
_colorAttribute(registerAttribute(new QRgbAttribute("color"))),
|
||||
_normalAttribute(registerAttribute(new PackedNormalAttribute("normal", qRgb(0, 127, 0)))) {
|
||||
_normalAttribute(registerAttribute(new PackedNormalAttribute("normal", qRgb(0, 127, 0)))),
|
||||
_spannerColorAttribute(registerAttribute(new QRgbAttribute("spannerColor"))),
|
||||
_spannerNormalAttribute(registerAttribute(new PackedNormalAttribute("spannerNormal", qRgb(0, 127, 0)))) {
|
||||
|
||||
// our baseline LOD threshold is for voxels; spanners are a different story
|
||||
const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 4.0f;
|
||||
|
@ -92,6 +94,10 @@ bool AttributeValue::isDefault() const {
|
|||
return !_attribute || _attribute->equal(_value, _attribute->getDefaultValue());
|
||||
}
|
||||
|
||||
AttributeValue AttributeValue::split() const {
|
||||
return _attribute ? _attribute->split(*this) : AttributeValue();
|
||||
}
|
||||
|
||||
bool AttributeValue::operator==(const AttributeValue& other) const {
|
||||
return _attribute == other._attribute && (!_attribute || _attribute->equal(_value, other._value));
|
||||
}
|
||||
|
@ -130,6 +136,14 @@ OwnedAttributeValue::~OwnedAttributeValue() {
|
|||
}
|
||||
}
|
||||
|
||||
void OwnedAttributeValue::mix(const AttributeValue& first, const AttributeValue& second, float alpha) {
|
||||
if (_attribute) {
|
||||
_attribute->destroy(_value);
|
||||
}
|
||||
_attribute = first.getAttribute();
|
||||
_value = _attribute->mix(first.getValue(), second.getValue(), alpha);
|
||||
}
|
||||
|
||||
OwnedAttributeValue& OwnedAttributeValue::operator=(const AttributeValue& other) {
|
||||
if (_attribute) {
|
||||
_attribute->destroy(_value);
|
||||
|
@ -206,6 +220,16 @@ bool QRgbAttribute::merge(void*& parent, void* children[]) const {
|
|||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
void* QRgbAttribute::mix(void* first, void* second, float alpha) const {
|
||||
QRgb firstValue = decodeInline<QRgb>(first);
|
||||
QRgb secondValue = decodeInline<QRgb>(second);
|
||||
return encodeInline(qRgba(
|
||||
glm::mix((float)qRed(firstValue), (float)qRed(secondValue), alpha),
|
||||
glm::mix((float)qGreen(firstValue), (float)qGreen(secondValue), alpha),
|
||||
glm::mix((float)qBlue(firstValue), (float)qBlue(secondValue), alpha),
|
||||
glm::mix((float)qAlpha(firstValue), (float)qAlpha(secondValue), alpha)));
|
||||
}
|
||||
|
||||
void* QRgbAttribute::createFromScript(const QScriptValue& value, QScriptEngine* engine) const {
|
||||
return encodeInline((QRgb)value.toUInt32());
|
||||
}
|
||||
|
@ -232,21 +256,23 @@ PackedNormalAttribute::PackedNormalAttribute(const QString& name, QRgb defaultVa
|
|||
|
||||
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);
|
||||
glm::vec3 total = unpackNormal(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);
|
||||
total += unpackNormal(value);
|
||||
allChildrenEqual &= (firstValue == value);
|
||||
}
|
||||
parent = encodeInline(packNormal(glm::normalize(glm::vec3(totalRed, totalGreen, totalBlue))));
|
||||
parent = encodeInline(packNormal(glm::normalize(total)));
|
||||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
void* PackedNormalAttribute::mix(void* first, void* second, float alpha) const {
|
||||
glm::vec3 firstNormal = unpackNormal(decodeInline<QRgb>(first));
|
||||
glm::vec3 secondNormal = unpackNormal(decodeInline<QRgb>(second));
|
||||
return encodeInline(packNormal(glm::normalize(glm::mix(firstNormal, secondNormal, alpha))));
|
||||
}
|
||||
|
||||
const float CHAR_SCALE = 127.0f;
|
||||
const float INVERSE_CHAR_SCALE = 1.0f / CHAR_SCALE;
|
||||
|
||||
|
@ -290,6 +316,10 @@ bool SharedObjectAttribute::merge(void*& parent, void* children[]) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
AttributeValue SharedObjectSetAttribute::split(const AttributeValue& parent) const {
|
||||
return AttributeValue();
|
||||
}
|
||||
|
||||
void* SharedObjectAttribute::createFromVariant(const QVariant& value) const {
|
||||
return create(encodeInline(value.value<SharedObjectPointer>()));
|
||||
}
|
||||
|
|
|
@ -71,9 +71,15 @@ public:
|
|||
/// Returns a reference to the standard QRgb "color" attribute.
|
||||
const AttributePointer& getColorAttribute() const { return _colorAttribute; }
|
||||
|
||||
/// Returns a reference to the standard QRgb "normal" attribute.
|
||||
/// Returns a reference to the standard packed normal "normal" attribute.
|
||||
const AttributePointer& getNormalAttribute() const { return _normalAttribute; }
|
||||
|
||||
/// Returns a reference to the standard QRgb "spannerColor" attribute.
|
||||
const AttributePointer& getSpannerColorAttribute() const { return _spannerColorAttribute; }
|
||||
|
||||
/// Returns a reference to the standard packed normal "spannerNormal" attribute.
|
||||
const AttributePointer& getSpannerNormalAttribute() const { return _spannerNormalAttribute; }
|
||||
|
||||
private:
|
||||
|
||||
static QScriptValue getAttribute(QScriptContext* context, QScriptEngine* engine);
|
||||
|
@ -83,6 +89,8 @@ private:
|
|||
AttributePointer _spannersAttribute;
|
||||
AttributePointer _colorAttribute;
|
||||
AttributePointer _normalAttribute;
|
||||
AttributePointer _spannerColorAttribute;
|
||||
AttributePointer _spannerNormalAttribute;
|
||||
};
|
||||
|
||||
/// Converts a value to a void pointer.
|
||||
|
@ -107,13 +115,14 @@ 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* getPointerValue() const { return static_cast<T*>(_value); }
|
||||
template<class T> T getSafeInlineValue() const { return _attribute ? decodeInline<T>(_value) : T(); }
|
||||
|
||||
void* copy() const;
|
||||
|
||||
bool isDefault() const;
|
||||
|
||||
AttributeValue split() const;
|
||||
|
||||
bool operator==(const AttributeValue& other) const;
|
||||
bool operator==(void* other) const;
|
||||
|
||||
|
@ -145,6 +154,9 @@ public:
|
|||
/// Destroys the current value, if any.
|
||||
~OwnedAttributeValue();
|
||||
|
||||
/// Sets this attribute to a mix of the first and second provided.
|
||||
void mix(const AttributeValue& first, const AttributeValue& second, float alpha);
|
||||
|
||||
/// Destroys the current value, if any, and copies the specified other value.
|
||||
OwnedAttributeValue& operator=(const AttributeValue& other);
|
||||
|
||||
|
@ -196,6 +208,12 @@ public:
|
|||
/// \return whether or not the children and parent values are all equal
|
||||
virtual bool merge(void*& parent, void* children[]) const = 0;
|
||||
|
||||
/// Returns the attribute value to pass to children below leaves (either the parent, or the default, or a null value).
|
||||
virtual AttributeValue split(const AttributeValue& parent) const { return parent; }
|
||||
|
||||
/// Mixes the first and the second, returning a new value with the result.
|
||||
virtual void* mix(void* first, void* second, float alpha) const = 0;
|
||||
|
||||
virtual void* getDefaultValue() const = 0;
|
||||
|
||||
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const { return create(); }
|
||||
|
@ -225,6 +243,8 @@ public:
|
|||
|
||||
virtual bool equal(void* first, void* second) const { return decodeInline<T>(first) == decodeInline<T>(second); }
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const { return create(alpha < 0.5f ? first : second); }
|
||||
|
||||
virtual void* getDefaultValue() const { return encodeInline(_defaultValue); }
|
||||
|
||||
protected:
|
||||
|
@ -245,27 +265,6 @@ template<class T, int bits> inline void InlineAttribute<T, bits>::write(Bitstrea
|
|||
}
|
||||
}
|
||||
|
||||
/// Provides merging using the =, ==, += and /= operators.
|
||||
template<class T, int bits = 32> class SimpleInlineAttribute : public InlineAttribute<T, bits> {
|
||||
public:
|
||||
|
||||
SimpleInlineAttribute(const QString& name, T defaultValue = T()) : InlineAttribute<T, bits>(name, defaultValue) { }
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
};
|
||||
|
||||
template<class T, int bits> inline bool SimpleInlineAttribute<T, bits>::merge(void*& parent, void* children[]) const {
|
||||
T& merged = *(T*)&parent;
|
||||
merged = decodeInline<T>(children[0]);
|
||||
bool allChildrenEqual = true;
|
||||
for (int i = 1; i < Attribute::MERGE_COUNT; i++) {
|
||||
merged += decodeInline<T>(children[i]);
|
||||
allChildrenEqual &= (decodeInline<T>(children[0]) == decodeInline<T>(children[i]));
|
||||
}
|
||||
merged /= Attribute::MERGE_COUNT;
|
||||
return allChildrenEqual;
|
||||
}
|
||||
|
||||
/// Provides appropriate averaging for RGBA values.
|
||||
class QRgbAttribute : public InlineAttribute<QRgb> {
|
||||
Q_OBJECT
|
||||
|
@ -277,6 +276,8 @@ public:
|
|||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
|
||||
virtual void* createFromScript(const QScriptValue& value, QScriptEngine* engine) const;
|
||||
|
||||
virtual void* createFromVariant(const QVariant& value) const;
|
||||
|
@ -293,6 +294,8 @@ public:
|
|||
Q_INVOKABLE PackedNormalAttribute(const QString& name = QString(), QRgb defaultValue = QRgb());
|
||||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
|
||||
virtual void* mix(void* first, void* second, float alpha) const;
|
||||
};
|
||||
|
||||
/// Packs a normal into an RGB value.
|
||||
|
@ -343,6 +346,8 @@ public:
|
|||
|
||||
virtual bool merge(void*& parent, void* children[]) const;
|
||||
|
||||
virtual AttributeValue split(const AttributeValue& parent) const;
|
||||
|
||||
virtual QWidget* createEditor(QWidget* parent = NULL) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -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).getInlineValue<SharedObjectSet>();
|
||||
SharedObjectSet set = info.inputValues.at(0).getSafeInlineValue<SharedObjectSet>();
|
||||
F(set, _object);
|
||||
info.outputValues[0] = AttributeValue(_attribute, encodeInline(set));
|
||||
return STOP_RECURSION;
|
||||
|
@ -177,7 +177,7 @@ template<SpannerUpdateFunction F> int SpannerUpdateVisitor<F>::visit(MetavoxelIn
|
|||
|
||||
void MetavoxelData::insert(const AttributePointer& attribute, const SharedObjectPointer& object) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
insert(attribute, spanner->getBounds(), spanner->getGranularity(), object);
|
||||
insert(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
|
||||
}
|
||||
|
||||
void MetavoxelData::insert(const AttributePointer& attribute, const Box& bounds,
|
||||
|
@ -192,7 +192,7 @@ void MetavoxelData::insert(const AttributePointer& attribute, const Box& bounds,
|
|||
|
||||
void MetavoxelData::remove(const AttributePointer& attribute, const SharedObjectPointer& object) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
remove(attribute, spanner->getBounds(), spanner->getGranularity(), object);
|
||||
remove(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
|
||||
}
|
||||
|
||||
void MetavoxelData::remove(const AttributePointer& attribute, const Box& bounds,
|
||||
|
@ -203,7 +203,7 @@ void MetavoxelData::remove(const AttributePointer& attribute, const Box& bounds,
|
|||
|
||||
void MetavoxelData::toggle(const AttributePointer& attribute, const SharedObjectPointer& object) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
toggle(attribute, spanner->getBounds(), spanner->getGranularity(), object);
|
||||
toggle(attribute, spanner->getBounds(), spanner->getPlacementGranularity(), object);
|
||||
}
|
||||
|
||||
void MetavoxelData::toggle(const AttributePointer& attribute, const Box& bounds,
|
||||
|
@ -875,7 +875,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).getInlineValue<SharedObjectSet>()) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getSafeInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->testAndSetVisited()) {
|
||||
if (!visit(spanner)) {
|
||||
|
@ -927,7 +927,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).getInlineValue<SharedObjectSet>()) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getSafeInlineValue<SharedObjectSet>()) {
|
||||
Spanner* spanner = static_cast<Spanner*>(object.data());
|
||||
if (spanner->testAndSetVisited()) {
|
||||
SpannerDistance spannerDistance = { spanner };
|
||||
|
@ -991,7 +991,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.split();
|
||||
}
|
||||
for (int j = 0; j < visitation.outputNodes.size(); j++) {
|
||||
MetavoxelNode* node = visitation.outputNodes.at(j);
|
||||
|
@ -1202,11 +1202,13 @@ AttributeValue MetavoxelVisitation::getInheritedOutputValue(int index) const {
|
|||
return AttributeValue(visitor.getOutputs().at(index));
|
||||
}
|
||||
|
||||
const float DEFAULT_GRANULARITY = 0.01f;
|
||||
const float DEFAULT_PLACEMENT_GRANULARITY = 0.01f;
|
||||
const float DEFAULT_VOXELIZATION_GRANULARITY = powf(2.0f, -3.0f);
|
||||
|
||||
Spanner::Spanner() :
|
||||
_renderer(NULL),
|
||||
_granularity(DEFAULT_GRANULARITY),
|
||||
_placementGranularity(DEFAULT_PLACEMENT_GRANULARITY),
|
||||
_voxelizationGranularity(DEFAULT_VOXELIZATION_GRANULARITY),
|
||||
_lastVisit(0) {
|
||||
}
|
||||
|
||||
|
@ -1223,10 +1225,19 @@ const QVector<AttributePointer>& Spanner::getAttributes() const {
|
|||
return emptyVector;
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Spanner::getVoxelizedAttributes() const {
|
||||
static QVector<AttributePointer> emptyVector;
|
||||
return emptyVector;
|
||||
}
|
||||
|
||||
bool Spanner::getAttributeValues(MetavoxelInfo& info) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spanner::blendAttributeValues(MetavoxelInfo& info) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Spanner::testAndSetVisited() {
|
||||
if (_lastVisit == _visit) {
|
||||
return false;
|
||||
|
@ -1320,6 +1331,13 @@ const QVector<AttributePointer>& Sphere::getAttributes() const {
|
|||
return attributes;
|
||||
}
|
||||
|
||||
const QVector<AttributePointer>& Sphere::getVoxelizedAttributes() const {
|
||||
static QVector<AttributePointer> attributes = QVector<AttributePointer>() <<
|
||||
AttributeRegistry::getInstance()->getSpannerColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getSpannerNormalAttribute();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
||||
// bounds check
|
||||
Box bounds = info.getBounds();
|
||||
|
@ -1339,7 +1357,7 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
|||
getNormal(info);
|
||||
return false;
|
||||
}
|
||||
if (info.size <= getGranularity()) {
|
||||
if (info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(qRgba(
|
||||
|
@ -1351,6 +1369,41 @@ bool Sphere::getAttributeValues(MetavoxelInfo& info) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Sphere::blendAttributeValues(MetavoxelInfo& info) const {
|
||||
// bounds check
|
||||
Box bounds = info.getBounds();
|
||||
if (!getBounds().intersects(bounds)) {
|
||||
return false;
|
||||
}
|
||||
// count the points inside the sphere
|
||||
int pointsWithin = 0;
|
||||
for (int i = 0; i < Box::VERTEX_COUNT; i++) {
|
||||
if (glm::distance(bounds.getVertex(i), getTranslation()) <= getScale()) {
|
||||
pointsWithin++;
|
||||
}
|
||||
}
|
||||
if (pointsWithin == Box::VERTEX_COUNT) {
|
||||
// entirely contained
|
||||
info.outputValues[0] = AttributeValue(getAttributes().at(0), encodeInline<QRgb>(_color.rgba()));
|
||||
info.outputValues[1] = getNormal(info);
|
||||
return false;
|
||||
}
|
||||
if (info.size <= getVoxelizationGranularity()) {
|
||||
// best guess
|
||||
if (pointsWithin > 0) {
|
||||
int oldAlpha = qAlpha(info.inputValues.at(0).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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sphere::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
return findRaySphereIntersection(origin, direction, getTranslation(), getScale(), distance);
|
||||
}
|
||||
|
@ -1364,7 +1417,7 @@ void Sphere::updateBounds() {
|
|||
setBounds(Box(getTranslation() - extent, getTranslation() + extent));
|
||||
}
|
||||
|
||||
void Sphere::getNormal(MetavoxelInfo& info) const {
|
||||
AttributeValue Sphere::getNormal(MetavoxelInfo& info) const {
|
||||
glm::vec3 normal = info.getCenter() - getTranslation();
|
||||
float length = glm::length(normal);
|
||||
QRgb color;
|
||||
|
@ -1379,7 +1432,7 @@ void Sphere::getNormal(MetavoxelInfo& info) const {
|
|||
const QRgb DEFAULT_NORMAL = 0x007F00;
|
||||
color = DEFAULT_NORMAL;
|
||||
}
|
||||
info.outputValues[1] = AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
|
||||
return AttributeValue(getAttributes().at(1), encodeInline<QRgb>(color));
|
||||
}
|
||||
|
||||
StaticModel::StaticModel() {
|
||||
|
|
|
@ -408,8 +408,9 @@ public:
|
|||
class Spanner : public SharedObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(Box bounds MEMBER _bounds WRITE setBounds NOTIFY boundsChanged DESIGNABLE false)
|
||||
Q_PROPERTY(float granularity MEMBER _granularity DESIGNABLE false)
|
||||
|
||||
Q_PROPERTY(float placementGranularity MEMBER _placementGranularity DESIGNABLE false)
|
||||
Q_PROPERTY(float voxelizationGranularity MEMBER _voxelizationGranularity DESIGNABLE false)
|
||||
|
||||
public:
|
||||
|
||||
/// Increments the value of the global visit counter.
|
||||
|
@ -420,16 +421,26 @@ public:
|
|||
void setBounds(const Box& bounds);
|
||||
const Box& getBounds() const { return _bounds; }
|
||||
|
||||
void setGranularity(float granularity) { _granularity = granularity; }
|
||||
float getGranularity() const { return _granularity; }
|
||||
void setPlacementGranularity(float granularity) { _placementGranularity = granularity; }
|
||||
float getPlacementGranularity() const { return _placementGranularity; }
|
||||
|
||||
void setVoxelizationGranularity(float granularity) { _voxelizationGranularity = granularity; }
|
||||
float getVoxelizationGranularity() const { return _voxelizationGranularity; }
|
||||
|
||||
/// Returns a reference to the list of attributes associated with this spanner.
|
||||
virtual const QVector<AttributePointer>& getAttributes() const;
|
||||
|
||||
/// Returns a reference to the list of corresponding attributes that we voxelize the spanner into.
|
||||
virtual const QVector<AttributePointer>& getVoxelizedAttributes() const;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Blends the attribute values associated with this spanner into the supplied info.
|
||||
/// \return true to recurse, false to stop
|
||||
virtual bool blendAttributeValues(MetavoxelInfo& info) 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.
|
||||
bool testAndSetVisited();
|
||||
|
@ -455,7 +466,8 @@ protected:
|
|||
private:
|
||||
|
||||
Box _bounds;
|
||||
float _granularity;
|
||||
float _placementGranularity;
|
||||
float _voxelizationGranularity;
|
||||
int _lastVisit; ///< the identifier of the last visit
|
||||
|
||||
static int _visit; ///< the global visit counter
|
||||
|
@ -521,7 +533,9 @@ public:
|
|||
const QColor& getColor() const { return _color; }
|
||||
|
||||
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 findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||
|
||||
signals:
|
||||
|
@ -538,7 +552,7 @@ private slots:
|
|||
|
||||
private:
|
||||
|
||||
void getNormal(MetavoxelInfo& info) const;
|
||||
AttributeValue getNormal(MetavoxelInfo& info) const;
|
||||
|
||||
QColor _color;
|
||||
};
|
||||
|
|
|
@ -104,8 +104,33 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
|
|||
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 InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
data.insert(attribute, spanner);
|
||||
data.insert(attribute, this->spanner);
|
||||
|
||||
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
|
||||
SetSpannerEditVisitor visitor(spanner->getVoxelizedAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
||||
RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id) :
|
||||
|
@ -130,27 +155,6 @@ void ClearSpannersEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& o
|
|||
data.clear(attribute);
|
||||
}
|
||||
|
||||
class SetSpannerEditVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
SetSpannerEditVisitor(Spanner* spanner);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
Spanner* _spanner;
|
||||
};
|
||||
|
||||
SetSpannerEditVisitor::SetSpannerEditVisitor(Spanner* spanner) :
|
||||
MetavoxelVisitor(spanner->getAttributes(), spanner->getAttributes()),
|
||||
_spanner(spanner) {
|
||||
}
|
||||
|
||||
int SetSpannerEditVisitor::visit(MetavoxelInfo& info) {
|
||||
return _spanner->getAttributeValues(info) ? DEFAULT_ORDER : STOP_RECURSION;
|
||||
}
|
||||
|
||||
SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) :
|
||||
spanner(spanner) {
|
||||
}
|
||||
|
@ -163,6 +167,6 @@ void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& obje
|
|||
data.expand();
|
||||
}
|
||||
|
||||
SetSpannerEditVisitor visitor(spanner);
|
||||
SetSpannerEditVisitor visitor(spanner->getAttributes(), spanner);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue