Working on subdivision.

This commit is contained in:
Andrzej Kapolka 2014-03-05 14:13:20 -08:00
parent 63b4a2453b
commit c4f29005a0
4 changed files with 159 additions and 15 deletions

View file

@ -165,6 +165,14 @@ void Attribute::writeDelta(const MetavoxelNode& root, const MetavoxelNode& refer
root.writeDelta(reference, state);
}
void Attribute::readSubdivision(MetavoxelData& data, MetavoxelStreamState& state) {
data.getRoot(state.attribute)->readSubdivision(state);
}
void Attribute::writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) {
root.writeSubdivision(state);
}
QRgbAttribute::QRgbAttribute(const QString& name, QRgb defaultValue) :
InlineAttribute<QRgb>(name, defaultValue) {
}
@ -313,3 +321,21 @@ void SpannerSetAttribute::writeDelta(const MetavoxelNode& root, const MetavoxelN
root.writeSpannerDelta(reference, state);
state.stream << SharedObjectPointer();
}
void SpannerSetAttribute::readSubdivision(MetavoxelData& data, MetavoxelStreamState& state) {
forever {
SharedObjectPointer object;
state.stream >> object;
if (!object) {
break;
}
data.insert(state.attribute, object);
}
}
void SpannerSetAttribute::writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) {
Spanner::incrementVisit();
root.writeSpannerSubdivision(state);
state.stream << SharedObjectPointer();
}

View file

@ -178,6 +178,9 @@ public:
virtual void readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state);
virtual void writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state);
virtual void readSubdivision(MetavoxelData& data, MetavoxelStreamState& state);
virtual void writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state);
virtual bool equal(void* first, void* second) const = 0;
@ -332,6 +335,9 @@ public:
virtual void readDelta(MetavoxelData& data, const MetavoxelNode& reference, MetavoxelStreamState& state);
virtual void writeDelta(const MetavoxelNode& root, const MetavoxelNode& reference, MetavoxelStreamState& state);
virtual void readSubdivision(MetavoxelData& data, MetavoxelStreamState& state);
virtual void writeSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state);
};
#endif /* defined(__interface__AttributeRegistry__) */

View file

