mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 19:04:32 +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;
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
|
@ -567,53 +579,67 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD
|
|||
// shallow copy the reference
|
||||
*this = reference;
|
||||
|
||||
QHash<AttributePointer, MetavoxelNode*> remainingRoots = _roots;
|
||||
glm::vec3 minimum = getMinimum();
|
||||
|
||||
bool changed;
|
||||
in >> changed;
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool sizeChanged;
|
||||
in >> sizeChanged;
|
||||
if (sizeChanged) {
|
||||
float size;
|
||||
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);
|
||||
if (changed) {
|
||||
bool sizeChanged;
|
||||
in >> sizeChanged;
|
||||
if (sizeChanged) {
|
||||
float size;
|
||||
in >> size;
|
||||
while (_size < size) {
|
||||
expand();
|
||||
}
|
||||
} 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 {
|
||||
AttributePointer attribute;
|
||||
in >> attribute;
|
||||
if (!attribute) {
|
||||
break;
|
||||
// read subdivisions for the remaining roots if there's any chance of a collapse
|
||||
if (!(lod.position == referenceLOD.position && lod.threshold <= referenceLOD.threshold)) {
|
||||
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = remainingRoots.constBegin();
|
||||
it != remainingRoots.constEnd(); it++) {
|
||||
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());
|
||||
}
|
||||
|
||||
bool MetavoxelStreamState::becameSubdividedOrCollapsed() const {
|
||||
return base.lod.becameSubdividedOrCollapsed(minimum, size, base.referenceLOD, base.attribute->getLODThresholdMultiplier());
|
||||
}
|
||||
|
||||
void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int 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]->readDelta(*reference._children[i], nextState);
|
||||
} else {
|
||||
if (nextState.becameSubdivided()) {
|
||||
if (nextState.becameSubdividedOrCollapsed()) {
|
||||
_children[i] = reference._children[i]->readSubdivision(nextState);
|
||||
if (_children[i] == reference._children[i]) {
|
||||
_children[i]->incrementReferenceCount();
|
||||
|
@ -972,42 +1002,46 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt
|
|||
}
|
||||
|
||||
MetavoxelNode* MetavoxelNode::readSubdivision(MetavoxelStreamState& state) {
|
||||
if (!state.shouldSubdivideReference()) {
|
||||
bool leaf;
|
||||
state.base.stream >> leaf;
|
||||
if (leaf) {
|
||||
return isLeaf() ? this : new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||
|
||||
} else {
|
||||
MetavoxelNode* newNode = new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||
if (state.shouldSubdivide()) {
|
||||
if (!state.shouldSubdivideReference()) {
|
||||
bool leaf;
|
||||
state.base.stream >> leaf;
|
||||
if (leaf) {
|
||||
return isLeaf() ? this : 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 };
|
||||
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 };
|
||||
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);
|
||||
if (nextState.becameSubdividedOrCollapsed()) {
|
||||
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);
|
||||
}
|
||||
node->_children[i] = child;
|
||||
_children[i]->decrementReferenceCount(state.base.attribute);
|
||||
}
|
||||
}
|
||||
if (node != this) {
|
||||
node->mergeChildren(state.base.attribute, true);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
if (node != this) {
|
||||
node->mergeChildren(state.base.attribute, true);
|
||||
}
|
||||
return node;
|
||||
} else if (!isLeaf()) {
|
||||
return new MetavoxelNode(getAttributeValue(state.base.attribute));
|
||||
}
|
||||
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.
|
||||
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)
|
||||
|
@ -181,6 +186,7 @@ public:
|
|||
bool shouldSubdivide() const;
|
||||
bool shouldSubdivideReference() const;
|
||||
bool becameSubdivided() const;
|
||||
bool becameSubdividedOrCollapsed() const;
|
||||
|
||||
void setMinimum(const glm::vec3& lastMinimum, int index);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue