mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 10:28:57 +02:00
Rather than backing out when we find that the delta is too big, we can just
write the whole thing and copy it over (with some mapping fiddlery) if it turns out to be too big.
This commit is contained in:
parent
44befbb019
commit
69e7a17f47
8 changed files with 42 additions and 74 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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<SharedObjectSet>(_attributeValue)) {
|
||||
if (static_cast<Spanner*>(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<Spanner*>(object.data())->testAndSetVisited() && !newSet.contains(object)) {
|
||||
state.stream << object;
|
||||
state.checkByteLimitExceeded();
|
||||
}
|
||||
}
|
||||
foreach (const SharedObjectPointer& object, newSet) {
|
||||
if (static_cast<Spanner*>(object.data())->testAndSetVisited() && !oldSet.contains(object)) {
|
||||
state.stream << object;
|
||||
state.checkByteLimitExceeded();
|
||||
}
|
||||
}
|
||||
if (isLeaf() || !state.shouldSubdivide()) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue