Spanner subdivision streaming bits.

This commit is contained in:
Andrzej Kapolka 2014-12-04 16:41:19 -08:00
parent a990b4ae1f
commit 9819658e20
7 changed files with 81 additions and 29 deletions

View file

@ -1274,25 +1274,37 @@ void SpannerSetAttribute::writeMetavoxelRoot(const MetavoxelNode& root, Metavoxe
void SpannerSetAttribute::readMetavoxelDelta(MetavoxelData& data,
const MetavoxelNode& reference, MetavoxelStreamState& state) {
forever {
SharedObjectPointer object;
state.base.stream >> object;
if (!object) {
break;
readMetavoxelSubdivision(data, state);
}
static void writeDeltaSubdivision(SharedObjectSet& oldSet, SharedObjectSet& newSet, Bitstream& stream) {
for (SharedObjectSet::iterator newIt = newSet.begin(); newIt != newSet.end(); ) {
SharedObjectSet::iterator oldIt = oldSet.find(*newIt);
if (oldIt == oldSet.end()) {
stream << *newIt; // added
newIt = newSet.erase(newIt);
} else {
oldSet.erase(oldIt);
newIt++;
}
data.toggle(state.base.attribute, object);
}
// even if the root is empty, it should still exist
if (!data.getRoot(state.base.attribute)) {
data.createRoot(state.base.attribute);
foreach (const SharedObjectPointer& object, oldSet) {
stream << object; // removed
}
stream << SharedObjectPointer();
foreach (const SharedObjectPointer& object, newSet) {
object->maybeWriteSubdivision(stream);
}
stream << SharedObjectPointer();
}
void SpannerSetAttribute::writeMetavoxelDelta(const MetavoxelNode& root,
const MetavoxelNode& reference, MetavoxelStreamState& state) {
state.base.visit = Spanner::getAndIncrementNextVisit();
root.writeSpannerDelta(reference, state);
state.base.stream << SharedObjectPointer();
SharedObjectSet oldSet, newSet;
reference.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet);
root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet);
writeDeltaSubdivision(oldSet, newSet, state.base.stream);
}
void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, MetavoxelStreamState& state) {
@ -1302,14 +1314,31 @@ void SpannerSetAttribute::readMetavoxelSubdivision(MetavoxelData& data, Metavoxe
if (!object) {
break;
}
data.insert(state.base.attribute, object);
data.toggle(state.base.attribute, object);
}
forever {
SharedObjectPointer object;
state.base.stream >> object;
if (!object) {
break;
}
SharedObjectPointer newObject = object->readSubdivision(state.base.stream);
if (newObject != object) {
data.replace(state.base.attribute, object, newObject);
state.base.stream.addSubdividedObject(newObject);
}
}
// even if the root is empty, it should still exist
if (!data.getRoot(state.base.attribute)) {
data.createRoot(state.base.attribute);
}
}
void SpannerSetAttribute::writeMetavoxelSubdivision(const MetavoxelNode& root, MetavoxelStreamState& state) {
state.base.visit = Spanner::getAndIncrementNextVisit();
root.writeSpannerSubdivision(state);
state.base.stream << SharedObjectPointer();
SharedObjectSet oldSet, newSet;
root.getSpanners(this, state.minimum, state.size, state.base.referenceLOD, oldSet);
root.getSpanners(this, state.minimum, state.size, state.base.lod, newSet);
writeDeltaSubdivision(oldSet, newSet, state.base.stream);
}
bool SpannerSetAttribute::metavoxelRootsEqual(const MetavoxelNode& firstRoot, const MetavoxelNode& secondRoot,

View file

@ -267,7 +267,9 @@ Bitstream::ReadMappings Bitstream::getAndResetReadMappings() {
_typeStreamerStreamer.getAndResetTransientValues(),
_attributeStreamer.getAndResetTransientValues(),
_scriptStringStreamer.getAndResetTransientValues(),
_sharedObjectStreamer.getAndResetTransientValues() };
_sharedObjectStreamer.getAndResetTransientValues(),
_subdividedObjects };
_subdividedObjects.clear();
return mappings;
}
@ -291,6 +293,16 @@ void Bitstream::persistReadMappings(const ReadMappings& mappings) {
reference = it.value();
_weakSharedObjectHash.remove(it.value()->getRemoteID());
}
foreach (const SharedObjectPointer& object, mappings.subdividedObjects) {
QPointer<SharedObject>& reference = _sharedObjectReferences[object->getRemoteOriginID()];
if (reference && reference != object) {
int id = _sharedObjectStreamer.removePersistentValue(reference.data());
if (id != 0) {
_sharedObjectStreamer.insertPersistentValue(id, object);
}
}
reference = object;
}
}
void Bitstream::persistAndResetReadMappings() {

View file

@ -99,10 +99,12 @@ public:
int takePersistentID(P value) { return _persistentIDs.take(value); }
void removePersistentValue(V value) { int id = _valueIDs.take(value); _persistentValues.remove(id); }
int removePersistentValue(V value) { int id = _valueIDs.take(value); _persistentValues.remove(id); return id; }
V takePersistentValue(int id) { V value = _persistentValues.take(id); _valueIDs.remove(value); return value; }
void insertPersistentValue(int id, V value) { _valueIDs.insert(value, id); _persistentValues.insert(id, value); }
void copyPersistentMappings(const RepeatedValueStreamer& other);
void clearPersistentMappings();
@ -289,6 +291,7 @@ public:
QHash<int, AttributePointer> attributeValues;
QHash<int, QScriptString> scriptStringValues;
QHash<int, SharedObjectPointer> sharedObjectValues;
QVector<SharedObjectPointer> subdividedObjects;
};
/// Performs all of the various lazily initializations (of object streamers, etc.) If multiple threads need to use
@ -374,6 +377,9 @@ public:
/// Resets to the initial state.
void reset();
/// Adds a subdivided object, which will be added to the read mappings and used as a reference if persisted.
void addSubdividedObject(const SharedObjectPointer& object) { _subdividedObjects.append(object); }
/// Returns the set of transient mappings gathered during writing and resets them.
WriteMappings getAndResetWriteMappings();
@ -576,6 +582,8 @@ private:
RepeatedValueStreamer<QScriptString> _scriptStringStreamer;
RepeatedValueStreamer<SharedObjectPointer, SharedObject*> _sharedObjectStreamer;
QVector<SharedObjectPointer> _subdividedObjects;
WeakSharedObjectHash _sharedObjectReferences;
WeakSharedObjectHash _weakSharedObjectHash;

