mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 12:49:34 +02:00
Collapse nodes when they fall out of LOD.
This commit is contained in:
parent
a722c4ba0a
commit
f356f0652b
2 changed files with 111 additions and 71 deletions
|
@ -54,6 +54,18 @@ bool MetavoxelLOD::becameSubdivided(const glm::vec3& minimum, float size,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MetavoxelLOD::becameSubdividedOrCollapsed(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 or collapsed if it doesn't change
|
||||||
|
}
|
||||||
|
if (!(shouldSubdivide(minimum, size, multiplier) || reference.shouldSubdivide(minimum, size, multiplier))) {
|
||||||
|
return false; // this one or the reference must be subdivided
|
||||||
|
}
|
||||||
|
// TODO: find some way of culling subtrees that can't possibly contain subdivided or collapsed nodes
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
MetavoxelData::MetavoxelData() : _size(1.0f) {
|
MetavoxelData::MetavoxelData() : _size(1.0f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,53 +579,67 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD
|
||||||
// shallow copy the reference
|
// shallow copy the reference
|
||||||
*this = reference;
|
*this = reference;
|
||||||
|
|
||||||
|
QHash<AttributePointer, MetavoxelNode*> remainingRoots = _roots;
|
||||||
|
glm::vec3 minimum = getMinimum();
|
||||||
|
|
||||||
bool changed;
|
bool changed;
|
||||||
in >> changed;
|
in >> changed;
|
||||||
if (!changed) {
|
if (changed) {
|
||||||
return;
|
bool sizeChanged;
|
||||||
}
|
in >> sizeChanged;
|
||||||
|
if (sizeChanged) {
|
||||||
bool sizeChanged;
|
float size;
|
||||||
in >> sizeChanged;
|
in >> size;
|
||||||
if (sizeChanged) {
|
while (_size < size) {
|
||||||
float size;
|
expand();
|
||||||
in >> size;
|
|
||||||
while (_size < size) {
|
|
||||||
expand();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
forever {
|
|
||||||
AttributePointer attribute;
|
|
||||||
in >> attribute;
|
|
||||||
if (!attribute) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MetavoxelStreamBase base = { attribute, in, lod, referenceLOD };
|
|
||||||
MetavoxelStreamState state = { base, getMinimum(), _size };
|
|
||||||
MetavoxelNode* oldRoot = _roots.value(attribute);
|
|
||||||
if (oldRoot) {
|
|
||||||
bool changed;
|
|
||||||
in >> changed;
|
|
||||||
if (changed) {
|
|
||||||
oldRoot->incrementReferenceCount();
|
|
||||||
attribute->readMetavoxelDelta(*this, *oldRoot, state);
|
|
||||||
oldRoot->decrementReferenceCount(attribute);
|
|
||||||
} else {
|
|
||||||
attribute->readMetavoxelSubdivision(*this, state);
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
attribute->readMetavoxelRoot(*this, state);
|
|
||||||
}
|
forever {
|
||||||
|
AttributePointer attribute;
|
||||||
|
in >> attribute;
|
||||||
|
if (!attribute) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MetavoxelStreamBase base = { attribute, in, lod, referenceLOD };
|
||||||
|
MetavoxelStreamState state = { base, minimum, _size };
|
||||||
|
MetavoxelNode* oldRoot = _roots.value(attribute);
|
||||||
|
if (oldRoot) {
|
||||||
|
bool changed;
|
||||||
|
in >> changed;
|
||||||
|
if (changed) {
|
||||||
|
oldRoot->incrementReferenceCount();
|
||||||
|
attribute->readMetavoxelDelta(*this, *oldRoot, state);
|
||||||
|
oldRoot->decrementReferenceCount(attribute);
|
||||||
|
} else {
|
||||||
|
attribute->readMetavoxelSubdivision(*this, state);
|
||||||
|
}
|
||||||
|
remainingRoots.remove(attribute);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
attribute->readMetavoxelRoot(*this, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forever {
|
||||||
|
AttributePointer attribute;
|
||||||
|
in >> attribute;
|
||||||
|
if (!attribute) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_roots.take(attribute)->decrementReferenceCount(attribute);
|
||||||
|
remainingRoots.remove(attribute);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forever {
|
// read subdivisions for the remaining roots if there's any chance of a collapse
|
||||||
AttributePointer attribute;
|
if (!(lod.position == referenceLOD.position && lod.threshold <= referenceLOD.threshold)) {
|
||||||
in >> attribute;
|
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = remainingRoots.constBegin();
|
||||||
if (!attribute) {
|
it != remainingRoots.constEnd(); it++) {
|
||||||
break;
|
MetavoxelStreamBase base = { it.key(), in, lod, referenceLOD };
|
||||||
|
MetavoxelStreamState state = { base, minimum, _size };
|
||||||
|
it.key()->readMetavoxelSubdivision(*this, state);
|
||||||
}
|
}
|
||||||
_roots.take(attribute)->decrementReferenceCount(attribute);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,6 +814,10 @@ bool MetavoxelStreamState::becameSubdivided() const {
|
||||||
return base.lod.becameSubdivided(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier());
|
return base.lod.becameSubdivided(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MetavoxelStreamState::becameSubdividedOrCollapsed() const {
|
||||||
|
return base.lod.becameSubdividedOrCollapsed(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier());
|
||||||
|
}
|
||||||
|
|
||||||
void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) {
|
void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) {
|
||||||
minimum = getNextMinimum(lastMinimum, size, index);
|
minimum = getNextMinimum(lastMinimum, size, index);
|
||||||
}
|
}
|
||||||
|
@ -923,7 +953,7 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta
|
||||||
_children[i] = new MetavoxelNode(state.base.attribute);
|
_children[i] = new MetavoxelNode(state.base.attribute);
|
||||||
_children[i]->readDelta(*reference._children[i], nextState);
|
_children[i]->readDelta(*reference._children[i], nextState);
|
||||||
} else {
|
} else {
|
||||||
if (nextState.becameSubdivided()) {
|
if (nextState.becameSubdividedOrCollapsed()) {
|
||||||
_children[i] = reference._children[i]->readSubdivision(nextState);
|
_children[i] = reference._children[i]->readSubdivision(nextState);
|
||||||
if (_children[i] == reference._children[i]) {
|
if (_children[i] == reference._children[i]) {
|
||||||
_children[i]->incrementReferenceCount();
|
_children[i]->incrementReferenceCount();
|
||||||
|
@ -972,42 +1002,46 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt
|
||||||
}
|
}
|
||||||
|
|
||||||
MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) {
|
MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) {
|
||||||
if (!state.shouldSubdivideReference()) {
|
if (state.shouldSubdivide()) {
|
||||||
bool leaf;
|
if (!state.shouldSubdivideReference()) {
|
||||||
state.base.stream >> leaf;
|
bool leaf;
|
||||||
if (leaf) {
|
state.base.stream >> leaf;
|
||||||
return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.base.attribute));
|
if (leaf) {
|
||||||
|
return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||||
} else {
|
|
||||||
MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.base.attribute));
|
} else {
|
||||||
|
MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||||
|
MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f };
|
||||||
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
|
nextState.setMinimum(state.minimum, i);
|
||||||
|
newNode->_children[i] = new MetavoxelNode(state.base.attribute);
|
||||||
|
newNode->_children[i]->read(nextState);
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
} else if (!isLeaf()) {
|
||||||
|
MetavoxelNode* node = this;
|
||||||
MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f };
|
MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f };
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
nextState.setMinimum(state.minimum, i);
|
nextState.setMinimum(state.minimum, i);
|
||||||
newNode->_children[i] = new MetavoxelNode(state.base.attribute);
|
if (nextState.becameSubdividedOrCollapsed()) {
|
||||||
newNode->_children[i]->read(nextState);
|
MetavoxelNode* child = _children[i]->readSubdivision(nextState);
|
||||||
}
|
if (child != _children[i]) {
|
||||||
return newNode;
|
if (node == this) {
|
||||||
}
|
node = new MetavoxelNode(state.base.attribute, this);
|
||||||
} else if (!isLeaf()) {
|
}
|
||||||
MetavoxelNode* node = this;
|
node->_children[i] = child;
|
||||||
MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f };
|
_children[i]->decrementReferenceCount(state.base.attribute);
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
|
||||||
nextState.setMinimum(state.minimum, i);
|
|
||||||
if (nextState.becameSubdivided()) {
|
|
||||||
MetavoxelNode* child = _children[i]->readSubdivision(nextState);
|
|
||||||
if (child != _children[i]) {
|
|
||||||
if (node == this) {
|
|
||||||
node = new MetavoxelNode(state.base.attribute, this);
|
|
||||||
}
|
}
|
||||||
node->_children[i] = child;
|
|
||||||
_children[i]->decrementReferenceCount(state.base.attribute);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node != this) {
|
||||||
|
node->mergeChildren(state.base.attribute, true);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
if (node != this) {
|
} else if (!isLeaf()) {
|
||||||
node->mergeChildren(state.base.attribute, true);
|
return new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,11 @@ public:
|
||||||
|
|
||||||
/// Checks whether the node or any of the nodes underneath it have had subdivision enabled as compared to the reference.
|
/// 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, float multiplier = 1.0f) const;
|
bool becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference, float multiplier = 1.0f) const;
|
||||||
|
|
||||||
|
/// Checks whether the node or any of the nodes underneath it have had subdivision
|
||||||
|
/// enabled or disabled as compared to the reference.
|
||||||
|
bool becameSubdividedOrCollapsed(const glm::vec3& minimum, float size,
|
||||||
|
const MetavoxelLOD& reference, float multiplier = 1.0f) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_STREAMABLE_METATYPE(MetavoxelLOD)
|
DECLARE_STREAMABLE_METATYPE(MetavoxelLOD)
|
||||||
|
@ -181,6 +186,7 @@ public:
|
||||||
bool shouldSubdivide() const;
|
bool shouldSubdivide() const;
|
||||||
bool shouldSubdivideReference() const;
|
bool shouldSubdivideReference() const;
|
||||||
bool becameSubdivided() const;
|
bool becameSubdivided() const;
|
||||||
|
bool becameSubdividedOrCollapsed() const;
|
||||||
|
|
||||||
void setMinimum(const glm::vec3& lastMinimum, int index);
|
void setMinimum(const glm::vec3& lastMinimum, int index);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue