diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index a01efddbf4..28f1a423c7 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -113,33 +113,31 @@ void MetavoxelSession::update() { return; } Bitstream& out = _sequencer.startPacket(); + int start = _sequencer.getOutputStream().getUnderlying().device()->pos(); out << QVariant::fromValue(MetavoxelDeltaMessage()); PacketRecord* sendRecord = getLastAcknowledgedSendRecord(); - out.setBytesRemaining(_sequencer.getMaxPacketSize()); - try { - _server->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); - _sequencer.endPacket(); - - } catch (const ByteLimitExceededException& exception) { - _sequencer.cancelPacket(); - + _server->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); + out.flush(); + int end = _sequencer.getOutputStream().getUnderlying().device()->pos(); + if (end > _sequencer.getMaxPacketSize()) { // we need to send the delta on the reliable channel _reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getOutputStream()); _reliableDeltaChannel->startMessage(); - _reliableDeltaChannel->getBitstream() << QVariant::fromValue(MetavoxelDeltaMessage()); - _server->getData().writeDelta(sendRecord->getData(), sendRecord->getLOD(), _reliableDeltaChannel->getBitstream(), _lod); - _reliableDeltaWriteMappings = _reliableDeltaChannel->getBitstream().getAndResetWriteMappings(); - _reliableDeltaChannel->getBitstream().clearPersistentMappings(); + _reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start); _reliableDeltaChannel->endMessage(); + _reliableDeltaWriteMappings = out.getAndResetWriteMappings(); _reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten(); _reliableDeltaData = _server->getData(); _reliableDeltaLOD = _lod; - Bitstream& out = _sequencer.startPacket(); + // go back to the beginning with the current packet and note that there's a delta pending + _sequencer.getOutputStream().getUnderlying().device()->seek(start); out << QVariant::fromValue(MetavoxelDeltaPendingMessage()); _sequencer.endPacket(); + + } else { + _sequencer.endPacket(); } } diff --git a/libraries/metavoxels/src/Bitstream.cpp b/libraries/metavoxels/src/Bitstream.cpp index 459a12dc15..bc662aa890 100644 --- a/libraries/metavoxels/src/Bitstream.cpp +++ b/libraries/metavoxels/src/Bitstream.cpp @@ -127,7 +127,6 @@ Bitstream::Bitstream(QDataStream& underlying, MetadataType metadataType, Generic _underlying(underlying), _byte(0), _position(0), - _bytesRemaining(INT_MAX), _metadataType(metadataType), _genericsMode(genericsMode), _objectStreamerStreamer(*this), @@ -194,16 +193,13 @@ Bitstream& Bitstream::read(void* data, int bits, int offset) { void Bitstream::flush() { if (_position != 0) { _underlying << _byte; - _bytesRemaining--; - _byte = 0; - _position = 0; + reset(); } } void Bitstream::reset() { _byte = 0; _position = 0; - _bytesRemaining = INT_MAX; } Bitstream::WriteMappings Bitstream::getAndResetWriteMappings() { diff --git a/libraries/metavoxels/src/Bitstream.h b/libraries/metavoxels/src/Bitstream.h index 97f1b70ff0..70fde94b79 100644 --- a/libraries/metavoxels/src/Bitstream.h +++ b/libraries/metavoxels/src/Bitstream.h @@ -329,6 +329,9 @@ public: Bitstream(QDataStream& underlying, MetadataType metadataType = NO_METADATA, GenericsMode = NO_GENERICS, QObject* parent = NULL); + /// Returns a reference to the underlying data stream. + QDataStream& getUnderlying() { return _underlying; } + /// Substitutes the supplied metaobject for the given class name's default mapping. This is mostly useful for testing the /// process of mapping between different types, but may in the future be used for permanently renaming classes. void addMetaObjectSubstitution(const QByteArray& className, const QMetaObject* metaObject); @@ -355,12 +358,6 @@ public: /// Resets to the initial state. void reset(); - /// Sets the number of "bytes remaining," which will be decremented with each byte written. - void setBytesRemaining(int bytesRemaining) { _bytesRemaining = bytesRemaining; } - - /// Returns the number of bytes remaining. - int getBytesRemaining() const { return _bytesRemaining; } - /// Returns the set of transient mappings gathered during writing and resets them. WriteMappings getAndResetWriteMappings(); @@ -546,7 +543,6 @@ private: QDataStream& _underlying; quint8 _byte; int _position; - int _bytesRemaining; MetadataType _metadataType; GenericsMode _genericsMode; diff --git a/libraries/metavoxels/src/DatagramSequencer.cpp b/libraries/metavoxels/src/DatagramSequencer.cpp index 2ef3d0213c..2c594fc1ca 100644 --- a/libraries/metavoxels/src/DatagramSequencer.cpp +++ b/libraries/metavoxels/src/DatagramSequencer.cpp @@ -113,17 +113,16 @@ Bitstream& DatagramSequencer::startPacket() { _outgoingPacketStream << (quint32)record.packetNumber; } - // write the high-priority messages - _outgoingPacketStream << (quint32)_highPriorityMessages.size(); - foreach (const HighPriorityMessage& message, _highPriorityMessages) { - _outputStream << message.data; - } - // return the stream, allowing the caller to write the rest return _outputStream; } void DatagramSequencer::endPacket() { + // write the high-priority messages + _outputStream << _highPriorityMessages.size(); + foreach (const HighPriorityMessage& message, _highPriorityMessages) { + _outputStream << message.data; + } _outputStream.flush(); // if we have space remaining, send some data from our reliable channels @@ -222,22 +221,22 @@ void DatagramSequencer::receivedDatagram(const QByteArray& datagram) { _sendRecords.erase(_sendRecords.begin(), it + 1); } + // alert external parties so that they can read the middle + emit readyToRead(_inputStream); + // read and dispatch the high-priority messages - quint32 highPriorityMessageCount; - _incomingPacketStream >> highPriorityMessageCount; + int highPriorityMessageCount; + _inputStream >> highPriorityMessageCount; int newHighPriorityMessages = highPriorityMessageCount - _receivedHighPriorityMessages; - for (quint32 i = 0; i < highPriorityMessageCount; i++) { + for (int i = 0; i < highPriorityMessageCount; i++) { QVariant data; _inputStream >> data; - if ((int)i >= _receivedHighPriorityMessages) { + if (i >= _receivedHighPriorityMessages) { emit receivedHighPriorityMessage(data); } } _receivedHighPriorityMessages = highPriorityMessageCount; - // alert external parties so that they can read the middle - emit readyToRead(_inputStream); - // read the reliable data, if any quint32 reliableChannels; _incomingPacketStream >> reliableChannels; diff --git a/libraries/metavoxels/src/DatagramSequencer.h b/libraries/metavoxels/src/DatagramSequencer.h index 32f645b13c..b85916b561 100644 --- a/libraries/metavoxels/src/DatagramSequencer.h +++ b/libraries/metavoxels/src/DatagramSequencer.h @@ -84,6 +84,9 @@ public: /// Returns a reference to the stream used to write packets. Bitstream& getOutputStream() { return _outputStream; } + /// Returns a reference to the outgoing packet data. + const QByteArray& getOutgoingPacketData() const { return _outgoingPacketData; } + /// Returns the packet number of the sent packet at the specified index. int getSentPacketNumber(int index) const { return _sendRecords.at(index).packetNumber; } diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 43206588cc..2d61ede796 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -681,12 +681,6 @@ void MetavoxelStreamState::setMinimum(const glm::vec3& lastMinimum, int index) { minimum = getNextMinimum(lastMinimum, size, index); } -void MetavoxelStreamState::checkByteLimitExceeded() { - if (stream.getBytesRemaining() < 0) { - throw ByteLimitExceededException(); - } -} - MetavoxelNode::MetavoxelNode(const AttributeValue& attributeValue, const MetavoxelNode* copyChildren) : _referenceCount(1) { @@ -778,13 +772,11 @@ void MetavoxelNode::read(MetavoxelStreamState& state) { void MetavoxelNode::write(MetavoxelStreamState& state) const { if (!state.shouldSubdivide()) { state.attribute->write(state.stream, _attributeValue, true); - state.checkByteLimitExceeded(); return; } bool leaf = isLeaf(); state.stream << leaf; state.attribute->write(state.stream, _attributeValue, leaf); - state.checkByteLimitExceeded(); if (!leaf) { MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, state.stream, state.lod, state.referenceLOD }; @@ -838,13 +830,11 @@ void MetavoxelNode::readDelta(const MetavoxelNode& reference, MetavoxelStreamSta void MetavoxelNode::writeDelta(const MetavoxelNode& reference, MetavoxelStreamState& state) const { if (!state.shouldSubdivide()) { state.attribute->writeDelta(state.stream, _attributeValue, reference._attributeValue, true); - state.checkByteLimitExceeded(); return; } bool leaf = isLeaf(); state.stream << leaf; state.attribute->writeDelta(state.stream, _attributeValue, reference._attributeValue, leaf); - state.checkByteLimitExceeded(); if (!leaf) { MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, state.stream, state.lod, state.referenceLOD }; @@ -907,7 +897,6 @@ void MetavoxelNode::writeSubdivision(MetavoxelStreamState& state) const { bool subdivideReference = state.shouldSubdivideReference(); if (!subdivideReference) { state.stream << leaf; - state.checkByteLimitExceeded(); } if (!leaf) { MetavoxelStreamState nextState = { glm::vec3(), state.size * 0.5f, state.attribute, @@ -932,7 +921,6 @@ void MetavoxelNode::writeSpanners(MetavoxelStreamState& state) const { foreach (const SharedObjectPointer& object, decodeInline(_attributeValue)) { if (static_cast(object.data())->testAndSetVisited()) { state.stream << object; - state.checkByteLimitExceeded(); } } if (!state.shouldSubdivide() || isLeaf()) { @@ -952,13 +940,11 @@ void MetavoxelNode::writeSpannerDelta(const MetavoxelNode& reference, MetavoxelS foreach (const SharedObjectPointer& object, oldSet) { if (static_cast(object.data())->testAndSetVisited() && !newSet.contains(object)) { state.stream << object; - state.checkByteLimitExceeded(); } } foreach (const SharedObjectPointer& object, newSet) { if (static_cast(object.data())->testAndSetVisited() && !oldSet.contains(object)) { state.stream << object; - state.checkByteLimitExceeded(); } } if (isLeaf() || !state.shouldSubdivide()) { diff --git a/libraries/metavoxels/src/MetavoxelData.h b/libraries/metavoxels/src/MetavoxelData.h index a0b0b6ef47..6a7ba33eb5 100644 --- a/libraries/metavoxels/src/MetavoxelData.h +++ b/libraries/metavoxels/src/MetavoxelData.h @@ -164,13 +164,6 @@ public: bool becameSubdivided() const; void setMinimum(const glm::vec3& lastMinimum, int index); - - /// Throws ByteLimitExceededException if the stream has fewer than zero bytes remaining. - void checkByteLimitExceeded(); -}; - -/// Thrown when we have exceeded the byte limit in writing. -class ByteLimitExceededException { }; /// A single node within a metavoxel layer. diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 48ce4716b7..4132270620 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -913,33 +913,30 @@ bool TestEndpoint::simulate(int iterationNumber) { return false; } Bitstream& out = _sequencer.startPacket(); + int start = _sequencer.getOutputStream().getUnderlying().device()->pos(); out << QVariant::fromValue(MetavoxelDeltaMessage()); PacketRecord* sendRecord = getLastAcknowledgedSendRecord(); - out.setBytesRemaining(_sequencer.getMaxPacketSize()); - try { - _data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); - _sequencer.endPacket(); - - } catch (const ByteLimitExceededException& exception) { - _sequencer.cancelPacket(); - + _data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), out, _lod); + out.flush(); + int end = _sequencer.getOutputStream().getUnderlying().device()->pos(); + if (end > _sequencer.getMaxPacketSize()) { // we need to send the delta on the reliable channel _reliableDeltaChannel = _sequencer.getReliableOutputChannel(RELIABLE_DELTA_CHANNEL_INDEX); - _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getOutputStream()); _reliableDeltaChannel->startMessage(); - _reliableDeltaChannel->getBitstream() << QVariant::fromValue(MetavoxelDeltaMessage()); - _data.writeDelta(sendRecord->getData(), sendRecord->getLOD(), _reliableDeltaChannel->getBitstream(), _lod); - _reliableDeltaWriteMappings = _reliableDeltaChannel->getBitstream().getAndResetWriteMappings(); - _reliableDeltaChannel->getBitstream().clearPersistentMappings(); + _reliableDeltaChannel->getBuffer().write(_sequencer.getOutgoingPacketData().constData() + start, end - start); _reliableDeltaChannel->endMessage(); + _reliableDeltaWriteMappings = out.getAndResetWriteMappings(); _reliableDeltaReceivedOffset = _reliableDeltaChannel->getBytesWritten(); _reliableDeltaData = _data; _reliableDeltaLOD = _lod; - Bitstream& out = _sequencer.startPacket(); + _sequencer.getOutputStream().getUnderlying().device()->seek(start); out << QVariant::fromValue(MetavoxelDeltaPendingMessage()); _sequencer.endPacket(); + + } else { + _sequencer.endPacket(); } } else { // enqueue some number of high priority messages