diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index 89b3102391..912183f5d6 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -311,7 +311,7 @@ MetavoxelPersister::MetavoxelPersister(MetavoxelServer* server) : const char* SAVE_FILE = "/resources/metavoxels.dat"; const int FILE_MAGIC = 0xDADAFACE; -const int FILE_VERSION = 2; +const int FILE_VERSION = 3; void MetavoxelPersister::load() { QString path = QCoreApplication::applicationDirPath() + SAVE_FILE; diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 860ab3e5e9..a412659f42 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -1188,67 +1188,6 @@ void MetavoxelNode::writeSpanners(MetavoxelStreamState& state) const { } } -void MetavoxelNode::writeSpannerDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const { - SharedObjectSet oldSet = decodeInline(reference.getAttributeValue()); - SharedObjectSet newSet = decodeInline(_attributeValue); - foreach (const SharedObjectPointer& object, oldSet) { - if (static_cast(object.data())->testAndSetVisited(state.base.visit) && !newSet.contains(object)) { - state.base.stream << object; - } - } - foreach (const SharedObjectPointer& object, newSet) { - if (static_cast(object.data())->testAndSetVisited(state.base.visit) && !oldSet.contains(object)) { - state.base.stream << object; - } - } - if (isLeaf() || !state.shouldSubdivide()) { - if (!reference.isLeaf() && state.shouldSubdivideReference()) { - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - reference._children[i]->writeSpanners(nextState); - } - } - return; - } - MetavoxelStreamState nextState = { state.base, glm::vec3(), state.size * 0.5f }; - if (reference.isLeaf() || !state.shouldSubdivideReference()) { - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - _children[i]->writeSpanners(nextState); - } - return; - } - for (int i = 0; i < CHILD_COUNT; i++) { - nextState.setMinimum(state.minimum, i); - if (_children[i] != reference._children[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 = { state.base, glm::vec3(), state.size * 0.5f }; - 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); - } - } - } - } -} - void MetavoxelNode::decrementReferenceCount(const AttributePointer& attribute) { if (!_referenceCount.deref()) { destroy(attribute); diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index 56d9dd3a8a..806c5bf2ae 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -239,9 +239,7 @@ public: void writeSubdivided(MetavoxelStreamState& state, const MetavoxelStreamState& ancestorState, void* ancestorValue) 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.ref(); } diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 956dc45729..f7c34b4a04 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1114,6 +1114,76 @@ template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const } } +HeightfieldStack::HeightfieldStack(int width, const QVector& materials) : + HeightfieldData(width), + _materials(materials) { +} + +HeightfieldStack::HeightfieldStack(Bitstream& in, int bytes) { + read(in, bytes); +} + +HeightfieldStack::HeightfieldStack(Bitstream& in, int bytes, const HeightfieldStackPointer& reference) { + if (!reference) { + read(in, bytes); + return; + } + QMutexLocker locker(&reference->getEncodedDeltaMutex()); + reference->setEncodedDelta(in.readAligned(bytes)); + in.readDelta(_materials, reference->getMaterials()); + reference->setDeltaData(DataBlockPointer(this)); + _width = reference->getWidth(); +} + +void HeightfieldStack::write(Bitstream& out) { + out << _materials; +} + +void HeightfieldStack::writeDelta(Bitstream& out, const HeightfieldStackPointer& reference) { +} + +void HeightfieldStack::read(Bitstream& in, int bytes) { + in >> _materials; +} + +Bitstream& operator<<(Bitstream& out, const HeightfieldStackPointer& value) { + if (value) { + value->write(out); + } else { + out << 0; + } + return out; +} + +Bitstream& operator>>(Bitstream& in, HeightfieldStackPointer& value) { + int size; + in >> size; + if (size == 0) { + value = HeightfieldStackPointer(); + } else { + value = new HeightfieldStack(in, size); + } + return in; +} + +template<> void Bitstream::writeRawDelta(const HeightfieldStackPointer& value, const HeightfieldStackPointer& reference) { + if (value) { + value->writeDelta(*this, reference); + } else { + *this << 0; + } +} + +template<> void Bitstream::readRawDelta(HeightfieldStackPointer& value, const HeightfieldStackPointer& reference) { + int size; + *this >> size; + if (size == 0) { + value = HeightfieldStackPointer(); + } else { + value = new HeightfieldStack(*this, size, reference); + } +} + bool HeightfieldStreamState::shouldSubdivide() const { return base.lod.shouldSubdivide(minimum, size); } @@ -1144,10 +1214,11 @@ void HeightfieldStreamState::setMinimum(const glm::vec2& lastMinimum, int index) } HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material) : + const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack) : _height(height), _color(color), _material(material), + _stack(stack), _renderer(NULL) { } @@ -1155,6 +1226,7 @@ HeightfieldNode::HeightfieldNode(const HeightfieldNode& other) : _height(other.getHeight()), _color(other.getColor()), _material(other.getMaterial()), + _stack(other.getStack()), _renderer(NULL) { for (int i = 0; i < CHILD_COUNT; i++) { @@ -1169,7 +1241,7 @@ HeightfieldNode::~HeightfieldNode() { const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION; void HeightfieldNode::setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material) { + const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack) { clearChildren(); int heightWidth = height->getWidth(); @@ -1246,9 +1318,13 @@ void HeightfieldNode::setContents(const HeightfieldHeightPointer& height, const childMaterial = new HeightfieldMaterial(childMaterialWidth, childMaterialContents, childMaterials); } + HeightfieldStackPointer childStack; + if (stack) { + } + _children[i] = new HeightfieldNode(); _children[i]->setContents(HeightfieldHeightPointer(new HeightfieldHeight(childHeightWidth, childHeightContents)), - childColor, childMaterial); + childColor, childMaterial, childStack); } mergeChildren(); @@ -2046,13 +2122,13 @@ void HeightfieldNode::read(HeightfieldStreamState& state) { clearChildren(); if (!state.shouldSubdivide()) { - state.base.stream >> _height >> _color >> _material; + state.base.stream >> _height >> _color >> _material >> _stack; return; } bool leaf; state.base.stream >> leaf; if (leaf) { - state.base.stream >> _height >> _color >> _material; + state.base.stream >> _height >> _color >> _material >> _stack; } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2067,13 +2143,13 @@ void HeightfieldNode::read(HeightfieldStreamState& state) { void HeightfieldNode::write(HeightfieldStreamState& state) const { if (!state.shouldSubdivide()) { - state.base.stream << _height << _color << _material; + state.base.stream << _height << _color << _material << _stack; return; } bool leaf = isLeaf(); state.base.stream << leaf; if (leaf) { - state.base.stream << _height << _color << _material; + state.base.stream << _height << _color << _material << _stack; } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2091,6 +2167,7 @@ void HeightfieldNode::readDelta(const HeightfieldNodePointer& reference, Heightf state.base.stream.readDelta(_height, reference->getHeight()); state.base.stream.readDelta(_color, reference->getColor()); state.base.stream.readDelta(_material, reference->getMaterial()); + state.base.stream.readDelta(_stack, reference->getStack()); return; } bool leaf; @@ -2099,6 +2176,7 @@ void HeightfieldNode::readDelta(const HeightfieldNodePointer& reference, Heightf state.base.stream.readDelta(_height, reference->getHeight()); state.base.stream.readDelta(_color, reference->getColor()); state.base.stream.readDelta(_material, reference->getMaterial()); + state.base.stream.readDelta(_stack, reference->getStack()); } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2135,6 +2213,7 @@ void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, Height state.base.stream.writeDelta(_height, reference->getHeight()); state.base.stream.writeDelta(_color, reference->getColor()); state.base.stream.writeDelta(_material, reference->getMaterial()); + state.base.stream.writeDelta(_stack, reference->getStack()); return; } bool leaf = isLeaf(); @@ -2143,6 +2222,7 @@ void HeightfieldNode::writeDelta(const HeightfieldNodePointer& reference, Height state.base.stream.writeDelta(_height, reference->getHeight()); state.base.stream.writeDelta(_color, reference->getColor()); state.base.stream.writeDelta(_material, reference->getMaterial()); + state.base.stream.writeDelta(_material, reference->getStack()); } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2174,10 +2254,10 @@ HeightfieldNode* HeightfieldNode::readSubdivision(HeightfieldStreamState& state) bool leaf; state.base.stream >> leaf; if (leaf) { - return isLeaf() ? this : new HeightfieldNode(_height, _color, _material); + return isLeaf() ? this : new HeightfieldNode(_height, _color, _material, _stack); } else { - HeightfieldNode* newNode = new HeightfieldNode(_height, _color, _material); + HeightfieldNode* newNode = new HeightfieldNode(_height, _color, _material, _stack); HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; for (int i = 0; i < CHILD_COUNT; i++) { nextState.setMinimum(state.minimum, i); @@ -2207,7 +2287,7 @@ HeightfieldNode* HeightfieldNode::readSubdivision(HeightfieldStreamState& state) return node; } } else if (!isLeaf()) { - return new HeightfieldNode(_height, _color, _material); + return new HeightfieldNode(_height, _color, _material, _stack); } return this; } @@ -2243,13 +2323,13 @@ void HeightfieldNode::readSubdivided(HeightfieldStreamState& state, const Height if (!state.shouldSubdivide()) { // TODO: subdivision encoding - state.base.stream >> _height >> _color >> _material; + state.base.stream >> _height >> _color >> _material >> _stack; return; } bool leaf; state.base.stream >> leaf; if (leaf) { - state.base.stream >> _height >> _color >> _material; + state.base.stream >> _height >> _color >> _material >> _stack; } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2266,13 +2346,13 @@ void HeightfieldNode::writeSubdivided(HeightfieldStreamState& state, const Heigh const HeightfieldNode* ancestor) const { if (!state.shouldSubdivide()) { // TODO: subdivision encoding - state.base.stream << _height << _color << _material; + state.base.stream << _height << _color << _material << _stack; return; } bool leaf = isLeaf(); state.base.stream << leaf; if (leaf) { - state.base.stream << _height << _color << _material; + state.base.stream << _height << _color << _material << _stack; } else { HeightfieldStreamState nextState = { state.base, glm::vec2(), state.size * 0.5f }; @@ -2516,6 +2596,7 @@ Heightfield::Heightfield() : connect(this, &Heightfield::heightChanged, this, &Heightfield::updateRoot); connect(this, &Heightfield::colorChanged, this, &Heightfield::updateRoot); connect(this, &Heightfield::materialChanged, this, &Heightfield::updateRoot); + connect(this, &Heightfield::stackChanged, this, &Heightfield::updateRoot); updateRoot(); } @@ -2549,9 +2630,9 @@ void Heightfield::setMaterial(const HeightfieldMaterialPointer& material) { } } -void Heightfield::setRoot(const HeightfieldNodePointer& root) { - if (_root != root) { - emit rootChanged(_root = root); +void Heightfield::setStack(const HeightfieldStackPointer& stack) { + if (_stack != stack) { + emit stackChanged(_stack = stack); } } @@ -2948,7 +3029,7 @@ bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float void Heightfield::writeExtra(Bitstream& out) const { if (getWillBeVoxelized()) { - out << _height << _color << _material; + out << _height << _color << _material << _stack; return; } MetavoxelLOD lod; @@ -2962,7 +3043,7 @@ void Heightfield::writeExtra(Bitstream& out) const { void Heightfield::readExtra(Bitstream& in) { if (getWillBeVoxelized()) { - in >> _height >> _color >> _material; + in >> _height >> _color >> _material >> _stack; return; } MetavoxelLOD lod; @@ -3072,7 +3153,7 @@ void Heightfield::updateBounds() { void Heightfield::updateRoot() { HeightfieldNodePointer root(new HeightfieldNode()); if (_height) { - root->setContents(_height, _color, _material); + root->setContents(_height, _color, _material, _stack); } setRoot(root); } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index bec1355b48..2e95d54528 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -23,6 +23,7 @@ class HeightfieldColor; class HeightfieldHeight; class HeightfieldMaterial; class HeightfieldNode; +class HeightfieldStack; class SpannerRenderer; /// An object that spans multiple octree cells. @@ -466,6 +467,36 @@ Bitstream& operator>>(Bitstream& in, HeightfieldMaterialPointer& value); template<> void Bitstream::writeRawDelta(const HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); template<> void Bitstream::readRawDelta(HeightfieldMaterialPointer& value, const HeightfieldMaterialPointer& reference); +typedef QExplicitlySharedDataPointer HeightfieldStackPointer; + +/// A block of stack data associated with a heightfield. +class HeightfieldStack : public HeightfieldData { +public: + + HeightfieldStack(int width, const QVector& materials); + HeightfieldStack(Bitstream& in, int bytes); + HeightfieldStack(Bitstream& in, int bytes, const HeightfieldStackPointer& reference); + + QVector& getMaterials() { return _materials; } + + void write(Bitstream& out); + void writeDelta(Bitstream& out, const HeightfieldStackPointer& reference); + +private: + + void read(Bitstream& in, int bytes); + + QVector _materials; +}; + +Q_DECLARE_METATYPE(HeightfieldStackPointer) + +Bitstream& operator<<(Bitstream& out, const HeightfieldStackPointer& value); +Bitstream& operator>>(Bitstream& in, HeightfieldStackPointer& value); + +template<> void Bitstream::writeRawDelta(const HeightfieldStackPointer& value, const HeightfieldStackPointer& reference); +template<> void Bitstream::readRawDelta(HeightfieldStackPointer& value, const HeightfieldStackPointer& reference); + typedef QExplicitlySharedDataPointer HeightfieldNodePointer; /// Holds the base state used in streaming heightfield data. @@ -499,14 +530,15 @@ public: HeightfieldNode(const HeightfieldHeightPointer& height = HeightfieldHeightPointer(), const HeightfieldColorPointer& color = HeightfieldColorPointer(), - const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer()); + const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer(), + const HeightfieldStackPointer& stack = HeightfieldStackPointer()); HeightfieldNode(const HeightfieldNode& other); ~HeightfieldNode(); void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color, - const HeightfieldMaterialPointer& material); + const HeightfieldMaterialPointer& material, const HeightfieldStackPointer& stack); void setHeight(const HeightfieldHeightPointer& height) { _height = height; } const HeightfieldHeightPointer& getHeight() const { return _height; } @@ -517,6 +549,9 @@ public: void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; } const HeightfieldMaterialPointer& getMaterial() const { return _material; } + void setStack(const HeightfieldStackPointer& stack) { _stack = stack; } + const HeightfieldStackPointer& getStack() const { return _stack; } + void setRenderer(AbstractHeightfieldNodeRenderer* renderer) { _renderer = renderer; } AbstractHeightfieldNodeRenderer* getRenderer() const { return _renderer; } @@ -566,6 +601,7 @@ private: HeightfieldHeightPointer _height; HeightfieldColorPointer _color; HeightfieldMaterialPointer _material; + HeightfieldStackPointer _stack; HeightfieldNodePointer _children[CHILD_COUNT]; @@ -588,8 +624,9 @@ class Heightfield : public Transformable { Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false) Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false DESIGNABLE false) - Q_PROPERTY(HeightfieldNodePointer root MEMBER _root WRITE setRoot NOTIFY rootChanged STORED false DESIGNABLE false) - + Q_PROPERTY(HeightfieldStackPointer stack MEMBER _stack WRITE setStack NOTIFY stackChanged STORED false + DESIGNABLE false) + public: Q_INVOKABLE Heightfield(); @@ -609,7 +646,10 @@ public: void setMaterial(const HeightfieldMaterialPointer& material); const HeightfieldMaterialPointer& getMaterial() const { return _material; } - void setRoot(const HeightfieldNodePointer& root); + void setStack(const HeightfieldStackPointer& stack); + const HeightfieldStackPointer& getStack() const { return _stack; } + + void setRoot(const HeightfieldNodePointer& root) { _root = root; } const HeightfieldNodePointer& getRoot() const { return _root; } MetavoxelLOD transformLOD(const MetavoxelLOD& lod) const; @@ -652,7 +692,7 @@ signals: void heightChanged(const HeightfieldHeightPointer& height); void colorChanged(const HeightfieldColorPointer& color); void materialChanged(const HeightfieldMaterialPointer& material); - void rootChanged(const HeightfieldNodePointer& root); + void stackChanged(const HeightfieldStackPointer& stack); protected: @@ -671,6 +711,7 @@ private: HeightfieldHeightPointer _height; HeightfieldColorPointer _color; HeightfieldMaterialPointer _material; + HeightfieldStackPointer _stack; HeightfieldNodePointer _root; }; diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 3f08cdec69..35fcee80a7 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -81,7 +81,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAudioStreamStats: return 1; case PacketTypeMetavoxelData: - return 10; + return 11; case PacketTypeVoxelData: return VERSION_VOXELS_HAS_FILE_BREAKS; default: