mirror of
https://github.com/lubosz/overte.git
synced 2025-04-19 16:44:04 +02:00
Added per-attribute LOD threshold multiplier; things like spanners need
different LOD thresholds than, say, voxels.
This commit is contained in:
parent
35be8cd941
commit
66e322ec55
4 changed files with 61 additions and 17 deletions
|
@ -28,6 +28,10 @@ AttributeRegistry::AttributeRegistry() :
|
|||
_spannersAttribute(registerAttribute(new SpannerSetAttribute("spanners", &Spanner::staticMetaObject))),
|
||||
_colorAttribute(registerAttribute(new QRgbAttribute("color"))),
|
||||
_normalAttribute(registerAttribute(new PackedNormalAttribute("normal", qRgb(0, 127, 0)))) {
|
||||
|
||||
// our baseline LOD threshold is for voxels; spanners are a different story
|
||||
const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 4.0f;
|
||||
_spannersAttribute->setLODThresholdMultiplier(SPANNER_LOD_THRESHOLD_MULTIPLIER);
|
||||
}
|
||||
|
||||
static QScriptValue qDebugFunction(QScriptContext* context, QScriptEngine* engine) {
|
||||
|
@ -143,7 +147,8 @@ OwnedAttributeValue& OwnedAttributeValue::operator=(const OwnedAttributeValue& o
|
|||
return *this;
|
||||
}
|
||||
|
||||
Attribute::Attribute(const QString& name) {
|
||||
Attribute::Attribute(const QString& name) :
|
||||
_lodThresholdMultiplier(1.0f) {
|
||||
setObjectName(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
/// Represents a registered attribute.
|
||||
class Attribute : public SharedObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float lodThresholdMultiplier MEMBER _lodThresholdMultiplier)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -163,6 +164,9 @@ public:
|
|||
|
||||
Q_INVOKABLE QString getName() const { return objectName(); }
|
||||
|
||||
float getLODThresholdMultiplier() const { return _lodThresholdMultiplier; }
|
||||
void setLODThresholdMultiplier(float multiplier) { _lodThresholdMultiplier = multiplier; }
|
||||
|
||||
void* create() const { return create(getDefaultValue()); }
|
||||
virtual void* create(void* copy) const = 0;
|
||||
virtual void destroy(void* value) const = 0;
|
||||
|
@ -197,6 +201,10 @@ public:
|
|||
/// Creates a widget to use to edit values of this attribute, or returns NULL if the attribute isn't editable.
|
||||
/// The widget should have a single "user" property that will be used to get/set the value.
|
||||
virtual QWidget* createEditor(QWidget* parent = NULL) const { return NULL; }
|
||||
|
||||
private:
|
||||
|
||||
float _lodThresholdMultiplier;
|
||||
};
|
||||
|
||||
/// A simple attribute class that stores its values inline.
|
||||
|
|
|
@ -29,15 +29,16 @@ MetavoxelLOD::MetavoxelLOD(const glm::vec3& position, float threshold) :
|
|||
threshold(threshold) {
|
||||
}
|
||||
|
||||
bool MetavoxelLOD::shouldSubdivide(const glm::vec3& minimum, float size) const {
|
||||
return size >= glm::distance(position, minimum + glm::vec3(size, size, size) * 0.5f) * threshold;
|
||||
bool MetavoxelLOD::shouldSubdivide(const glm::vec3& minimum, float size, float multiplier) const {
|
||||
return size >= glm::distance(position, minimum + glm::vec3(size, size, size) * 0.5f) * threshold * multiplier;
|
||||
}
|
||||
|
||||
bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference) const {
|
||||
bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size,
|
||||
const MetavoxelLOD& reference, float multiplier) const {
|
||||
if (position == reference.position && threshold >= reference.threshold) {
|
||||
return false; // first off, nothing becomes subdivided if it doesn't change
|
||||
}
|
||||
if (!shouldSubdivide(minimum, size)) {
|
||||
if (!shouldSubdivide(minimum, size, multiplier)) {
|
||||
return false; // this one must be subdivided
|
||||
}
|
||||
// the general check is whether we've gotten closer (as multiplied by the threshold) to any point in the volume,
|
||||
|
@ -468,6 +469,18 @@ static glm::vec3 getNextMinimum(const glm::vec3& minimum, float nextSize, int in
|
|||
(index & Z_MAXIMUM_FLAG) ? nextSize : 0.0f);
|
||||
}
|
||||
|
||||
bool MetavoxelStreamState::shouldSubdivide() const {
|
||||
return lod.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier());
|
||||
}
|
||||
|
||||
bool MetavoxelStreamState::shouldSubdivideReference() const {
|
||||
return referenceLOD.shouldSubdivide(minimum, size, attribute->getLODThresholdMultiplier());
|
||||
}
|
||||
|
||||
bool MetavoxelStreamState::becameSubdivided() const {
|
||||
return lod.becameSubdivided(minimum, size, referenceLOD, attribute->getLODThresholdMultiplier());
|
||||
}
|
||||
|
||||
void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) {
|
||||
minimum = getNextMinimum(lastMinimum, size, index);
|
||||
}
|
||||
|
@ -831,7 +844,16 @@ MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
|||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
_inputs(inputs),
|
||||
_outputs(outputs),
|
||||
_lod(lod) {
|
||||
_lod(lod),
|
||||
_minimumLODThresholdMultiplier(FLT_MAX) {
|
||||
|
||||
// find the minimum LOD threshold multiplier over all attributes
|
||||
foreach (const AttributePointer& attribute, _inputs) {
|
||||
_minimumLODThresholdMultiplier = qMin(attribute->getLODThresholdMultiplier(), _minimumLODThresholdMultiplier);
|
||||
}
|
||||
foreach (const AttributePointer& attribute, _outputs) {
|
||||
_minimumLODThresholdMultiplier = qMin(attribute->getLODThresholdMultiplier(), _minimumLODThresholdMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
MetavoxelVisitor::~MetavoxelVisitor() {
|
||||
|
@ -928,8 +950,11 @@ DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
|||
}
|
||||
|
||||
bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
bool shouldSubdivide = visitation.visitor.getLOD().shouldSubdivide(visitation.info.minimum, visitation.info.size);
|
||||
visitation.info.isLeaf = !shouldSubdivide || visitation.allInputNodesLeaves();
|
||||
// save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute
|
||||
float lodBase = glm::distance(visitation.visitor.getLOD().position, visitation.info.getCenter()) *
|
||||
visitation.visitor.getLOD().threshold;
|
||||
visitation.info.isLeaf = (visitation.info.size < lodBase * visitation.visitor.getMinimumLODThresholdMultiplier()) ||
|
||||
visitation.allInputNodesLeaves();
|
||||
int encodedOrder = visitation.visitor.visit(visitation.info);
|
||||
if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) {
|
||||
return false;
|
||||
|
@ -955,20 +980,23 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
{ 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
|
||||
const int ORDER_ELEMENT_BITS = 3;
|
||||
const int ORDER_ELEMENT_MASK = (1 << ORDER_ELEMENT_BITS) - 1;
|
||||
int index = encodedOrder & ORDER_ELEMENT_MASK;
|
||||
encodedOrder >>= ORDER_ELEMENT_BITS;
|
||||
for (int j = 0; j < visitation.inputNodes.size(); j++) {
|
||||
MetavoxelNode* node = visitation.inputNodes.at(j);
|
||||
MetavoxelNode* child = (node && shouldSubdivide) ? node->getChild(index) : NULL;
|
||||
const AttributeValue& parentValue = visitation.info.inputValues.at(j);
|
||||
MetavoxelNode* child = (node && (visitation.info.size >= lodBase *
|
||||
parentValue.getAttribute()->getLODThresholdMultiplier())) ? node->getChild(index) : NULL;
|
||||
nextVisitation.info.inputValues[j] = ((nextVisitation.inputNodes[j] = child)) ?
|
||||
child->getAttributeValue(visitation.info.inputValues[j].getAttribute()) :
|
||||
visitation.info.inputValues[j];
|
||||
child->getAttributeValue(parentValue.getAttribute()) : parentValue;
|
||||
}
|
||||
for (int j = 0; j < visitation.outputNodes.size(); j++) {
|
||||
MetavoxelNode* node = visitation.outputNodes.at(j);
|
||||
MetavoxelNode* child = (node && shouldSubdivide) ? node->getChild(index) : NULL;
|
||||
MetavoxelNode* child = (node && (visitation.info.size >= lodBase *
|
||||
visitation.visitor.getOutputs().at(j)->getLODThresholdMultiplier())) ? node->getChild(index) : NULL;
|
||||
nextVisitation.outputNodes[j] = child;
|
||||
}
|
||||
nextVisitation.info.minimum = getNextMinimum(visitation.info.minimum, nextVisitation.info.size, index);
|
||||
|
|
|
@ -43,10 +43,10 @@ public:
|
|||
|
||||
bool isValid() const { return threshold > 0.0f; }
|
||||
|
||||
bool shouldSubdivide(const glm::vec3& minimum, float size) const;
|
||||
bool shouldSubdivide(const glm::vec3& minimum, float size, float multiplier = 1.0f) const;
|
||||
|
||||
/// Checks whether the node or any of the nodes underneath it have had subdivision enabled as compared to the reference.
|
||||
bool becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference) const;
|
||||
bool becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(MetavoxelLOD)
|
||||
|
@ -119,9 +119,9 @@ public:
|
|||
const MetavoxelLOD& lod;
|
||||
const MetavoxelLOD& referenceLOD;
|
||||
|
||||
bool shouldSubdivide() const { return lod.shouldSubdivide(minimum, size); }
|
||||
bool shouldSubdivideReference() const { return referenceLOD.shouldSubdivide(minimum, size); }
|
||||
bool becameSubdivided() const { return lod.becameSubdivided(minimum, size, referenceLOD); }
|
||||
bool shouldSubdivide() const;
|
||||
bool shouldSubdivideReference() const;
|
||||
bool becameSubdivided() const;
|
||||
|
||||
void setMinimum(const glm::vec3& lastMinimum, int index);
|
||||
};
|
||||
|
@ -230,6 +230,8 @@ public:
|
|||
|
||||
void setLOD(const MetavoxelLOD& lod) { _lod = lod; }
|
||||
|
||||
float getMinimumLODThresholdMultiplier() const { return _minimumLODThresholdMultiplier; }
|
||||
|
||||
/// Prepares for a new tour of the metavoxel data.
|
||||
virtual void prepare();
|
||||
|
||||
|
@ -243,6 +245,7 @@ protected:
|
|||
QVector<AttributePointer> _inputs;
|
||||
QVector<AttributePointer> _outputs;
|
||||
MetavoxelLOD _lod;
|
||||
float _minimumLODThresholdMultiplier;
|
||||
};
|
||||
|
||||
/// Base class for visitors to spanners.
|
||||
|
|
Loading…
Reference in a new issue