@ -31,6 +31,10 @@ 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::becameSubdivided(const glm::vec3& minimum, float size, const MetavoxelLOD& reference) const {
return shouldSubdivide(minimum, size) && !reference.shouldSubdivide(minimum, size);
}
MetavoxelData::MetavoxelData() : _size(1.0f) {
}
@ -295,10 +299,15 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD
MetavoxelStreamState state = { getMinimum(), _size, attribute, in, lod, referenceLOD };
MetavoxelNode* oldRoot = _roots.value(attribute);
if (oldRoot) {
oldRoot->incrementReferenceCount();
attribute->readDelta(*this, *oldRoot, state);
oldRoot->decrementReferenceCount(attribute);
bool changed;
in >> changed;
if (changed) {
oldRoot->incrementReferenceCount();
attribute->readDelta(*this, *oldRoot, state);
oldRoot->decrementReferenceCount(attribute);
} else {
attribute->readSubdivision(*this, state);
}
} else {
attribute->read(*this, state);
}
@ -317,7 +326,9 @@ void MetavoxelData::readDelta(const MetavoxelData& reference, const MetavoxelLOD
void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD,
Bitstream& out, const MetavoxelLOD& lod) const {
// first things first: there might be no change whatsoever
if (_size == reference._size && _roots == reference._roots) {
glm::vec3 minimum = getMinimum();
bool becameSubdivided = lod.becameSubdivided(minimum, _size, referenceLOD);
if (_size == reference._size && _roots == reference._roots && !becameSubdivided) {
out << false;
return;
}
@ -338,14 +349,20 @@ void MetavoxelData::writeDelta(const MetavoxelData& reference, const MetavoxelLO
expandedReference = expanded;
}
// write the added/changed roots
// write the added/changed/subdivided roots
for (QHash<AttributePointer, MetavoxelNode*>::const_iterator it = _roots.constBegin(); it != _roots.constEnd(); it++) {
MetavoxelNode* referenceRoot = expandedReference->_roots.value(it.key());
if (it.value() != referenceRoot) {
out << it.key();
MetavoxelStreamState state = { getMinimum(), _size, it.key(), out, lod, referenceLOD };
MetavoxelStreamState state = { minimum, _size, it.key(), out, lod, referenceLOD };
if (it.value() != referenceRoot || becameSubdivided) {
out << it.key();
if (referenceRoot) {
it.key()->writeDelta(*it.value(), *referenceRoot, state);
if (it.value() == referenceRoot) {
out << false;
it.key()->writeSubdivision(*it.value(), state);
} else {
out << true;
it.key()->writeDelta(*it.value(), *referenceRoot, state);
}
} else {
it.key()->write(*it.value(), state);
}
@ -506,15 +523,18 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta
}
} else {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
bool changed;
state.stream >> changed;
if (changed) {
nextState.setMinimum(state.minimum, i);
if (changed) {
_children[i] = new MetavoxelNode(state.attribute);
_children[i]->readDelta(*reference._children[i], nextState);
} else {
_children[i] = reference._children[i];
_children[i]->incrementReferenceCount();
if (nextState.becameSubdivided()) {
_children[i]->readSubdivision(nextState);
}
}
}
}
@ -539,10 +559,13 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt
}
} else {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
if (_children[i] == reference._children[i]) {
state.stream << false;
} else {
nextState.setMinimum(state.minimum, i);
if (nextState.becameSubdivided()) {
_children[i]->writeSubdivision(nextState);
}
} else {
state.stream << true;
_children[i]->writeDelta(*reference._children[i], nextState);
}
@ -551,6 +574,63 @@ void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamSt
}
}
void MetavoxelNode::readSubdivision(MetavoxelStreamState& state) {
bool leaf;
bool subdivideReference = state.shouldSubdivideReference();
if (!subdivideReference) {
state.stream >> leaf;
} else {
leaf = isLeaf();
}
if (leaf) {
clearChildren(state.attribute);
} else {
MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute,
state.stream, state.lod, state.referenceLOD };
if (!subdivideReference) {
clearChildren(state.attribute);
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
_children[i] = new MetavoxelNode(state.attribute);
_children[i]->read(nextState);
}
} else {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
if (nextState.becameSubdivided()) {
_children[i]->readSubdivision(nextState);
}
}
}
}
}
void MetavoxelNode::writeSubdivision(MetavoxelStreamState& state) const {
bool leaf = isLeaf();
bool subdivideReference = state.shouldSubdivideReference();
if (!subdivideReference) {
state.stream << leaf;
}
if (!leaf) {
MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute,
state.stream, state.lod, state.referenceLOD };
if (!subdivideReference) {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
_children[i]->write(nextState);
}
} else {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
if (nextState.becameSubdivided()) {
_children[i]->writeSubdivision(nextState);
}
}
}
}
}
void MetavoxelNode::writeSpanners(MetavoxelStreamState& state) const {
foreach (const SharedObjectPointer& object, decodeInline<SharedObjectSet>(_attributeValue)) {
if (static_cast<Spanner*>(object.data())->testAndSetVisited()) {
@ -602,9 +682,32 @@ void MetavoxelNode::writeSpannerDelta(const MetavoxelNode& reference, MetavoxelS
return;
}
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
if (_children[i] != reference._children[i]) {
nextState.setMinimum(state.minimum, i);
_children[i]->writeSpannerDelta(*reference._children[i], nextState);
} else if (nextState.becameSubdivided()) {
_children[i]->writeSpannerSubdivision(nextState);
}
}
}
void MetavoxelNode::writeSpannerSubdivision(MetavoxelStreamState& state) const {
if (!isLeaf()) {
MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute,
state.stream, state.lod, state.referenceLOD };
if (!state.shouldSubdivideReference()) {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
_children[i]->writeSpanners(nextState);
}
} else {
for (int i = 0; i < CHILD_COUNT; i++) {
nextState.setMinimum(state.minimum, i);
if (nextState.becameSubdivided()) {
_children[i]->writeSpannerSubdivision(nextState);
}
}
}
}
}

View file

@ -44,6 +44,9 @@ public:
bool isValid() const { return threshold > 0.0f; }
bool shouldSubdivide(const glm::vec3& minimum, float size) 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;
};
DECLARE_STREAMABLE_METATYPE(MetavoxelLOD)
@ -88,6 +91,7 @@ public:
void writeDelta(const MetavoxelData& reference, const MetavoxelLOD& referenceLOD,
Bitstream& out, const MetavoxelLOD& lod) const;
MetavoxelNode* getRoot(const AttributePointer& attribute) const { return _roots.value(attribute); }
MetavoxelNode* createRoot(const AttributePointer& attribute);
private:
@ -113,6 +117,7 @@ public:
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); }
void setMinimum(const glm::vec3& lastMinimum, int index);
};
@ -144,8 +149,12 @@ public:
void readDelta(const MetavoxelNode& reference, MetavoxelStreamState& state);
void writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const;
void readSubdivision(MetavoxelStreamState& state);
void writeSubdivision(MetavoxelStreamState& state) const;
void writeSpanners(MetavoxelStreamState& state) const;
void writeSpannerDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const;
void writeSpannerSubdivision(MetavoxelStreamState& state) const;
/// Increments the node's reference count.
void incrementReferenceCount() { _referenceCount++; }