View file

@ -147,11 +147,11 @@ void SharedObject::readExtraDelta(Bitstream& in, const SharedObject* reference)
// nothing by default
}
void SharedObject::writeExtraSubdivision(Bitstream& out) {
void SharedObject::maybeWriteSubdivision(Bitstream& out) {
// nothing by default
}
SharedObject* SharedObject::readExtraSubdivision(Bitstream& in) {
SharedObject* SharedObject::readSubdivision(Bitstream& in) {
return this;
}

View file

@ -92,12 +92,13 @@ public:
/// Reads the delta-encoded non-property contents of this object from the specified stream.
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
/// Writes the subdivision of the non-property contents of this object to the specified stream.
virtual void writeExtraSubdivision(Bitstream& out);
/// Writes the subdivision of the contents of this object (preceeded by a
/// reference to the object itself) to the specified stream if necessary.
virtual void maybeWriteSubdivision(Bitstream& out);
/// Reads the subdivision of the non-property contents of this object from the specified stream.
/// Reads the subdivision of this object from the specified stream.
/// \return the modified object, or this if no modification was performed
virtual SharedObject* readExtraSubdivision(Bitstream& in);
virtual SharedObject* readSubdivision(Bitstream& in);
private:

View file

@ -3016,7 +3016,7 @@ void Heightfield::readExtraDelta(Bitstream& in, const SharedObject* reference) {
}
}
void Heightfield::writeExtraSubdivision(Bitstream& out) {
void Heightfield::maybeWriteSubdivision(Bitstream& out) {
MetavoxelLOD lod, referenceLOD;
if (out.getContext()) {
MetavoxelStreamBase* base = static_cast<MetavoxelStreamBase*>(out.getContext());
@ -3026,13 +3026,13 @@ void Heightfield::writeExtraSubdivision(Bitstream& out) {
HeightfieldStreamBase base = { out, lod, referenceLOD };
HeightfieldStreamState state = { base, glm::vec2(), 1.0f };
if (state.becameSubdivided()) {
if (state.becameSubdividedOrCollapsed()) {
out << SharedObjectPointer(this);
_root->writeSubdivision(state);
}
}
SharedObject* Heightfield::readExtraSubdivision(Bitstream& in) {
SharedObject* Heightfield::readSubdivision(Bitstream& in) {
MetavoxelLOD lod, referenceLOD;
if (in.getContext()) {
MetavoxelStreamBase* base = static_cast<MetavoxelStreamBase*>(in.getContext());
@ -3046,6 +3046,8 @@ SharedObject* Heightfield::readExtraSubdivision(Bitstream& in) {
HeightfieldNodePointer root(_root->readSubdivision(state));
if (_root != root) {
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
newHeightfield->setRemoteID(getRemoteID());
newHeightfield->setRemoteOriginID(getRemoteOriginID());
newHeightfield->setRoot(root);
return newHeightfield;
}

View file

@ -642,8 +642,8 @@ public:
virtual void readExtra(Bitstream& in);
virtual void writeExtraDelta(Bitstream& out, const SharedObject* reference) const;
virtual void readExtraDelta(Bitstream& in, const SharedObject* reference);
virtual void writeExtraSubdivision(Bitstream& out);
virtual SharedObject* readExtraSubdivision(Bitstream& in);
virtual void maybeWriteSubdivision(Bitstream& out);
virtual SharedObject* readSubdivision(Bitstream& in);
signals: